Usando o Enumerador de Dispositivo do Sistema

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in 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 Audio/Video Capture in 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.]

O Enumerador de Dispositivo do Sistema fornece uma maneira uniforme de enumerar, por categoria, os filtros registrados no sistema de um usuário. Além disso, ele diferencia entre dispositivos de hardware individuais, mesmo que o mesmo filtro dê suporte a eles. Isso é particularmente útil para dispositivos que usam o WDM (Modelo de Driver do Windows) e o filtro KSProxy. Por exemplo, o usuário pode ter vários dispositivos de captura de vídeo WDM, todos compatíveis com o mesmo filtro. O Enumerador de Dispositivo do Sistema os trata como instâncias de dispositivo separadas.

O Enumerador de Dispositivo do Sistema funciona criando um enumerador para uma categoria específica, como captura de áudio ou compactação de vídeo. O enumerador de categoria retorna um moniker exclusivo para cada dispositivo na categoria. O enumerador de categoria inclui automaticamente todos os dispositivos Plug and Play relevantes na categoria. Para obter uma lista de categorias, consulte Categorias de filtro.

Para usar o Enumerador de Dispositivo do Sistema, faça o seguinte:

  1. Crie o enumerador de dispositivo do sistema chamando CoCreateInstance. O CLSID (identificador de classe) é CLSID_SystemDeviceEnum.
  2. Obtenha um enumerador de categoria chamando ICreateDevEnum::CreateClassEnumerator com o CLSID da categoria desejada. Esse método retorna um ponteiro de interface IEnumMoniker . Se a categoria estiver vazia (ou não existir), o método retornará S_FALSE em vez de um código de erro. Nesse caso, o ponteiro IEnumMoniker retornado é NULL e desreferenciar isso causará uma exceção. Portanto, teste explicitamente para S_OK ao chamar CreateClassEnumerator, em vez de chamar a macro SUCCEEDED usual.
  3. Use o método IEnumMoniker::Next para enumerar cada moniker. Esse método retorna um ponteiro de interface IMoniker . Quando o método Next atinge o final da enumeração, ele também retorna S_FALSE, portanto, novamente marcar para S_OK.
  4. Para recuperar o nome amigável do dispositivo (por exemplo, para exibir na interface do usuário), chame o método IMoniker::BindToStorage .
  5. Para criar e inicializar o filtro DirectShow que gerencia o dispositivo, chame IMoniker::BindToObject no moniker. Chame IFilterGraph::AddFilter para adicionar o filtro ao grafo.

O diagrama a seguir ilustra esse processo.

enumerando dispositivos

O exemplo a seguir mostra como enumerar os compressores de vídeo instalados no sistema do usuário. Para fins de brevidade, o exemplo executa a verificação mínima de erros.

// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
    return hr;
}

// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

if (hr == S_OK) 
{
    // Enumerate the monikers.
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // Display the name in your UI somehow.
            }
            VariantClear(&varName);

            // To create an instance of the filter, do the following:
            IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
                (void**)&pFilter);
            // Now add the filter to the graph. 
            //Remember to release pFilter later.
            pPropBag->Release();
        }
        pMoniker->Release();
    }
    pEnumCat->Release();
}
pSysDevEnum->Release();

Monikers de dispositivo

Para monikers de dispositivo, você pode passar o moniker para o método IFilterGraph2::AddSourceFilterForMoniker para criar um filtro de captura para o dispositivo. Para obter um código de exemplo, consulte a documentação desse método.

O método IMoniker::GetDisplayName retorna o nome de exibição do moniker. Embora o nome de exibição seja legível, você normalmente não o exibiria para um usuário final. Obtenha o nome amigável do recipiente de propriedades, conforme descrito anteriormente.

O método IMoniker::P arseDisplayName ou a função MkParseDisplayName pode ser usado para criar um moniker de dispositivo padrão para uma determinada categoria de filtro. Use um nome de exibição com o formulário @device:*:{category-clsid}, em que category-clsid é a representação de cadeia de caracteres do GUID da categoria. O moniker padrão é o primeiro moniker retornado pelo enumerador de dispositivo para essa categoria.