Share via


Grundlegendes MFT-Verarbeitungsmodell

In diesem Thema wird beschrieben, wie ein Client eine Media Foundation-Transformation (MFT) verwendet, um Daten zu verarbeiten. Der Client ist alles, was Methoden direkt auf dem MFT aufruft. Dies kann die Anwendung oder die Media Foundation-Pipeline sein.

Lesen Sie dieses Thema, wenn Sie folgendes sind:

  • Schreiben einer Anwendung, die direkte Aufrufe an mindestens ein MFTs angibt.
  • Schreiben eines benutzerdefinierten MFT und möchten das erwartete Verhalten eines MFT verstehen.

In diesem Thema wird ein synchrones Verarbeitungsmodell beschrieben. In diesem Modell blockieren alle Datenverarbeitungsmethoden, bis sie abgeschlossen sind. MFTs können auch ein asynchrones Modell unterstützen, das im Thema asynchrone MFTs beschrieben wird.

Grundlegendes Verarbeitungsmodell

Erstellen des MFT

Es gibt mehrere Möglichkeiten zum Erstellen eines MFT:

Einige MFTs bieten möglicherweise andere Optionen, z. B. eine spezielle Erstellungsfunktion.

Abrufen von Streambezeichnern

Ein MFT verfügt über einen oder mehrere Datenströme. Eingabedaten erhalten Eingabedaten, und Ausgabeströme generieren Ausgabedaten. Streams werden nicht als verschiedene Objekte dargestellt. Stattdessen nehmen verschiedene MFT-Methoden Datenstrombezeichner als Parameter an.

Einige MFTs ermöglichen es dem Client, Eingabeströme hinzuzufügen oder zu entfernen. Während des Streamings kann ein MFT Ausgabeströme hinzufügen oder entfernen. (Der Client kann Keine Ausgabeströme hinzufügen oder entfernen.)

  1. (Optional.) Rufen Sie IMFTransform::GetStreamLimits auf, um die minimale und maximale Anzahl von Datenströme abzurufen, die die MFT unterstützen kann. Wenn das Mindest- und Maximum identisch ist, weist die MFT eine feste Anzahl von Datenströme auf.
  2. Rufen Sie IMFTransform::GetStreamCount auf, um die anfängliche Anzahl von Streams abzurufen.
  3. Rufen Sie IMFTransform::GetStreamIDs auf, um die Streambezeichner abzurufen. Wenn diese Methode E_NOTIMPL zurückgibt, bedeutet dies, dass die MFT eine feste Anzahl von Datenströme aufweist, und die Datenstrombezeichner sind ab Null aufeinander.
  4. (Optional.) Wenn die MFT keine feste Anzahl von Datenströme enthält, rufen Sie IMFTransform::AddInputStreams auf, um weitere Eingabeströme hinzuzufügen oder IMFTransform::D eleteInputStream zu entfernen. (Sie können Ausgabeströme nicht hinzufügen oder entfernen.)

Festlegen von Medientypen

Bevor ein MFT Daten verarbeiten kann, muss der Client für jeden der Datenströme des MFT einen Medientyp festlegen. Ein MFT kann erfordern, dass der Client die Eingabetypen vor dem Festlegen der Ausgabetypen festlegt oder die entgegengesetzte Reihenfolge (zuerst Ausgabetypen) erfordert. Einige MFTs verfügen nicht über eine Anforderung an die Bestellung.

Ein MFT kann eine Liste der bevorzugten Medientypen für einen Stream bereitstellen. Außerdem können MFTs die allgemeinen Formate angeben, die sie unterstützen, indem sie diese Informationen zur Registrierung hinzufügen.

