启用 DirectX 视频加速

[与此页面关联的功能 Windows Media Format 11 SDK 是旧版功能。 它已被源读取器和接收器编写器取代。 源读取器和接收器编写器已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用源读取器和接收器编写器,而不是 Windows Media Format 11 SDK。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

本部分介绍如何在自定义播放器中播放流内容时启用 Microsoft® DirectX® 视频加速。

背景

DirectX 视频加速 (DirectX VA) 是用于二维解码操作的硬件加速的 API 规范。 它使软件解码器能够将某些 CPU 密集型操作卸载到图形卡进行处理。 对于最终用户,这可以实现高比特率视频,例如在配备 DirectX VA 兼容显卡的旧计算机上全屏 DVD 播放。

从 Windows Media Format 9 系列 SDK 开始,DMO 包装器筛选器支持 DirectX VA。 这意味着,对于本地播放,应用程序可以使用 WM ASF 阅读器筛选器来播放基于 Windows 媒体的内容,如果图形卡支持,则会自动调用 DirectX VA 硬件加速。 但是,WM ASF 读取器筛选器不支持播放流式内容。 因此,如果要在自定义播放器中播放流式传输内容时支持 DirectX VA,则必须使用备用机制,即Windows 媒体播放器从 Windows Media 9 系列开始使用的机制。

由于Windows 媒体播放器是在开发 QASF 筛选器之前设计的,因此Windows 媒体播放器具有自己的基于 Windows 媒体格式 SDK 的源筛选器,用于播放基于 Windows 媒体的内容。 WMP Windows 媒体源筛选器将解压缩的数据直接在下游传送到音频和视频呈现器。 相比之下,WM ASF 读取器将压缩内容下游传递到 Windows Media 解码器 DirectX 媒体对象 (DMO 包装器中托管的 DMO) 。 下图说明了 WM ASF 读取器和 WMP Windows 媒体源筛选器之间的差异。

自定义源筛选器输出未压缩的示例

qasf 源筛选器输出压缩示例

若要为流式传输的内容启用 DirectX VA,必须创建自定义源筛选器,如顶部关系图中的筛选器。 基本上,此筛选器将使用 Windows 媒体格式 SDK 来实例化 WM 读取器对象、解压缩示例,并将其发送到其输出引脚的下游。 此讨论假定你已创建源筛选器,现在已准备好实现 DirectX VA 支持。

若要启用 DirectX VA,源筛选器的基本任务是为视频呈现器和 WMV 解码器 DMO 提供协商 DirectX VA 连接所需的接口。 源筛选器不参与这些协商。 流式传输启动后,源筛选器可以执行的唯一与 DirectX VA 相关的任务是在 WMV 解码器将其传送到视频呈现器之前修改视频样本上的时间戳。 执行此操作的主要原因是提供超出标准 DirectShow® 接口所启用的自定义时间线控件。

定义了三个接口,用于在 Windows Media Format SDK、播放器的源筛选器、Windows Media Video 解码器 DMO 和覆盖混音器或视频混合呈现器之间启用必要的通信。 下表介绍了这些接口。

接口 说明
IWMCodecAMVideoAccelerator 由 Windows Media 解码器 DMO 公开并由媒体播放器的源筛选器调用,以设置启用 DirectX VA 以解码 Windows Media 视频内容所需的各种连接。
IWMPlayerTimestampHook 在玩家的源筛选器上实现。 它使筛选器能够在将视频样本传送到下游之前修改视频样本上的时间戳。
IWMReaderAccelerator 在 WM Reader 对象上实现。 它由玩家源筛选器调用,以从解码器 DMO 获取接口。

 

已启用 DirectX VA 的播放中的操作顺序

本部分介绍已启用 DirectX VA 的播放器及其源筛选器在运行时的一般操作顺序。 本节中提到的组件包括:

  • 第三方媒体播放器,称为播放器。
  • 由播放器实例化的自定义源筛选器,它使用 Windows 媒体格式 SDK 来解压缩基于 Windows 媒体的内容。
  • 播放器源筛选器的视频输出引脚,称为输出固定。
  • DirectShow 视频播放筛选器图,称为图形。
  • 视频混合呈现器,称为 VMR。
  • Windows Media Format SDK 异步读取器对象,称为读取器。
  • Windows Media 视频解码器 DirectX 媒体对象,称为解码器 DMO。

操作顺序如下:

  1. 玩家实例化其源筛选器和读取器对象。 读取器创建视频解码器 DMO 并设置 (压缩) 输入类型。 在玩家尝试配置其视频播放图之前,必须发生这种情况,因为 SDK 和解码器 DMO 必须参与图形的协商过程,并且 DMO 必须在步骤 9 中知道输入格式。
  2. 播放器调用 IGraphBuilder::Render,为其提供视频源筛选器的输出引脚。 此时,DirectShow 筛选器图管理器会尝试将 VMR 连接到播放器的视频源筛选器。
  3. 筛选器图管理器在播放器的视频源筛选器的输出引脚上调用 IPin::Connect

步骤 4 到 10 发生在 IPin::Connect 内部。

  1. 源筛选器从读取器的 IWMReaderAccelerator::GetCodecInterface 方法获取 IWMCodecAMVideoAccelerator 接口。 如果编解码器不支持 DirectX VA,则对 GetCodecInterface 的调用可能会失败。 在这种情况下,协商将照常进行,没有 DirectX VA 支持。

  2. 源筛选器通过 IWMCodecAMVideoAccelerator::SetAcceleratorInterface 将 IAMVideoAccelerator 指针从传递到 Connect 的引脚传递到解码器 DMO。

  3. 然后,源筛选器将 IPin::Connect 操作的其余部分委托给 CBaseOutputPin::Connect 方法。 SDK 的格式枚举会像现在一样进行。 如果编解码器支持所连接内容的 DirectX VA,则编解码器 DMO 先显示这些 DirectX VA 子类型,然后再显示支持的 YUV 和 RGB 类型。 如果 DirectX VA 支持可用,则会在 DirectX VA 子类型的上下文中尝试步骤 7 到 11。 以下代码片段演示如何标识 DirectX VA 媒体子类型。

    bool IsDXVASubtype( AM_MEDIA_TYPE * pmt )
    {
        // All DXVA types have the same last 3 DWORDs.
        // guidDXVA is the base GUID for all DXVA subtypes.
    
        GUID guidDXVA = { 0x00000000, 0xa0c7, 0x11d3, { 0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5 } };
    
        unsigned long const * plguid;
        unsigned long const * plguidDXVA;
        plguid = (unsigned long const *)&pmt->subtype;
        plguidDXVA = (unsigned long *)&guidDXVA;
    
        if( ( plguid[1] == plguidDXVA[1] ) &&
            ( plguid[2] == plguidDXVA[2] ) &&
            ( plguid[3] == plguidDXVA[3] ) )
        {
            return true;
        }
    
        return false;
    }
    
    
  4. CBaseOutputPin::Connect 实现在步骤 3 期间调用 IPin::CompleteConnect。 如果正在考虑 DirectX VA 子类型,则会尝试 DirectX VA 协商。 输出引脚调用 IWMCodecAMVideoAccelerator::NegotiateConnection,向其传递当前输出媒体类型。

  5. 解码器 DMO 通过 IAMVideoAccelerator 接口与 VMR 执行所需的协商,并返回两者已同意的视频子类型 GUID。 输出引脚将在此过程中收到的所有 IAMVideoAcceleratorNotify 调用委托给解码器 DMO 的 IAMVideoAcceleratorNotify 接口,该接口也可以通过 IWMReaderAccelerator::GetCodecInterface 方法获取。

  6. 如果 NegotiateConnection 成功,则输出引脚使用 IWMPlayerTimestampHook 接口调用 IWMCodecAMVideoAccelerator::SetPlayerNotify 此挂钩允许源筛选器在将样本传递给呈现器之前更新样本上的时间戳。

  7. 源筛选器使用协商媒体类型调用 IWMReaderAccelerator::Notify 。 这允许读取器更新其内部变量并提交到 DirectX VA。 这是编解码器或读取器可能失败的最后一个位置。 如果上述任何步骤失败,源筛选器应返回到步骤 3,并尝试读取器枚举的下一类型。

  8. 播放开始。 如果连接输出类型为 DirectX VA,读取器将忽略解码器 DMO 的输出缓冲区。

  9. 发生 IPin::D isconnect 时,源筛选器使用 NULL 调用 IWMCodecAMVideoAccelerator::SetAcceleratorInterface。 这会断开编解码器和呈现器之间的 DirectX VA 连接。

读取 ASF 文件