Beispiele und Zuweisungen

Wenn eine Stecknadel Mediendaten an einen anderen Pin übergibt, wird kein direkter Zeiger auf den Speicherpuffer übergeben. Stattdessen stellt sie einen Zeiger auf ein COM-Objekt zur Verwaltung des Arbeitsspeichers zur Verfügung. Dieses Objekt, das als Medienbeispiel bezeichnet wird, macht die IMediaSample-Schnittstelle verfügbar. Der empfangende Pin ruft IMediaSample-Methoden wie IMediaSample::GetPointer, IMediaSample::GetSizeund IMediaSample::GetActualDataLengthauf den Speicherpuffer auf.

Beispiele werden immer nachgeschaltet, vom Ausgabepin bis zum Eingabepin. Im Pushmodell liefert der Ausgabepin ein Beispiel durch Aufrufen von IMemInputPin::Receive am Eingabepin. Der Eingabepin verarbeiten die Daten entweder synchron (d. h. vollständig innerhalb der Receive-Methode) oder asynchron in einem Arbeitsthread. Der Eingabepin darf innerhalb der Receive-Methode blockiert werden, wenn er auf Ressourcen warten muss.

Ein anderes COM-Objekt, das als Zuweisung bezeichnet wird, ist für das Erstellen und Verwalten von Medienbeispielen verantwortlich. Zuweisungen 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 Stecknadelverbindung teilt sich eine Zuweisung. Wenn zwei Stecknadeln eine Verbindung herstellen, entscheiden sie, welcher Filter die Zuweisung bereitstellen soll. Die Pins legen auch Eigenschaften für die Zuweisung fest, z. B. die Anzahl der Puffer und die Größe der einzelnen Puffer. (Weitere Informationen finden Sie unter How Filters Verbinden and Negotiating Allocators.)

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

Medienbeispiele und Zuweisungen

Anzahl von Medienbeispielverweisen

Eine Zuweisung erstellt einen begrenzten 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 nachzuverfolgung. Die GetBuffer-Methode gibt ein Beispiel mit einem Verweiszähler von 1 zurück. Wenn der Verweiszähler auf 0 (null) gesetzt wird, wird das Beispiel wieder in den Pool der Zuweisung zurückverläuft, wo es im nächsten GetBuffer-Aufruf verwendet werden kann. Solange die Verweisanzahl über 0 (null) bleibt, ist das Beispiel für GetBuffer nicht verfügbar. Wenn jede Stichprobe, die zur Zuweisung gehört, verwendet wird, wird die GetBuffer-Methode blockiert, bis ein Beispiel verfügbar wird.

Angenommen, ein Eingabepin empfängt eine Stichprobe. Wenn das Beispiel synchron verarbeitet wird, wird der Verweiszähler 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) gesetzt, und das Beispiel wird an den Pool der Zuweisung zurückgegeben. Wenn der Eingabepin hingegen die Stichprobe in einem Arbeitsthread verarbeitet, erhöht er die Verweisanzahl, bevor die Receive-Methode verlassen wird. Die Verweisanzahl ist jetzt 2. Wenn der Ausgabepin das Beispiel frei gibt, wird die Anzahl auf 1 angerechnet. Das Beispiel wird noch nicht an den Pool zurück. Nachdem der Arbeitsthread mit dem Beispiel fertig ist, wird Release aufgerufen, um das Beispiel frei zu geben. Nun kehrt das Beispiel zum Pool zurück.

Wenn eine Stecknadel ein Beispiel empfängt, kann sie die Daten in eine andere Stichprobe kopieren oder die ursprüngliche Stichprobe ändern und an den nächsten Filter liefern. Möglicherweise kann ein Beispiel die gesamte Länge des Diagramms durchwechseln, und jeder Filter ruft wiederum AddRef und Release auf. Aus diesem Grund darf der Ausgabepin niemals ein Beispiel erneut verwenden, nachdem er Receive aufruft, da ein Downstreamfilter das Beispiel verwenden kann. Der Ausgabepin muss immer GetBuffer aufrufen, um ein neues Beispiel zu erhalten.

Dieser Mechanismus reduziert die Speicherzuweisung, da Filter die gleichen Puffer wiederver verwenden. 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 Dekomprimieren). Wenn die Ausgabe nicht größer als die Eingabe ist, kann ein Filter die Daten an Ort und Stelle verarbeiten, ohne sie in ein neues Beispiel zu kopieren. In diesem Fall können zwei oder mehr Pinverbindungen eine Zuweisung gemeinsam verwenden.

Committen und Decommitieren von Zuweisungen

Wenn ein Filter zum ersten Mal eine Zuweisung erstellt, hat die Zuweisung keine Speicherpuffer reserviert. An diesem Punkt können alle Aufrufe der GetBuffer-Methode nicht mehr verwendet werden. Beim Starten des Streamings ruft der Ausgabepin IMemAllocator::Commitauf, wodurch ein Commit für die Zuweisung gestartet wird, wodurch Speicher zugewiesen wird. Pins können jetzt GetBuffer aufrufen.

Wenn das Streaming beendet wird, ruft der Pin IMemAllocator::D ecommitauf, wodurch die Zuweisung decommitiert wird. Alle nachfolgenden Aufrufe von GetBuffer führen zu einem Fehler, bis für die Zuweisung erneut ein Committed für die Zuweisung anfällt. Wenn Aufrufe von GetBuffer derzeit blockiert sind und auf ein Beispiel warten, geben sie sofort einen Fehlercode zurück. Die Decommit-Methode gibt je nach Implementierung möglicherweise Arbeitsspeicher frei. Beispielsweise wartet die CMemAllocator-Klasse, bis ihre Destruktormethode Arbeitsspeicher frei gibt.

Daten Flow im Filter-Graph