MFT 和 DMO 的比較

媒體基礎轉換 (MFT) 是 DirectX Media Objects (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 沒有搭配 DMO 使用的 IMediaObject::AllocateStreamingResourcesIMediaObject::FreeStreamingResources 方法。 若要有效率地處理資源的配置和解除配置,MFT 可以回應 IMFTransform::P rocessMessage 方法中的下列訊息:

此外,用戶端可以使用下列訊息呼叫 ProcessMessage ,以發出資料流程的開始和結束訊號:

這兩則訊息沒有完全相同的 DMO 對等專案。

處理資料

MFT 會使用媒體範例來保存輸入和輸出資料。 媒體範例會公開 IMFSample 介面,並包含下列資料:

  • 時間戳記和持續時間。
  • 包含每個範例資訊的屬性。 如需屬性清單,請參閱 範例屬性
  • 零或多個媒體緩衝區。 每個媒體緩衝區都會公開 IMFMediaBuffer 介面。

IMFMediaBuffer介面類別似于 DMO IMediaBuffer介面。 若要存取基礎記憶體緩衝區,請呼叫 IMFMediaBuffer::Lock。 這個方法大致相當於 IMediaBuffer::GetBufferAndLength for DMO。

針對未壓縮的視訊資料,媒體緩衝區也可能支援 IMF2DBuffer 介面。 處理未壓縮視訊的 MFT (做為輸入或輸出) ,應該準備好在緩衝區公開 時使用 IMF2DBuffer 介面。 如需詳細資訊,請參閱 未壓縮的視訊緩衝區

媒體基礎提供 一些 IMFMediaBuffer的標準實作,因此通常不需要撰寫您自己的實作。 若要從 Media Foundation 緩衝區建立 DMO 緩衝區,請呼叫 MFCreateLegacyMediaBufferOnMFMediaBuffer

沖洗

MFT 沒有 Flush 方法。 若要排清 MFT,請使用MFT_MESSAGE_COMMAND_FLUSH訊息呼叫IMFTransform::P rocessMessage

串流中斷

MFT 沒有 Discontinuity 方法。 若要發出資料流程中的不連續訊號,請在輸入範例上設定 MFSampleExtension_Discontinuity 屬性。

其他差異

以下是 MFT 與 DMO 之間的一些額外差異。

Flags

下表列出各種 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,這項技術最有用。 您可以新增 MFT 方法,而不需變更 DMO 方法。

解決方案 2:使用 C++ 語法來厘清繼承自多個介面的名稱。 例如,宣告 ProcessInput 的 MFT 版本,如下所示:

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

宣告 ProcessInput 的 DMO 版本,如下所示:

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

如果您對 物件內的方法進行內部呼叫,則可以使用此語法,但這樣做會覆寫方法的虛擬狀態。 從 物件內部進行呼叫的較佳方式如下:

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

如此一來,如果您從 CMyHybridObject 衍生另一個類別,並覆寫 CMyHybridObject::IMediaObject::P rocessInput 方法,則會呼叫正確的虛擬方法。 DMO 介面記載于 DirectShow SDK 檔中。

媒體基礎轉換