Erstellen von Graphen mit dem Capture Graph Builder

[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.]

Trotz seines Namens ist der Capture Graph Builder nützlich, um viele Arten von benutzerdefinierten Filterdiagrammen zu erstellen, nicht nur zum Erfassen von Diagrammen. Dieser Artikel bietet eine kurze Übersicht über die Verwendung dieses Objekts.

Der Capture Graph Builder macht die ICaptureGraphBuilder2-Schnittstelle verfügbar. Rufen Sie zunächst CoCreateInstance auf, um den Capture Graph Builder und den Filter Graph Manager zu erstellen. Initialisieren Sie dann den Capture Graph Builder, indem Sie ICaptureGraphBuilder2::SetFiltergraph mit einem Zeiger auf den Filtergraph-Manager aufrufen:

IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;

// Create the Filter Graph Manager.
HRESULT hr =  CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (SUCCEEDED(hr))
{
    // Create the Capture Graph Builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, 
        (void **)&pBuilder);
    if (SUCCEEDED(hr))
    {
        pBuilder->SetFiltergraph(pGraph);
    }
};

Verbinden von Filtern

Die ICaptureGraphBuilder2::RenderStream-Methode verbindet zwei oder drei Filter in einer Kette. Im Allgemeinen funktioniert die Methode am besten, wenn jeder Filter nicht mehr als einen Eingabe- oder Ausgabestift desselben Typs hat. Diese Diskussion beginnt damit, die ersten beiden Parameter von RenderStream zu ignorieren und sich auf die letzten drei Parameter zu konzentrieren. Der dritte Parameter ist ein IUnknown-Zeiger , der entweder einen Filter (als IBaseFilter-Schnittstellenzeiger ) oder einen Ausgabepin (als IPin-Schnittstellenzeiger ) angeben kann. Der vierte und fünfte Parameter geben IBaseFilter-Zeiger an. Die RenderStream-Methode verbindet alle drei Filter in einer Kette. Angenommen, A, B und C sind Filter. Angenommen, jeder Filter hat genau einen Eingabe- und einen Ausgabestift. Der folgende Aufruf verbindet A mit B und dann B mit C:

"RenderStream(NULL, NULL, A, B, C)"

Alle Verbindungen sind "intelligent", was bedeutet, dass dem Diagramm nach Bedarf zusätzliche Filter hinzugefügt werden. Ausführliche Informationen finden Sie unter Intelligent Connect. Um nur zwei Filter zu verbinden, legen Sie den Mittleren Wert auf NULL fest. Mit diesem Aufruf wird beispielsweise eine Verbindung zwischen A und C hergestellt:

"RenderStream(NULL, NULL, A, NULL, C)"

Sie können längere Ketten erstellen, indem Sie die Methode zweimal aufrufen:

'RenderStream(NULL, NULL, A, B, C)' 'RenderStream(NULL, NULL, C, D, E)'

Wenn der letzte Parameter NULL ist, sucht die Methode automatisch nach einem Standardrenderer. Es verwendet den Video-Renderer für Video und den DirectSound-Renderer für Audio. So:

"RenderStream(NULL, NULL, A, NULL, NULL)"

für die folgende Syntax:

"RenderStream(NULL, NULL, A, NULL, R)"

wobei R der geeignete Renderer ist. Um den Video mixing Renderer-Filter anstelle des Videorenderers zu verbinden, müssen Sie ihn jedoch explizit angeben.

Wenn Sie im dritten Parameter einen Filter anstelle eines Pins angeben, müssen Sie möglicherweise angeben, welcher Ausgabenadel für die Verbindung verwendet werden soll. Dies ist der Zweck der ersten beiden Parameter der Methode. Der erste Parameter gilt nur für Erfassungsfilter. Es gibt eine GUID an, die eine Anheftkategorie angibt. Eine vollständige Liste der Kategorien finden Sie unter Eigenschaftensatz anheften. Zwei der Kategorien sind für alle Erfassungsfilter gültig:

  • PIN_CATEGORY_CAPTURE
  • PIN_CATEGORY_PREVIEW

Wenn ein Erfassungsfilter keine separaten Pins für die Erfassung und Vorschau liefert, fügt die RenderStream-Methode einen Smart Tee-Filter ein, der den Stream in einen Aufzeichnungsstream und einen Vorschaudatenstrom aufteilt. Aus Sicht der Anwendung können Sie einfach alle Erfassungsfilter als separate Pins behandeln und die zugrunde liegende Topologie des Graphen ignorieren.

Verbinden Sie bei der Dateierfassung den Erfassungspin mit einem Muxfilter. Verbinden Sie für die Livevorschau den Vorschaunadel mit einem Renderer. Wenn Sie die beiden Kategorien wechseln, kann das Diagramm während der Dateierfassung eine übermäßige Anzahl von Frames löschen. Wenn das Diagramm jedoch ordnungsgemäß verbunden ist, wird die Vorschauframes nach Bedarf gelöscht, um den Durchsatz für den Aufzeichnungsstream zu erhalten.

