硬件 MFT
注意
本主题适用于 Windows 7 或更高版本。
本主题介绍如何编写媒体基础转换(MFT),该转换充当硬件编码器、解码器或数字信号处理器(DSP)的代理。
重要
如果硬件编解码器使用 AVStream 多媒体类驱动程序,则不需要自定义 MFT。 Media Foundation 为此提供了 AVStream 代理。 本主题中的信息仅适用于硬件编解码器不使用 AVStream 的特殊情况。 有关详细信息,请参阅 AVStream 中的硬件编解码器支持。
本主题包含以下部分:
介绍
任何不基于 AVStream 的硬件编解码器都必须提供自己的 MFT 来充当驱动程序的代理。 硬件编解码器可能包含多个不同的功能块:
- 编码器
- 译码器
- 帧缩放/格式转换
其中每个函数都应由单独的 MFT 管理。 硬件 MFT 绝不应充当多用途“转码器”。相反,将编码函数放入编码器 MFT,并将解码函数放入解码器 MFT 中。 如果硬件提供帧缩放和格式转换,请将这些函数置于单独的视频处理器中,并在 MFT_CATEGORY_VIDEO_PROCESSOR 类别中注册。 如果硬件不支持帧缩放或格式转换,Media Foundation 提供软件视频处理器。
硬件 MFT 具有以下常规要求:
硬件 MFT 属性
硬件 MFT 必须实现以下与属性相关的方法:
- IMFTransform::GetAttributes:返回全局 MFT 属性的属性存储。
- IMFTransform::GetInputStreamAttributes:返回输入流的属性存储。
- IMFTransform::GetOutputStreamAttributes:返回输出流的属性存储。
首次创建 MFT 时,它必须在自己的全局属性存储(即 getAttributes 返回的属性存储)上设置以下属性:
属性 | 描述 |
---|---|
MF_TRANSFORM_ASYNC | 必须设置为 true 。 指示 MFT 执行异步处理。 |
MFT_ENUM_HARDWARE_URL_Attribute | 包含硬件设备的符号链接。 拓扑加载程序使用此属性的存在来测试 MFT 是否表示硬件设备。 |
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE | 必须设置为 true 。 指示 MFT 支持动态格式更改。 |
硬件握手序列
如果两个 MFT 表示相同的物理设备,则可以在硬件内交换数据,例如,通过硬件总线交换数据。 无需将数据复制到系统内存中,然后返回到设备。
在下图中,标记为“A”和“B”的 MFT 表示同一硬件中的功能块。 例如,在转码方案中,“A”可能表示硬件解码器,“B”可能表示硬件编码器。 “A”和“B”之间的数据流发生在硬件中。 标记为“C”的 MFT 是软件 MFT。 从“B”到“C”的数据流使用系统内存。
若要建立硬件连接,这两个硬件 MFT 必须使用专用信道。 此连接是在格式协商期间建立的,在设置媒体类型之前,在首次 调用 processInput之前建立。 连接过程如下所示:
拓扑加载程序检查两个 MFT 是否存在 MFT_ENUM_HARDWARE_URL_Attribute 属性。 请注意,它不检查此属性的值。
如果这两个 MFT 上都存在 MFT_ENUM_HARDWARE_URL_Attribute,拓扑加载程序将执行以下作:
- 拓扑加载程序调用 IMFTransform::GetOutputStreamAttributes 上游 MFT (A)。 此方法返回 IMFAttributes 指针。 让此指针在 pUpstream 表示。
- 拓扑加载程序调用 IMFTransform::GetInputStreamAttributes 下游 MFT (B)。 此调用还返回 IMFAttributes 指针。 pDownstream表示此指针。
- 拓扑加载程序通过调用 IMFAttributes::SetUnknown在 pDownstream 上设置 MFT_CONNECTED_STREAM_ATTRIBUTE 属性。 该属性的值是 pUpstream 指针。
- 拓扑加载程序在 pDownstream 和 pUpstream上将 MFT_CONNECTED_TO_HW_STREAM 属性设置为TRUE。
此时,下游 MFT 具有指向上游 MFT 属性存储的指针,如下图所示。
注意
为了清楚起见,此关系图将流和属性存储为不同的对象,但实现不需要这样做。
下游 MFT 使用 IMFAttributes 指针与上游 MFT 建立专用信道。 由于通道是专用的,因此确切的机制由实现定义。 例如,MFT 可能会查询专用 COM 接口。
在步骤 4 中,下游 MFT 必须验证这两个 MFT 是否共享同一物理设备。 否则,它们必须回退到使用系统内存进行数据传输。 这使 MFT 能够使用软件 MFT 和其他硬件设备正确运行。
如果握手成功,并且两个 MFT 共享专用数据通道,则它们不会在连接点使用标准数据处理模型(下一部分所述)。 具体而言,下游 MFT 不会发送 METransformNeedInput 事件;有关更多详细信息,请参阅本主题中的下一部分。
数据处理
当硬件 MFT 使用系统内存进行数据传输时,该过程的工作原理如下:
- 若要请求更多输入,MFT 将发送 METransformNeedInput 事件。
- METransformNeedInput 事件会导致管道调用 IMFTransform::P rocessInput。
- 当 MFT 具有输出数据时,MFT 会发送 METransformHaveOutput 事件。
- METransformHaveOutput 事件会导致管道调用 IMFTransform::P rocessOutput。
有关详细信息,请参阅 异步 MFT。
但是,如果 MFT 使用硬件通道,则不会在硬件连接点发送这些事件,因为所有数据传输都在硬件内部发生。 因此,管道不会 在连接点调用 processInput 或 ProcessOutput。
例如,请考虑本主题中的第一个关系图。 鉴于此配置,数据处理将如下所示:
- “A”发送 METransformNeedInput 以请求数据。
- 管道在“A”上 ProcessInput 调用。
- “A”和“B”处理硬件中的数据。
- 处理完成后,“B”将发送 METransformHaveOutput 事件。
- 管道在“B”上调用 ProcessOutput。
配对解码器/编码器
如果解码器和编码器位于同一硬件芯片上,则转码时最好将它们一起使用。 也就是说,选择一个应在转码管道中选择另一个。 为了确保选择匹配的硬件编解码器,这两个编解码器 MFT 都应提供自定义媒体类型。 创建自定义媒体类型:
- 根据需要将 MF_MT_MAJOR_TYPE 属性设置为 MFMediaType_Audio 或 MFMediaType_Video。
- 将 MF_MT_SUBTYPE 属性设置为自定义 GUID 值。
其他类型属性是可选的。 解码器从其 IMFTransform::GetOutputAvailableType返回自定义类型,编码器从其 IMFTransform::GetInputAvailableType 方法返回自定义类型。 在这两种情况下,自定义类型必须是列表中的第一个条目(dwTypeIndex = 0)。
若要使用软件编解码器,编解码器还应至少返回一种标准格式,例如 NV12 作为视频。 标准格式应出现在自定义类型之后(dwTypeIndex> 0)。 如果两个编解码器必须始终配对且无法与软件编解码器互作,则 MFT 应仅返回自定义格式,并且不返回任何标准格式。
注意
如果解码器不返回任何标准格式,则它不能用于播放 增强视频呈现器。 在这种情况下,应将其注册为仅转码解码器。 请参阅 Transcode-Only 解码器。
相关主题