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.
Chame CoCreateInstance para criar uma instância do Enumerador de Dispositivo do Sistema.
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.
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.
- Chame IMoniker::BindToStorage para obter um ponteiro para a interface IPropertyBag .
- 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");
}
Tópicos relacionados