Gehen Sie wie folgt vor, um die Medientypen festzulegen:

  1. (Optional.) Rufen Sie für jeden Eingabedatenstrom IMFTransform::GetInputAvailableType auf, um die Liste der bevorzugten Typen für diesen Stream abzurufen.
    • Wenn diese Methode MF_E_TRANSFORM_TYPE_NOT_SET zurückgibt, müssen Sie die Ausgabetypen zuerst festlegen; Wechseln Sie zu Schritt 3.
    • Wenn die Methode E_NOTIMPL zurückgibt, verfügt die MFT nicht über eine Liste der bevorzugten Eingabetypen; Wechseln Sie zu Schritt 2.
  2. Rufen Sie für jeden Eingabedatenstrom IMFTransform::SetInputType auf, um den Eingabetyp festzulegen. Sie können einen Medientyp aus Schritt 1 oder einen Typ verwenden, der Ihre Eingabedaten beschreibt. Wenn ein Datenstrom MF_E_TRANSFORM_TYPE_NOT_SET zurückgibt, wechseln Sie zu Schritt 3.
  3. (Optional.) Rufen Sie für jeden Ausgabedatenstrom IMFTransform::GetOutputAvailableType auf, um eine Liste der bevorzugten Typen für diesen Stream abzurufen.
    • Wenn diese Methode MF_E_TRANSFORM_TYPE_NOT_SET zurückgibt, müssen Sie die Eingabetypen zuerst festlegen; kehren Sie zurück zu Schritt 1.
    • Wenn ein Datenstrom E_NOTIMPL zurückgibt, verfügt die MFT nicht über eine Liste der bevorzugten Ausgabetypen; Wechseln Sie zu Schritt 4.
  4. Rufen Sie für jeden Ausgabedatenstrom IMFTransform::SetOutputType auf, um den Ausgabetyp festzulegen. Sie können einen Medientyp aus Schritt 3 oder einen Typ verwenden, der Ihr erforderliches Ausgabeformat beschreibt.
  5. Wenn keine Eingabedatenströme über einen Medientyp verfügen, wechseln Sie zurück zu Schritt 1.

Abrufen von Pufferanforderungen

Nachdem der Client die Medientypen festgelegt hat, sollte er die Pufferanforderungen für jeden Datenstrom abrufen:

Daten verarbeiten

Ein MFT ist so konzipiert, dass es sich um einen zuverlässigen Zustandscomputer handelt. Es macht keine Anrufe zurück an den Client.

  1. Rufen Sie IMFTransform::P rocessMessage mit der MFT_MESSAGE_NOTIFY_BEGIN_STREAMING Nachricht auf. Diese Nachricht fordert die MFT an, alle Ressourcen zuzuweisen, die während des Streamings benötigt werden.
  2. Rufen Sie IMFTransform::P rocesInput auf mindestens einem Eingabedatenstrom auf, um ein Eingabebeispiel an die MFT zu liefern.
  3. (Optional.) Rufen Sie IMFTransform::GetOutputStatus auf, um abzufragen, ob die MFT ein Ausgabebeispiel generieren kann. Wenn die Methode S_OK zurückgibt, überprüfen Sie den pdwFlags-Parameter . Wenn pdwFlags das MFT_OUTPUT_STATUS_SAMPLE_READY-Flag enthält, wechseln Sie zu Schritt 4. Wenn pdwFlags null ist, gehen Sie zurück zu Schritt 2. Wenn die Methode E_NOTIMPL zurückgibt, wechseln Sie zu Schritt 4.
  4. Rufen Sie IMFTransform::P rocesOutput auf, um Ausgabedaten abzurufen.
    • Wenn die Methode MF_E_TRANSFORM_NEED_MORE_INPUT zurückgibt, bedeutet dies, dass die MFT mehr Eingabedaten erfordert; gehen Sie zurück zu Schritt 2.
    • Wenn die Methode MF_E_TRANSFORM_STREAM_CHANGE zurückgibt, bedeutet dies, dass die Anzahl der Ausgabeströme geändert wurde oder das Ausgabeformat geändert wurde. Der Client muss möglicherweise nach neuen Datenstrombezeichnern abfragen oder neue Medientypen festlegen. Weitere Informationen finden Sie in der Dokumentation für ProcessOutput.
  5. Wenn weiterhin Eingabedaten verarbeitet werden, wechseln Sie zu Schritt 2. Wenn die MFT alle verfügbaren Eingabedaten verbraucht hat, fahren Sie mit Schritt 6 fort.
  6. Rufen Sie ProcessMessage mit der MFT_MESSAGE_NOTIFY_END_OF_STREAM Nachricht auf.
  7. Rufen Sie ProcessMessage mit der MFT_MESSAGE_COMMAND_DRAIN Nachricht auf.
  8. Rufen Sie ProcessOutput auf, um die verbleibende Ausgabe abzurufen. Wiederholen Sie diesen Schritt, bis die Methode MF_E_TRANSFORM_NEED_MORE_INPUT zurückgibt. Dieser Rückgabewert signalisiert, dass alle Ausgabe vom MFT abgelassen wurden. (Behandeln Sie dies nicht als Fehlerbedingung.)

