MFT 和 DMO 的比较

媒体基础转换(MFT)是 DirectX 媒体对象(DMO)首次引入的转换模型的演变。 本主题总结了 MFT 与 DMO 的不同主要方式。 如果已熟悉 DMO 接口,或者想要将现有 DMO 转换为 MFT,请阅读本主题。

本主题包含以下部分:

流数

DMO 具有固定数量的流,而 MFT 可以支持动态数量的流。 客户端可以添加输入流,MFT 可以在处理过程中添加新的输出流。 但是,不支持动态流不需要 MFT。 MFT 可以具有固定数量的流,就像 DMO 一样。

以下方法用于支持 MFT 上的动态流:

此外,IMFTransform::P rocessOutput 方法定义添加或删除输出流的行为。

由于 DMO 具有固定流,因此使用从零开始的索引值标识 DMO 上的流。 另一方面,MFT 使用不一定对应于索引值的流标识符。 这是因为 MFT 上的流数可能会更改。 例如,可能会删除流 0,将流 1 保留为第一个流。 但是,具有固定数量的流的 MFT 应遵守与 DMO 相同的约定,并使用流标识符的索引值。

格式协商

MFT 使用 IMFMediaType 接口来描述媒体类型。 否则,与 MFT 进行格式协商的工作方式与 DMO 具有相同的基本原则。 下表列出了 DMO 的格式协商方法和 MFT 的相应方法。

DMO 方法 MFT 方法
IMediaObject::GetInputCurrentType IMFTransform::GetInputCurrentType
IMediaObject::GetInputMaxLatency IMFTransform::GetInputStreamInfo
IMediaObject::GetInputSizeInfo IMFTransform::GetInputStreamInfo
IMediaObject::GetInputType IMFTransform::GetInputAvailableType
IMediaObject::GetOutputCurrentType IMFTransform::GetOutputCurrentType
IMediaObject::GetOutputSizeInfo IMFTransform::GetOutputStreamInfo
IMediaObject::GetOutputType IMFTransform::GetOutputAvailableType

 

与 DMO 一样,MFT 通过调用 ProcessInputProcessOutput 方法来处理数据。 下面是流式处理数据时 DMO 和 MFT 进程之间的主要差异。

分配资源

MFT 没有 IMediaObject::AllocateStreamingResourcesIMediaObject::FreeStreamingResources 与 DMO 一起使用的方法。 若要高效处理资源的分配和解除分配,MFT 可以响应 IMFTransform::P rocessMessage 方法中的以下消息:

此外,客户端还可以通过使用以下消息调用 ProcessMessage 来发出流的开始和结束信号:

这两条消息没有确切的 DMO 等效项。

处理数据

MFT 使用媒体示例来保存输入和输出数据。 媒体示例公开 IMFSample 接口,并包含以下数据:

  • 时间戳和持续时间。
  • 包含每个样本信息的属性。 有关属性列表,请参阅 示例属性
  • 零个或多个媒体缓冲区。 每个媒体缓冲区都公开 IMFMediaBuffer 接口。

IMFMediaBuffer 接口类似于 DMO IMediaBuffer 接口。 若要访问基础内存缓冲区,请调用 IMFMediaBuffer::Lock。 此方法大致相当于适用于 DMO 的 IMediaBuffer::GetBufferAndLength

对于未压缩的视频数据,媒体缓冲区还可能支持 IMF2DBuffer 接口。 处理未压缩的视频(输入或输出)的 MFT 应准备好在缓冲区公开视频时使用 IMF2DBuffer 接口。 有关详细信息,请参阅 未压缩的视频缓冲区

媒体基础提供了 IMFMediaBuffer的一些标准实现,因此通常不需要编写自己的实现。 若要从 Media Foundation 缓冲区创建 DMO 缓冲区,请调用 MFCreateLegacyMediaBufferOnMFMediaBuffer

冲洗

MFT 没有 Flush 方法。 若要刷新 MFT,请使用 MFT_MESSAGE_COMMAND_FLUSH 消息调用 IMFTransform::P rocessMessage

流中断性

MFT 没有 非连续 方法。 若要在流中发出不连续信号,请对输入示例设置 MFSampleExtension_Discontinuity 属性。

其他差异

下面是 MFT 和 DMO 之间的一些附加细微差异。

标志

下表列出了各种 DMO 标志及其 MFT 等效项。 每当 DMO 标志直接映射到 MFT 标志时,这两个标志具有相同的数值。 但是,某些 DMO 标志没有确切的 MFT 等效项,反之亦然。

ProcessInput 标志

DMO:_DMO_INPUT_DATA_BUFFER_FLAGS 枚举。

MFT:无等效枚举。

DMO 标志 MFT 标志
DMO_INPUT_DATA_BUFFERF_SYNCPOINT 无等效标志。 而是在示例中设置 MFSampleExtension_CleanPoint 属性。
DMO_INPUT_DATA_BUFFERF_TIME 无等效标志。 相反,请对示例调用 IMFSample::SetSampleTime
DMO_INPUT_DATA_BUFFERF_TIMELENGTH 无等效标志。 相反,请对示例调用 IMFSample::SetSampleDuration

 

ProcessOutput 标志

DMO:_DMO_PROCESS_OUTPUT_FLAGS 枚举。

MFT:_MFT_PROCESS_OUTPUT_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER MFT_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER

 

DMO:_DMO_OUTPUT_DATA_BUFFER_FLAGS 枚举。

