blog tags:


I'm Dmitry Popov,
lead developer and director of Infognition.

Known in the interwebs as Dee Mon since 1997. You could see me as thedeemon on reddit or LiveJournal.

Articles Technology Blog News Forum Company
Older posts Newer posts

Buggy VirtualDub filters
August 16, 2012

The same day I was dealing with VDFilter issue described in previous post I ran Video Enhancer (which also uses VDFilter), picked a random VirtualDub plugin and tried to process one file. Suddenly I've got a message telling me about an exception arised inside that VirtualDub plugin. Most VD plugins have been here for a while and are known for thair speed, stability and high quality, so I immediately decided the problem was in VDFilter, our DirectShow wrapper for those plugins. I started a debug session to find what caused the exception and luckily the source code for that plugin was available on its web page. The plugin is called Flip 1.1 (ef_flip.vdf from the big collection of filters by Emiliano Ferrari). To my surprise however I've found the bug quite fast and it was not in VDFilter, this time it was in the plugin itself. Source code of the main routine is pretty short:

void Rotate180 (Pixel32 *dst,Pixel32 *tmp,const int pitch,const int w,const int h, 
                const FilterFunctions *ff)
  Pixel32 *a,*b;
  int i;
  a= dst;
  b= dst + (h*pitch);
  int alf = h/2;
  if (h&1) alf++;

  for (int j=0; j<alf; j++)
    _memcpy (tmp,a,w*sizeof(Pixel32)); // tmp= a;
    a+= w;      
    for (i=0; i<w; i++) *a--= *b++;   // a=b 
    for (i=0; i<w; i++) *b--= *tmp++; // b=tmp
    tmp-= w;      
    a+= pitch;
    b-= pitch;
  if (!(h&1)) // even lines
    _memcpy (tmp,a,w*sizeof(Pixel32));
    a+= w;      
    for (i=0; i<w; i++) *a--= *tmp++;         
Take a look at the two red lines. h is the image height and pitch here is equal to the number of Pixel32 values in one row of image, so h*pitch is the number of pixels in whole image. At first pointer b points to dst + (h*pitch), i.e. the first byte outside the image buffer! And then in the loop it's being read and then incremented to point even farther from the end of the buffer. It didn't cause crashes in VirtualDub because for some reason memory after the image buffer always belonged to the application, however it did read garbage there so the first line of "rotated" image should contain garbage after applying this filter. In case of VDFilter and its use in Video Enhancer one line of memory after the image buffer not always completely belonged to the program, so for small frames it worked ok but with a larger frame the b pointer walked too far and caused a segmentation fault which was caught as an exception and caused our wrapper to show the message box.

It may be the case that author assumed pitch to be a negative value, however this assumption doesn't look correct. Here's a quote from VirtualDub Plugin SDK:
"Bitmaps can be stored top-down as well as bottom-up. The pitch value value is positive if the image is stored bottom-up in memory and negative if the image is stored top-down. This is only permitted if the filter declares support for flexible formats by returning FILTERPARAM_SUPPORTS_ALTFORMATS from paramProc; otherwise, the host ensures that the filter receives a bottom-up orientation with a positive pitch, flipping the bitmap beforehand if necessary."

Lessons learned: 1) some VirtualDub plugins, even very simple ones, may contain bugs. 2) pointer arithmetic requires a lot of attention to be used correctly.


Working with old Video Renderer
August 15, 2012

There are several different video renderers available in DirectShow. When you look at the list of DirectShow filters you can see two filters named "Video Renderer" among others.

One of them, with GUID starting with "6BC1..", is VMR-7 (video mixing renderer), it is the default video renderer on Windows XP and later. The other, with GUID starting with "70E1..", is the old Video Renderer used by default on earlier versions of Windows. This filter may bring some surprises even today.

Recently someone reported a crash in VDFilter, our DirectShow wrapper for VirtualDub filters. He sent us a .grf file, a saved graph which forced the crash when run. In that graph our filter was connected directly to the old Video Renderer. After building a similar graph I could reproduce the case, indeed something went wrong there. First minutes of debugging showed that memory buffer of a media sample provided by video renderer to upstream filter was smaller than size of data our filter tried to write here. How could this happen? Usually when two filters agree on connection at some point the downstream filter (which will receive data) calls upstream filter's DecideBufferSize() method to ask how big the data samples will be. It uses this value to create buffers for the samples and provide the buffers to upstream filter to fill with data. Video Renderer does that, however during playback if its window doesn't fit into the screen or gets resized Video Renderer tries to renegotiate connection type and offers media type for the connection with different video dimensions - according to its window size. If upstream filter accepts such media type then Video Renderer starts to provide buffers of changed size even without calling DecideBufferSize(). Our filter wasn't ready for this sneaky behaviour, it continued to provide amount of data specified in last call to DecideBufferSize(), which caused overflow of the new shrinked buffers provided by Video Renderer. We had to change our filter to refuse connection type changes while running (otherwise it would have to include a resizer to rescale output images to the new dimensions given by Video Renderer).