Die hier beschriebene Sequenz hält so wenig Daten wie möglich im MFT. Nach jedem Aufruf von ProcessInput versucht der Client, die Ausgabe abzurufen. Mehrere Eingabebeispiele müssen möglicherweise ein Ausgabebeispiel erstellen, oder ein einzelnes Eingabebeispiel kann mehrere Ausgabebeispiele generieren. Das optimale Verhalten für den Client besteht darin, Ausgabebeispiele aus dem MFT abzurufen, bis die MFT mehr Eingabe erfordert.

Die MFT sollte jedoch in der Lage sein, eine andere Reihenfolge von Methodenaufrufen vom Client zu behandeln. Der Client kann beispielsweise einfach zwischen Aufrufen von ProcessInput und ProcessOutput wechseln. Die MFT sollte die Menge an Eingaben einschränken, die sie abrufen, indem sie MF_E_NOTACCEPTING von ProcessInput zurückgibt, wenn es eine Ausgabe hat, die erstellt werden soll.

Die reihenfolge der hier beschriebenen Methodenaufrufe ist nicht die einzige gültige Sequenz von Ereignissen. In den Schritten 3 und 4 wird beispielsweise davon ausgegangen, dass der Client mit den Eingabetypen beginnt und dann die Ausgabetypen versucht. Der Client kann diese Reihenfolge auch rückgängig machen und mit den Ausgabetypen beginnen. Falls der MFT die gegenteilige Reihenfolge erfordert, sollte der Fehlercode MF_E_TRANSFORM_TYPE_NOT_SET zurückgegeben werden.

Der Client kann Informationsmethoden wie GetInputCurrentType und GetOutputStreamInfo jederzeit während des Streamings aufrufen. Der Client kann auch versuchen, die Medientypen jederzeit zu ändern. Der MFT sollte einen Fehlercode zurückgeben, wenn dies kein gültiger Vorgang ist. Kurz gesagt sollten MFTs sehr wenig über die Reihenfolge der Vorgänge ausgehen, außer was in den Aufrufen selbst dokumentiert ist.

Das folgende Diagramm zeigt ein Flussdiagramm der in diesem Thema beschriebenen Verfahren.

flow chart that leads from get stream identifiers through loops that set input types, get input, and process output

Erweiterungen für das Basic-Modell

Optional kann ein MFT einige Erweiterungen für das grundlegende Streamingmodell unterstützen.

  • Lazy-read Streams. Wenn die IMFTransform::GetOutputStreamInfo-Methode das MFT_OUTPUT_STREAM_LAZY_READ Flag für einen Ausgabedatenstrom zurückgibt, muss der Client keine Daten aus diesem Ausgabedatenstrom sammeln. Die MFT akzeptiert weiterhin Eingaben, und an einem bestimmten Punkt verwerfen die MFT die Ausgabedaten aus diesem Datenstrom. Wenn alle Ausgabedatenströme über dieses Flag verfügen, kann die MFT niemals die Eingabe akzeptieren. Ein Beispiel kann eine Visualisierungstransformation sein, bei der der Client nur die Ausgabe erhält, wenn er über ersatzte CPU-Zyklen verfügt, um die Visualisierung zu zeichnen.
  • Verwerfende Datenströme. Wenn die GetOutputStreamInfo-Methode das MFT_OUTPUT_STREAM_DISCARDABLE-Flag für einen Ausgabedatenstrom zurückgibt, kann der Client die MFT anfordern, die Ausgabe verwerfen, aber die MFT verwerfen keine Ausgabe, es sei denn, dies wird angefordert. Wenn der MFT seinen maximalen Eingabepuffer erreicht, muss der Client entweder einige Ausgabedaten sammeln oder die MFT anfordern, die Ausgabe zu verwerfen.
  • Optionale Datenströme. Wenn die GetOutputStreamInfo-Methode das MFT_OUTPUT_STREAM_OPTIONAL Flag für einen Ausgabestrom oder die IMFTransform::GetInputStreamInfo-Methode zurückgibt, gibt die MFT_INPUT_STREAM_OPTIONAL-Kennzeichnung für einen Eingabedatenstrom zurück, dieser Stream ist optional. Der Client muss keinen Medientyp im Stream festlegen. Wenn der Client den Typ nicht festgelegt hat, wird der Stream deaktiviert. Ein deaktivierter Ausgabedatenstrom erzeugt keine Beispiele, und der Client stellt keinen Puffer für den Datenstrom bereit, wenn er ProcessOutput aufruft. Ein nicht ausgewählter Eingabedatenstrom akzeptiert keine Eingabedaten. Ein MFT kann alle Eingabe- und Ausgabeströme als optional markieren. Es wird jedoch erwartet, dass mindestens eine Eingabe und eine Ausgabe für die Arbeit von MFT ausgewählt werden müssen.
  • Asynchrone Verarbeitung. Das asynchrone Verarbeitungsmodell wurde in Windows 7 eingeführt. Es wird im Thema asynchrone MFTs beschrieben.

