Partilhar via


Usando a Enumeração de Dispositivos do Sistema

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize 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.]

O System Device Enumerator fornece uma maneira uniforme de enumerar, por categoria, os filtros registrados no sistema de um usuário. Além disso, diferencia entre dispositivos de hardware individuais, mesmo que o mesmo filtro os suporte. Isso é particularmente útil para dispositivos que usam o WDM (Windows Driver Model) e o filtro KSProxy. Por exemplo, o usuário pode ter vários dispositivos de captura de vídeo WDM, todos suportados pelo mesmo filtro. O System Device Enumerator trata-os como instâncias de dispositivo separadas.

O System Device Enumerator 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 apelido 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 System Device Enumerator, faça o seguinte:

  1. Crie o enumerador de dispositivo do sistema chamando CoCreateInstance. O identificador de classe (CLSID) é 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 desreferenciá-lo causará uma exceção. Portanto, teste explicitamente para S_OK quando o chamar CreateClassEnumerator, em vez de chamar a macro usual SUCCEEDED.
  3. Use o método IEnumMoniker::Next para enumerar cada moniker. Esse método retorna um ponteiro para a interface IMoniker. Quando o método Next atinge o final da enumeração, ele também retorna S_FALSE, portanto, verifique novamente se há S_OK.
  4. Para recuperar o nome amigável do dispositivo (por exemplo, para exibir na interface do usuário), chame o IMoniker::BindToStorage método.
  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 gráfico.

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 maior brevidade, o exemplo executa uma verificação de erro mínima.

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

Identificadores de Dispositivos

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

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

O método IMoniker::ParseDisplayName ou a função MkParseDisplayName pode ser usado para criar um moniker de dispositivo padrão para uma determinada categoria de filtro. Utilize um nome de exibição no formato @device:*:{category-clsid}, onde category-clsid é a sequência que representa o GUID da categoria. O moniker padrão é o primeiro moniker retornado pelo enumerador de dispositivo para essa categoria.