Video Format Negotiation in the Sample Video DSP Plug-in

[The feature associated with this page, Windows Media Player SDK, is a legacy feature. It has been superseded by MediaPlayer. MediaPlayer has been optimized for Windows 10 and Windows 11. Microsoft strongly recommends that new code use MediaPlayer instead of Windows Media Player SDK, when possible. Microsoft suggests that existing code that uses the legacy APIs be rewritten to use the new APIs if possible.]

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.

Implementing a Video DSP Plug-in