Asynchrone MFTs
In diesem Thema wird die asynchrone Datenverarbeitung für Media Foundation Transformationen (MFTs) beschrieben.
Hinweis
Dieses Thema gilt für Windows 7 oder höher.
- Informationen zu asynchronen MFTs
- Allgemeine Anforderungen
- Ereignisse
- ProcessInput
- ProcessOutput
- Ausgleichen
- Spülung
- Marker
- Formatänderungen
- Attribute
- Entsperren asynchroner MFTs
- Herunterfahren des MFT
- Registrierung und Enumeration
- Zugehörige Themen
Informationen zu asynchronen MFTs
Als MFTs in Windows Vista eingeführt wurden, wurde die API für die synchrone Datenverarbeitung entwickelt. In diesem Modell wartet MFT immer entweder darauf, Eingaben zu erhalten oder eine Ausgabe zu erzeugen.
Betrachten Sie einen typischen Videodecoder. Um einen decodierten Frame zu erhalten, ruft der Client DIETRANSFORM::P rocessOutput auf. Wenn der Decoder über genügend Daten zum Decodieren eines Frames verfügt, blockiert ProcessOutput, während der MFT den Frame decodiert. Andernfalls gibt ProcessOutput MF_E_TRANSFORM_NEED_MORE_INPUT zurück, was angibt, dass der Client DENKtransform::P rocessInput aufrufen soll.
Dieses Modell funktioniert gut, wenn der Decoder alle seine Decodierungsvorgänge für einen Thread ausführt. Angenommen, der Decoder verwendet mehrere Threads, um Frames parallel zu decodieren. Um die beste Leistung zu erzielen, sollte der Decoder immer dann neue Eingaben empfangen, wenn ein Decodierungsthread in den Leerlauf über geht. Die Rate, mit der Threads Decodierungsvorgänge abschließen, entspricht jedoch nicht genau den Clientaufrufen von ProcessInput und ProcessOutput,was dazu führt, dass Threads auf Arbeit warten.
Windows 7 führt eine ereignisgesteuerte, asynchrone Verarbeitung für MFTs ein. In diesem Modell sendet der MFT immer dann ein Ereignis an den Client, wenn er Eingaben benötigt oder über eine Ausgabe verfügt.
Allgemeine Anforderungen
In diesem Thema wird beschrieben, wie sich asynchrone MFTs von synchronem MFT unterscheiden. Sofern in diesem Thema nicht erwähnt, sind die beiden Verarbeitungsmodelle identisch. (Insbesondere ist die Formataushandlung identisch.)
Ein asynchrones MFT muss die folgenden Schnittstellen implementieren:
Events
Ein asynchroner MFT verwendet die folgenden Ereignisse, um seinen Datenverarbeitungsstatus zu signalisieren:
| Ereignis | BESCHREIBUNG |
|---|---|
| METransformNeedInput | Wird gesendet, wenn MFT mehr Eingaben akzeptieren kann. |
| METransformHaveOutput | Wird gesendet, wenn die MFT-Ausgabe auft. |
| METransformDgreifComplete | Wird gesendet, wenn ein Entleerungsvorgang abgeschlossen ist. Weitere Informationen finden Sie unter Leeren von. |
| METransformMarker | Wird gesendet, wenn ein Marker prozessweise ist. Weitere Informationen finden Sie unter Marker. |
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.
Der ursprüngliche MFT-Entwurf 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 MFT, indem er DURCH AUFRUFEN von ZUEgeTransform::P rocessEvent aufruft. Der MFT kann In-Band-Ereignisse in der ProcessOutput-Methode zurück an den Client senden. (Insbesondere werden Ereignisse im pEvents-Member der MFT_OUTPUT_DATA_BUFFER übermittelt.)
Ein MFT sendet Out-of-Band-Ereignisse wie folgt über die BERMEDIAEventGenerator-Schnittstelle:
- Der MFT implementiert die BERMEDIAEventGenerator-Schnittstelle, wie unter Media Event Generators (Medienereignis-Generatoren) beschrieben.
- Der Client ruft IUnknown::QueryInterface auf der MFT für die BENUTZEROBERFLÄCHENmediaEventGenerator auf. Eine asynchrone MFT muss diese Schnittstelle verfügbar machen. Synchrone MFTs sollten diese Schnittstelle nicht verfügbar machen.
- Der Client ruft DIE FOLGENDEN Aufrufe auf: 10002222221111111111111111111111111111111111111111111111111111111DMediaEventGenerator::EndGetEvent,um Out-of-Band-Ereignisse von MFT zu empfangen.
ProcessInput
Die METHODE ZUEgetransform::P rocessInput wird wie folgt geändert:
- Beim Starten des Streamings sendet der Client die MFT_MESSAGE_NOTIFY_START_OF_STREAM Nachricht.
- Während des Streamings fordert der MFT Daten an, indem er ein METransformNeedInput-Ereignis sendet. Die Ereignisdaten sind der Streambezeichner.
- Für jedes METransformNeedInput-Ereignis ruft der Client ProcessInput für den angegebenen Stream auf.
- Am Ende des Streamings kann der Client ProcessMessage mit der MFT_MESSAGE_NOTIFY_END_OF_STREAM aufrufen.
Implementierungshinweise:
- Der MFT darf keine METransformNeedInput-Ereignisse senden, bis er die MFT_MESSAGE_NOTIFY_START_OF_STREAM empfängt.
- Während des Streamings kann MFT jederzeit METransformNeedInput-Ereignisse senden.
- MFT sollte die Anzahl ausstehender METransformNeedInput-Ereignisse verwalten. Jeder Aufruf von ProcessInput, der keinem METransformNeedInput-Ereignis entspricht, muss MF_E_NOTACCEPTING.
- Wenn der MFT die MFT_MESSAGE_NOTIFY_END_OF_STREAM empfängt, wird die Anzahl ausstehender METransformNeedInput-Ereignisse auf 0 (null) zurückgesetzt.
- Der MFT darf keine METransformNeedInput-Ereignisse senden, nachdem er die MFT_MESSAGE_NOTIFY_END_OF_STREAM empfangen hat.
- Wenn ProcessInput vor MFT_MESSAGE_NOTIFY_START_OF_STREAM oder nach MFT_MESSAGE_NOTIFY_END_OF_STREAM aufgerufen wird,muss die Methode MF_E_NOTACCEPTING.
ProcessOutput
Die METHODE ROCTransform::P rocessOutput wird wie folgt geändert:
- Wenn der MFT eine Ausgabe hat, sendet er ein METransformHaveOutput-Ereignis.
- Für jedes METransformHaveOutput-Ereignis ruft der Client ProcessOutput auf.
Implementierungshinweise:
- Wenn der Client ProcessOutput zu einem anderen Zeitpunkt aufruft, gibt die Methode E_UNEXPECTED.
- Ein asynchroner MFT sollte niemals MF_E_TRANSFORM_NEED_MORE_INPUT ProcessOutput-Methode zurückgeben. Wenn der MFT mehr Eingaben erfordert, sendet er ein METransformNeedInput-Ereignis.
Ausgleichen
Das Leeren eines MFT führt dazu, dass MFT so viele Ausgaben wie möglich aus den bereits gesendeten Eingabedaten erzeugt. Das Leeren eines asynchronen MFT funktioniert wie folgt:
- Der Client sendet die MFT_MESSAGE_COMMAND_DRAIN Nachricht.
- Der MFT sendet weiterhin METransformHaveOutput-Ereignisse, bis keine Daten mehr zu verarbeiten sind. Während dieser Zeit werden keine METransformNeedInput-Ereignisse gesendet.
- Nachdem der MFT das letzte METransformHaveOutput-Ereignis sendet, sendet er ein METransformDgreifComplete-Ereignis.
Nach Abschluss des Leerens sendet MFT erst dann ein weiteres METransformNeedInput-Ereignis, wenn es eine MFT_MESSAGE_NOTIFY_START_OF_STREAM Clientnachricht empfängt.
Spülung
Der Client kann den MFT leeren, indem er die MFT_MESSAGE_COMMAND_FLUSH sendet. Der MFT löscht alle Eingabe- und Ausgabebeispiele, die er hält.
Der MFT sendet kein weiteres METransformNeedInput-Ereignis, bis er eine MFT_MESSAGE_NOTIFY_START_OF_STREAM Nachricht vom Client empfängt.
Marker
Der Client kann einen Punkt im Stream markieren, indem er die MFT_MESSAGE_COMMAND_MARKER Nachricht sendet. Der MFT antwortet wie folgt:
- Der MFT generiert beliebig viele Ausgabebeispiele aus den vorhandenen Eingabedaten und sendet ein METransformHaveOutput-Ereignis für jedes Ausgabebeispiel.
- Nachdem die gesamte Ausgabe generiert wurde, sendet der 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, stellt der MFT vier METransformHaveOutput-Ereignisse in die Warteschlange (eins pro Ausgabebeispiel), gefolgt von einem METransformMarker-Ereignis.
Die Markermeldung ähnelt der Entleerungsmeldung. Eine Entleerung wird jedoch als Unterbrechung im Stream betrachtet, während ein Marker nicht ist. Die Entleerungen und Marker weisen die folgenden Unterschiede auf.
Entwässerung:
- Beim Entladen sendet der MFT keine METransformNeedInput-Ereignisse.
- Der MFT verwirft alle Eingabedaten, die nicht zum Erstellen eines Ausgabebeispiels verwendet werden können.
- Einige MFTs erzeugen ein "Ende" am Ende der Daten. Beispielsweise erzeugen Audioeffekte wie Hall oder Echo zusätzliche Daten, nachdem die Eingabedaten beendet wurden. Ein MFT, der ein Ende generiert, sollte dies am Ende eines Entleerungsvorgangs tun.
- Nachdem die MFT-Bereinigung abgeschlossen ist, markiert sie das nächste Ausgabebeispiel mit dem MFSampleExtension_Discontinuity Attribut, um eine Diskontinuität im Stream anzugeben.
Marker:
- Der MFT sendet weiterhin METransformNeedInput-Ereignisse, bevor das Markerereignis gesendet wird.
- Der MFT verwirft keine Eingabedaten. Wenn Teildaten vorhanden sind, sollten sie nach dem Markerpunkt verarbeitet werden.
- Der MFT erzeugt am Markerpunkt kein Ende.
- Der MFT legt das Diskontinuitätsflag nach dem Markerpunkt nicht fest.
Formatänderungen
Ein asynchroner MFT muss dynamische Formatänderungen unterstützen, wie unter Verarbeiten von Streamänderungenbeschrieben.
Attributes
Ein asynchroner MFT-Wert muss die METHODE VONTRANSFORM::GetAttributes implementieren, um einen gültigen Attributspeicher zurückzugeben. Die folgenden Attribute gelten für asynchrone MFTs:
| attribute | BESCHREIBUNG |
|---|---|
| MF_TRANSFORM_ASYNC | Der MFT muss dieses Attribut auf TRUE (1) festlegen. Der Client kann dieses Attribut abfragen, um zu ermitteln, ob der MFT asynchron ist. |
| MF_TRANSFORM_ASYNC_UNLOCK | |
| MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE | Der 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 abbrechen, wird der folgende Mechanismus definiert:
- Der Client ruft ÜBERTRANSFORM::GetAttributes für den MFT auf.
Der Client fragt die nach diesem MF_TRANSFORM_ASYNC Attribut ab. Bei einem asynchronen MFT ist der Wert dieses Attributs **TRUE.**
Um den MFT zu entsperren, muss der Client das attribut MF_TRANSFORM_ASYNC_UNLOCK auf **TRUE** setzen.
Bis der Client den MFT entsperrt, sollten alle METHODEN VONTRANSFORM mit den folgenden Ausnahmen MF_E_TRANSFORM_ASYNC_LOCKED zurückgeben:
- SUBSCRIBERTransform::GetAttributes (alle asynchronen MFTs)
- SUBSCRIBERTransform::GetInputAvailableType (alle asynchronen MFTs)
- CODTRANSFORM::GetOutputCurrentType (nur Encoder)
- CODTRANSFORM::SetOutputType (nur Encoder)
- SUBSCRIBERTransform::GetStreamCount (alle asynchronen MFTs)
- SUBSCRIBERTransform::GetStreamIDs (alle asynchronen MFTs)
Der folgende Code zeigt, wie Ein asynchroner MFT entsperrt wird:
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 INTERFACESShutdown-Schnittstelle implementieren.
- Herunterfahren:Der MFT muss seine Ereigniswarteschlange herunterfahren. Wenn Sie die Standardereigniswarteschlange verwenden, rufen Sie DENMEDIAEventQueue::Shutdownauf. Optional kann der MFT andere Ressourcen freigeben. Der Client darf den MFT nach dem Aufruf von Shutdown nicht mehr verwenden.
- GetShutdownStatus:Nachdem Shutdown aufgerufen wurde, sollte der MFT den Wert MFSHUTDOWN_COMPLETED im pStatus-Parameter zurückgeben. Der Wert MFSHUTDOWN_INITIATED sollte nicht zurückgegeben werden.
Registrierung und Enumeration
Um einen asynchronen MFT zu registrieren, rufen Sie die MFTRegister-Funktion auf, und legen Sie das flag MFT_ENUM_FLAG_ASYNCMFT im Flags-Parameter fest. (Bisher war dieses Flag reserviert.)
Um asynchrone MFTs aufzuzählen, rufen Sie die MFTEnumEx-Funktion auf, und legen Sie das flag MFT_ENUM_FLAG_ASYNCMFT im Flags-Parameter fest. Aus Gründen der Abwärtskompatibilität führt die MFTEnum-Funktion keine asynchronen MFTs auf. Andernfalls kann die Installation eines asynchronen MFT auf dem Computer des Benutzers vorhandene Anwendungen unterbrechen.