Current version

v1.10.4 (stable)

Navigation

Main page
Archived news
Downloads
Documentation
   Capture
   Compiling
   Processing
   Crashes
Features
Filters
Plugin SDK
Knowledge base
Donate
Contact info
Forum
 
Other projects
   Altirra

Search

Calendar

« May 2013 »
S M T W T F S
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Archives

01 Aug - 31 Aug 2013
01 May - 31 May 2013
01 Mar - 31 Mar 2013
01 Feb - 29 Feb 2013
01 Dec - 31 Dec 2012
01 Nov - 30 Nov 2012
01 Oct - 31 Oct 2012
01 Sep - 30 Sep 2012
01 Aug - 31 Aug 2012
01 June - 30 June 2012
01 May - 31 May 2012
01 Apr - 30 Apr 2012
01 Dec - 31 Dec 2011
01 Nov - 30 Nov 2011
01 Oct - 31 Oct 2011
01 Sep - 30 Sep 2011
01 Aug - 31 Aug 2011
01 Jul - 31 Jul 2011
01 June - 30 June 2011
01 May - 31 May 2011
01 Apr - 30 Apr 2011
01 Mar - 31 Mar 2011
01 Feb - 29 Feb 2011
01 Jan - 31 Jan 2011
01 Dec - 31 Dec 2010
01 Nov - 30 Nov 2010
01 Oct - 31 Oct 2010
01 Sep - 30 Sep 2010
01 Aug - 31 Aug 2010
01 Jul - 31 Jul 2010
01 June - 30 June 2010
01 May - 31 May 2010
01 Apr - 30 Apr 2010
01 Mar - 31 Mar 2010
01 Feb - 29 Feb 2010
01 Jan - 31 Jan 2010
01 Dec - 31 Dec 2009
01 Nov - 30 Nov 2009
01 Oct - 31 Oct 2009
01 Sep - 30 Sep 2009
01 Aug - 31 Aug 2009
01 Jul - 31 Jul 2009
01 June - 30 June 2009
01 May - 31 May 2009
01 Apr - 30 Apr 2009
01 Mar - 31 Mar 2009
01 Feb - 29 Feb 2009
01 Jan - 31 Jan 2009
01 Dec - 31 Dec 2008
01 Nov - 30 Nov 2008
01 Oct - 31 Oct 2008
01 Sep - 30 Sep 2008
01 Aug - 31 Aug 2008
01 Jul - 31 Jul 2008
01 June - 30 June 2008
01 May - 31 May 2008
01 Apr - 30 Apr 2008
01 Mar - 31 Mar 2008
01 Feb - 29 Feb 2008
01 Jan - 31 Jan 2008
01 Dec - 31 Dec 2007
01 Nov - 30 Nov 2007
01 Oct - 31 Oct 2007
01 Sep - 30 Sep 2007
01 Aug - 31 Aug 2007
01 Jul - 31 Jul 2007
01 June - 30 June 2007
01 May - 31 May 2007
01 Apr - 30 Apr 2007
01 Mar - 31 Mar 2007
01 Feb - 29 Feb 2007
01 Jan - 31 Jan 2007
01 Dec - 31 Dec 2006
01 Nov - 30 Nov 2006
01 Oct - 31 Oct 2006
01 Sep - 30 Sep 2006
01 Aug - 31 Aug 2006
01 Jul - 31 Jul 2006
01 June - 30 June 2006
01 May - 31 May 2006
01 Apr - 30 Apr 2006
01 Mar - 31 Mar 2006
01 Feb - 29 Feb 2006
01 Jan - 31 Jan 2006
01 Dec - 31 Dec 2005
01 Nov - 30 Nov 2005
01 Oct - 31 Oct 2005
01 Sep - 30 Sep 2005
01 Aug - 31 Aug 2005
01 Jul - 31 Jul 2005
01 June - 30 June 2005
01 May - 31 May 2005
01 Apr - 30 Apr 2005
01 Mar - 31 Mar 2005
01 Feb - 29 Feb 2005
01 Jan - 31 Jan 2005
01 Dec - 31 Dec 2004
01 Nov - 30 Nov 2004
01 Oct - 31 Oct 2004
01 Sep - 30 Sep 2004
01 Aug - 31 Aug 2004

