Filterzustände

[Das dieser Seite zugeordnete Feature DirectShow ist ein Legacyfeature. Es wurde durch MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation ersetzt. Diese Features wurden für Windows 10 und Windows 11 optimiert. Microsoft empfiehlt dringend, dass neuer Code nach Möglichkeit MediaPlayer, IMFMediaEngine und Audio/Video Capture in Media Foundation anstelle von DirectShow verwendet. Microsoft schlägt vor, vorhandenen Code, der die Legacy-APIs verwendet, um nach Möglichkeit die neuen APIs zu verwenden.]

Filter haben drei mögliche Zustände: beendet, angehalten und ausgeführt. Der Zweck des angehaltenen Zustands besteht darin, Daten im Diagramm anzuzeigen, sodass ein Ausführungsbefehl sofort reagiert. Der Filter Graph-Manager steuert alle Zustandsübergänge. Wenn eine Anwendung IMediaControl::Run, IMediaControl::P ause oder IMediaControl::Stop aufruft, ruft der Filter Graph Manager die entsprechende IMediaFilter-Methode für alle Filter auf. Übergänge zwischen beendetem und ausgeführtem Zustand durchlaufen immer den Angehaltenen Zustand. Wenn also die Anwendung Run on a stopped graph aufruft, hält der Filter Graph Manager das Diagramm an, bevor es ausgeführt wird.

Bei den meisten Filtern sind die ausführungs- und angehaltenen Zustände identisch. Betrachten Sie das folgende Filterdiagramm:

Quelltransformationsrenderer >>

Angenommen, der Quellfilter ist keine Liveaufnahmequelle. Wenn der Quellfilter anhält, wird ein Thread erstellt, der neue Daten generiert und so schnell wie möglich in Medienbeispiele schreibt. Der Thread "pusht" die Beispiele nachgeschaltet, indem er IMemInputPin::Receive am Eingabenadel des Transformationsfilters aufruft. Der Transformationsfilter empfängt die Beispiele im Thread des Quellfilters. Es kann einen Workerthread verwenden, um die Beispiele an den Renderer zu übermitteln, in der Regel werden sie jedoch im selben Thread übermittelt. Während der Renderer angehalten wird, wartet er auf den Empfang eines Beispiels. Nachdem es einen empfangen hat, blockiert und hält es dieses Beispiel auf unbestimmte Zeit fest. Wenn es sich um einen Videorenderer handelt, wird das Beispiel als Posterbild angezeigt, wobei das Bild nach Bedarf neu gezeichnet wird.

An diesem Punkt ist der Stream vollständig erstellt und bereit für das Rendern. Wenn das Diagramm angehalten bleibt, werden die Beispiele im Diagramm hinter dem ersten Beispiel "stapeln", bis jeder Filter in Receive oder IMemAllocator::GetBuffer blockiert ist. Es werden jedoch keine Daten verloren. Sobald der Quellthread entsperrt wurde, wird er einfach an dem Punkt fortgesetzt, an dem er blockiert wurde.

Der Quellfilter und der Transformationsfilter ignorieren den Übergang von angehalten zur Ausführung – sie verarbeiten die Daten einfach so schnell wie möglich. Wenn der Renderer jedoch ausgeführt wird, beginnt er mit dem Rendern von Beispielen. Zuerst wird das Beispiel gerendert, das es während der Pause gespeichert hat. Jedes Mal, wenn es ein neues Beispiel erhält, berechnet es die Präsentationszeit des Beispiels. (Ausführliche Informationen finden Sie unter Zeit und Uhren in DirectShow.) Der Renderer hält jedes Beispiel bis zur Präsentationszeit bereit, und an diesem Punkt wird das Beispiel gerendert. Während sie auf die Präsentationszeit wartet, blockiert sie entweder die Receive-Methode oder empfängt neue Beispiele für einen Workerthread mit einer Warteschlange. Filter Upstream aus dem Renderer sind nicht an der Planung beteiligt.

Livequellen, z. B. Aufzeichnungsgeräte, sind eine Ausnahme von dieser allgemeinen Architektur. Bei einer Livequelle ist es nicht angebracht, daten im Voraus zu melden. Die Anwendung kann das Diagramm anhalten und dann lange warten, bevor sie ausgeführt wird. Das Diagramm sollte keine veralteten Beispiele rendern. Daher erzeugt eine Livequelle keine Beispiele, während sie angehalten wird, nur während der Ausführung. Um diese Tatsache an den Filtergraph-Manager zu signalisieren, gibt die IMediaFilter::GetState-Methode des Quellfilters VFW_S_CANT_CUE zurück. Dieser Rückgabecode gibt an, dass der Filter in den angehaltenen Zustand gewechselt ist, obwohl der Renderer keine Daten empfangen hat.

Wenn ein Filter beendet wird, lehnt er alle weiteren an ihn übermittelten Beispiele ab. Quellfilter fahren ihre Streamingthreads herunter, und andere Filter fahren alle Workerthreads herunter, die sie möglicherweise erstellt haben. Pins heben ihre Zuordnungen auf.

Statusübergänge

Der Filter Graph-Manager führt alle Zustandsübergänge in Upstream Reihenfolge aus, beginnend mit dem Renderer und rückwärts bis zum Quellfilter. Diese Reihenfolge ist erforderlich, um zu verhindern, dass Stichproben gelöscht werden, und um zu verhindern, dass das Diagramm deadlockt. Die wichtigsten Zustandsübergänge liegen zwischen angehalten und beendet:

  • Angehalten, um anzuhalten: Wenn jeder Filter anhält, wird er bereit für den Empfang von Beispielen aus dem nächsten Filter. Der Quellfilter ist der letzte, der angehalten wird. Es erstellt den Streamingthread und beginnt mit der Übermittlung von Beispielen. Da alle nachgelagerten Filter angehalten werden, lehnt kein Filter Proben ab. Der Filter Graph-Manager schließt den Übergang erst ab, wenn jeder Renderer im Graphen ein Beispiel erhalten hat (mit Ausnahme von Livequellen, wie weiter oben beschrieben).
  • Angehalten bis beendet: Wenn ein Filter beendet wird, gibt er alle darin enthaltenen Beispiele frei, wodurch alle Upstream in GetBuffer wartenden Filter entsperrt werden. Wenn der Filter auf eine Ressource in der Receive-Methode wartet, beendet er das Warten und gibt von Receive zurück, wodurch die Blockierung des aufrufenden Filters aufgehoben wird. Wenn der Filter Graph-Manager daher den nächsten Upstream-Filter beendet, wird dieser Filter weder in GetBuffer noch in Receive blockiert und kann auf den Befehl beenden reagieren. Der Upstream-Filter liefert möglicherweise einige zusätzliche Beispiele, bevor er den Befehl beenden erhält, aber der nachgeschaltete Filter lehnt sie einfach ab, da er bereits angehalten wurde.

Datenfluss im Filterdiagramm