Video Format Negotiation in the Sample Video DSP Plug-in
Before Windows Media Player inserts a video DSP plug-in into the signal chain, the Player must determine whether the plug-in can process the video being played. The process by which the plug-in and the Player communicate about supported video formats is called format negotiation.
Providing the Supported Input and Output Types
If the DSP plug-in is acting as a DirectX Media Object (DMO), the Player queries the plug-in about its supported formats by making a sequence of calls to IMediaObject::GetInputType and IMediaObject::GetOutputType.
If the DSP plug-in is acting as a Media Foundation Transform (MFT), the Player queries the plug-in about its supported formats by making a sequence of calls to IMFTransform::GetInputAvailableType and IMFTransform::GetOutputAvailableType.
The sample video plug-in generated by the Windows Media Player Plug-in Wizard stores the list of supported video formats as an array of GUIDs. The following code is from the main .cpp file:
static const GUID* k_guidValidSubtypes[] = {
&MEDIASUBTYPE_NV12,
&MEDIASUBTYPE_YV12,
&MEDIASUBTYPE_YUY2,
&MEDIASUBTYPE_UYVY,
&MEDIASUBTYPE_RGB32,
&MEDIASUBTYPE_RGB24,
&MEDIASUBTYPE RGB555,
&MEDIASUBTYPE RGB565
};
The Player can call IMediaObject::GetInputType and IMediaObject::GetOutputType in any order, so the plug-in code must anticipate this. Similary, the Player can call IMFTransform::GetInputAvailableType and IMFTransform::GetOutputAvailableType in any order. The sample implementations of GetOutputType and GetOutputAvailableType test whether the input type has already been defined. If it has, the plug-in responds that it supports only that type. Otherwise, the plug-in returns the type that corresponds to the supplied index, as the following code demonstrates:
// If input type has been defined, then use that as output type.
if (GUID_NULL != m_mtInput.majortype)
{
hr = ::MoCopyMediaType( pmt, &m_mtInput );
}
else // Otherwise use default for this plug-in.
{
::ZeroMemory( pmt, sizeof( DMO_MEDIA_TYPE ) );
pmt->majortype = MEDIATYPE_Video;
pmt->subtype = *k_guidValidSubtypes[dwTypeIndex];
}
Setting the Input and Output Types
If the DSP plug-in is acting as a DMO, Windows Media Player sets the media type by calling IMediaObject::SetInputType and IMediaObject::SetOutputType, passing to each function a pointer to a DMO_MEDIA_TYPE structure that represents the requested media type.
If the DSP plug-in is acting as an MFT, Windows Media Player sets the media type by calling IMFTransform::SetInputType and IMFTransform::SetOutputType, passing to each function a pointer to an IMFMediaType interface that represents the requested media type.
There is no guarantee that the Player will call format negotiation methods in any particular order, so plug-in code must handle any case. For instance, if the Player calls SetOutputType before calling SetInputType, it is a valid course of action for the plug-in to reject the proposed output media type. The following code from the sample implementation of IMediaObject::SetOutputType demonstrates this:
if( GUID_NULL != m_mtInput.majortype )
{
// Validate that the output media type matches our requirements
// and matches our input type (if set).
hr = ValidateMediaType(pmt, &m_mtInput);
}
else
{
hr = DMO_E_TYPE_NOT_ACCEPTED;
}
The sample plug-in implementations of SetInputType and SetOutputType call the custom function named ValidateMediaType. This plug-in function performs a series of tests on the proposed media type designed to ensure that the media type is well-formed and supported by the plug-in. ValidateMediaType performs the following tests:
- Verifies that the majortype and formattype members contain the correct values.
- Verifies that the subtype member matches one of the supported formats.
- Verifies that the information in the BITMAPINFOHEADER and VIDEOINFOHEADER or VIDEOINFOHEADER2 structures contain valid values.
- Tests whether the input and output media types match because the plug-in does not convert formats from input to output.
If the proposed media type passes the validation tests, it is stored in a member variable: m_mtInput for the input media type, m_mtOutput for the output media type.
Related topics