步驟 5. 轉換影像
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine和媒體基金會中的音訊/視訊擷取 所取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
這是教學課程的步驟 5,撰寫轉換篩選。
上游篩選會藉由在轉換篩選器的輸入釘選上呼叫 IMemInputPin::Receive 方法,將媒體範例傳遞至轉換篩選器。 若要處理數據,轉換濾鏡會呼叫 Transform 方法,這是純虛擬函數。 CTransformFilter 和 CTransInPlaceFilter 類別會使用兩個不同的此方法版本:
- CTransformFilter::Transform 會取得輸入範例的指標和輸出範例的指標。 在篩選條件呼叫 方法之前,它會將範例屬性從輸入範例複製到輸出範例,包括時間戳。
- CTransInPlaceFilter::Transform 會取得輸入範例的指標。 過濾器會就地修改數據。
如果 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 類別中,這會導致依序呼叫 CheckInputType 和 CheckTransform。 下游篩選也可以使用相同的機制來變更媒體類型。 在您自己的篩選中,有兩件事需要注意:
- 確保 QueryAccept 不會傳回錯誤接受。
- 如果您的篩選條件接受格式變更,請藉由呼叫 IMediaSample::GetMediaType,在 Transform 方法內檢查它們。 如果該方法傳回S_OK,您的篩選必須回應格式變更。
如需詳細資訊,請參閱 動態格式變更。
線程。 在 CTransformFilter 和 CTransInPlaceFilter中,轉換篩選器會在 Receive 方法內同步傳遞輸出樣本。 篩選不會建立任何背景工作線程來處理數據。 一般而言,轉換過濾器沒有理由建立工作線程。
下一步:步驟 6。新增 COM的支援。
相關主題