在媒体基础中支持 DXVA 2.0
本主题介绍如何在使用 Microsoft Direct3D 9 的媒体基础转换 (MFT) 中支持 DirectX 视频加速 (DXVA) 2.0 具体而言,它描述了解码器和视频呈现器之间的通信,这由拓扑加载程序调解。 本主题不介绍如何实现 DXVA 解码。
在本主题的其余部分,术语 解码器 是指解码器 MFT,它接收压缩的视频并输出未压缩的视频。 术语 解码器设备 是指由图形驱动程序实现的硬件视频加速器。
提示
有关 Microsoft Direct3D 11 视频解码的信息,请参阅 支持 Media Foundation 中的 Direct3D 11 视频解码。
注意
Windows 应用商店应用必须使用 Direct3D 11。
下面是解码器在媒体基础中支持 DXVA 2.0 时必须执行的基本步骤:
- 打开 Direct3D 9 设备的句柄。
- 查找 DXVA 解码器配置。
- 分配未压缩的缓冲区。
- 解码帧。
本主题的其余部分更详细地介绍了这些步骤。
打开 Direct3D 设备句柄
MFT 使用 Microsoft Direct3D 设备管理器获取 Direct3D 9 设备的句柄。 若要打开设备句柄,请执行以下步骤:
- 公开值为 TRUE的 MF_SA_D3D_AWARE 属性。 拓扑加载程序通过调用 IMFTransform::GetAttributes 来查询此属性。 将 属性设置为 TRUE 会通知拓扑加载程序 MFT 支持 DXVA。
- 格式协商开始时,拓扑加载程序使用MFT_MESSAGE_SET_D3D_MANAGER消息调用 IMFTransform::P rocessMessage。 ulParam 参数是指向视频呈现器的 Direct3D 设备管理器的 IUnknown 指针。 查询 IDirect3DDeviceManager9 接口的此指针。
- 调用 IDirect3DDeviceManager9::OpenDeviceHandle 以获取呈现器 Direct3D 设备的句柄。
- 调用 IDirect3DDeviceManager9::GetVideoService 并传入设备句柄。 此方法返回指向 IDirectXVideoDecoderService 接口的 指针。
- 缓存指针和设备句柄。
查找解码器配置
MFT 必须找到 DXVA 解码器设备的兼容配置。 验证输入类型后,在 IMFTransform::SetInputType 方法中执行以下步骤:
调用 IDirectXVideoDecoderService::GetDecoderDeviceGuids。 此方法返回解码器设备 GUID 的数组。
循环访问解码器 GUID 数组,查找解码器支持的 GUID。 例如,对于 MPEG-2 解码器,可以查找 DXVA2_ModeMPEG2_MOCOMP、 DXVA2_ModeMPEG2_IDCT或 DXVA2_ModeMPEG2_VLD。
找到候选解码器设备 GUID 时,将 GUID 传递给 IDirectXVideoDecoderService::GetDecoderRenderTargets 方法。 此方法返回呈现目标格式的数组,指定为 D3DFORMAT 值。
循环访问呈现目标格式,并查找解码器支持的格式。
调用 IDirectXVideoDecoderService::GetDecoderConfigurations。 传入相同的解码器设备 GUID,以及描述建议的输出格式 的DXVA2_VideoDesc 结构。 方法返回 DXVA2_ConfigPictureDecode 结构的数组。 每个结构都描述了解码器设备的一种可能配置。 查找解码器支持的配置。
存储呈现目标格式和配置。
在 IMFTransform::GetOutputAvailableType 方法中,基于建议的呈现目标格式返回未压缩的视频格式。
在 IMFTransform::SetOutputType 方法中,根据呈现目标格式检查媒体类型。
回退到软件解码
例如,如果 MFT 找不到 DXVA 配置 (,则图形驱动程序) 没有正确的功能,它应从 SetInputType 和 SetOutputType 方法返回MF_E_UNSUPPORTED_D3D_TYPE错误代码。 拓扑加载程序将通过发送具有 ulParam 参数值 NULL 的MFT_MESSAGE_SET_D3D_MANAGER消息进行响应。 MFT 应释放指向 IDirect3DDeviceManager9 接口的指针。 然后,拓扑加载程序将重新协商媒体类型,MFT 可以使用软件解码。
分配未压缩的缓冲区
在 DXVA 2.0 中,解码器负责分配 Direct3D 图面以用作未压缩的视频缓冲区。 解码器应为 EVR 分配 3 个用于去交错的图面。 此数字是固定的,因为媒体基础没有为 EVR 提供一种方法来指定图形驱动程序需要多少个图面进行去交错。 对于任何驱动程序来说,三个表面都应该足够。
在 IMFTransform::GetOutputStreamInfo 方法中,设置 MFT_OUTPUT_STREAM_INFO 结构中的 MFT_OUTPUT_STREAM_PROVIDES_SAMPLES 标志。 此标志通知媒体会话 MFT 分配其自己的输出样本。
若要创建图面,请调用 IDirectXVideoAccelerationService::CreateSurface。 (IDirectXVideoDecoderService 接口从 IDirectXVideoAccelerationService.) 在找到呈现目标格式后,可以在 SetInputType 中执行此操作。
对于每个图面,调用 MFCreateVideoSampleFromSurface 以创建用于保存图面的媒体样本。 方法返回指向 IMFSample 接口的指针。
解码
若要创建解码器设备,请调用 IDirectXVideoDecoderService::CreateVideoDecoder。 方法返回指向解码 器设备的 IDirectXVideoDecoder 接口的指针。
解码应在 IMFTransform::P rocessOutput 方法内进行。 在每个帧上,调用 IDirect3DDeviceManager9::TestDevice 以测试设备句柄。 如果设备已更改,该方法将返回 DXVA2_E_NEW_VIDEO_DEVICE。 如果发生这种情况,请执行以下操作:
- 通过调用 IDirect3DDeviceManager9::CloseDeviceHandle 关闭设备句柄。
- 释放 IDirectXVideoDecoderService 和 IDirectXVideoDecoder 指针。
- 打开新的设备句柄。
- 协商新的解码器配置,如本页前面的“查找解码器配置”中所述。
- 创建新的解码器设备。
假设设备句柄有效,解码过程如下所示:
- 获取当前未使用的可用图面。 (最初所有图面都可用。)
- 查询 IMFTrackedSample 接口的媒体示例。
- 调用 IMFTrackedSample::SetAllocator 并提供指向由解码器实现的 IMFAsyncCallback 接口的指针。 当视频呈现器释放示例时,将调用解码器的回调。
- 调用 IDirectXVideoDecoder::BeginFrame。
- 执行以下一次或多次操作:
- 调用 IDirectXVideoDecoder::GetBuffer 以获取 DXVA 解码器缓冲区。
- 填充缓冲区。
- 调用 IDirectXVideoDecoder::ReleaseBuffer。
- 调用 IDirectXVideoDecoder::Execute 对帧执行解码操作。
DXVA 2.0 使用与 DXVA 1.0 相同的数据结构进行解码操作。 对于 H.261、H.263 和 MPEG-2) (的原始 DXVA 配置文件集, DXVA 1.0 规范中介绍了这些数据结构。
在每对 BeginFrame/Execute 调用中,可以多次调用 GetBuffer ,但对于每种类型的 DXVA 缓冲区,只能调用一次。 如果使用相同的缓冲区类型调用它两次,将覆盖数据。
使用 SetAllocator 方法 (步骤 3) 中的回调来跟踪当前可用的示例以及正在使用的样本。
相关主题