Share via


Compilazione di grafici con Capture Graph Builder

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Nonostante il nome, Capture Graph Builder è utile per la creazione di molti tipi di grafici di filtro personalizzati, non solo per acquisire grafici. Questo articolo fornisce una breve panoramica di come usare questo oggetto.

Capture Graph Builder espone l'interfaccia ICaptureGraphBuilder2 . Per iniziare , chiamare CoCreateInstance per creare Capture Graph Builder e Filter Graph Manager. Inizializzare quindi Capture Graph Builder chiamando ICaptureGraphBuilder2::SetFiltergraph con un puntatore a Filter Graph Manager, come indicato di seguito:

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);
    }
};

Connessione di filtri

Il metodo ICaptureGraphBuilder2::RenderStream connette due o tre filtri insieme in una catena. In genere, il metodo funziona meglio quando ogni filtro non ha più di un pin di input o un pin di output dello stesso tipo. Questa discussione inizia ignorando i primi due parametri di RenderStream e concentrandosi sugli ultimi tre parametri. Il terzo parametro è un puntatore IUnknown , che può specificare un filtro (come puntatore all'interfaccia IBaseFilter ) o un pin di output (come puntatore all'interfaccia IPin ). I parametri quarto e quinto specificano i puntatori IBaseFilter . Il metodo RenderStream connette tutti e tre i filtri in una catena. Si supponga, ad esempio, che A, B e C siano filtri. Si supponga ora che ogni filtro abbia esattamente un pin di input e un pin di output. La chiamata seguente connette A a B e quindi B a C:

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

Tutte le connessioni sono "intelligenti", ovvero vengono aggiunti altri filtri al grafico in base alle esigenze. Per informazioni dettagliate, vedere Intelligent Connect. Per connettere solo due filtri, impostare il valore intermedio su NULL. Ad esempio, questa chiamata connette A a C:

'RenderStream(NULL, NULL, A, NULL, C)'

È possibile creare catene più lunghe chiamando il metodo due volte:

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

Se l'ultimo parametro è NULL, il metodo individua automaticamente un renderer predefinito. Usa il Renderer video per video e DirectSound Renderer per l'audio. Così:

'RenderStream(NULL, NULL, A, NULL, NULL)'

equivale a

'RenderStream(NULL, NULL, A, NULL, R)'

dove R è il renderer appropriato. Per connettere il filtro Renderer di combinazione video anziché il renderer video, è tuttavia necessario specificarlo in modo esplicito.

Se si specifica un filtro nel terzo parametro, anziché un pin, potrebbe essere necessario indicare quale pin di output deve essere usato per la connessione. Questo è lo scopo dei primi due parametri del metodo. Il primo parametro si applica solo ai filtri di acquisizione. Specifica un GUID che indica una categoria di pin. Per un elenco completo delle categorie, vedere Pin Property Set.For a complete list of categories, see Pin Property Set. Due delle categorie sono valide per tutti i filtri di acquisizione:

  • PIN_CATEGORY_CAPTURE
  • PIN_CATEGORY_PREVIEW

Se un filtro di acquisizione non fornisce pin separati per l'acquisizione e l'anteprima, il metodo RenderStreaminserisce un filtro Tee intelligente , che suddivide il flusso in un flusso di acquisizione e in un flusso di anteprima. Dal punto di vista dell'applicazione, è sufficiente considerare tutti i filtri di acquisizione come con pin separati e ignorare la topologia sottostante del grafico.

Per l'acquisizione di file, connettere il pin di acquisizione a un filtro mux. Per l'anteprima live, connettere il pin di anteprima a un renderer. Se si cambiano le due categorie, il grafico potrebbe eliminare un numero eccessivo di fotogrammi durante l'acquisizione del file; ma se il grafico è connesso correttamente, elimina i fotogrammi di anteprima in base alle esigenze per mantenere la velocità effettiva nel flusso di acquisizione.

L'esempio seguente illustra come connettere entrambi i flussi:

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

Alcuni filtri di acquisizione supportano anche sottotitoli chiusi, indicati da PIN_CATEGORY_VBI. Per acquisire le didascalie chiuse in un file, eseguire il rendering di questa categoria nel filtro mux. Per visualizzare i sottotitoli chiusi nella finestra di anteprima, connettersi al renderer:

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

Il secondo parametro di RenderStream identifica il tipo di supporto ed è in genere uno dei seguenti:

  • MEDIATYPE_Audio
  • MEDIATYPE_Video
  • MEDIATYPE_Interleaved (DV)

È possibile usare questo parametro ogni volta che i pin di output del filtro supportano l'enumerazione dei tipi di supporti preferiti. Per le origini file, Capture Graph Builder aggiunge automaticamente un filtro parser, se necessario, e quindi esegue query sui tipi di supporti nel parser. Per un esempio, vedere Recompressing an AVI File(Ricomprimere un file AVI). Inoltre, se l'ultimo filtro nella catena ha diversi pin di input, il metodo tenta di enumerare i relativi tipi di supporti. Tuttavia, non tutti i filtri supportano questa funzionalità.

Ricerca di interfacce su filtri e pin

Dopo aver creato un grafico, in genere sarà necessario individuare varie interfacce esposte da filtri e puntini nel grafico. Ad esempio, un filtro di acquisizione potrebbe esporre l'interfaccia IAMDroppedFrames , mentre i pin di output del filtro potrebbero esporre l'interfaccia IAMStreamConfig .

Il modo più semplice per trovare un'interfaccia consiste nell'usare il metodo ICaptureGraphBuilder2::FindInterface . Questo metodo illustra il grafico (filtri e puntini) finché non individua l'interfaccia desiderata. È possibile specificare il punto iniziale per la ricerca ed è possibile limitare la ricerca ai filtri upstream o downstream dal punto iniziale.

L'esempio seguente cerca l'interfaccia IAMStreamConfig in un pin di anteprima video:

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

Nota

L'argomento Trova un'interfaccia in un filtro o un pin mostra un approccio alternativo che usa l'interfaccia IGraphBuilder anziché ICaptureGraphBuilder2. L'approccio da usare dipende dall'applicazione. Se l'applicazione usa già ICaptureGraphBuilder2 per compilare il grafo, ICaptureGraphBuilder2::FindInterface è un buon approccio. In caso contrario, prendere in considerazione l'uso dei metodi IGraphBuilder .

 

Ricerca di pin

Meno comunemente, potrebbe essere necessario individuare un singolo pin in un filtro, anche se nella maggior parte dei casi i metodi RenderStream e FindInterface salveranno i problemi. Se è necessario trovare un pin specifico in un filtro, il metodo helper ICaptureGraphBuilder2::FindPin è utile. Specificare la categoria, il tipo di supporto (video o audio), la direzione e se il pin deve essere non connesso.

Ad esempio, il codice seguente cerca un pin di anteprima video non connesso in un filtro di acquisizione:

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();
}

Acquisizione video