Compartir a través de


Selección de un dispositivo de captura

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Para seleccionar un dispositivo de captura de audio o vídeo, use el enumerador de dispositivos del sistema, descrito en el tema Uso del enumerador de dispositivos del sistema. El enumerador de dispositivos del sistema devuelve una colección de monikers de dispositivo, seleccionados por categoría de dispositivo. Un moniker es un objeto COM que contiene información sobre otro objeto. Monikers permite a la aplicación obtener información sobre un objeto sin crear realmente el objeto. Más adelante, la aplicación puede usar el moniker para crear el objeto . Para obtener más información sobre monikers, consulte la documentación de IMoniker.

Para usar el enumerador de dispositivos del sistema, realice los pasos siguientes.

  1. Llame a CoCreateInstance para crear una instancia del enumerador de dispositivos del sistema.

  2. Llame a ICreateDevEnum::CreateClassEnumerator y especifique la categoría de dispositivo como GUID. En el caso de los dispositivos de captura, las siguientes categorías son relevantes.

    GUID de categoría Descripción
    CLSID_AudioInputDeviceCategory Dispositivos de captura de audio
    CLSID_VideoInputDeviceCategory Dispositivos de captura de vídeo

     

    Si una cámara de vídeo tiene un micrófono integrado, aparece en ambas categorías. Sin embargo, el sistema trata la cámara y el micrófono como dispositivos independientes con fines de enumeración, creación de dispositivos y streaming de datos.

  3. El método CreateClassEnumerator devuelve un puntero a la interfaz IEnumMoniker . Para enumerar los monikers, llame a IEnumMoniker::Next.

El código siguiente crea un enumerador para una categoría 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;
}

La interfaz IEnumMoniker enumera una lista de interfaces IMoniker , cada una de las cuales representa un moniker de dispositivo. La aplicación puede leer las propiedades del moniker o usar el moniker para crear un filtro de captura de DirectShow para el dispositivo. Las propiedades de Moniker se devuelven como valores VARIANT . Las siguientes propiedades son compatibles con monikers de dispositivo.

Propiedad Descripción Tipo de VARIANTE
"FriendlyName" Nombre del dispositivo. VT_BSTR
"Descripción" Una descripción del dispositivo. VT_BSTR
"DevicePath" Cadena única que identifica el dispositivo. (Solo dispositivos de captura de vídeo). VT_BSTR
"WaveInID" Identificador de un dispositivo de captura de audio. (Solo dispositivos de captura de audio). VT_I4

 

Las propiedades "FriendlyName" y "Description" son adecuadas para mostrarse en una interfaz de usuario.

  • La propiedad "FriendlyName" está disponible para cada dispositivo. Contiene un nombre legible para el dispositivo.
  • La propiedad "Description" solo está disponible para dispositivos DV y D-VHS/MPEG. Para obtener más información, consulte MsDV Driver y MSTape Driver. Si está disponible, contiene una descripción del dispositivo que es más específico que la propiedad "FriendlyName". Normalmente, incluye el nombre del proveedor.
  • La propiedad "DevicePath" no es una cadena legible, pero se garantiza que es única para cada dispositivo de captura de vídeo del sistema. Puede usar esta propiedad para distinguir entre dos o más instancias del mismo modelo de dispositivo.
  • Si la propiedad "WaveInID" está presente, significa que el filtro de captura directShow usa internamente las API de audio waveform para comunicarse con el dispositivo. El valor de la propiedad "WaveInID" corresponde al identificador utilizado por las funciones waveIn* , como waveInOpen.

Para leer las propiedades del moniker, realice los pasos siguientes.

  1. Llame a IMoniker::BindToStorage para obtener un puntero a la interfaz IPropertyBag .
  2. Llame a IPropertyBag::Read para leer la propiedad.

En el ejemplo de código siguiente se muestra cómo enumerar una lista de monikers de dispositivo y obtener las propiedades.

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 crear un filtro de captura de DirectShow para el dispositivo, llame al método IMoniker::BindToObject para obtener un puntero IBaseFilter . A continuación, llame a IFilterGraph::AddFilter para agregar el filtro al gráfico de filtros:

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 audio

Captura de vídeo