Selezione di un dispositivo di acquisizione

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

Per selezionare un dispositivo di acquisizione audio o video, usare l'enumeratore del dispositivo di sistema, descritto nell'argomento Uso dell'enumeratore del dispositivo di sistema. L'enumeratore di dispositivi di sistema restituisce una raccolta di moniker del dispositivo, selezionata per categoria di dispositivi. Un moniker è un oggetto COM che contiene informazioni su un altro oggetto . I moniker consentono all'applicazione di ottenere informazioni su un oggetto senza creare effettivamente l'oggetto. Successivamente, l'applicazione può usare il moniker per creare l'oggetto. Per altre informazioni sui moniker, vedere la documentazione per IMoniker.

Per usare l'enumeratore di dispositivi di sistema, seguire questa procedura.

  1. Chiamare CoCreateInstance per creare un'istanza dell'enumeratore del dispositivo di sistema.

  2. Chiamare ICreateDevEnum::CreateClassEnumerator e specificare la categoria di dispositivi come GUID. Per i dispositivi di acquisizione, le categorie seguenti sono rilevanti.

    GUID categoria Descrizione
    CLSID_AudioInputDeviceCategory Dispositivi di acquisizione audio
    CLSID_VideoInputDeviceCategory Dispositivi di acquisizione video

     

    Se una videocamera ha un microfono integrato, viene visualizzato in entrambe le categorie. Tuttavia, la fotocamera e il microfono vengono considerati come dispositivi separati dal sistema, ai fini dell'enumerazione, della creazione del dispositivo e dello streaming dei dati.

  3. Il metodo CreateClassEnumeratorrestituisce un puntatore all'interfaccia IEnumMoniker . Per enumerare i moniker, chiamare IEnumMoniker::Next.

Il codice seguente crea un enumeratore per una categoria di dispositivi specificata.

#include <windows.h>
#include <dshow.h>

#pragma comment(lib, "strmiids")

HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
    // Create the System Device Enumerator.
    ICreateDevEnum *pDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,  
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

    if (SUCCEEDED(hr))
    {
        // Create an enumerator for the category.
        hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
        if (hr == S_FALSE)
        {
            hr = VFW_E_NOT_FOUND;  // The category is empty. Treat as an error.
        }
        pDevEnum->Release();
    }
    return hr;
}

L'interfaccia IEnumMoniker enumera un elenco di interfacce IMoniker , ognuna delle quali rappresenta un moniker del dispositivo. L'applicazione può leggere le proprietà dal moniker o usare il moniker per creare un filtro di acquisizione DirectShow per il dispositivo. Le proprietà del moniker vengono restituite come valori VARIANT . Le proprietà seguenti sono supportate dai moniker del dispositivo.

Proprietà Descrizione Tipo VARIANT
"FriendlyName" Nome del dispositivo. VT_BSTR
"Descrizione" Descrizione del modello. VT_BSTR
"DevicePath" Stringa univoca che identifica il dispositivo. (Solo dispositivi di acquisizione video). VT_BSTR
"WaveInID" Identificatore per un dispositivo di acquisizione audio. (Solo dispositivi di acquisizione audio). VT_I4

 

Le proprietà "FriendlyName" e "Description" sono adatte per la visualizzazione in un'interfaccia utente.

  • La proprietà "FriendlyName" è disponibile per ogni dispositivo. Contiene un nome leggibile per il dispositivo.
  • La proprietà "Description" è disponibile solo per i dispositivi DV e D-VHS/MPEG. Per altre informazioni, vedere Driver MSDV e driver MSTape. Se disponibile, contiene una descrizione del dispositivo più specifica della proprietà "FriendlyName". In genere include il nome del fornitore.
  • La proprietà "DevicePath" non è una stringa leggibile, ma è garantito che sia univoca per ogni dispositivo di acquisizione video nel sistema. È possibile usare questa proprietà per distinguere tra due o più istanze dello stesso modello di dispositivo.
  • Se la proprietà "WaveInID" è presente, significa che il filtro di acquisizione DirectShow usa le API Audio Waveform internamente per comunicare con il dispositivo. Il valore della proprietà "WaveInID" corrisponde all'identificatore usato dalle funzioni waveIn* , ad esempio waveInOpen.

Per leggere le proprietà dal moniker, seguire questa procedura.

  1. Chiama IMoniker::BindToStorage per ottenere un puntatore all'interfaccia IPropertyBag .
  2. Chiamare IPropertyBag::Read per leggere la proprietà.

Nell'esempio di codice seguente viene illustrato come enumerare un elenco di moniker del dispositivo e ottenere le proprietà.

void DisplayDeviceInformation(IEnumMoniker *pEnum)
{
    IMoniker *pMoniker = NULL;

    while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
    {
        IPropertyBag *pPropBag;
        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
        if (FAILED(hr))
        {
            pMoniker->Release();
            continue;  
        } 

        VARIANT var;
        VariantInit(&var);

        // Get description or friendly name.
        hr = pPropBag->Read(L"Description", &var, 0);
        if (FAILED(hr))
        {
            hr = pPropBag->Read(L"FriendlyName", &var, 0);
        }
        if (SUCCEEDED(hr))
        {
            printf("%S\n", var.bstrVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Write(L"FriendlyName", &var);

        // WaveInID applies only to audio capture devices.
        hr = pPropBag->Read(L"WaveInID", &var, 0);
        if (SUCCEEDED(hr))
        {
            printf("WaveIn ID: %d\n", var.lVal);
            VariantClear(&var); 
        }

        hr = pPropBag->Read(L"DevicePath", &var, 0);
        if (SUCCEEDED(hr))
        {
            // The device path is not intended for display.
            printf("Device path: %S\n", var.bstrVal);
            VariantClear(&var); 
        }

        pPropBag->Release();
        pMoniker->Release();
    }
}

void main()
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (SUCCEEDED(hr))
    {
        IEnumMoniker *pEnum;

        hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
        if (SUCCEEDED(hr))
        {
            DisplayDeviceInformation(pEnum);
            pEnum->Release();
        }
        hr = EnumerateDevices(CLSID_AudioInputDeviceCategory, &pEnum);
        if (SUCCEEDED(hr))
        {
            DisplayDeviceInformation(pEnum);
            pEnum->Release();
        }
        CoUninitialize();
    }
}

Per creare un filtro di acquisizione DirectShow per il dispositivo, chiamare il metodo IMoniker::BindToObject per ottenere un puntatore IBaseFilter . Chiamare quindi IFilterGraph::AddFilter per aggiungere il filtro al grafico del filtro:

IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
    hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
}

Acquisizione audio

Acquisizione video