次の方法で共有


キャプチャ デバイスの選択

[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayerIMFMediaEngineAudio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]

オーディオまたはビデオ キャプチャ デバイスを選択するには、「 システム デバイス列挙子の使用」のトピックで説明されている システム デバイス列挙子を使用します。 システム デバイス列挙子は、デバイス カテゴリで選択されたデバイス モニカーのコレクションを返します。 モニカーは、別のオブジェクトに関する情報を含む COM オブジェクトです。 モニカーを使用すると、アプリケーションはオブジェクトを実際に作成することなく、オブジェクトに関する情報を取得できます。 後で、アプリケーションはモニカーを使用して オブジェクトを作成できます。 モニカーの詳細については、 IMoniker のドキュメントを参照してください。

システム デバイス列挙子を使用するには、次の手順を実行します。

  1. CoCreateInstance を呼び出して、システム デバイス列挙子のインスタンスを作成します。

  2. ICreateDevEnum::CreateClassEnumerator を呼び出し、デバイス カテゴリを GUID として指定します。 キャプチャ デバイスの場合、次のカテゴリが関連します。

    カテゴリ GUID 説明
    CLSID_AudioInputDeviceCategory オーディオ キャプチャ デバイス
    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 キャプチャ フィルターを作成したりできます。 モニカー プロパティは VARIANT 値として返されます。 デバイス モニカーでは、次のプロパティがサポートされています。

プロパティ 説明 バリアント型
"FriendlyName" デバイスの名前。 VT_BSTR
"Description" デバイスの説明。 VT_BSTR
"DevicePath" デバイスを識別する一意の文字列。 (ビデオ キャプチャ デバイスのみ)。 VT_BSTR
"WaveInID" オーディオ キャプチャ デバイスの識別子。 (オーディオ キャプチャ デバイスのみ)。 VT_I4

 

"FriendlyName" プロパティと "Description" プロパティは、UI での表示に適しています。

  • "FriendlyName" プロパティは、すべてのデバイスで使用できます。 これには、デバイスの人間が判読できる名前が含まれています。
  • "Description" プロパティは、DV および D-VHS/MPEG ビデオカメラ デバイスでのみ使用できます。 詳細については、「 MSDV ドライバー 」と「 MSTape ドライバー」を参照してください。 使用可能な場合は、"FriendlyName" プロパティよりも具体的なデバイスの説明が含まれます。 通常、ベンダー名が含まれます。
  • "DevicePath" プロパティは人間が判読できる文字列ではありませんが、システム上のビデオ キャプチャ デバイスごとに一意であることが保証されます。 このプロパティを使用すると、同じデバイス モデルの 2 つ以上のインスタンスを区別できます。
  • "WaveInID" プロパティが存在する場合は、DirectShow キャプチャ フィルターが 波形オーディオ API を内部的に使用してデバイスと通信することを意味します。 "WaveInID" プロパティの値は、 waveInOpen などの waveIn* 関数で使用される識別子 に対応します

モニカーからプロパティを読み取るために、次の手順を実行します。

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

オーディオ キャプチャ

ビデオ キャプチャ