Megosztás a következőn keresztül:


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.

DirectShow-szűrők írása