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:
- Crie o enumerador de dispositivo do sistema chamando CoCreateInstance. O identificador de classe (CLSID) é CLSID_SystemDeviceEnum.
- 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.
- 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.
- Para recuperar o nome amigável do dispositivo (por exemplo, para exibir na interface do usuário), chame o IMoniker::BindToStorage método.
- 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.
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.