Share via


Beispiele und Zuweisungen

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde von MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation abgelöst. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code mediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet, wenn möglich. Microsoft schlägt vor, dass vorhandener Code, der die Legacy-APIs verwendet, so umgeschrieben wird, dass nach Möglichkeit die neuen APIs verwendet werden.]

Wenn ein Pin Mediendaten an eine andere Pin übermittelt, wird kein direkter Zeiger auf den Speicherpuffer übergeben. Stattdessen wird ein Zeiger auf ein COM-Objekt bereitgestellt, das den Arbeitsspeicher verwaltet. Dieses Objekt, das als Medienbeispiel bezeichnet wird, macht die IMediaSample-Schnittstelle verfügbar. Die empfangende Pin greift auf den Speicherpuffer zu, indem IMediaSample-Methoden wie IMediaSample::GetPointer, IMediaSample::GetSize und IMediaSample::GetActualDataLength aufgerufen werden.

Beispiele werden immer nachgeschaltet, vom Ausgabe- bis zum Eingabestift. Im Pushmodell liefert der Ausgabepin ein Beispiel, indem IMemInputPin::Receive am Eingabepin aufgerufen wird. Der Eingabepin verarbeitet die Daten entweder synchron (d. h. vollständig innerhalb der Receive-Methode ) oder asynchron in einem Workerthread. Der Eingabenadel darf innerhalb der Receive-Methode blockiert werden, wenn er auf Ressourcen warten muss.

Ein anderes COM-Objekt, das als Allocator bezeichnet wird, ist für das Erstellen und Verwalten von Medienbeispielen zuständig. Allocators machen die IMemAllocator-Schnittstelle verfügbar. Wenn ein Filter ein Medienbeispiel mit einem leeren Puffer benötigt, ruft er die IMemAllocator::GetBuffer-Methode auf, die einen Zeiger auf das Beispiel zurückgibt. Jede Pinverbindung teilt sich eine Zuweisung. Wenn zwei Pins eine Verbindung herstellen, entscheiden sie, welcher Filter die Zuweisung bereitstellt. Die Pins legen auch Eigenschaften für die Zuweisung fest, z. B. die Anzahl der Puffer und die Größe jedes Puffers. (Weitere Informationen finden Sie unter Verbinden von Filtern und Aushandeln von Zuweisungen.)

Die folgende Abbildung zeigt die Beziehungen zwischen der Zuweisung, den Medienbeispielen und dem Filter.

Medienbeispiele und Zuweisungen

Referenzanzahl von Medienbeispielen

Eine Zuweisung erstellt einen endlichen Pool von Stichproben. Einige Beispiele können jederzeit verwendet werden, während andere für GetBuffer-Aufrufe verfügbar sind. Die Zuweisung verwendet die Verweiszählung, um die Stichproben nachzuverfolgen. Die GetBuffer-Methode gibt ein Beispiel mit einer Verweisanzahl von 1 zurück. Wenn die Verweisanzahl auf 0 (null) festgelegt ist, wird das Beispiel wieder in den Pool des Zuweisungsgebers geleitet, wo es im nächsten GetBuffer-Aufruf verwendet werden kann. Solange die Verweisanzahl über 0 (null) liegt, ist das Beispiel für GetBuffer nicht verfügbar. Wenn jedes Beispiel verwendet wird, das zum Allocator gehört, blockiert die GetBuffer-Methode , bis ein Beispiel verfügbar ist.

Angenommen, ein Eingabenadel empfängt ein Beispiel. Wenn das Beispiel synchron verarbeitet wird, wird die Verweisanzahl innerhalb der Receive-Methode nicht erhöht. Nach der Rückgabe von Receive gibt der Ausgabepin das Beispiel frei, die Verweisanzahl wird auf 0 (null) und das Beispiel an den Pool des Zuweisungsgebers zurückgegeben. Wenn der Eingabepin hingegen das Beispiel in einem Workerthread verarbeitet, erhöht er die Verweisanzahl, bevor die Receive-Methode verlassen wird. Die Verweisanzahl ist jetzt 2. Wenn der Ausgabepin das Beispiel loslässt, geht die Anzahl auf 1; das Beispiel wird noch nicht an den Pool zurückgegeben. Nachdem der Workerthread mit dem Beispiel fertig ist, wird Release aufgerufen, um das Beispiel freizugeben. Nun kehrt das Beispiel zum Pool zurück.

Wenn ein Pin ein Beispiel empfängt, kann er die Daten in ein anderes Beispiel kopieren oder das ursprüngliche Beispiel ändern und an den nächsten Filter übermitteln. Möglicherweise kann ein Beispiel die gesamte Länge des Diagramms übertragen, wobei jeder Filter AddRef und Release aufruft. Aus diesem Grund darf der Ausgabepin nach dem Aufruf von Receive niemals ein Beispiel wiederverwenden, da das Beispiel möglicherweise von einem Downstreamfilter verwendet wird. Der Ausgabepin muss immer GetBuffer aufrufen, um ein neues Beispiel zu erhalten.

Dieser Mechanismus reduziert die Speicherbelegung, da Filter dieselben Puffer wiederverwenden. Außerdem wird verhindert, dass Filter versehentlich Daten überschreiben, die nicht verarbeitet wurden, da die Zuweisung eine Liste der verfügbaren Beispiele verwaltet.

Ein Filter kann separate Zuweisungen für Eingabe und Ausgabe verwenden. Dies kann der Fall sein, wenn die Eingabedaten erweitert werden (z. B. durch Dekomprimierung). Wenn die Ausgabe nicht größer als die Eingabe ist, verarbeitet ein Filter die Daten möglicherweise, ohne sie in ein neues Beispiel zu kopieren. In diesem Fall können zwei oder mehr Pinverbindungen eine Zuweisung gemeinsam nutzen.

Committen und Deaktivieren von Zuweisungen

Wenn ein Filter zum ersten Mal eine Zuweisung erstellt, hat die Zuweisung keine Speicherpuffer reserviert. An diesem Punkt schlagen alle Aufrufe der GetBuffer-Methode fehl. Wenn das Streaming gestartet wird, ruft der Ausgabenadel IMemAllocator::Commit auf, wodurch der Zuweisungsvorgang committet wird, wodurch Arbeitsspeicher zugewiesen wird. Pins können jetzt GetBuffer aufrufen.

Wenn das Streaming beendet wird, ruft der Pin IMemAllocator::D ecommit auf, wodurch die Zuweisung aufgehoben wird. Alle nachfolgenden Aufrufe von GetBuffer schlagen fehl, bis der Zuweisungsvorgang erneut committet wird. Wenn Aufrufe von GetBuffer derzeit blockiert sind und auf ein Beispiel warten, wird sofort ein Fehlercode zurückgegeben. Die Decommit-Methode kann den Arbeitsspeicher je nach Implementierung freigeben oder nicht. Beispielsweise wartet die CMemAllocator-Klasse , bis ihre Destruktormethode Arbeitsspeicher freigibt.

Datenfluss im Filtergraphen