Freigeben über


Asynchrone MFTs

In diesem Thema wird die asynchrone Datenverarbeitung für Media Foundation-Transformationen (MFTs) beschrieben.

Anmerkung

Dieses Thema bezieht sich auf Windows 7 oder höher.

 

Informationen zu asynchronen MFTs

Als MFTs in Windows Vista eingeführt wurden, wurde die API für synchrone Datenverarbeitung entwickelt. In diesem Modell wartet der MFT immer darauf, eingaben zu erhalten oder auf die Ausgabe zu warten.

Betrachten Sie einen typischen Videodecoder. Um einen decodierten Frame abzurufen, ruft der Client IMFTransform::P rocessOutputauf. Wenn der Decoder über genügend Daten verfügt, um einen Frame zu decodieren, ProcessOutput Blöcke, während der MFT den Frame decodiert. Andernfalls gibt ProcessOutputMF_E_TRANSFORM_NEED_MORE_INPUTzurück, der angibt, dass der Client IMFTransform::P rocessInputaufrufen soll.

Dieses Modell funktioniert gut, wenn der Decoder alle decodierungsvorgänge in einem Thread ausführt. Angenommen, der Decoder verwendet mehrere Threads, um Frames parallel zu decodieren. Um eine optimale Leistung zu erzielen, sollte der Decoder immer dann neue Eingaben erhalten, wenn ein Decodierungsthread im Leerlauf ist. Die Rate, mit der Threads decodierungsvorgänge abgeschlossen werden, werden jedoch nicht genau mit den Aufrufen des Clients an ProcessInput und ProcessOutputausgerichtet, was dazu führt, dass Threads auf Arbeit warten.

Windows 7 führt ereignisgesteuerte asynchrone Verarbeitung für MFTs ein. Bei diesem Modell sendet das Ereignis jedes Mal, wenn die MFT Eingaben benötigt oder ausgabe hat, ein Ereignis an den Client.

Allgemeine Anforderungen

In diesem Thema wird beschrieben, wie sich asynchrone MFTs von synchronen MFT unterscheiden. Sofern in diesem Thema nicht erwähnt, sind die beiden Verarbeitungsmodelle identisch. (Insbesondere ist die Formatverhandlung identisch.)

Ein asynchroner MFT muss die folgenden Schnittstellen implementieren:

Ereignisse

Ein asynchroner MFT verwendet die folgenden Ereignisse, um den Datenverarbeitungsstatus zu signalisieren:

Ereignis Beschreibung
METransformNeedInput Gesendet, wenn der MFT weitere Eingaben annehmen kann.
METransformHaveOutput Wird gesendet, wenn die MFT ausgabe hat.
METransformDrainComplete Gesendet, wenn ein Abflussvorgang abgeschlossen ist. Siehe Entwässerung.
METransformMarker- Gesendet, wenn eine Markierung verarbeitet wird. Siehe Markierungen.

 

Diese Ereignisse werden out-of-band gesendet. Es ist wichtig, den Unterschied zwischen In-Band- und Out-of-Band-Ereignissen im Kontext eines MFT zu verstehen.

Das ursprüngliche MFT-Design unterstützt In-Band- Ereignisse. Ein In-Band-Ereignis enthält Informationen zum Datenstrom, z. B. Informationen zu einer Formatänderung. Der Client sendet In-Band-Ereignisse an den MFT, indem IMFTransform::P rocessEventaufgerufen wird. MFT kann In-Band-Ereignisse zurück an den Client in der ProcessOutput--Methode senden. (Insbesondere werden Ereignisse im pEvents Member der MFT_OUTPUT_DATA_BUFFER-Struktur vermittelt.)

Ein MFT sendet Out-of-Band-Ereignisse über die IMFMediaEventGenerator Schnittstelle wie folgt:

  1. Die MFT implementiert die IMFMediaEventGenerator Schnittstelle, wie in Media Event Generatorsbeschrieben.
  2. Der Client ruft IUnknown::QueryInterface für die IMFMediaEventGenerator Schnittstelle auf. Eine asynchrone MFT muss diese Schnittstelle verfügbar machen. Synchrone MFTs sollten diese Schnittstelle nicht verfügbar machen.
  3. Der Client ruft IMFMediaEventGenerator::BeginGetEvent und IMFMediaEventGenerator::EndGetEvent auf, um Out-of-Band-Ereignisse von der MFT zu empfangen.

ProcessInput