Das folgende Beispiel zeigt, wie beide Streams verbunden werden:

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);

Einige Erfassungsfilter unterstützen auch Untertitel, die durch PIN_CATEGORY_VBI angegeben werden. Um die Untertitel in einer Datei zu erfassen, rendern Sie diese Kategorie in den mux-Filter. Stellen Sie eine Verbindung mit dem Renderer her, um die Untertitel in Ihrem Vorschaufenster anzuzeigen:

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);

Der zweite Parameter für RenderStream identifiziert den Medientyp und ist in der Regel einer der folgenden:

  • MEDIATYPE_Audio
  • MEDIATYPE_Video
  • MEDIATYPE_Interleaved (DV)

Sie können diesen Parameter immer dann verwenden, wenn die Ausgabepins des Filters die Enumeration der bevorzugten Medientypen unterstützen. Für Dateiquellen fügt der Capture Graph Builder bei Bedarf automatisch einen Parserfilter hinzu und fragt dann die Medientypen im Parser ab. (Ein Beispiel finden Sie unter Neukomprimieren einer AVI-Datei.) Wenn der letzte Filter in der Kette über mehrere Eingabestifte verfügt, versucht die Methode außerdem, ihre Medientypen aufzulisten. Diese Funktionalität wird jedoch nicht von allen Filtern unterstützt.

Suchen nach Schnittstellen für Filter und Pins

Nachdem Sie ein Diagramm erstellt haben, müssen Sie in der Regel nach verschiedenen Schnittstellen suchen, die durch Filter und Pins im Diagramm verfügbar gemacht werden. Beispielsweise kann ein Erfassungsfilter die IAMDroppedFrames-Schnittstelle verfügbar machen, während die Ausgabepins des Filters die IAMStreamConfig-Schnittstelle verfügbar machen können.

Die einfachste Möglichkeit, eine Schnittstelle zu finden, besteht darin, die ICaptureGraphBuilder2::FindInterface-Methode zu verwenden. Diese Methode führt das Diagramm durch (Filter und Pins), bis die gewünschte Schnittstelle gefunden wird. Sie können den Startpunkt für die Suche angeben, und Sie können die Suche auf Filter beschränken, die Upstream oder nach dem Startpunkt nachgeschaltet werden.

Im folgenden Beispiel wird die IAMStreamConfig-Schnittstelle auf einer Videovorschau-Pin gesucht:

IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
    &PIN_CATEGORY_PREVIEW, 
    &MEDIATYPE_Video,
    pVCap, 
    IID_IAMStreamConfig, 
    (void**)&pConfig
);
if (SUCCESSFUL(hr))
{
    /* ... */
    pConfig->Release();
}

Hinweis

Das Thema Suchen einer Schnittstelle in einem Filter oder Pin zeigt einen alternativen Ansatz, der die IGraphBuilder-Schnittstelle anstelle von ICaptureGraphBuilder2 verwendet. Welcher Ansatz verwendet werden soll, hängt von Ihrer Anwendung ab. Wenn Ihre Anwendung bereits ICaptureGraphBuilder2 zum Erstellen des Graphen verwendet, ist ICaptureGraphBuilder2::FindInterface ein guter Ansatz. Andernfalls sollten Sie die IGraphBuilder-Methoden verwenden.

 

Suchen nach Pins

Seltener müssen Sie möglicherweise eine einzelne Pin in einem Filter suchen, obwohl in den meisten Fällen die Methoden RenderStream und FindInterface Ihnen die Probleme ersparen. Wenn Sie eine bestimmte Pin in einem Filter finden müssen, ist die ICaptureGraphBuilder2::FindPin-Hilfsmethode nützlich. Geben Sie die Kategorie, den Medientyp (Video oder Audio), die Richtung und an, ob die Verbindung aufgehoben werden muss.

Der folgende Code sucht beispielsweise nach einer nicht verbundenen Videovorschau-Pin für einen Erfassungsfilter:

IPin *pPin = NULL;
hr = pBuild->FindPin(
    pCap,                   // Pointer to the filter to search.
    PINDIR_OUTPUT,          // Search for an output pin.
    &PIN_CATEGORY_PREVIEW,  // Search for a preview pin.
    &MEDIATYPE_Video,       // Search for a video pin.
    TRUE,                   // The pin must be unconnected. 
    0,                      // Return the first matching pin (index 0).
    &pPin);                 // This variable receives the IPin pointer.
if (SUCCESSFUL(hr))
{
    /* ... */
    pPin->Release();
}

Videoaufnahme