Поделиться через


Выбор устройства записи

[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменён MediaPlayer, IMFMediaEngineи захватом аудио/видео в системе Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый программный код MediaPlayer, IMFMediaEngine и Аудио/Видео захват в Media Foundation вместо DirectShow, если это возможно. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]

Чтобы выбрать устройство захвата аудио или видео, используйте системный перечислитель устройств , который описан в разделе Использование системного перечислителя устройств. Перечислитель системных устройств возвращает коллекцию моникеров устройств, выбранных по категориям устройств. моникер — это COM-объект, содержащий информацию о другом объекте. Моникеры позволяют приложению получать сведения об объекте без фактического создания объекта. Позже приложение может использовать псевдоним для создания объекта. Дополнительную информацию о моникерах вы можете найти в документации по IMoniker.

Чтобы использовать перечислитель системных устройств, выполните следующие действия.

  1. Вызовите CoCreateInstance, чтобы создать экземпляр перечислителя системных устройств.

  2. Вызовите ICreateDevEnum::CreateClassEnumerator и укажите категорию устройства в качестве GUID. Для устройств записи относятся следующие категории.

    GUID категории Описание
    CLSID_КатегорияУстройствАудиовхода Устройства записи звука
    CLSID_VideoInputDeviceCategory Устройства записи видео

     

    Если видеокамер имеет встроенный микрофон, он отображается в обеих категориях. Однако камера и микрофон рассматриваются как отдельные устройства системой для перечисления, создания устройства и потоковой передачи данных.

  3. МетодCreateClassEnumeratorвозвращает указатель на интерфейс IEnumMoniker. Чтобы перечислить моникеры, вызовите IEnumMoniker::Next.

Следующий код создает перечислитель для указанной категории устройств.

#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;
}

Интерфейс IEnumMoniker перечисляет список интерфейсов IMoniker, каждый из которых представляет моникер устройства. Приложение может считывать свойства из моникера или использовать моникер для создания фильтра записи DirectShow для данного устройства. Свойства Moniker возвращаются как значения VARIANT. Следующие свойства поддерживаются идентификаторами устройств.

Свойство Описание Тип VARIANT
Отображаемое имя Имя устройства. VT_BSTR
"Описание" Описание устройства. VT_BSTR
Путь устройства Уникальная строка, определяющая устройство. (Только устройства записи видео.) VT_BSTR
"WaveInID" Идентификатор устройства записи звука. (Только устройства записи звука.) VT_I4

 

Свойства "FriendlyName" и "Description" подходят для отображения в пользовательском интерфейсе.

  • Свойство "FriendlyName" доступно для каждого устройства. Он содержит понятное для пользователя имя устройства.
  • Свойство Description доступно только для устройств DV и D-VHS/MPEG camcorder. Дополнительные сведения см. в драйвере MSDV и драйвере MSTape. Если оно доступно, оно содержит описание устройства, которое является более конкретным, чем свойство "FriendlyName". Как правило, он содержит имя поставщика.
  • Свойство DevicePath не является удобочитаемой для человека строкой, но гарантированно будет уникальным для каждого устройства записи видео в системе. Это свойство можно использовать для различения двух или нескольких экземпляров одной модели устройства.
  • Если свойство WaveInID присутствует, это означает, что фильтр захвата DirectShow использует API Waveform Audio для взаимодействия с устройством. Значение свойства WaveInID соответствует идентификатору, используемому функциями waveIn*, например waveInOpen.

Чтобы считывать свойства из моникера, выполните следующие действия.

  1. Вызовите IMoniker::BindToStorage, чтобы получить указатель на интерфейс IPropertyBag.
  2. Необходимо вызвать IPropertyBag::Read для чтения свойства.

В следующем примере кода показано, как перечислить список моникеров устройств и получить свойства.

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

Чтобы создать фильтр записи DirectShow для устройства, вызовите метод IMoniker::BindToObject, чтобы получить указатель IBaseFilter. Затем вызовите IFilterGraph::AddFilter, чтобы добавить фильтр в граф фильтров:

IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
    hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
}

захват звука

создание видео