MFT 和 DMO 的比较

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

本主题包含以下各节:

流数

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

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

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

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

格式协商

MRT 使用 IMFMediaType 接口来描述媒体类型。 否则,与 MMT 的格式协商遵循与 MDO 相同的基本原则。 下表列出了 MDO 的格式协商方法和 MMT 的相应方法。

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

 

流式处理

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

分配资源

MMT 没有用于 DMO 的 IMediaObject::AllocateStreamingResourcesIMediaObject::FreeStreamingResources 方法。 为了有效地处理资源的分配和解除分配,MFT 可以在 IMFTransform::P rocessMessage 方法中响应以下消息:

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

这两条消息没有完全等效的 DMO。

处理数据

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

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

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

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

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

冲洗

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

流不连续

MRT 没有 非连续方法 。 若要指示流中的不连续性,请在输入样本上设置 MFSampleExtension_Discontinuity 属性。

其他差异

下面是 MMT 和 MTO 之间的一些其他细微差异。

Flags

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

ProcessInput 标志

DMO: _DMO_INPUT_DATA_BUFFER_FLAGS 枚举。

MCT:无等效枚举。

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 枚举。

MRT: _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 枚举。

MRT: _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 枚举。

MCT: _MFT_INPUT_STATUS_FLAGS 枚举。

DMO 标志 MFT 标志
DMO_INPUT_STATUSF_ACCEPT_DATA MFT_INPUT_STATUS_ACCEPT_DATA

 

GetOutputStatus 标志

DMO:无等效枚举。

MCT: _MFT_OUTPUT_STATUS_FLAGS 枚举。

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

 

GetInputStreamInfo 标志

DMO: _DMO_INPUT_STREAM_INFO_FLAGS 枚举。

MCT: _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 枚举。

MCT: _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 标志

DSO: _DMO_SET_TYPE_FLAGS 枚举。

MMFT: _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,IMediaObject 是 DirectX 媒体对象 (DMC) 的主要接口。 可以创建公开这两个接口的对象。 但是,这可能会导致命名冲突,因为接口的某些方法具有相同的名称。 可以通过以下两种方式之一来解决此问题:

解决方案 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 方法,则会调用正确的虚拟方法。 DirectShow SDK 文档中记录了 DMO 接口。

Media Foundation 转换