Stuff

One of the bitter lessons I've learned while working on VirtualDub is that for every single field in a file format, there's at least one program out there that writes a bogus value into it. Usually it's just due to unintended bugs; occasionally it's due to some moron who reads "denominator of a fraction" in the docs and decides it's a good idea to write zero. In the case of audio in the Microsoft AVI and WAV formats, there are several fields which make more or less sense depending on the specific audio encoding you're working with, and that means that sometimes you find programs writing values in files that are... less than optimal.

A user recently reported to me that a specific video file that he had wouldn't process in VirtualDub, sticking on frame 0. The app wasn't hung, and he could abort the operation, but the pipeline simply wouldn't advance. It turned out that he had been using a WAV file with an incorrect nAvgBytesPerSec field that was far too low -- it came out to something like 0.216 kbps for an MP3 stream, when in reality it was actually more like 96 kbps. This field normally indicates the data rate of the audio stream in bytes per second, but in his case it was so small that it was causing VirtualDub to allocate a zero byte audio buffer, which then caused the pipeline to immediately stall. Soon afterward, another user gave me a sample that was even worse in that it had zero for this field, which not only was invalid, but also caused the Fraunhofer-IIS codec to crash with a divide-by-zero error when the format was handed off to the waveOut API. These were no doubt the result of works-for-me syndrome, caused primarily by decoders that don't validate or even check all of the fields, which then causes people to ship applications that don't write correct values. nBlockAlign=0 is another oddball that I've seen in the wild and already had to put in workarounds for.

I've queued a sort of fix for this issue for the next 1.8.4 release, which is to ensure that the audio buffer can always hold at least one sample and that it's at least 64K in size. It's not a great fix by any means, but it'll at least get things working until I get a better one in. In the meantime, if you're suffering with this issue with an MP3-encoded WAV file, your best bet is to change the file type in the "audio from other file" open dialog from the default to MPEG audio; this will force the MPEG audio parser to be used, which will do a full scan of the stream and compute the data rate instead. For AVI-sourced audio, I might try to correct with dwRate/dwScale of the stream, which has to be reasonable for seeking to work. For WAV audio, it might be a bit tougher, although it might be possible to estimate a reasonable value based on the 'fact' chunk, which is supposed to holds the uncompressed length of the audio stream... assuming it's correct. I'll probably make the program apply this correction only if the value is obviously bogus (i.e., zero), and emit a warning when it does so.

A couple of days ago, I was running one of my side projects that uses several of VirtualDub's core libraries, including the display code, and discovered to my annoyance that the full-screen mode was not working properly. The program displays video at lock-step 60 fps, so it's sensitive to timing and the glitches are very apparent when it misses frames. This was a particularly bad case, though, because it was missing very badly -- enough that the audio was breaking up -- and this was on a CPU that was about 50% faster than the previous one I had, which ran this program perfectly. The windowed mode wasn't syncing very well either, but that's understandable given the non-exclusive nature of windowed mode, and so clearly the speed of the program core wasn't the problem.

I eventually tracked it down to something odd in the NVIDIA driver for my Quadro NVS 140M. For some strange reason, the driver was lying to me and actually running the full-screen display at 50Hz, but lying to my program and saying it was 60Hz, which of course totally trashed the program timing. I didn't notice because I'm on an LCD, which doesn't show a 50Hz refresh rate by flickering like a CRT would. The desktop was also suffering from the same problem, which was even more bizarre. It turned out that the culprit in the windowed case was a setting in the NVIDIA control panel called "Extend battery charge by using less power for the display"; clearing that restored the desktop at least to 60Hz and gave me clean frame sync again. I still can't figure out how to get the full screen mode back to 60Hz, though. The DirectX APIs are all reporting only 60Hz being available for refresh rate on all available display modes, but every single one of them is actually 50Hz. I tried turning off all the PowerMizer options, but to no avail. How annoying.

Anyway, if you're getting a lot of tearing when you try to play video on your laptop, it may not be the video player. The video driver may be fooling with it a bit.

1.8.3 is out, and fixes a horrendously stupid regression in 1.8.2 where VirtualDub's main window wouldn't display if you didn't already have saved window position data in the Registry. If anyone's still seeing issues in 1.8.3 like this, please let me know.

On the other hand, I already received an email from a software site saying that VirtualDub 1.8.2 has been added to the database and awarded 5 stars....

I have to apologize for the quality of the last couple of releases. To be honest, I haven't found a good solution to the testing problem. Having only one release line didn't work, because I couldn't push experimental changes out without breaking the mainline. Splitting development into two release lines still didn't really fix the problem because most people didn't try the experimental version and so I still ended up with showstopper bugs in the stable line. Lately I've been pushing out test releases at a much faster rate to the forum; that's helped a lot with specific issues since I can get bug fixes to people and have them verify it in much less time, but it's generally still the case that the first stable release end up with a few major bugs that didn't get caught in the pre-testing. In this case, it happened because I and everyone who had been trying those test releases already had the position data in the Registry because we'd been running incremental releases up to the final, and because the few tests that currently exist in the release script are scripted and don't notice issues in the UI. I'd like to beef up the automated testing, but that's going slowly since it's about as major as developing the program itself. Sigh.

If you have some time and tend to track VirtualDub releases, please swing over to the Testing section of the forums, and try the latest test releases there from time to time. I can't implement features very quickly -- particularly right now -- but if you spot new bugs, I can usually fix those on a time scale of days to weeks instead of months as it would be for a full release. I really apprecate this kind of feedback as it helps avoid releasing a dog like I did today.

VirtualDub 1.8.2 is now posted as a new stable release. This version contains a number of bug fixes, including those for audio sync issues with frame rate conversion, missing audio with type-1 DV files, synchronization errors with distributed job lists, and issues with frame sampling with video filters with certain color formats. Enjoy.

For the most part the graphs weren't too interesting, except the ones that are tagged "VirtualDub import." Upon seeing that, I couldn't help but cock my head and think, what the heck is that? The main function, opening an AVI, doesn't do much I/O. There are about fifteen other import paths, depending on whether you're opening an MPEG-1, ANIM, image sequence, WAV, MP3, or whatever you can open with input plugins... all of which are technically "VirtualDub import." What the heck... I wrote the program, and I still don't know what that is!

(I learned later, after digging through a bunch of links, that it specially refers to opening MPEG-2 via the modded version VirtualDub-MPEG2, which does a full file scan like my original MPEG-1 module. Still, it had me confused for a while.)