Stuff

Powered by Pivot  
XML: RSS feed 
XML: Atom feed 

§ AVIFile library in Windows Vista creates invalid AVI files

I was tipped off by a reader about some problems with AVI files in Windows Vista, based on this MSDN forum link:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=844438&SiteID=1

I ran test the test application and can confirm that this bug occurs in Windows Vista RTM. Essentially, every program that uses the Microsoft AVIFile APIs (avifil32.dll) to generate AVI files will produce them with a malformed RIFF structure!

(Sigh.... one more reason to avoid Vista....)

Here's the file produced by the program under Vista: vista-avifile-output.zip (57K)

The specific problem is a rather odd chunk arrangement near the beginning of the file where the 'movi' LIST chunk lies. This chunk holds all of the stream data in the file, but it's a bit odd here:

000000a0: 40 01 F0 00 73 74 72 66-28 00 00 00 28 00 00 00  |@...strf(...(...|
000000b0: 40 01 00 00 F0 00 00 00-01 00 10 00 4D 53 56 43  |@...........MSVC|
000000c0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  |................|
000000d0: 00 00 00 00 4A 55 4E 4B-00 00 00 00 4C 49 53 54  |....JUNK....LIST|
000000e0: 48 37 0D 00 6D 6F 76 69-00 00 00 00 00 00 00 00  |H7..movi........|
...
000007f0: 00 00 00 00 4C 49 53 54-30 30 0D 00 6D 6F 76 69  |....LIST00..movi|
00000800: 30 30 64 62 82 70 00 00-00 00 00 00 00 00 00 00  |00db.p..........|
00000810: 00 00 01 00 00 00 00 00-02 00 00 00 00 00 03 00  |................|
00000820: 00 00 00 00 04 00 00 00-00 00 05 00 00 00 00 00  |................|

There's two of them, and one's generated in a very odd place. Worse yet, LIST chunks are supposed to be containers for other chunks, but the first 'movi' LIST starts with garbage.

What's going on here: In most cases, it isn't possible to generate an AVI in a single pass. The reason is that AVI, like any other RIFF file, uses chunks which are prefixed with the data length, and it isn't generally possible to predict the size of the 'movi' chunk when generating the AVI incrementally, nor is the data small enough to buffer everything in memory. To get around this, the AVI file is generated with dummy size fields, and when the file is finished, those size fields are backpatched with the correct sizes, which are known after all of the data has been written. It looks like someone either broke the backpatching code in Vista so that it fails to rewrite the 'movi' header in the right place, aligned to 2K - 12 bytes, instead effectively extending it backwards, or somehow managed to open two 'movi' chunks.

I should note that VirtualDub does write correct AVI files when running under Windows Vista, because it has its own internal routines for doing so. It's still affected by this bug, though more on that in a bit.

So, what's the correct fix? Well, it's not so simple. Here is a hex dump of the index at the end of the file:

000d3820: 00 00 0A 74 00 00 00 00-09 74 00 00 69 64 78 31  |...t.....t..idx1|
000d3830: E0 01 00 00 30 30 64 62-10 00 00 00 1C 07 00 00  |....00db........|
000d3840: 82 70 00 00 30 30 64 62-10 00 00 00 A6 77 00 00  |.p..00db.....w..|
000d3850: 82 70 00 00 30 30 64 62-10 00 00 00 30 E8 00 00  |.p..00db....0...|
000d3860: 82 70 00 00 30 30 64 62-10 00 00 00 BA 58 01 00  |.p..00db.....X..|
000d3870: 82 70 00 00 30 30 64 62-10 00 00 00 44 C9 01 00  |.p..00db....D...|
000d3880: 82 70 00 00 30 30 64 62-10 00 00 00 CE 39 02 00  |.p..00db.....9..|

The field highlighted in red is the position value for the first video frame in the file, and is supposed to be an relative index within the 'movi' LIST chunk to the start of the sample chunk header. Well, the first 'movi' LIST is at 0xDC, and 0xDC + 0x08 + 0x71C = 0x800, which is where the first sample in video stream 0 lies ('00db'). So the first 'movi' chunk is the one that is consistent with the index. We can fix the RIFF structure of the file by turning the garbage at the start of the 'movi' chunk into another padding (JUNK) chunk:

000000d0: 00 00 00 00 4A 55 4E 4B-00 00 00 00 4C 49 53 54  |....JUNK....LIST|
000000e0: 48 37 0D 00 6D 6F 76 69-4A 55 4E 4B 10 07 00 00  |H7..moviJUNK....|

Now the file is consistent... but it still isn't compatible. It turns out that VirtualDub still won't read the file because the oddball positioning conflicts with some code I have to try to detect relative vs. absolute indexing. (There are some other applications that have similar problems.) To make matters worse, the AVIFile library in Windows XP SP2 also has problems with the file, so the "AVIFile input driver (compat.)" mode in VirtualDub, which tells it to use AVIFile, won't work either. In fact, when I tried to use the old Media Player (mplay32.exe) to play the file, since it can be forced to use AVIFile through the Video for Windows MCI driver, the Windows XP AVIFile library actually crashed in memmove(). Great.

So, basically, I don't have a good solution at this time, other than to... chastise... the nearest Microsoft representative. I can tell you that VirtualDub 1.7.2 will be able to read such files, because I was tipped off to this problem and checked a fix into my dev tree before I became aware that Windows Vista itself was the culprit. For those of you who are shipping or have shipped applications that write AVI files through AVIFile, I don't know what to tell you. I haven't dug into the Vista avifil32.dll and couldn't tell you a fix, and DirectShow is a very rough way to write an AVI file from scratch. AVIFile writes relatively simple AVI files compared to what's flying around, though it doesn't handle indexing beyond 2GB so I'd recommend looking into writing a replacement. It's not that hard to generate a basic AVI file.

(Read more....)

§ Sometimes I hate 3D hardware

VirtualDub 1.7.1 has a hidden feature: it tests whether your 3D card supports occlusion query in OpenGL.

If you see a crash when selecting the "screen capture" driver in capture mode, you don't have it.

Some people have unfortunately discovered that this prevents entering capture mode again, since the crash happens after VirtualDub remembers the last capture driver. Workaround: Hold down SHIFT when selecting File > Capture AVI from the menu.

(Read more....)

§ "Fixing" working code

One of the lessons you eventually learn the hard way as a programmer is never to "fix" working code. If you have a confirmed bug, then fix it; if you have a feature you need to add, then by all means, change it.

"Fixing" code that just looks buggy, without actually knowing how it is bad, is a mistake.

Let's say you have an 80% chance of getting code right in the first place, and thus a 20% chance of getting it wrong. That means if you just look at it again, you have a 64% chance of verifying it right again, a 16% chance of writing it incorrectly but catching the bug, and a 4% chance of blowing it both times. That leaves a 16% chance of writing it correctly and thinking it's wrong. There's then a chance that you'll act on that instinct and break working code.

Here's a real example that I just discovered:

A certain vendor's C runtime library has code to display an error dialog under certain circumstances, such as an assert, with a program path. If the program path is too long, it truncates it and only displays the end of the path with an ellipsis at the start. This was done via strncpy():

if (strlen(path) > MAXLENGTH) {
    path += strlen(path) - MAXLENGTH;
    strncpy(path, "...", 3);
}

In a later version of the product, someone noticed the use of strncpy() and replaced it with strncpy_s():

if (strlen(path) > MAXLENGTH) {
    path += strlen(path) - MAXLENGTH;
    strncpy_s(path, "...", 3);
}

Now, I'm not really a fan of the secure string library -- I'd rather just use a string class instead -- but strncpy() is admittedly a bit risky to use given its tendency to create non-null terminated strings. You can use strncpy() safely, but it's easy to forget or goof the boundary check. Safer alternatives like strlcpy() are often used instead. At first glance, the change looks like a perfectly good improvement to eliminate any potential buffer overrun mistakes... except for two problems. One, the source is a string literal and the destination is a fixed buffer that is far larger than four characters, so there was never any issue with non-termination. Second, the original code actually depended on strncpy()'s non-terminating behavior, because it is putting the ellipsis at the beginning of the string. The attempt to fix a non-existent bug actually broke the code.

So, basically, don't guess at bugs. If you think there is a bug, reproduce it first so you can actually confirm it and verify that you actually fixed something instead of breaking it, and then keep that case around for regression testing.

(Read more....)

§ VirtualDub 1.7.1 (27021) released

New experimental version.

...

Well, you know the drill.

Animated GIF support is indeed in this version. I experimented with an animated palette delta trick that a reader suggested, and it does indeed create some really nice animated GIFs. (For the three of you who remember my really old DOS paint program, I pulled the adaptive palette generation code from it.) Animated GIF output wasn't really meant to be a real feature in VirtualDub, particularly since I don't want to implement two-pass encoding just for an optimized global palette, so the output path doesn't have options and tends to write enormous files. Still, if you want to experiment with it, you can do so via the Tools > Create Animated GIF menu option.

There are a few other miscellaneous features in this version as well. I threw in a CPU version of the "warp resize" display pixel shader I posted a while back, and the "display decompressed output" option can now be toggled on the fly, so you can preview part of a save operation without slowing down the whole thing.

The real features in this version, though, are all due to me screwing around a bit with 3D acceleration.

First, the Direct3D and D3DFX display minidrivers now have hardware YCbCr acceleration support for most formats, including UYVY, YUY2, YV24, YV16, YV12, I420, and YVU9. I used pixel shaders for this, so it's not vulnerable to the imprecise or incorrectly ranged hardware conversions that the DirectShow Video Mixing Renderer 9 sometimes hits with StretchBlt(). Also, the D3D9 and D3DFX minidrivers now have full support for field display modes. The plan is to eventually switch the default display path from DirectDraw to Direct3D for Windows Vista, but I'm not ready to make the switch yet, as I'm still seeing annoying issues with Vista and NVIDIA display drivers... and I haven't gotten around to reinstalling Vista RTM on my ATI-based machine to figure out who to blame.

Second, preview acceleration in capture mode now has options to do field-based display. This isn't particularly useful during normal capture, but they're more useful if you're viewing non-interlaced output... like if a certain programmer decided to use his new capture device to play an old Playstation 1 game, like Lunar 2....

The distinctive feature in this version, though, is the screen capture support in capture mode. Now, you might think... why the heck did he add screen capture? Because he's too cheap to buy a real screen capture program? Well, yes, but the real reason is that I found an interesting way to do it. The screen capture minidriver supports OpenGL acceleration, which means that if you have a 3D card with pixel shaders, you can get hardware accelerated scaling, RGB-to-YCbCr conversion, and duplicate frame detection (probably the strangest use ever for occlusion query). I have successfully captured a 1920x1200 desktop, shrunk to 960x600, converted to YUY2, and compressed to Huffyuv at 30 fps. Combine this with "What U Hear" or "Stereo Mix" or whatever your sound card calls the loopback, and you can capture motion video with sound with surprisingly good sync. Surprisingly, it works even if another program is using the 3D hardware -- I successfully captured Final Fantasy VII in an emulator at full rate. The downside is that it doesn't seem to work with the NVIDIA drivers for Vista, where it just gives a black screen. It fails even if the DWM is disabled and only Aero Basic is displayed. Again, I haven't tried this with ATI's Vista drivers yet, although I did test it successfully on a RADEON X850XT in Windows XP. If anyone has an idea how to get desktop readback into a texture working on Vista or manages to get it working with WDDM drivers, please let me know.

Read on for the change list.

(Read more....)