Moral of this story: when you create a DirectShow transform filter don't expect output samples to be the same size you requested in DecideBufferSize() and be ready to be asked for connection type change during playback!


Deciphering .grf files
August 10, 2012

In DirectShow we work with graphs of filters. We build them in tools like GraphEdit or GraphEditPlus while experimenting and then we build them in our own code. Some parts of graph can be built automatically by DirectShow's intelligent connect procedure which selects filters according to their ability to handle given mediatypes and their priorities. To see details of graph built by our code we can save the graph to a file and then open it in an editor. Loading a graph from a file is done by calling IPersistStream::Load() method which performs all the loading logic and either succeeds or fails, there's not much control over its actions. If the graph was created on a different machine or the same machine but in different circumstances and it mentions some filters, devices or even files not available at the moment of loading, then loading fails and the graph file is pretty much worthless.

Not anymore! Here is a small utility which can read a .grf file and translate it to plain text containing most of useful information. Now you can easily see graph details (filters, connections, mediatypes, including all basic info for video and audio streams) even if you don't have all the mentioned filters and files. (134 KB)

It's a command line tool, you run it like

grfdump.exe file.grf > plain_text.txt
and get something like:



Reviving this blog
August 09, 2012

It's been a while since I wrote something meaningful here. Partly because I've already got a personal blog here (in Russian language) and partly because I wanted to upgrade the blog engine first to include tags and pagination at least. Now it's finally done (blog engine has doubled its size and reached a whole hundred lines of OCaml code ;) ) and I'm going to write here more often. Mainly programmer stuff about DirectShow, video processing, compression etc.


Sales continued
June 25, 2011

We have switched our payments processor and now use Avangate to accept payments in different forms. All the products can now be purchased online without any delays.


Sales through RegNow temporarily unavailable
June 23, 2011

Due to a temporal problem all retail sales through RegNow (payments processor we've been using for last 5 years) are currently unavailable. We're working on a solution. Our products are try-before-you-buy, so don't be in a hurry, take your time to evaluate them, and when sales will be active again you'll be able to purchase licenses for full versions.


How many frames super resolution needs?
December 27, 2010

As you already know, super resolution is a method to upsample video which for each frame uses information from neighbour frames. I was asked many times: how many frames does it use? Well, our SR implementation is "streaming": frame in - frame out. Internally for each new frame it uses its own result for previous frame, i.e. to upsample frame N it uses upsampled frame N-1 for which frame N-2 was used, for which frame N-3 was used and so on. In this sense all previous frames are used to make the current one. However video is changing from frame to frame and as new information gets accumulated old information gets forgotten. And when processing frame 100 there is hardly anything left from frame 1. So how many frames are really used?

To answer this question we took some files from our video resize shootout and upsized them 2 times first the whole files, then starting from frame 20, then starting from frame 40 etc. Then we measured PSNR for each frame and looked at the charts.



Resizing video 4x
December 14, 2010

Our super resolution implementation internally upscales video 2 times. If you ask Video Enhancer or Super Resolution plugin to upsize video 4 times using one instance of SR, it will upsize it 2x with super resolution approach and then 2x more using just a high quality image resampling method. For this reason we usually recommended to make a chain of 2 SR instances, each upsizing 2 times. This is what we did in our comparison. But are two instances really required?

To answer this question we took 10 videos from the comparison and upsized them 4 times using just one instance of SR. Here are the results in terms of PSNR:



Digital Video and Audio in 30 minutes
November 1, 2010

A very good explanation of digital video and audio basics in just 30 minutes of video:

Requires a modern browser to watch, I guess (it plays fine in my Firefox 3.6).


Disabling Windows Media Player
October 26, 2010

On my office PC I'm running Windows 7 with automatic updates turned on. It seems that recently it updated Windows Media Player (WMP) and when I tried to play an AVI file, instead of my usual player of choice (Media Player Classic installed with K-Lite Codec Pack) WMP popped up and offered to configure itself. It showed a list of different file extensions which it could play and some of them, including AVI, were checked by default and were impossible to uncheck! Moreover, when I ran Media Player Classic and asked it to be the default player for AVI files it couldn't do it anymore: the system returned WMP to be the default AVI player. That was horrible because I can't stand Windows Media Player. So I looked for a way to uninstall it, but it's not in the list of programs to uninstall. Luckily, everything's not lost yet because there is an easy way to disable WMP without any registry hacks.



Older posts Newer posts