Come riprodurre un file
[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente di usare un nuovo codice MediaPlayer, IMFMediaEngine e Acquisizione audio/video in Media Foundation anziché DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.
Questo articolo è progettato per offrire il sapore della programmazione DirectShow. Presenta una semplice applicazione console che riproduce un file audio o video. Il programma è lungo solo poche righe, ma dimostra alcune delle potenzialità della programmazione DirectShow.
Come illustrato nell'articolo Introduzione a DirectShow Application Programming, un'applicazione DirectShow esegue sempre gli stessi passaggi di base:
- Crea un'istanza di Filter Graph Manager.
- Usare Filter Graph Manager per creare un grafico di filtro.
- Esegui il grafico, causando il passaggio dei dati attraverso i filtri.
Per compilare e collegare il codice in questo argomento, includere il file di intestazione Dshow.h e collegarsi al file della libreria statica strmiids.lib. Per altre informazioni, vedere Creazione di applicazioni DirectShow.
Per iniziare, chiamare CoInitialize o CoInitializeEx per inizializzare la libreria COM:
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
// Add error-handling code here. (Omitted for clarity.)
}
Per semplificare le operazioni, in questo esempio viene ignorato il valore restituito, ma è consigliabile controllare sempre il valore HRESULT da qualsiasi chiamata al metodo.
Chiamare quindi CoCreateInstance per creare Filter Graph Manager:
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
Come illustrato, l'identificatore di classe (CLSID) è CLSID_FilterGraph. Filter Graph Manager viene fornito da una DLL in-process, quindi il contesto di esecuzione è CLSCTX_INPROC_SERVER. DirectShow supporta il modello di threading libero, quindi è anche possibile chiamare CoInitializeEx con il flag COINIT_MULTITHREADED.
La chiamata a CoCreateInstance restituisce l'interfacciaIGraphBuilder, che contiene principalmente metodi per la compilazione del grafico del filtro. Per questo esempio sono necessarie altre due interfacce:
- IMediaControl controlla lo streaming. Contiene metodi per arrestare e avviare il grafico.
- IMediaEvent include metodi per ottenere eventi da Filter Graph Manager. In questo esempio, l'interfaccia viene usata per attendere il completamento della riproduzione.
Entrambe queste interfacce vengono esposte da Filter Graph Manager. Usare il puntatore IGraphBuilder restituito per interrogarli:
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
È ora possibile compilare il grafico dei filtri. Per la riproduzione di file, questa operazione viene eseguita da una singola chiamata al metodo:
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
Il metodo IGraphBuilder::RenderFile compila un grafico di filtro in grado di riprodurre il file specificato. Il primo parametro è il nome del file, rappresentato come stringa di caratteri wide (2 byte). Il secondo parametro è riservato e deve essere uguale a NULL.
Questo metodo può non riuscire se il file specificato non esiste o il formato di file non viene riconosciuto. Supponendo che il metodo abbia esito positivo, tuttavia, il grafico del filtro è ora pronto per la riproduzione. Per eseguire il grafo, chiamare il metodo IMediaControl::Run:
hr = pControl->Run();
Quando viene eseguito il grafico del filtro, i dati si spostano attraverso i filtri e vengono visualizzati come video e audio. La riproduzione avviene in un thread separato. È possibile attendere il completamento della riproduzione chiamando il metodo IMediaEvent::WaitForCompletion:
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
Questo metodo si blocca fino a quando il file non viene eseguito o fino a quando non scade l'intervallo di timeout specificato. Il valore INFINITE indica che l'applicazione si blocca a tempo indeterminato fino a quando il file non viene eseguito. Per un esempio più realistico di gestione degli eventi, vedere Rispondere agli eventi.
Al termine dell'applicazione, rilasciare i puntatori all'interfaccia e chiudere la libreria COM:
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
Codice di esempio
Di seguito è riportato il codice completo per l'esempio descritto in questo articolo:
#include <dshow.h>
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
Argomenti correlati