Direct3D 12 视频概述

本文包含有关使用 Direct3D 12 视频 API 的一般指南。

关于 Direct3D 12 视频

Direct3D 12 视频接口为应用实现视频解码和处理提供了一种新方法。 Direct3D 12 接口不同于以前的 Direct3D 11 接口,因为它的设计旨在与 Direct3D 12 的原则和样式保持一致,其中包括:

  • 为开发人员提供更多控制权
  • 对硬件可访问内存的分配
  • 用于生成和提交命令的 CPU 线程
    • 独立生成和提交
    • 非阻止
  • 计划硬件工作
  • 涵盖现有功能,包括大多数 Direct3D 11 视频功能,但同时保持简单性和易用性。
  • 主要 Direct3D 12 应用程序的功耗和性能等于或优于 Direct3D 11
  • 与其他 Direct3D 12 API 保持一致性
  • 与现有图形 API 具有互操作性

视频解码

以下部分将介绍实现 Direct3D 12 视频解码所涉及的一些任务。

查询解码功能

调用 ID3D12VideoDevice::CheckFeatureSupport 以检查 Direct3D 12 视频解码操作的支持详细信息。 从 D3D12_FEATURE_VIDEO 枚举传递一个值,以指定要为其请求支持信息的功能。

创建视频解码器

调用 ID3D12VideoDevice::CreateVideoDecoder 以创建 ID3D12VideoDecoder 接口的实例。 解码器会保存解码会话的状态,包括与引用相关的数据,例如运动向量。 如果分辨率更改或 MaxDecodePictureBufferCount 更改,则将重新创建解码器对象。 解码宽度和高度指定任何缩放之前的本机流分辨率。 最大解码图片缓冲区 (DPB) 计数指定最大 DPB 计数,无需重新创建视频解码器即可使用。

解码器可用于记录来自多个命令列表的命令,但一次只能与一个命令列表相关联。 应用程序负责同步对解码器的访问。

创建视频解码器堆

调用 ID3D12VideoDevice::CreateVideoDecoderHeap 以创建 ID3D12VideoDecoderHeap 接口的实例。 此对象包含依赖于解析的驱动程序资源和状态。

对帧进行解码

视频处理操作的所有输入和输出参数都会组织为输入参数结构 D3D12_VIDEO_DECODE_INPUT_STREAM_ARGUMENTS 和输出参数结构 D3D12_VIDEO_DECODE_OUTPUT_STREAM_ARGUMENTS。 应用程序管理引用帧,因此,需要为每个解码操作设置引用帧。 正确记录命令列表后,请在视频命令队列上调用 ID3D12CommandQueue::ExecuteCommandLists 将帧解码提交到 GPU。

启用解码器输出转换

如果解码器支持转换,则通过正确填充 D3D12_VIDEO_DECODE_CONVERSION_ARGUMENTS 结构来启用所需的转换。 所需输出与解码器的本机输出的格式和分辨率通过转换参数中指定的颜色空间和分辨率的差异进行通信。

查询解码状态

使用 ID3D12VideoDecodeCommandList::BeginQueryID3D12VideoDecodeCommandList::EndQuery 方法查询解码操作的状态。

D3D12_QUERY_DATA_VIDEO_DECODE_STATISTICS 结构用于描述视频解码统计信息。 若要获取此结构调用的实例 ID3D12VideoDecodeCommandList::EndQuery,请传入 D3D12_QUERY_TYPE_VIDEO_DECODE_STATISTIC 的堆查询类型值。 请注意,此查询不使用 ID3D12VideoDecodeCommandList::BeginQuery

视频处理

Direct3D 12 视频 API 采用简化的视频处理方法,消除了未广泛使用的 Direct3D 11 功能,并移除了对跨设备强制功能的功能检查。 已消除视频处理的枚举过程。 请改为调用 ID3D12VideoDevice::CheckFeatureSupport,使应用能够识别视频处理器的功能。 所需的视频、隔行、立体声格式和速率会作为输入提供给 CheckFeatureSupport

已移除的功能

Direct3D 11 中的以下功能在 Direct3D 12 视频处理中不受支持:

创建视频处理器

调用 ID3D12VideoDevice::CreateVideoProcessor,以创建 ID3D12VideoProcessor 的实例。 视频处理器保持视频处理会话的状态,包括所需的中间内存、缓存的处理数据或其他临时工作空间。 视频处理器创建参数指定 ID3D12VideoProcessCommandList1::ProcessFrames1 时间执行的或可用的操作。 用于执行视频进程操作(例如中间过程)的驱动程序分配会在视频处理器创建时分配。 使用 D3D12_FEATURE_VIDEO_PROCESSOR_SIZE 提前确定视频处理器的分配大小。

视频处理器可能仅可用于记录来自多个命令列表的命令,但一次只能与一个命令列表相关联。 应用程序负责同步访问视频处理器。 应用程序还必须按照在 GPU 上执行的顺序来记录针对视频处理器的视频处理命令。

视频处理操作的所有输入和输出参数都组织成一个输入参数结构 D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS 和一个输出参数结构 D3D12_VIDEO_PROCESS_OUTPUT_STREAM_ARGUMENTS。 应用程序必须调用 ID3D12VideoProcessCommandList::ProcessFrames 来记录它要执行的视频处理操作。

记录命令列表后,请在视频命令队列上调用 ID3D12CommandQueue::ExecuteCommandLists,将帧处理提交到 GPU。

Direct3D 12 视频定义了将硬件设备的功能分组的层级,以便应用程序可以通过更少的代码路径来适应各种硬件。 层是使用 D3D12_VIDEO_DECODE_TIER 枚举指定的。

在所有层中,以下各项都可用:

  • 无需在分辨率更改时重新制作解码器。 只有解码器堆需要在分辨率更改时重新创建。
  • 所有引用帧将由应用管理。 这样,系统就可以节省内存,因为我们不需要在某些层中分配解码器创建时间的最大 DPB 数,并且在分辨率变化的情况下给应用程序提供了灵活性。

请注意,层是超集。 应用可能会决定执行第 1 层,而不使用更高级别的功能,该操作是允许的,但可能无法提供最佳性能。 有关与不同层级别关联的功能的详细信息,请参阅 D3D12_VIDEO_DECODE_TIER

参考帧

使用 Direct3D 12 视频时,将显式传递参考帧。 这允许在解码帧时清楚地使用纹理或纹理数组的数组。 当将应用用作参考时,不需要传递完全相同的资源句柄;例如,它可能决定将一个资源复制到另一个资源,然后传递副本而不是原始资源。 驱动程序仍使用 DXVA RefFrameListCurrPic 索引来存储每个解码帧的相关数据。

DirectX 12 围栏

在 DirectX 12 中,应用负责同步对缓冲区的访问。 对于解码情况,需要向输入缓冲区和输出缓冲区添加围栏。 每个围栏都有一个与之关联的值,用于同步 CPU 和硬件引擎。 有关详细信息,请参阅在 Direct3D 12 中使用资源屏障同步资源状态

典型的实现为每个输入缓冲区都有一个围栏。 对于输入缓冲区,在完成整个解码过程之前,缓冲区可能可用。 系统将忽略此情况,并假定在解码完成后输入缓冲区可用。 实现通常还会为每个输出缓冲区设置围栏。 例如,在将输出发送到合成器的情况下,在最终完成该帧的呈现时,需要一个发出信号的围栏,指示输出再次可供解码器使用。

[Direct3D 12 视频 API](direct3d-12-video-apis.md)
[媒体基础编程指南](media-foundation-programming-guide.md)