5. lépés. A kép átalakítása
[A laphoz társított funkció, DirectShowegy régi funkció. Azon MediaPlayer, IMFMediaEngineés Audio/Video Capture a Media Foundationváltotta fel. Ezek a funkciók Windows 10-hez és Windows 11-hez lettek optimalizálva. A Microsoft határozottan javasolja, hogy az új kód, amikor csak lehetséges, a MediaPlayer, a IMFMediaEngine és a Media Foundation keretén belül történő audió/videó rögzítést alkalmazza a DirectShowhelyett. A Microsoft javasolja, hogy az örökölt API-kat használó meglévő kódot át kell írni az új API-k használatára, ha lehetséges.]
Ez az oktatóanyag 5. lépése, Átalakító szűrők írása.
A felsőbb rétegbeli szűrő médiamintákat biztosít az átalakító szűrőhöz az IMemInputPin::Receive metódus meghívásával az átalakítási szűrő bemeneti pin-kódján. Az adatok feldolgozásához az átalakítási szűrő meghívja a Átalakítás metódust, amely tiszta virtuális. A CTransformFilter és CTransInPlaceFilter osztályok a módszer két különböző verzióját használják:
- CTransformFilter::Transform egy mutatót vesz fel a bemeneti mintára, és egy másik mutatót a kimeneti mintára. Mielőtt a szűrő meghívja a metódust, átmásolja a mintatulajdonságokat a bemeneti mintából a kimeneti mintába, beleértve az időbélyegeket is.
- CTransInPlaceFilter::Transform egy mutatót vesz át a bemeneti mintához. A szűrő módosítja az adatokat a helyén.
Ha az Átalakítás metódus S_OK ad vissza, a szűrő a mintát lefelé továbbítja. Keret kihagyásához adja vissza S_FALSE. Streamelési hiba esetén adjon vissza egy hibakódot.
Az alábbi példa bemutatja, hogyan implementálhatja ezt a módszert az RLE-kódoló. A saját implementációja jelentősen eltérhet attól függően, hogy mit csinál a szűrő.
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;
}
Ez a példa feltételezi, hogy az EncodeFrame egy privát módszer, amely implementálja az RLE kódolást. Magát a kódolási algoritmust itt nem ismertetjük; részletekért tekintse meg a Platform SDK dokumentációjában található "Bitkép-tömörítés" című témakört.
Először is a példa meghívja IMediaSample::GetPointer a mögöttes pufferek címeinek lekéréséhez. Ezeket átadja a privát EncoderFrame metódusnak. Ezután meghívja IMediaSample::SetActualDataLength a kódolt adatok hosszának megadásához. Az alsóbb rétegbeli szűrőnek szüksége van ezekre az információkra, hogy megfelelően tudja kezelni a puffert. Végül a metódus meghívja IMediaSample::SetSyncPoint, hogy a kulcskeret jelölője IGAZlegyen. A futáshosszú kódolás nem használ deltakereteket, ezért minden keret egy kulcskeret. A delta keretek esetében állítsa az értéket a HAMISértékre.
Egyéb, megfontolandó problémák:
Időbélyegek. A CTransformFilter osztály időbélyeget ad a kimeneti mintának, mielőtt meghívná a Transform metódust. Az időbélyeg értékeit a bemeneti mintából másolja át módosítás nélkül. Ha a szűrőnek módosítania kell az időbélyegeket, hívja meg IMediaSample::SetTime a kimeneti mintán.
Formázási változások. A felsőbb rétegbeli szűrő a médiatípus mintához csatolásával módosíthatja a formátumokat a stream közepén. Ez előtt meghívja IPin::QueryAccept a szűrő bemeneti tűjén. A CTransformFilter osztályban ez a CheckInputType hívását eredményezi, amelyet CheckTransformkövet. Az alsóbb rétegbeli szűrő is módosíthatja a médiatípusokat ugyanazzal a mechanizmussal. A saját szűrőjében két dologra kell figyelnie:
- Győződjön meg arról, hogy QueryAccept nem ad vissza hamis elfogadást.
- Ha a szűrő elfogadja a formátummódosításokat, ellenőrizze őket az Átalakítás metódusban az IMediaSample::GetMediaTypemeghívásával. Ha ez a módszer S_OK ad vissza, a szűrőnek reagálnia kell a formátumváltozásra.
További információ: Dinamikus formázási módosítások.
Szálak. Mind a CTransformFilter, mind a CTransInPlaceFiltertranszformációs szűrő szinkron módon szolgáltat kimeneti mintákat a Receive metóduson belül. A szűrő nem hoz létre feldolgozószálakat az adatok feldolgozásához. Általában nincs ok arra, hogy egy átalakítási szűrő feldolgozószálakat hozzon létre.
Következő: 6. lépés. A COMtámogatásának hozzáadása.
Kapcsolódó témakörök