Microsoft DirectX 8.1 (C++) |
Video renderers in DirectShow accept only video formats that can be drawn efficiently. For example, the window-based run-time renderer will accept only the RGB format that matches the current display device mode (for example, RGB565 when the display is set to 65,536 colors). As a last resort, it also accepts 8-bit palettized formats, as most display cards can draw this format efficiently. When the renderer has Microsoft® DirectDraw® loaded, it might later ask the source filter to switch to something that can be written onto a DirectDraw surface and drawn directly through display hardware. In some cases, the renderer's upstream filter might try to change the video format while the video is playing. This often occurs when a video stream has a palette change. It is most often the video decompressor that initiates a dynamic format change.
An upstream filter attempting to change formats dynamically should always call the IPin::QueryAccept method on the renderer input pin (for filters based on CTransformFilter, this is implemented in CTransformFilter::CheckInputType). The formats a renderer will allow an upstream filter to change dynamically are undefined. However, at a very minimum, it should allow the upstream filter to change palettes. When an upstream filter changes media types, it will attach the format to the first sample delivered in that new type. If the renderer holds many samples in a queue waiting to be rendered, it should delay changing the format until the sample with the type change is actually about to be rendered.
In order to force a decoder to provide DirectDraw-ready formats with a negative biHeight, the renderer must request a custom format change.
When the renderer is paused, it should call QueryAccept on the upstream pin to see which of these formats the decoder can provide. A decoder might not enumerate all the types it can accept, so the renderer should offer some types even if the decoder doesn’t advertise them.
If the decoder succeeds QueryAccept, the renderer next tells the decoder to switch to the new format, by putting the new media type on the sample the renderer give to the decoder from the renderer’s allocator (using IMediaSample::SetMediaType). This only works if the renderer has provided the allocator. Override NotifyAllocator to fail unless you are given your own allocator given to the decoder in GetAllocator. Now the decoder will give you samples in this new format.
Some decoders have a bug that requires the renderer to set biHeight to a negative number when asking for any YUV type, or else they will draw the image upside down.
Whenever a format change is detected by the video renderer, it should send an EC_DISPLAY_CHANGED notification. Most video renderers pick a format during connection so that the format can be drawn efficiently through GDI. If the user changes the current display mode without restarting the computer, a renderer might find itself with a bad image format connection and should send this notification. The first parameter should be the pin that needs reconnecting. The Filter Graph Manager will arrange for the filter graph to be stopped and the pin reconnected. During the subsequent reconnection, the renderer can accept a more appropriate format.
Whenever a video renderer detects a palette change in the stream it should send the EC_PALETTE_CHANGED notification to the Filter Graph Manager. The DirectShow video renderers detect whether a palette has really changed in dynamic format or not. The video renderers do this not only to filter out the number of EC_PALETTE_CHANGED notifications sent but also to reduce the amount of palette creation, installation, and deletion required.
Finally, the video renderer might also detect that the size of the video has changed, in which case, it should send the EC_VIDEO_SIZE_CHANGED notification. An application might use this notification to negotiate space in a compound document. The actual video dimensions are available through the IBasicVideo control interface. The DirectShow renderers detect whether the video has actually changed size or not prior to sending these events.