IMF2DBuffer

Wenn ein MFT unkomprimierte Videodaten verarbeitet, sollte die IMF2DBuffer-Schnittstelle verwendet werden, um die Beispielpuffer zu bearbeiten. Um diese Schnittstelle abzurufen, abfragen Sie die IMFMediaBuffer-Schnittstelle auf jedem Eingabe- oder Ausgabepuffer. Diese Schnittstelle wird nicht verwendet, wenn sie verfügbar ist, kann zu zusätzlichen Pufferkopien führen. Um diese Schnittstelle ordnungsgemäß zu verwenden, sollte die Transformation den Puffer nicht mit der IMFMediaBuffer-Schnittstelle sperren, wenn IMF2DBuffer verfügbar ist.

Weitere Informationen zur Verarbeitung von Videodaten finden Sie unter Unkomprimierte Videopuffer.

Spülen eines MFT

Das Spülen eines MFT führt dazu, dass die MFT alle Eingabedaten verwerfen kann. Dies kann zu einem Bruch im Ausgabedatenstrom führen. Ein Client würde in der Regel einen MFT spülen, bevor er auf einen neuen Punkt im Eingabedatenstrom sucht oder zu einem neuen Eingabedatenstrom wechselt, wenn der Client sich nicht darum kümmert, Daten zu verlieren.

Um eine MFT zu löschen, rufen Sie IMFTransform::P rocessMessage mit der MFT_MESSAGE_COMMAND_FLUSH Nachricht auf.

Entleeren eines MFT

Das Entlassen eines MFT bewirkt, dass die MFT so viel Ausgabe erzeugt, wie sie von allen Eingabedaten bereits gesendet wurde. Wenn die MFT kein vollständiges Ausgabebeispiel aus der verfügbaren Eingabe erstellen kann, wird die Eingabedaten abgebrochen. Ein Client würde in der Regel einen MFT ablassen, wenn er das Ende des Quelldatenstroms erreicht hat oder unmittelbar vor einer Formatänderung im Quelldatenstrom. Gehen Sie wie folgt vor, um einen MFT zu entleeren:

  1. Rufen Sie ProcessMessage mit der MFT_MESSAGE_COMMAND_DRAIN Nachricht auf. Diese Nachricht benachrichtigt die MFT, dass sie so viel Ausgabedaten wie aus den bereits gesendeten Eingabedaten liefern sollte.
  2. Rufen Sie ProcessOutput auf, um Ausgabedaten abzurufen, bis die Methode MF_E_TRANSFORM_NEED_MORE_INPUT zurückgibt.

Während die MFT abgelassen wird, akzeptiert sie keine weiteren Eingaben.

Beispielattribute

Die Eingabebeispiele verfügen möglicherweise über Attribute, die in die entsprechenden Ausgabebeispiele kopiert werden müssen.

Für eine MFT mit einer Eingabe und einer Ausgabe können Sie die folgende allgemeine Regel verwenden:

  • Wenn jedes Eingabebeispiel genau ein Ausgabebeispiel erzeugt, können Sie den Client die Attribute kopieren lassen. Lassen Sie die MFPKEY_EXATTRIBUTE_SUPPORTED Eigenschaft nicht festgelegt.
  • Wenn keine 1-1-Übereinstimmung zwischen Eingabebeispielen und Ausgabebeispielen vorhanden ist, muss die MFT die richtigen Attribute für Ausgabebeispiele bestimmen. Legen Sie die MFPKEY_EXATTRIBUTE_SUPPORTED-Eigenschaft auf VARIANT_TRUE fest.

