示例视频 DSP 插件中的视频格式协商

[与此页面关联的功能(Windows 媒体播放器 SDK)是旧版功能。 它已被 MediaPlayer 取代。 MediaPlayer 已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用 MediaPlayer 而不是 Windows 媒体播放器 SDK。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

在Windows 媒体播放器将视频DSP插件插入信号链之前,播放器必须确定插件是否可以处理正在播放的视频。 插件和播放器就支持的视频格式进行通信的过程称为格式协商。

提供支持的输入和输出类型

如果 DSP 插件充当 DirectX 媒体对象 (DMO) ,则播放器将通过对 IMediaObject::GetInputType 和 IMediaObject::GetOutputType 进行一系列调用来查询插件支持的格式。

如果 DSP 插件充当媒体基础转换 (MFT) ,播放器将通过对 IMFTransform::GetInputAvailableType 和 IMFTransform::GetOutputAvailableType 进行一系列调用来查询插件支持的格式。

Windows 媒体播放器插件向导生成的示例视频插件将受支持的视频格式列表存储为 GUID 数组。 以下代码来自 main .cpp 文件:

static const GUID*    k_guidValidSubtypes[] = {
    &MEDIASUBTYPE_NV12,
    &MEDIASUBTYPE_YV12,
    &MEDIASUBTYPE_YUY2,
    &MEDIASUBTYPE_UYVY,
    &MEDIASUBTYPE_RGB32,
    &MEDIASUBTYPE_RGB24,
    &MEDIASUBTYPE RGB555,
    &MEDIASUBTYPE RGB565
};

播放器可以按任意顺序调用 IMediaObject::GetInputTypeIMediaObject::GetOutputType ,因此插件代码必须对此进行预测。 同样,玩家可以按任意顺序调用 IMFTransform::GetInputAvailableTypeIMFTransform::GetOutputAvailableTypeGetOutputTypeGetOutputAvailableType 的示例实现测试输入类型是否已定义。 如果支持,插件将响应它仅支持该类型。 否则,插件将返回与提供的索引对应的类型,如以下代码所示:

// 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];     
}

设置输入和输出类型

如果 DSP 插件充当 DMO,Windows 媒体播放器通过调用 IMediaObject::SetInputTypeIMediaObject::SetOutputType 来设置媒体类型,向每个函数传递指向表示所请求媒体类型的DMO_MEDIA_TYPE结构的指针。

如果 DSP 插件充当 MFT,Windows 媒体播放器通过调用 IMFTransform::SetInputTypeIMFTransform::SetOutputType 来设置媒体类型,向每个函数传递指向表示所请求媒体类型的 IMFMediaType 接口的指针。

无法保证播放器将以任何特定顺序调用格式协商方法,因此插件代码必须处理任何情况。 例如,如果播放器在调用 SetInputType 之前调用 SetOutputType,则插件拒绝建议的输出媒体类型是有效的操作过程。 IMediaObject::SetOutputType 的示例实现中的以下代码对此进行了演示:

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;
}

SetInputTypeSetOutputType 的示例插件实现调用名为 ValidateMediaType 的自定义函数。 此插件函数对建议的媒体类型执行一系列测试,旨在确保媒体类型格式良好且受插件支持。 ValidateMediaType 执行以下测试:

  • 验证 majortypeformattype 成员是否包含正确的值。
  • 验证 子类型 成员是否与受支持的格式之一匹配。
  • 验证 BITMAPINFOHEADERVIDEOINFOHEADERVIDEOINFOHEADER2 结构中的信息是否包含有效值。
  • 测试输入和输出媒体类型是否匹配,因为插件不会将格式从输入转换为输出。

如果建议的媒体类型通过验证测试,则它存储在成员变量中:输入媒体类型的 m_mtInputm_mtOutput 输出媒体类型。

实现视频 DSP 插件