媒體基礎轉換(MFT)是第一次引進 DirectX 媒體物件(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 沒有 IMediaObject::AllocateStreamingResources 和 IMediaObject::FreeStreamingResources 搭配 DMO 使用的方法。 若要有效率地處理資源的配置和解除分配,MFT 可以回應IMFTransform::P rocessMessage方法中的下列訊息:
此外,用戶端可以使用下列訊息呼叫 ProcessMessage,以發出數據流的開始和結束訊號:
這兩個訊息沒有完全相同的 DMO 對等專案。
處理數據
MFT 會使用媒體範例來保存輸入和輸出數據。 媒體範例會公開IMFSample介面,並包含下列數據:
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 對等專案:
不支持匯總時不需要 MFT。
MFT 支援稱為 清空的作業。 清空的目的是要處理保留在 MF 中的任何數據,而不需將任何輸入數據提供給 MFT (例如,在數據流結尾)。 若要清空 MFT,請使用 MFT_MESSAGE_COMMAND_DRAIN 訊息呼叫 IMFTransform::P rocessMessage。 如需詳細資訊,請參閱 基本 MFT 處理模型。
MFT 可以有屬性,包括每個數據流屬性。 使用下列方法從 MFT 取得屬性:
MFT 可以處理事件。 若要將事件傳送至 MFT,請呼叫 IMFTransform::P rocessEvent。 MFT 可以透過 ProcessOutput 方法,將事件傳送至用戶端。 如需詳細資訊,請參閱 基本 MFT 處理模型。
標誌
下表列出各種 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 檔中。
相關主題