Unterbrechungen

Eine Unterbrechung ist eine Unterbrechung in einem Audio- oder Videostream. Unterbrechungen können durch abgelegte Pakete in einer Netzwerkverbindung, beschädigte Dateidaten, einen Wechsel von einem Quelldatenstrom zu einem anderen oder einer vielzahl anderer Ursachen verursacht werden. Kontinuitäten werden signalisiert, indem sie das attribut MFSampleExtension_Discontinuity auf dem ersten Beispiel nach der Unterbrechung festlegen. Es ist nicht möglich, eine Unterbrechung in der Mitte eines Beispiels zu signalisieren. Daher sollten in separaten Beispielen keine unabgestellten Daten gesendet werden.

Einige Transformationen, insbesondere diejenigen, die unkomprimierte Daten wie Audio- und Videoeffekte behandeln, sollten Unterbrechungen ignorieren, wenn sie Eingabedaten verarbeiten. Diese MFTs sind im Allgemeinen so konzipiert, dass fortlaufende Daten verarbeitet werden und alle Daten behandelt werden, die sie erhalten, auch nach einer Unterbrechung.

Wenn ein MFT eine Unterbrechung der Eingabedaten ignoriert, sollte es weiterhin das Einstellungszeichen für das Ausgabebeispiel festlegen, wenn das Ausgabebeispiel den gleichen Zeitstempel wie das Eingabebeispiel aufweist. Wenn das Ausgabebeispiel einen anderen Zeitstempel aufweist, sollte die MFT jedoch nicht die Unterbrechung verteilen. (Dies wäre beispielsweise in einigen Audio-Resamplers der Fall.) Eine Unterbrechung an der falschen Stelle im Stream ist schlechter als keine Unterbrechung.

Die meisten Decoder können keine Unterbrechungen ignorieren, da sich eine Unterbrechung auf die Interpretation des nächsten Beispiels auswirkt. Jede Codierungstechnologie, die die Interframekomprimierung verwendet, z. B. MPEG-2, fällt in diese Kategorie. Einige Codierungsschemas verwenden nur die Intraframekomprimierung, z. B. DV und MJPEG. Diese Decoder können unterbrechungen sicher ignorieren.

Transformationen, die auf Unterbrechungen reagieren, sollten in der Regel so viele Daten ausgeben, bevor die Unterbrechung möglich ist, und den Rest verwerfen. Das Eingabebeispiel mit dem Einstellungsflagge sollte verarbeitet werden, als sei es das erste Beispiel im Stream. (Dieses Verhalten entspricht dem, was für die MFT_MESSAGE_COMMAND_DRAIN Nachricht angegeben ist.) Die genauen Details hängen jedoch vom Medienformat ab.

Wenn ein Decoder nichts zur Entschärfung einer Unterbrechung ausführt, sollte es das Einstellungszeichen in die Ausgabedaten kopieren. Demultiplexer und andere MFTs, die vollständig mit komprimierten Daten arbeiten, müssen alle Unterbrechungen in ihre Ausgabeströme kopieren. Andernfalls können die nachgelagerten Komponenten die komprimierten Daten möglicherweise nicht ordnungsgemäß codieren. Im Allgemeinen ist es fast immer richtig, nachgelagerte Unterbrechungen zu übergeben, es sei denn, die MFT enthält expliziten Code, um Unterbrechungen zu glätten.

Dynamische Formatänderungen

Formate können sich während des Streamings ändern. Beispielsweise kann sich das Seitenverhältnis in der Mitte eines Videodatenstroms ändern.

Details zur Behandlung von Streamänderungen durch einen MFT finden Sie unter Behandeln von Streamänderungen.

Streamereignisse

Um ein Ereignis an einen MFT zu senden, rufen Sie IMFTransform::P rocessEvent auf. Wenn die Methode MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT zurückgibt, gibt der MFT das Ereignis an den Aufrufer auf einem nachfolgenden Aufruf von ProcessOutput zurück. Wenn die Methode einen anderen HRESULT-Wert zurückgibt, gibt der MFT das Ereignis nicht an den Client in ProcessOutput zurück. In diesem Fall ist der Client verantwortlich für die Verteilung des Ereignisses nach der nächsten Komponente in der Pipeline, falls zutreffend. Weitere Informationen finden Sie unter IMFTransform::P rocessOutput.

Media Foundation-Transformationen