步驟 5: 轉換影像
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
這是 撰寫轉換篩選教學課程的步驟 5。
上游篩選會藉由在轉換篩選器的輸入針腳上呼叫 IMemInputPin::Receive 方法,將媒體範例傳遞至轉換篩選。 若要處理資料,轉換篩選準則會呼叫 Pure virtual 的 Transform 方法。 CTransformFilter和CTransInPlaceFilter類別會使用兩個不同的此方法版本:
- CTransformFilter::Transform 會取得輸入範例的指標,以及輸出範例的指標。 在篩選準則呼叫 方法之前,它會將範例屬性從輸入範例複製到輸出範例,包括時間戳記。
- CTransInPlaceFilter::Transform 會取得輸入範例的指標。 篩選準則會就地修改資料。
如果 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::GetMediaType在Transform方法內檢查它們。 如果該方法傳回S_OK,您的篩選必須回應格式變更。
如需詳細資訊,請參閱 動態格式變更。
執行緒。 在 CTransformFilter 和 CTransInPlaceFilter中,轉換篩選會在 Receive 方法內同步傳遞輸出樣本。 篩選不會建立任何背景工作執行緒來處理資料。 一般而言,轉換篩選無法建立背景工作執行緒。
相關主題