Share via


Schritt 5: Transformieren des Bilds

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde durch MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation ersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code nach Möglichkeit MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet. Microsoft schlägt vor, vorhandenen Code, der die Legacy-APIs verwendet, um nach Möglichkeit die neuen APIs zu verwenden.]

Dies ist Schritt 5 des Tutorials Schreiben von Transformationsfiltern.

Der Upstream-Filter übermittelt Medienbeispiele an den Transformationsfilter, indem die IMemInputPin::Receive-Methode auf dem Eingabenadel des Transformationsfilters aufgerufen wird. Um die Daten zu verarbeiten, ruft der Transformationsfilter die Transform-Methode auf, die rein virtuell ist. Die Klassen CTransformFilter und CTransInPlaceFilter verwenden zwei verschiedene Versionen dieser Methode:

  • CTransformFilter::Transform verwendet einen Zeiger auf das Eingabebeispiel und einen Zeiger auf das Ausgabebeispiel. Bevor der Filter die -Methode aufruft, kopiert er die Beispieleigenschaften aus dem Eingabebeispiel in das Ausgabebeispiel, einschließlich der Zeitstempel.
  • CTransInPlaceFilter::Transform verwendet einen Zeiger auf das Eingabebeispiel. Der Filter ändert die Daten direkt.

Wenn die Transform-Methode S_OK zurückgibt, wird das Beispiel vom Filter nachgeschaltet. Um einen Frame zu überspringen, geben Sie S_FALSE zurück. Wenn ein Streamingfehler vorliegt, geben Sie einen Fehlercode zurück.

Das folgende Beispiel zeigt, wie der RLE-Encoder diese Methode implementieren kann. Ihre eigene Implementierung kann sich erheblich unterscheiden, je nachdem, was Ihr Filter tut.

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;
}

In diesem Beispiel wird davon ausgegangen, dass EncodeFrame eine private Methode ist, die die RLE-Codierung implementiert. Der Codierungsalgorithmus selbst wird hier nicht beschrieben. Weitere Informationen finden Sie im Thema "Bitmapkomprimierung" in der Platform SDK-Dokumentation.

Zunächst ruft das Beispiel IMediaSample::GetPointer auf, um die Adressen der zugrunde liegenden Puffer abzurufen. Diese werden an die private EncoderFrame-Methode übergeben. Anschließend wird IMediaSample::SetActualDataLength aufgerufen, um die Länge der codierten Daten anzugeben. Der Downstreamfilter benötigt diese Informationen, damit er den Puffer ordnungsgemäß verwalten kann. Schließlich ruft die -Methode IMediaSample::SetSyncPoint auf, um das Keyframeflag auf TRUE festzulegen. Bei der Laufzeitcodierung werden keine Deltaframes verwendet, sodass jeder Frame ein Keyframe ist. Legen Sie für Deltaframes den Wert auf FALSE fest.

Weitere Probleme, die Sie berücksichtigen müssen, sind:

  • Zeitstempel. Die CTransformFilter-Klasse zeitstempelt das Ausgabebeispiel vor dem Aufrufen der Transform-Methode . Es kopiert die Zeitstempelwerte aus dem Eingabebeispiel, ohne sie zu ändern. Wenn Ihr Filter die Zeitstempel ändern muss, rufen Sie IMediaSample::SetTime im Ausgabebeispiel auf.

  • Formatänderungen. Der Upstream-Filter kann Formate in der Mitte des Datenstroms ändern, indem ein Medientyp an das Beispiel angefügt wird. Zuvor wird IPin::QueryAccept am Eingabenadel Ihres Filters aufgerufen. In der CTransformFilter-Klasse führt dies zu einem Aufruf von CheckInputType gefolgt von CheckTransform. Der Nachgelagerte Filter kann auch die Medientypen mithilfe desselben Mechanismus ändern. In Ihrem eigenen Filter müssen Sie zwei Dinge watch:

    • Stellen Sie sicher, dass QueryAccept keine falschen Annahmen zurückgibt.
    • Wenn Ihr Filter Formatänderungen akzeptiert, überprüfen Sie diese in der Transform-Methode , indem Sie IMediaSample::GetMediaType aufrufen. Wenn diese Methode S_OK zurückgibt, muss Ihr Filter auf die Formatänderung reagieren.

    Weitere Informationen finden Sie unter Dynamische Formatänderungen.

  • Threads. Sowohl in CTransformFilter als auch in CTransInPlaceFilter liefert der Transformationsfilter Ausgabebeispiele synchron innerhalb der Receive-Methode . Der Filter erstellt keine Workerthreads, um die Daten zu verarbeiten. In der Regel gibt es keinen Grund für einen Transformationsfilter zum Erstellen von Workerthreads.

Weiter: Schritt 6. Fügen Sie Support für COM hinzu.

Schreiben von DirectShow-Filtern