Die IMFTransform::P rocessInput-Methode wird wie folgt geändert:

  1. Beim Starten des Streamings sendet der Client die MFT_MESSAGE_NOTIFY_START_OF_STREAM Nachricht.
  2. Während des Streamings fordert die MFT Daten an, indem ein METransformNeedInput-Ereignis gesendet wird. Die Ereignisdaten sind der Datenstrombezeichner.
  3. Für jedes METransformNeedInput--Ereignis ruft der Client ProcessInput- für den angegebenen Datenstrom auf.
  4. Am Ende des Streamings kann der Client ProcessMessage- mit der MFT_MESSAGE_NOTIFY_END_OF_STREAM Nachricht aufrufen.

Implementierungshinweise:

ProcessOutput

Die IMFTransform::P rocessOutput-Methode wird wie folgt geändert:

  1. Wenn die MFT ausgabe hat, sendet sie ein METransformHaveOutput-Ereignis.
  2. Für jedes METransformHaveOutput-Ereignis ruft der Client ProcessOutputauf.

Implementierungshinweise:

  • Wenn der Client ProcessOutput- zu einem anderen Zeitpunkt aufruft, gibt die Methode E_UNEXPECTEDzurück.
  • Ein asynchroner MFT sollte niemals MF_E_TRANSFORM_NEED_MORE_INPUT aus der ProcessOutput--Methode zurückgeben. Wenn der MFT mehr Eingabe erfordert, sendet es ein METransformNeedInput-Ereignis.

Entwässernd

Durch das Entwässern eines MFT erzeugt der MFT so viel Ausgabe, wie es aus den bereits gesendeten Eingabedaten möglich ist. Das Entwässern eines asynchronen MFT funktioniert wie folgt:

  1. Der Client sendet die MFT_MESSAGE_COMMAND_DRAIN Nachricht.
  2. MFT sendet weiterhin METransformHaveOutput- Ereignisse, bis keine weiteren Daten verarbeitet werden. Es sendet METransformNeedInput Ereignisse während dieser Zeit nicht.
  3. Nachdem der MFT das letzte METransformHaveOutput--Ereignis gesendet hat, sendet es ein METransformDrainComplete--Ereignis.

Nachdem die Entwässerung abgeschlossen ist, sendet MFT keine weitere METransformNeedInput- Ereignis, bis sie eine MFT_MESSAGE_NOTIFY_START_OF_STREAM Nachricht vom Client empfängt.

Spülung

Der Client kann die MFT durch Senden der MFT_MESSAGE_COMMAND_FLUSH Nachricht leeren. Die MFT legt alle Eingabe- und Ausgabebeispiele ab, die sie hält.

MFT sendet keine weitere METransformNeedInput- Ereignis, bis es eine MFT_MESSAGE_NOTIFY_START_OF_STREAM Nachricht vom Client empfängt.

Markierungen

Der Client kann einen Punkt im Datenstrom markieren, indem die MFT_MESSAGE_COMMAND_MARKER Nachricht gesendet wird. Die MFT antwortet wie folgt:

  1. Der MFT generiert so viele Ausgabebeispiele wie aus den vorhandenen Eingabedaten und sendet für jedes Ausgabebeispiel ein METransformHaveOutput-Ereignis.
  2. Nachdem alle Ausgaben generiert wurden, sendet die MFT ein METransformMarker--Ereignis. Dieses Ereignis muss nach allen METransformHaveOutput- Ereignissen gesendet werden.

Angenommen, ein Decoder verfügt über genügend Eingabedaten, um vier Ausgabebeispiele zu erzeugen. Wenn der Client die MFT_MESSAGE_COMMAND_MARKER Nachricht sendet, wird die MFT vier METransformHaveOutput--Ereignisse (eins pro Ausgabebeispiel) in die Warteschlange gestellt, gefolgt von einem METransformMarker--Ereignis.

Die Markierungsnachricht ähnelt der Entwässerungsnachricht. Ein Abfluss wird jedoch als Bruch im Datenstrom betrachtet, während eine Markierung nicht erfolgt. Entwässerung und Markierungen weisen die folgenden Unterschiede auf.

