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!
tags: directshow
|