基本 MFT 處理模型

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

如果您是下列專案,請閱讀本主題:

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

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

基本處理模型

建立 MFT

有數種方式可以建立 MFT:

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

某些 MFT 可能會提供其他選項,例如特製化的建立函式。

取得資料流程識別碼

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

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

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

設定媒體類型

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

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

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

  1. (Optional.) 針對每個輸入資料流程,呼叫 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. (Optional.) 針對每個輸出資料流程,呼叫 IMFTransform::GetOutputAvailableType 以取得該資料流程的慣用類型清單。
    • 如果此方法傳回MF_E_TRANSFORM_TYPE_NOT_SET,您必須先設定輸入類型;返回步驟 1。
    • 如果有任何資料流程傳回E_NOTIMPL,MFT 沒有慣用的輸出類型清單;跳至步驟 4。
  4. 針對每個輸出資料流程,呼叫 IMFTransform::SetOutputType 以設定輸出類型。 您可以使用步驟 3 中的媒體類型,或描述所需輸出格式的類型。
  5. 如果有任何輸入資料流程沒有媒體類型,請返回步驟 1。

取得緩衝區需求

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

處理資料

MFT 是設計成可靠的狀態機器。 它不會對用戶端進行任何回呼。

  1. 使用MFT_MESSAGE_NOTIFY_BEGIN_STREAMING訊息呼叫IMFTransform::P rocessMessage。 此訊息會要求 MFT 在串流期間配置它所需的任何資源。
  2. 在至少一個輸入資料流程上呼叫 IMFTransform::P rocessInput ,以將輸入範例傳遞至 MFT。
  3. (Optional.) 呼叫 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. 使用MFT_MESSAGE_NOTIFY_END_OF_STREAM訊息呼叫ProcessMessage
  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::P rocessMessage

清空 MFT

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

  1. 使用MFT_MESSAGE_COMMAND_DRAIN訊息呼叫ProcessMessage。 此訊息會通知 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 message.) 指定的行為,確切的詳細資料會取決於媒體格式。

如果解碼器未執行任何動作來減輕不連續性,它應該將不連續旗標複製到輸出資料。 完全搭配壓縮資料運作的解構函式和其他 MFT,必須將任何不連續的內容複寫到其輸出資料流程。 否則,下游元件可能無法正確解碼壓縮的資料。 一般而言,除非 MFT 包含明確的程式碼來平滑化不連續,否則傳遞不連續的下游幾乎一律正確。

動態格式變更

在串流期間,格式可能會變更。 例如,外觀比例可以在視訊串流中間變更。

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

串流事件

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

媒體基礎轉換