Schreiben einer benutzerdefinierten Medienquelle
In diesem Thema wird beschrieben, wie eine benutzerdefinierte Medienquelle in Microsoft Media Foundation implementiert wird. Sie enthält die folgenden Abschnitte:
- Erstellen des Präsentationsdeskriptors
- Starten der Medienquelle
- Anhalten der Medienquelle
- Generieren von Quelldaten
- Herunterfahren der Medienquelle
- Livequellen
- Zugehörige Themen
Erstellen des Präsentationsdeskriptors
Die METHODE VONMEDIASOURCE::CreatePresentationDescriptor gibt eine Kopie des Präsentationsdeskriptors der Quelle zurück. Um den Präsentationsdeskriptor zu erstellen, müssen Sie die Anzahl der Streams im Quellinhalt und die möglichen Formate der einzelnen Streams kennen. Erstellen Sie für jeden Stream einen Streamdeskriptor wie folgt:
- Erstellen Sie ein Array von Medientypen. Jeder Medientyp im Array stellt ein mögliches Format für den Stream dar. Weitere Informationen zum Erstellen von Medientypen finden Sie unter Medientypen.
- Rufen Sie MFCreateStreamDescriptor auf, um den Streamdeskriptor zu erstellen. Übergeben Sie das Array von Medientypen. Die Funktion gibt einen POINTERStreamDescriptor-Zeiger zurück.
- Rufen Sie DEN HANDLERSTREAMDescriptor::GetMediaTypeHandler auf, um den Medientyphandler des Streamdeskriptors abzurufen.
- Rufen Sie DAS DEFAULTMediaTypeHandler::SetCurrentMediaType-Format auf, um das Standardstreamformat festzulegen. Verwenden Sie einen der Medientypen, die Sie in Schritt 1 erstellt haben. Im Allgemeinen sollten Sie das Format mit der höchsten Qualität verwenden.
- Legen Sie optional Attribute für den Streamdeskriptor fest. Eine Liste der Attribute, die für Streamdeskriptoren gelten, finden Sie unter Stream Descriptor Attributes.
Erstellen Sie nun den Präsentationsdeskriptor:
- Rufen Sie MFCreatePresentationDescriptor auf, und übergeben Sie das Array von Streamdeskriptoren. Die Funktion gibt einen POINTERPresentationDescriptor-Zeiger zurück.
- Wählen Sie die Standarddatenstromauswahl aus, indem Sie DENKPresentationDescriptor::SelectStream aufrufen, um einen oder mehrere Streams auszuwählen. In der Standardkonfiguration muss mindestens ein Stream ausgewählt werden.
- Legen Sie optional Attribute für den Präsentationsdeskriptor fest. Eine Liste der Attribute, die für Streamdeskriptoren gelten, finden Sie unter Presentation Descriptor Attributes.
Sie sollten den Präsentationsdeskriptor einmal erstellen, entweder beim Start oder nachdem die Quelle genügend der Quelldaten analysiert hat, um den Inhalt zu bestimmen. Die CreatePresentationDescriptor-Methode sollte eine Kopie des Präsentationsdeskriptors zurückgeben. Um die Kopie zu erstellen, rufen Sie DENKPresentationDescriptor::Cloneauf. Das Zurückgeben einer Kopie verhindert, dass der Client den Zustand des ursprünglichen Präsentationsdeskriptors ändert, z. B. die Attribute oder die Streamauswahl. Beachten Sie jedoch, dass Clone eine flache Kopie erstellt, sodass der Client möglicherweise die zugrunde liegenden Streamdeskriptoren ändern kann.
Starten der Medienquelle
Die METHODE SEEKMediaSource::Start startet die Medienquelle oder sucht an einer neuen Position. Ein Aufruf von Start bewirkt eine Suche, wenn der vorherige Zustand entweder angehalten wurde oder ausgeführt wurde und eine neue Startzeit angegeben wird. Andernfalls bewirkt die Start-Methode einen Start. Wenn der Startvorgang abgeschlossen ist, senden Sie die folgenden Ereignisse.
- Senden Sie ein MENewStream-Ereignis für jeden neuen Stream, d. h. jeden Stream, der zuvor deaktiviert und jetzt ausgewählt wurde. Die Ereignisdaten sind ein Zeiger auf den Stream.
- Senden Sie ein MEUpdatedStream-Ereignis für jeden Stream, der zuvor ausgewählt und noch ausgewählt wurde. Die Ereignisdaten sind ein Zeiger auf den Stream. (Senden Sie kein Ereignis für deaktivierte Streams.)
- Wenn die Quelle sucht, senden Sie ein MESourceSeeked-Ereignis. Senden Sie andernfalls ein MESourceStarted-Ereignis. Die Ereignisdaten sind die Startzeit, die in der Start-Methode angegeben wurde. Wenn die Startzeit für das MESourceStarted-Ereignis VT _ EMPTY ist, legen Sie das MF EVENT SOURCE ACTUAL _ _ _ _ START-Attribut für das Ereignis fest. Der Attributwert ist die tatsächliche Startzeit.
- Wenn die Quelle nach jedem Stream sucht, senden Sie ein MEStreamSeeked-Ereignis. Andernfalls senden Sie ein MEStreamStarted-Ereignis. Die Ereignisdaten sind die Startzeit. (Die Medienquelle kann ein Ereignis im Stream in die Warteschlange stellen, indem sie die WARTESCHLANGENMediaEventGenerator::QueueEvent-Methode des Streams aufruft.)
Wenn die Auswahl eines Streams aufgehoben wird, fahren Sie den Stream herunter. Der Stream sollte an diesem Punkt keine weiteren Ereignisse in die Warteschlange einreihen.
Das Zeitformat für die Start-Methode wird im pguidTimeFormat-Parameter angegeben. Das durch GUID _ NULL angegebene Standardzeitformat beträgt 100 Nanosekundeneinheiten. Eine Medienquelle muss dieses Zeitformat unterstützen.
Suchen
Bei der Suche fällt die angeforderte Startposition möglicherweise nicht auf eine genaue Stichprobengrenze. Bei komprimierten Inhalten kann die Startposition zwischen Keyframes liegen. Ein Stream sollte Beispiele ab dem frühestmöglichen Zeitpunkt bereitstellen, der zum Erstellen einer unkomprimierten Stichprobe an der angeforderten Startposition erforderlich ist. Für Video bedeutet dies, dass vom vorherigen Keyframe aus begonnen wird. Die Pipeline ist dafür verantwortlich, die zusätzlichen Frames aus dem Decoder zu löschen, sodass die Wiedergabe zum angeforderten Zeitpunkt beginnt.
Die in den Quellereignissen (MESourceStarted, MESourceSeeked, MEStreamStartedund MEStreamSeeked)angegebene Startzeit ist die angeforderte Startzeit (der in der Startmethode angegebene Wert), unabhängig von der tatsächlichen Startposition.
Angenommen, die ersten Frames eines Videostreams weisen die folgenden Merkmale auf:
| Beispiel | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| Time | 33 Ms | 66 msec | 100 msec | 133 Ms |
| Keyframe? | Ja | Nein | Nein | Ja |
Wenn die Start-Methode mit einem Wert von 100 Millisekunden aufgerufen wird, muss die Quelle das Video ab Frame 1 ausgeben, dem ersten Keyframe vor diesem Zeitpunkt. Das Startereignis gibt weiterhin 100 Millisekunden in den Ereignisdaten an.
Anhalten der Medienquelle
Die :P AUSE-Methode hält die Medienquelle an.
Während die Quelle angehalten wird, kann ein Stream neue Beispiele erstellen und in einer Warteschlange speichern, aber der Stream liefert die Beispiele nicht. Hier sind einige Ausnahmen für diese Regel aufgeführt:
- Livequellen sollten Daten löschen, während sie angehalten wurden.
- Wenn die Quelle Daten aus einem Netzwerk erhält, wird der Server möglicherweise angehalten.
Wenn der Client WÄHREND des Anhaltens der Quelle DENMEDIASTREAM::RequestSample aufruft, wird die Anforderung in die Warteschlange eingereiht, bis die Quelle erneut gestartet wird. Anforderungen sollten nicht gelöscht werden.
Das Anhalten ist nur ab dem Gestartet-Zustand zulässig. Andernfalls sollte Pause MF E INVALID STATE _ _ TRANSITION _ _ zurückgeben.
Generieren von Quelldaten
Media Foundation verwendet ein Pullmodell, d. h. Streams generieren und liefern Beispiele als Reaktion auf Anforderungen aus der Pipeline. Ein Stream kann Beispiele liefern, wenn die Medienquelle ausgeführt wird und der Stream ausgewählt ist. Ein Stream stellt Daten nur dann zur Verfügung, wenn der Client ein neues Beispiel angibt.
Beispielanforderungen
Der Client fordert ein neues Beispiel an, indem er DURCH AUFRUFEN VON NSMEDIAStream::RequestSample aufruft. Dies ist die Abfolge der Vorgänge:
Der Client ruft DIETMEDIAStream::RequestSample auf. Das Argument ist ein Zeiger auf ein optionales Tokenobjekt, das der Client zum Nachverfolgen der Anforderung verwendet. Der Client implementiert das Token. Token müssen die IUnknown-Schnittstelle verfügbar machen. Der Client kann auch einen NULL-Zeiger anstelle eines Tokens übergeben.
Wenn der Client ein Token bereitgestellt hat, ruft der Medienstream AddRef für das Token auf und platziert das Token in einer First-In-First-Out-Warteschlange. Die Methode gibt zurück, und die verbleibenden Schritte werden asynchron ausgeführt.
Wenn weitere Daten verfügbar sind, erstellt der Medienstream ein neues Beispiel. (Dieser Schritt wird im nächsten Abschnitt ausführlicher beschrieben.)
Der Medienstream pullt das erste Token aus der Warteschlange.
Wenn das Token nicht NULL ist, legt der Medienstream das MFSampleExtension _ Token-Attribut für das Medienbeispiel fest. Der Wert des Attributs ist ein Zeiger auf das Token.
Der Medienstream sendet ein MEMediaSample-Ereignis. Bei den Ereignisdaten handelt es sich um einen Zeiger auf die BENUTZEROBERFLÄCHESample-Schnittstelle des Beispiels.
Wenn der Client ein Token bereitgestellt hat, ruft der Medienstream Release für das Tokenobjekt auf.
Wenn der Medienstream die RequestSample-Anforderung des Clients nicht erfüllen kann, ruft er das Token aus der Warteschlange ab und ruft Release für das Token auf, sendet aber kein MEMediaSample-Ereignis.
Der Client kann das Token zum Nachverfolgen des Status der Anforderung verwenden. Wenn der Client das MEMediaSample-Ereignis empfängt, kann er das Token aus dem Beispiel abrufen und mit der ursprünglichen Anforderung ab stimmen. Der Client kann das Token auch verwenden, um zu ermitteln, ob die Medienquelle die Anforderung gelöscht hat. Wenn die Verweisanzahl des Tokens auf 0 (null) fällt und der Medienstream kein MEMediaSample-Ereignis sendet, bedeutet dies, dass die Anforderung gelöscht wurde.
Bei den hier aufgeführten Schritten wird davon ausgegangen, dass die RequestSample-Methode als asynchroner Vorgang implementiert wird. Wenn die Methode synchron ist, müssen Sie das Anforderungstoken nicht in eine Warteschlange stellen. Wenn das Generieren von Daten jedoch eine erhebliche Zeit in Dauert, wird ein asynchroner Ansatz empfohlen, z. B. wenn die Quelle Daten aus einem Bytestream liest.
Der Stream ist für das Puffern von Daten zuständig, die sich zwischen Aufrufen von RequestSample ansammeln.
Wenn der Medienstream das Ende des Streams erreicht, sendet er nach dem letzten Beispiel ein MEEndOfStream-Ereignis. Nachdem jeder Stream beendet wurde, sendet die Medienquelle ein MEEndOfPresentation-Ereignis. Nachdem ein Medienstream das MEEndOfStream-Ereignis sendet, gibt die RequestSample-Methode MF _ E END OF _ _ _ STREAM zurück, bis die Quelle neu gestartet wird.
Zuordnen von Beispielen
Wenn der Stream bereit ist, eine ausstehende Beispielanforderung zu füllen, erstellt er ein neues Beispiel und fügt dem Beispiel mindestens einen Medienpuffer hinzu. Weitere Informationen zum Erstellen von Medienpuffern finden Sie unter Medienpuffer.
Der Stream muss den Zeitstempel und die Dauer festlegen, sofern bekannt. Der Zeitstempel ist relativ zur Quelle. In den meisten Fällen entspricht der Anfang des Inhalts einem Zeitstempel von null. Wenn die Quelle beispielsweise aus einer Mediendatei liest, hat der Anfang der Datei einen Zeitstempel von 0 (null).
Der Zeitstempel des Beispiels entspricht nicht unbedingt der Präsentationszeit. Die Mediensitzung wird von der Quellzeit in die Präsentationszeit übersetzt. Bei komprimierten Daten sollte der Stream Daten generieren, die vom nächstgelegenen Keyframe vor der Startzeit beginnen. Dadurch kann der Decoder den Frame liefern, der zur angeforderten Startzeit angezeigt wird. (Andernfalls muss der Decoder bis zum folgenden Keyframe warten.)
Wenn die Wiedergaberate schneller oder langsamer als 1,0 ist, passt die Pipeline die Rate der Präsentationsuhr an. Die Quelle passt die Zeitstempel für Stichproben nicht an.
Die Quelle kann zusätzliche Informationen zum Beispiel festlegen, indem Attribute festgelegt werden. Eine Liste der Beispielattribute finden Sie unter Beispielattribute.
Lücken im Stream
Wenn ein Stream eine Lücke von signifikanter Länge enthält, wird empfohlen, dass der Stream ein MEStreamTick-Ereignis sendet. Dieses Ereignis benachrichtigt den Client, dass ein Beispiel fehlt. Die Ereignisdaten sind der Zeitstempel der fehlenden Stichprobe in Einheiten von 100 Nanosekunden (VT _ I8). Dieses Ereignis kann downstream-Komponenten daran speichern, auf Beispiele zu warten, die nicht eintreffen. Der Stream kann so viele MEStreamTick-Ereignisse wie erforderlich senden, um die Lücke im Stream zu überspannen.
Herunterfahren der Medienquelle
Wenn der Client die Medienquelle verwendet, ruft er DIEMEDIASOURCE::Shutdown auf. Innerhalb dieser Methode sollte die Medienquelle alle Zirkelverweiszähler unterbricht. In der Regel gibt es Zirkelverweise zwischen der Medienquelle und den Medienstreams.
Wenn Sie die Ereigniswarteschlange verwenden, um DEN WARTESCHLANGEN-Generator ZUIMPLEMENTIEREN, rufen Sie FÜR DIE Ereigniswarteschlange DEN AUFRUF ANZMediaEventQueue::Shutdown auf. Diese Methode fährt die Ereigniswarteschlange herunter und signalisiert jedem Aufrufer, der derzeit auf ein Ereignis wartet.
Nach dem Herunterfahren geben alle Methoden in der Quelle MF _ E _ SHUTDOWN mit Ausnahme von IUnknown-Methoden zurück.
Livequellen
Ab Windows 7 unterstützt Media Foundation automatisch Audio- und Videoaufnahmegeräte. Für Videos muss das Gerät einen Kernelstreaming-Minitreiber (KS) in der Kategorie Videoaufnahme bereitstellen. Media Foundation verwendet den PnP-Pfad, um das Gerät zu aufzählen. Für Audiodaten verwendet Media Foundation die Windows MMDevice-API (Multimedia Device), um Audioendpunktgeräte zu aufzählen. Wenn das Gerät diese Kriterien erfüllt, ist es nicht notwendig, eine benutzerdefinierte Medienquelle zu implementieren.
Möglicherweise möchten Sie jedoch eine benutzerdefinierte Medienquelle für einen anderen Gerätetyp oder eine andere Livedatenquelle implementieren. Es gibt nur wenige Unterschiede zwischen einer Livequelle und anderen Medienquellen:
- Geben Sie in der METHODE FÜR DIE MEDIENQUELLE::GetCharacteristics das MFMEDIASOURCE _ IS _ LIVE-Flag zurück.
- Das erste Beispiel sollte einen Zeitstempel von 0 (null) haben.
- Ereignisse und Streamingzustände werden mit Ausnahme des angehaltenen Zustands wie Medienquellen behandelt.
- Warteschlangenbeispiele sollten nicht in die Warteschlange gestellt werden, solange sie angehalten wurden. Alle Daten, die während des Anhaltens generiert werden, werden verdringt.
- Livequellen unterstützen in der Regel keine Such-, Reverseplay- oder Ratensteuerung.