MFT:_MFT_OUTPUT_DATA_BUFFER_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT 无等效标志。 而是检查示例上的 MFSampleExtension_CleanPoint 属性。
DMO_OUTPUT_DATA_BUFFERF_TIME 无等效标志。 相反,请对示例调用 IMFSample::GetSampleTime
DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH 无等效标志。 相反,请对示例调用 IMFSample::GetSampleDuration
DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE MFT_OUTPUT_DATA_BUFFER_INCOMPLETE
无等效标志。 MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
无等效标志。 MFT_OUTPUT_DATA_BUFFER_STREAM_END
无等效标志。 MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE

 

GetInputStatus 标志

DMO:_DMO_INPUT_STATUS_FLAGS 枚举。

MFT:_MFT_INPUT_STATUS_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_INPUT_STATUSF_ACCEPT_DATA MFT_INPUT_STATUS_ACCEPT_DATA

 

GetOutputStatus 标志

DMO:无等效枚举。

MFT:_MFT_OUTPUT_STATUS_FLAGS 枚举。

DMO 标志 MFT 标志
无等效标志。 MFT_OUTPUT_STATUS_SAMPLE_READY

 

GetInputStreamInfo 标志

DMO:_DMO_INPUT_STREAM_INFO_FLAGS 枚举。

MFT:_MFT_INPUT_STREAM_INFO_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_INPUT_STREAMF_WHOLE_SAMPLES MFT_INPUT_STREAM_WHOLE_SAMPLES
DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE
DMO_INPUT_STREAMF_HOLDS_BUFFERS MFT_INPUT_STREAM_HOLDS_BUFFERS
无等效标志。 MFT_INPUT_STREAM_DOES_NOT_ADDREF
无等效标志。 MFT_INPUT_STREAM_REMOVABLE
无等效标志。 MFT_INPUT_STREAM_OPTIONAL

 

GetOutputStreamInfo 标志

DMO:_DMO_OUTPUT_STREAM_INFO_FLAGS 枚举。

MFT:_MFT_OUTPUT_STREAM_INFO_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_OUTPUT_STREAMF_WHOLE_SAMPLES MFT_OUTPUT_STREAM_WHOLE_SAMPLES
DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
DMO_OUTPUT_STREAMF_DISCARDABLE MFT_OUTPUT_STREAM_DISCARDABLE
DMO_OUTPUT_STREAMF_OPTIONAL MFT_OUTPUT_STREAM_OPTIONAL
无等效标志。 MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
无等效标志。 MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
无等效标志。 MFT_OUTPUT_STREAM_LAZY_READ
无等效标志。 MFT_OUTPUT_STREAM_REMOVABLE

 

SetInputType/SetOutputType 标志

DMO:_DMO_SET_TYPE_FLAGS 枚举。

MFT:_MFT_SET_TYPE_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_SET_TYPEF_TEST_ONLY MFT_SET_TYPE_TEST_ONLY
DMO_SET_TYPEF_CLEAR 无等效标志。 相反,将媒体类型设置为 NULL 清除媒体类型。

 

错误代码

下表显示了如何将 DMO 错误代码映射到 MFT 错误代码。 混合 MFT/DMO 对象应从 IMediaObject 方法返回 DMO 错误代码,以及来自 IMFTransform 方法的 MFT 错误代码。 DMO 错误代码在头文件 MediaErr.h 中定义。 MFT 错误代码在头文件 mferror.h 中定义。

DMO 错误代码 MFT 错误代码
DMO_E_INVALIDTYPE MF_E_INVALIDTYPE
DMO_E_INVALIDSTREAMINDEX MF_E_INVALIDSTREAMNUMBER
DMO_E_NOTACCEPTING MF_E_NOTACCEPTING
DMO_E_NO_MORE_ITEMS MF_E_NO_MORE_TYPES
DMO_E_TYPE_NOT_ACCEPTED MF_E_INVALIDMEDIATYPE
DMO_E_TYPE_NOT_SET MF_E_TRANSFORM_TYPE_NOT_SET

 

创建混合 DMO/MFT 对象

IMFTransform 接口基于 IMediaObject,这是 DirectX 媒体对象(DMO)的主要接口。 可以创建公开这两个接口的对象。 但是,这可能会导致命名冲突,因为接口具有共享相同名称的一些方法。 可以通过以下两种方式之一解决此问题:

解决方案 1:在包含 MFT 函数的任何.cpp文件的顶部包含以下行:

#define MFT_UNIQUE_METHOD_NAMES

这会更改 IMFTransform 接口的声明,以便大多数方法名称的前缀为“MFT”。 因此,IMFTransform::P rocessInput 变为 IMFTransform::MFTProcessInput,而 IMediaObject::P rocessInput 保留其原始名称。 如果将现有 DMO 转换为混合 DMO/MFT,此方法最有用。 无需更改 DMO 方法,即可添加新的 MFT 方法。

解决方案 2:使用C++语法消除从多个接口继承的名称的歧义。 例如,按如下所示声明 ProcessInput 的 MFT 版本:

CMyHybridObject::IMFTransform::ProcessInput(...)

声明 ProcessInput 的 DMO 版本,如下所示:

CMyHybridObject::IMediaObject::ProcessInput(...)

如果对对象内的方法进行内部调用,则可以使用此语法,但这样做将替代方法的虚拟状态。 从对象内部发出调用的更好方法是:

hr = ((IMediaObject*)this)->ProcessInput(...)

这样,如果从 CMyHybridObject 派生另一个类 并重写 CMyHybridObject::IMediaObject::P rocessInput 方法,则会调用正确的虚拟方法。 DMO 接口记录在 DirectShow SDK 文档中。

媒体基础转换