Entwässernd:

  • Während der Entwässerung sendet der MFT nicht METransformNeedInput--Ereignisse.
  • MFT verwirft alle Eingabedaten, die nicht zum Erstellen eines Ausgabebeispiels verwendet werden können.
  • Einige MFTs erzeugen am Ende der Daten einen "Tail". Audioeffekte wie Hall oder Echo erzeugen beispielsweise zusätzliche Daten, nachdem die Eingabedaten beendet wurden. Ein MFT, der einen Schwanz generiert, sollte dies am Ende eines Abflussvorgangs tun.
  • Nachdem der MFT den Abfluss abgeschlossen hat, markiert es das nächste Ausgabebeispiel mit dem attribut MFSampleExtension_Discontinuity, um eine Einstellung im Datenstrom anzugeben.

Markierung:

  • MFT sendet weiterhin METransformNeedInput Ereignisse, bevor das Markierungsereignis gesendet wird.
  • Die MFT verwirft keine Eingabedaten. Wenn Teildaten vorhanden sind, sollte sie nach dem Markierungspunkt verarbeitet werden.
  • Der MFT erzeugt keinen Schwanz am Markierungspunkt.
  • Die MFT legt die Einstellungskennzeichnung nach dem Markierungspunkt nicht fest.

Formatänderungen

Ein asynchroner MFT muss dynamische Formatänderungen unterstützen, wie in Behandeln von Datenstromänderungenbeschrieben.

Attribute

Ein asynchroner MFT muss die IMFTransform::GetAttributes Methode implementieren, um einen gültigen Attributspeicher zurückzugeben. Die folgenden Attribute gelten für asynchrone MFTs:

Attribut Beschreibung
MF_TRANSFORM_ASYNC MFT muss dieses Attribut auf TRUE- (1) festlegen. Der Client kann dieses Attribut abfragen, um zu ermitteln, ob die MFT asynchron ist.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE MFT muss dieses Attribut auf TRUE- (1) festlegen. Der Client kann davon ausgehen, dass dieses Attribut festgelegt ist.

 

Entsperren asynchroner MFTs

Asynchrone MFTs sind nicht mit dem ursprünglichen MFT-Datenverarbeitungsmodell kompatibel. Um zu verhindern, dass asynchrone MFTs vorhandene Anwendungen unterbrechen, wird der folgende Mechanismus definiert:

Der Client ruft IMFTransform::GetAttributes- für die MFT auf. Der Client fragt das Attribut für dieses MF_TRANSFORM_ASYNC ab. Bei einem asynchronen MFT lautet der Wert dieses Attributs **TRUE**. Um die MFT zu entsperren, muss der Client das attribut MF_TRANSFORM_ASYNC_UNLOCK auf **TRUE** festlegen.

Bis der Client die MFT entsperrt, sollten alle IMFTransform- Methoden MF_E_TRANSFORM_ASYNC_LOCKEDzurückgeben, mit den folgenden Ausnahmen:

Der folgende Code zeigt, wie Sie ein asynchrones MFT entsperren:

HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
    IMFAttributes *pAttributes = NULL;

    HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
        pAttributes->Release();
    }
    
    return hr;
}

Herunterfahren des MFT

Asynchrone MFTs müssen die IMFShutdown--Schnittstelle implementieren.

  • Herunterfahren: Die MFT muss die Ereigniswarteschlange herunterfahren. Wenn Sie die Standardereigniswarteschlange verwenden, rufen Sie IMFMediaEventQueue::Shutdownauf. Optional kann der MFT andere Ressourcen freigeben. Der Client darf den MFT nach dem Aufrufen Herunterfahrennicht verwenden.
  • GetShutdownStatus-: Nachdem Herunterfahren aufgerufen wurde, sollte MFT den Wert MFSHUTDOWN_COMPLETED im pStatus-parameter zurückgeben. Der Wert sollte nicht MFSHUTDOWN_INITIATEDzurückgegeben werden.

Registrierung und Aufzählung

Um ein asynchrones MFT zu registrieren, rufen Sie die MFTRegister--Funktion auf, und legen Sie das MFT_ENUM_FLAG_ASYNCMFT Flag im Flags-Parameter fest. (Zuvor war dieses Flag reserviert.)

Rufen Sie zum Aufzählen asynchroner MFTs die MFTEnumEx--Funktion auf, und legen Sie das MFT_ENUM_FLAG_ASYNCMFT Flag im parameter Flags fest. Aus Gründen der Abwärtskompatibilität führt die MFTEnum--Funktion keine asynchronen MFTs auf. Andernfalls könnte die Installation eines asynchronen MFT auf dem Computer des Benutzers vorhandene Anwendungen unterbrechen.

Media Foundation Transforms