MFT 和 DMO 的比較
媒體基礎轉換 (MFT) 是 DirectX Media Objects (DMO) 引進的轉換模型演進。 本主題摘要說明 MFT 與 DMO 不同的主要方式。 如果您已經熟悉 DMO 介面,或想要將現有的 DMO 轉換成 MFT,請閱讀本主題。
本主題包含下列幾節:
資料流程數目
DMO 具有固定數目的資料流程,而 MFT 可以支援動態數目的資料流程。 用戶端可以新增輸入資料流程,而 MFT 可以在處理期間新增輸出資料流程。 不過,不支援動態資料流不需要 MFT。 MFT 可以有固定數目的資料流程,就像 DMO 一樣。
下列方法可用來支援 MFT 上的動態資料流:
- IMFTransform::AddInputStreams
- IMFTransform::D eleteInputStream
- IMFTransform::GetStreamIDs
- IMFTransform::GetStreamLimits
此外, IMFTransform::P rocessOutput 方法會定義新增或移除輸出資料流程的行為。
由於 DMO 具有固定資料流程,因此 DMO 上的資料流程會使用以零起始的索引值來識別。 另一方面,MFT 會使用不一定對應至索引值的資料流程識別碼。 這是因為 MFT 上的資料流程數目可能會變更。 例如,可能會移除資料流程 0,將資料流程 1 保留為第一個資料流程。 不過,具有固定資料流程數目的 MFT 應該觀察與 DMO 相同的慣例,並使用資料流程識別碼的索引值。
格式交涉
MFT 使用 IMFMediaType 介面來描述媒體類型。 否則,與 MFT 的格式交涉適用于與 DMO 相同的基本準則。 下表列出 DMO 的格式交涉方法,以及 MFT 的對應方法。
串流
如同 DMO,MFT 會透過呼叫 ProcessInput 和 ProcessOutput 方法來處理資料。 以下是串流資料時 DMO 和 MFT 進程之間的主要差異。
配置資源
MFT 沒有搭配 DMO 使用的 IMediaObject::AllocateStreamingResources 和 IMediaObject::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 之間的一些額外差異。
下列 DMO 方法沒有 MFT 對等專案:
不支援匯總時不需要 MFT。
MFT 支援稱為 清空的作業。 清空的目的是要處理保留在 MF 中的任何資料,而不需在資料流程結尾提供任何輸入資料給 MFT (,例如資料流程結尾) 。 若要清空 MFT,請使用MFT_MESSAGE_COMMAND_DRAIN訊息呼叫IMFTransform::P rocessMessage。 如需詳細資訊,請參閱 基本 MFT 處理模型。
MFT 可以有屬性,包括每個資料流程屬性。 使用下列方法從 MFT 取得屬性:
MFT 可以處理事件。 若要將事件傳送至 MFT,請呼叫 IMFTransform::P rocessEvent。 MFT 可以透過 ProcessOutput 方法將事件傳送給用戶端。 如需詳細資訊,請參閱 基本 MFT 處理模型。
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 檔中。
相關主題