共用方式為


步驟 5: 轉換影像

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

這是 撰寫轉換篩選教學課程的步驟 5。

上游篩選會藉由在轉換篩選器的輸入針腳上呼叫 IMemInputPin::Receive 方法,將媒體範例傳遞至轉換篩選。 若要處理資料,轉換篩選準則會呼叫 Pure virtual 的 Transform 方法。 CTransformFilterCTransInPlaceFilter類別會使用兩個不同的此方法版本:

如果 Transform 方法傳回S_OK,篩選會傳遞範例下游。 若要略過框架,請傳回S_FALSE。 如果有串流錯誤,請傳回失敗碼。

下列範例示範 RLE 編碼器如何實作此方法。 根據篩選的功能而定,您自己的實作可能會有很大的差異。

HRESULT CRleFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
    // Get pointers to the underlying buffers.
    BYTE *pBufferIn, *pBufferOut;
    hr = pSource->GetPointer(&pBufferIn);
    if (FAILED(hr))
    {
        return hr;
    }
    hr = pDest->GetPointer(&pBufferOut);
    if (FAILED(hr))
    {
        return hr;
    }
    // Process the data.
    DWORD cbDest = EncodeFrame(pBufferIn, pBufferOut);
    KASSERT((long)cbDest <= pDest->GetSize());

    pDest->SetActualDataLength(cbDest);
    pDest->SetSyncPoint(TRUE);
    return S_OK;
}

此範例假設 EncodeFrame 是實作 RLE 編碼的私人方法。 此處未說明編碼演算法本身;如需詳細資訊,請參閱平臺 SDK 檔中的主題。

首先,此範例會呼叫 IMediaSample::GetPointer 來擷取基礎緩衝區的位址。 它會將這些傳遞給私人 EncoderFrame 方法。 然後它會呼叫 IMediaSample::SetActualDataLength 來指定編碼資料的長度。 下游篩選需要這項資訊,才能正確管理緩衝區。 最後,方法會呼叫 IMediaSample::SetSyncPoint ,將主要畫面格旗標設定為 TRUE。 執行長度編碼不會使用任何差異畫面,因此每個畫面都是主要畫面格。 針對差異畫面,請將值設定為 FALSE

您必須考慮的其他問題包括:

  • 時間戳記。 CTransformFilter類別會先將輸出範例時間戳記,再呼叫Transform方法。 它會從輸入範例複製時間戳記值,而不需修改它們。 如果您的篩選需要變更時間戳記,請在輸出範例上呼叫 IMediaSample::SetTime

  • 格式變更。 上游篩選可以藉由將媒體類型附加至範例,來變更中間資料流程的格式。 這麼做之前,它會在篩選的輸入針腳上呼叫 IPin::QueryAccept 。 在 CTransformFilter 類別中,這會導致呼叫 CheckInputType ,後面接著 CheckTransform。 下游篩選器也可以使用相同的機制來變更媒體類型。 在您自己的篩選中,有兩件事可以watch:

    • 請確定 QueryAccept 不會傳回誤接受。
    • 如果您的篩選準則接受格式變更,請呼叫IMediaSample::GetMediaTypeTransform方法內檢查它們。 如果該方法傳回S_OK,您的篩選必須回應格式變更。

    如需詳細資訊,請參閱 動態格式變更

  • 執行緒。 在 CTransformFilterCTransInPlaceFilter中,轉換篩選會在 Receive 方法內同步傳遞輸出樣本。 篩選不會建立任何背景工作執行緒來處理資料。 一般而言,轉換篩選無法建立背景工作執行緒。

下一 步:步驟 6。新增 COM 的支援

撰寫 DirectShow 篩選