共用方式為


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,因此通常不需要撰寫您自己的實作。 若要從媒體基礎緩衝區建立 DMO 緩衝區,請呼叫 MFCreateLegacyMediaBufferOnMFMediaBuffer

沖洗

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

串流不連續

MFT 沒有 Discontinuity 方法。 若要發出數據流中的不連續訊號,請在輸入範例上設定 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,這項技術最有用。 您可以新增 MFT 方法,而不需變更 DMO 方法。

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

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

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

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

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

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

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

媒體基礎轉換