Compartilhar via


Selecionando um dispositivo de captura

[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]

Para selecionar um dispositivo de captura de áudio ou vídeo, use o Enumerador de Dispositivo do Sistema, descrito no tópico Usando o Enumerador de Dispositivo do Sistema. O Enumerador de Dispositivo do Sistema retorna uma coleção de monikers de dispositivo, selecionados por categoria de dispositivo. Um moniker é um objeto COM que contém informações sobre outro objeto. Os monikers permitem que o aplicativo obtenha informações sobre um objeto sem realmente criar o objeto. Posteriormente, o aplicativo pode usar o moniker para criar o objeto. Para obter mais informações sobre monikers, consulte a documentação do IMoniker.

Para usar o Enumerador de Dispositivo do Sistema, execute as etapas a seguir.

  1. Chame CoCreateInstance para criar uma instância do Enumerador de Dispositivo do Sistema.

  2. Chame ICreateDevEnum::CreateClassEnumerator e especifique a categoria do dispositivo como UM GUID. Para dispositivos de captura, as categorias a seguir são relevantes.

    GUID de categoria Descrição
    CLSID_AudioInputDeviceCategory Dispositivos de captura de áudio
    CLSID_VideoInputDeviceCategory Dispositivos de captura de vídeo

     

    Se uma câmera de vídeo tiver um microfone integrado, ela aparecerá em ambas as categorias. No entanto, a câmera e o microfone são tratados como dispositivos separados pelo sistema, para fins de enumeração, criação de dispositivo e streaming de dados.

  3. O método CreateClassEnumerator retorna um ponteiro para a interface IEnumMoniker . Para enumerar os monikers, chame IEnumMoniker::Next.

O código a seguir cria um enumerador para uma categoria de dispositivo especificada.

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

A interface IEnumMoniker enumera uma lista de interfaces IMoniker , cada uma delas representando um moniker de dispositivo. O aplicativo pode ler propriedades do moniker ou usar o moniker para criar um filtro de captura do DirectShow para o dispositivo. As propriedades moniker são retornadas como valores VARIANT . As propriedades a seguir são compatíveis com monikers de dispositivo.

Propriedade Descrição Tipo de VARIANTE
"FriendlyName" O nome do dispositivo. VT_BSTR
"Descrição" Uma descrição do dispositivo. VT_BSTR
"DevicePath" Uma cadeia de caracteres exclusiva que identifica o dispositivo. (Somente dispositivos de captura de vídeo.) VT_BSTR
"WaveInID" O identificador de um dispositivo de captura de áudio. (Somente dispositivos de captura de áudio.) VT_I4

 

As propriedades "FriendlyName" e "Description" são adequadas para exibição em uma interface do usuário.

  • A propriedade "FriendlyName" está disponível para cada dispositivo. Ele contém um nome legível para o dispositivo.
  • A propriedade "Description" está disponível apenas para dispositivos de filmador DV e D-VHS/MPEG. Para obter mais informações, consulte Driver MSDV e Driver MSTape. Se disponível, ele contém uma descrição do dispositivo que é mais específica do que a propriedade "FriendlyName". Normalmente, ele inclui o nome do fornecedor.
  • A propriedade "DevicePath" não é uma cadeia de caracteres legível por humanos, mas tem a garantia de ser exclusiva para cada dispositivo de captura de vídeo no sistema. Você pode usar essa propriedade para distinguir entre duas ou mais instâncias do mesmo modelo de dispositivo.
  • Se a propriedade "WaveInID" estiver presente, isso significa que o filtro de captura directShow usa as APIs de áudio Waveform internamente para se comunicar com o dispositivo. O valor da propriedade "WaveInID" corresponde ao identificador usado pelas funções waveIn* , como waveInOpen.

Para ler as propriedades do moniker, execute as etapas a seguir.

  1. Chame IMoniker::BindToStorage para obter um ponteiro para a interface IPropertyBag .
  2. Chame IPropertyBag::Read para ler a propriedade.

O exemplo de código a seguir mostra como enumerar uma lista de monikers de dispositivo e obter as propriedades.

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

Para criar um filtro de captura do DirectShow para o dispositivo, chame o método IMoniker::BindToObject para obter um ponteiro IBaseFilter . Em seguida, chame IFilterGraph::AddFilter para adicionar o filtro ao grafo de filtro:

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

Captura de áudio

Captura de vídeo