共用方式為


步驟 5. 轉換影像

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngine和媒體基金會中的音訊/視訊擷取 所取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

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

上游篩選會藉由在轉換篩選器的輸入釘選上呼叫 IMemInputPin::Receive 方法,將媒體範例傳遞至轉換篩選器。 若要處理數據,轉換濾鏡會呼叫 Transform 方法,這是純虛擬函數。 CTransformFilterCTransInPlaceFilter 類別會使用兩個不同的此方法版本:

如果 Transform 方法傳回S_OK,篩選會傳遞下游範例。 若要略過一個 frame,請傳回 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 編碼的私人方法。 此處未描述編碼演算法本身;如需詳細資訊,請參閱 Platform SDK 文件中的「位圖壓縮」主題。

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

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

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

  • 格式變更。 上游篩選可以藉由將媒體類型附加至範例,來變更中間數據流的格式。 在這麼做之前,它會在篩選器的輸入接點呼叫 IPin::QueryAccept。 在 CTransformFilter 類別中,這會導致依序呼叫 CheckInputTypeCheckTransform。 下游篩選也可以使用相同的機制來變更媒體類型。 在您自己的篩選中,有兩件事需要注意:

    • 確保 QueryAccept 不會傳回錯誤接受。
    • 如果您的篩選條件接受格式變更,請藉由呼叫 IMediaSample::GetMediaType,在 Transform 方法內檢查它們。 如果該方法傳回S_OK,您的篩選必須回應格式變更。

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

  • 線程。 在 CTransformFilterCTransInPlaceFilter中,轉換篩選器會在 Receive 方法內同步傳遞輸出樣本。 篩選不會建立任何背景工作線程來處理數據。 一般而言,轉換過濾器沒有理由建立工作線程。

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

撰寫 DirectShow 過濾器