共用方式為


基本 MFT 處理模型

本主題描述用戶端如何使用媒體基礎轉換 (MFT) 來處理數據。 用戶端 是任何直接在 MFT 上呼叫方法的對象。 這可能是應用程式或媒體基礎管線。

如果您屬於以下角色,請閱讀這個主題:

  • 撰寫直接呼叫一或多個 MFT 的應用程式。
  • 撰寫自定義 MFT 並想要瞭解 MFT 的預期行為。

本主題描述 同步 處理模型。 在此模型中,所有數據處理方法都會封鎖,直到完成為止。 MFT 也可以支援 異步 模型,如異步 MFT 主題所述。

基本處理模型

建立 MFT

有數種方式可以建立 MFT:

  • 呼叫 MFTEnum 函式。
  • 呼叫 MFTEnumEx 函式。
  • 如果您已經知道 MFT 的 CLSID,只要呼叫 CoCreateInstance即可。

某些 MFT 可能會提供其他選項,例如專門的創建函式。

取得數據流標識碼

MFT 有一或多個 資料流。 輸入數據流會接收輸入數據,而輸出數據流會產生輸出數據。 數據流不會表示為不同的物件。 相反地,各種 MFT 方法會採用數據流標識碼作為參數。

某些 MFT 可讓用戶端新增或移除輸入數據流。 在串流期間,MFT 可以新增或移除輸出數據流。 (客戶端無法新增或移除輸出資料流。

  1. (選擇性。)呼叫 IMFTransform::GetStreamLimits,以取得 MFT 可支援的最小和最大數據流數目。 如果最小值和最大值相同,MFT 就會有固定數目的數據流。
  2. 呼叫 IMFTransform::GetStreamCount,以取得初始數據流數目。
  3. 呼叫 IMFTransform::GetStreamIDs 以取得數據流標識符。 如果這個方法傳回E_NOTIMPL,表示 MFT 有固定的數據流數目,而且數據流標識碼是從零開始的連續。
  4. (選擇性。)如果 MFT 沒有固定的數據流數目,請呼叫 IMFTransform::AddInputStreams 以新增更多輸入數據流,或 IMFTransform::D eleteInputStream 移除輸入數據流。 (您無法新增或移除輸出資料流。

設定媒體類型

在 MFT 可以處理數據之前,客戶端必須為每個 MFT 數據流設定媒體類型。 MFT 可能需要用戶端在設定輸出類型之前設定輸入類型,或可能需要相反的順序(先輸出類型)。 某些 MFT 對順序沒有要求。

MFT 可以提供數據流慣用媒體類型的清單。 此外,MFT 也可以藉由將這項資訊新增至登錄來指出其支援的一般格式。

若要設定媒體類型,請執行下列動作:

  1. (選擇性。)針對每個輸入數據流,呼叫 IMFTransform::GetInputAvailableType,以取得該數據流的慣用類型清單。
    • 如果此方法傳回MF_E_TRANSFORM_TYPE_NOT_SET,您必須先設定輸出類型;跳至步驟 3。
    • 如果方法傳回E_NOTIMPL,MFT 沒有慣用的輸入類型清單;跳至步驟 2。
  2. 針對每個輸入數據流,呼叫 IMFTransform::SetInputType 來設定輸入類型。 您可以使用步驟 1 中的媒體類型,或描述輸入資料的類型。 如果有任何數據流傳回MF_E_TRANSFORM_TYPE_NOT_SET,請跳至步驟 3。
  3. (選擇性。)針對每個輸出數據流,呼叫 IMFTransform::GetOutputAvailableType,以取得該數據流的慣用類型清單。
    • 如果此方法傳回MF_E_TRANSFORM_TYPE_NOT_SET,您必須先設定輸入類型;返回步驟 1。
    • 如果有任何數據流傳回E_NOTIMPL,MFT 就不會有慣用的輸出類型清單;跳至步驟 4。
  4. 針對每個輸出數據流,呼叫 IMFTransform::SetOutputType 來設定輸出類型。 您可以使用步驟 3 中的媒體類型,或描述所需輸出格式的類型。
  5. 如果有任何輸入數據流沒有媒體類型,請返回步驟 1。

獲取緩衝區需求

用戶端設定媒體類型之後,它應該會取得每個數據流的緩衝區需求:

處理數據

MFT 的設計目的是要成為可靠的狀態機器。 它不會撥打任何電話給客戶端。

  1. 呼叫 IMFTransform::ProcessMessageMFT_MESSAGE_NOTIFY_BEGIN_STREAMING 訊息。 此訊息會要求 MFT 在串流期間配置它所需的任何資源。
  2. 在至少一個輸入流上呼叫 IMFTransform::ProcessInput,以將輸入範例傳遞至 MFT。
  3. (選擇性。)呼叫 IMFTransform::GetOutputStatus 查詢 MFT 是否可以產生輸出範例。 如果方法傳回S_OK,請檢查 pdwFlags 參數。 如果 pdwFlags 包含 MFT_OUTPUT_STATUS_SAMPLE_READY 旗標,請移至步驟 4。 如果 pdwFlags 為零,請返回步驟 2。 如果方法傳回E_NOTIMPL,請移至步驟 4。
  4. 呼叫 IMFTransform::P rocessOutput 以取得輸出數據。
    • 如果方法傳回 MF_E_TRANSFORM_NEED_MORE_INPUT,表示 MFT 需要更多輸入數據;返回步驟 2。
    • 如果方法傳回 MF_E_TRANSFORM_STREAM_CHANGE,表示輸出數據流的數目已變更,或輸出格式已變更。 用戶端可能需要查詢新的數據流標識碼或設定新的媒體類型。 如需詳細資訊,請參閱 ProcessOutput的檔。
  5. 如果仍有要處理的輸入數據,請移至步驟 2。 如果 MFT 已取用所有可用的輸入資料,請繼續進行步驟 6。
  6. 呼叫 ProcessMessage,使用 MFT_MESSAGE_NOTIFY_END_OF_STREAM 訊息。
  7. 使用 MFT_MESSAGE_COMMAND_DRAIN 訊息呼叫 ProcessMessage
  8. 呼叫 ProcessOutput 以取得剩餘的輸出。 重複此步驟,直到方法返回 MF_E_TRANSFORM_NEED_MORE_INPUT的值為止。 這個傳回值表示所有輸出都已從 MFT 清空。 (請勿將此視為錯誤狀況。

此處所述的序列會在 MFT 中保留最少的數據。 每次呼叫 ProcessInput之後,用戶端會嘗試取得輸出。 可能需要數個輸入範例來產生一個輸出範例,或單一輸入範例可能會產生數個輸出範例。 用戶端的最佳行為是從 MFT 提取輸出範例,直到 MFT 需要更多輸入為止。

不過,MFT 應該能夠處理用戶端的不同方法呼叫順序。 例如,用戶端可能只是在 ProcessInputProcessOutput之間交替呼叫。 MFT 應該在有一些輸出要產生時,透過從 ProcessInput 傳回 MF_E_NOTACCEPTING,來限制它取得的輸入量。

這裡所述的方法呼叫順序並不是唯一有效的事件序列。 例如,步驟 3 和 4 假設用戶端以輸入類型開頭,然後嘗試輸出類型。 用戶端也可以反轉這個順序,並從輸出類型開始。 在任一情況下,如果 MFT 需要相反的順序,它應該會傳回錯誤碼MF_E_TRANSFORM_TYPE_NOT_SET。

用戶端可以在串流期間隨時呼叫資訊方法,例如 GetInputCurrentTypeGetOutputStreamInfo。 用戶端也可以隨時嘗試變更媒體類型。 如果這不是有效的作業,MFT 應該會傳回錯誤碼。 簡言之,MFT 應該對作業順序的假設保持極少,除了呼叫本身記載的內容之外。

下圖顯示本主題中所述程式的流程圖。

流程圖從取得數據流標識符開始,然後通過設定輸入類型、取得輸入和處理輸出的迴圈

基本模型的延伸模組

選擇性地,MFT 也可以支援基礎串流模型的某些擴展。

  • 延遲讀取數據流。 如果 IMFTransform::GetOutputStreamInfo 方法傳回輸出數據流的 MFT_OUTPUT_STREAM_LAZY_READ 旗標,用戶端就不需要從該輸出數據流收集數據。 MFT 會繼續接受輸入,而且在某些時候,MFT 會捨棄該數據流的輸出數據。 如果所有輸出數據流都有此旗標,MFT 永遠不會無法接受輸入。 範例可能是視覺效果轉換,其中用戶端只有在有備用 CPU 週期來繪製視覺效果時,才會取得輸出。
  • 可拋棄的資料流。 如果 GetOutputStreamInfo 方法傳回輸出數據流的 MFT_OUTPUT_STREAM_DISCARDABLE 旗標,用戶端可以要求 MFT 捨棄輸出,但除非要求,否則 MFT 不會捨棄任何輸出。 當 MFT 達到其最大輸入緩衝區時,客戶端必須收集一些輸出數據,或要求 MFT 捨棄輸出。
  • 可選流媒體。 如果 GetOutputStreamInfo 方法傳回輸出數據流的 MFT_OUTPUT_STREAM_OPTIONAL 旗標,或 IMFTransform::GetInputStreamInfo 方法會傳回輸入數據流的 MFT_INPUT_STREAM_OPTIONAL 旗標,該數據流是選擇性的。 用戶端不需要在數據流上設定媒體類型。 如果客戶端未設定類型,則會取消選取流。 已取消選取的輸出數據流不會產生範例,而且用戶端在呼叫 processOutput 時,不會提供數據流的緩衝區。 未選取的輸入資料流不接受輸入資料。 MFT 可以將其所有輸入和輸出數據流標示為選擇性。 不過,預期至少必須選取一個輸入和一個輸出,MFT 才能運作。
  • 異步處理。 異步處理模型是在 Windows 7 中引進的。 在主題 異步 MFT中描述。

IMF2DBuffer

如果 MFT 處理未壓縮的視訊數據,它應該使用 IMF2DBuffer 介面來操控範例緩衝區。 若要取得此介面,請在任何輸入或輸出緩衝區上查詢 IMFMediaBuffer 介面。 當此介面可用時,不使用可能會導致額外的緩衝區複本。 若要適當使用這個介面,在有 IMF2DBuffer 可用的情況下,轉換不應該使用 IMFMediaBuffer 介面來鎖定緩衝區。

如需處理視訊資料的詳細資訊,請參閱 未壓縮的視訊緩衝區

排清 MFT

刷新 一個 MFT 會導致該 MFT 捨棄其所有輸入數據。 這可能會導致輸出數據流中斷。 當用戶端不在意遺失數據時,用戶端通常會先排清 MFT,再尋求輸入數據流中的新點或切換到新的輸入數據流。

若要清空 MFT,請傳送 MFT_MESSAGE_COMMAND_FLUSH 訊息呼叫 IMFTransform::ProcessMessage

清空 MFT

清空 MFT 會導致 MFT 從任何已傳送的輸入數據產生盡可能多的輸出。 如果 MFT 無法從可用的輸入產生完整的輸出範例,則會卸除輸入數據。 客戶通常會在到達來源數據流結尾時清空 MFT,或在來源數據流中的格式變更前立即清空。 若要清空 MFT,請執行下列動作:

  1. 呼叫 ProcessMessage,並使用 MFT_MESSAGE_COMMAND_DRAIN 訊息。 此訊息會通知 MFT,它應該從已傳送的輸入資料中輸出盡可能多的資料。
  2. 呼叫 ProcessOutput 以取得輸出數據,直到方法傳回 MF_E_TRANSFORM_NEED_MORE_INPUT為止。

當 MFT 正在清空時,它將不會再接受任何輸入。

範例屬性

輸入範例可能有必須複製到對應輸出範例的屬性。

針對具有一個輸入和輸出的 MFT,您可以使用下列一般規則:

  • 如果每個輸入範例只產生一個輸出範例,您可以讓客戶端複製屬性。 讓 MFPKEY_EXATTRIBUTE_SUPPORTED 屬性保持未設定。
  • 如果輸入樣本與輸出樣本之間沒有一對一的對應,MFT 必須判斷輸出範例的正確屬性。 將 MFPKEY_EXATTRIBUTE_SUPPORTED 屬性設定為 VARIANT_TRUE

不連續性

不連續是音訊或視訊串流中的中斷。 中斷可能是因為網路連線上的封包中斷、檔案數據損毀、從一個來源數據流切換到另一個來源數據流,或各種其他原因所造成。 不連續性會藉由在不連續性之後的第一個範例上設定 MFSampleExtension_Discontinuity 屬性來表示。 不可能在樣本中間發出不連續的訊號。 因此,任何不連續的數據都應該在不同的範例中傳送。

某些轉換,特別是處理未壓縮數據,例如音訊和視訊效果的轉換,在處理輸入數據時應該忽略不連續。 這些 MFT 通常設計來處理連續數據,而且應該將接收的任何數據視為連續,即使在中斷之後也一樣。

如果 MFT 忽略輸入資料的不連續性,如果輸出範例與輸入範例具有相同時間戳,它仍應該在輸出範例上設定不連續旗標。 不過,如果輸出範例有不同的時間戳,MFT 不應該傳播不連續。 (例如,在某些音訊重新取樣器中,情況就是這樣。數據流中錯誤位置的不連續性比不連續更差。

大部分譯碼器都無法忽略不連續,因為不連續會影響下一個範例的解譯。 任何使用框架間壓縮的編碼技術,例如 MPEG-2,都屬於此類別。 某些編碼配置只會使用框架內部壓縮,例如 DV 和 MJPEG。 這些譯碼器可以安全地忽略不連續。

回應不連續的轉換通常會在不連續之前輸出盡可能多的數據,並捨棄其餘的數據。 應處理具有不連續旗標的輸入範例,就像是數據流中的第一個範例一樣。 (此行為符合為 MFT_MESSAGE_COMMAND_DRAIN 訊息所指定的內容。不過,具體細節將取決於媒體格式。)

如果譯碼器不執行任何動作來減輕不連續性,它應該將不連續旗標複製到輸出數據。 完全處理壓縮數據的解多工器和其他 MFT 必須將任何不連續性複製到其輸出數據流。 否則,下游元件可能無法正確譯碼壓縮的數據。 一般而言,傳遞不連續性到下游通常是正確的,除非 MFT 包含明確的程式代碼來緩和不連續性。

動態格式變更

格式可以在串流期間變更。 例如,畫面比例可能會在視訊串流過程中變更。

如需 MFT 如何處理數據流變更的詳細資訊,請參閱 處理數據流變更

串流事件

若要將事件傳送至 MFT,請呼叫 IMFTransform::P rocessEvent。 如果方法傳回 MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT,MFT 會在後續再度呼叫 ProcessOutput時,將事件傳回給呼叫者。 如果方法傳回任何其他 HRESULT 值,MFT 將不會將事件傳回至 ProcessOutput中的用戶端。 在此情況下,如果適用,用戶端會負責將事件下游傳播至管線中的下一個元件。 如需詳細資訊,請參閱 IMFTransform::P rocessOutput

媒體基金會革新