システム デバイス列挙子の使用

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

システム デバイス列挙子は、ユーザーのシステムに登録されているフィルターをカテゴリ別に一様に列挙する方法を提供します。 さらに、同じフィルターでサポートされている場合でも、個々のハードウェア デバイスを区別します。 これは、Windows ドライバー モデル (WDM) と KSProxy フィルターを使用するデバイスに特に役立ちます。 たとえば、ユーザーは複数の WDM ビデオ キャプチャ デバイスを持ち、すべて同じフィルターでサポートされている場合があります。 システム デバイス列挙子は、それらを個別のデバイス インスタンスとして扱います。

システム デバイス列挙子は、オーディオ キャプチャやビデオ圧縮など、特定のカテゴリの列挙子を作成することによって機能します。 カテゴリ列挙子は、カテゴリ内の各デバイスに対して一意のモニカーを返します。 カテゴリ列挙子には、カテゴリ内の関連するプラグ アンド プレイ デバイスが自動的に含まれます。 カテゴリの一覧については、「 カテゴリのフィルター処理」を参照してください。

システム デバイス列挙子を使用するには、次の操作を行います。

  1. CoCreateInstance を呼び出して、システム デバイス列挙子を作成します。 クラス識別子 (CLSID) がCLSID_SystemDeviceEnum。
  2. 目的のカテゴリの CLSID を使用して ICreateDevEnum::CreateClassEnumerator を呼び出して、カテゴリ列挙子を取得します。 このメソッドは、 IEnumMoniker インターフェイス ポインターを返します。 カテゴリが空の場合 (または存在しない場合)、メソッドはエラー コードではなくS_FALSEを返します。 その場合、返された IEnumMoniker ポインターは NULL であり、逆参照すると例外が発生します。 したがって、通常の SUCCEEDED マクロを呼び出す代わりに、CreateClassEnumerator を呼び出すときに、S_OKを明示的にテストします。
  3. 各モニカーを列挙するには、 IEnumMoniker::Next メソッドを使用します。 このメソッドは 、IMoniker インターフェイス ポインターを返します。 Next メソッドが列挙体の末尾に達すると、S_FALSEも返されるため、S_OKに対してもう一度チェック。
  4. デバイスのフレンドリ名 (ユーザー インターフェイスに表示するなど) を取得するには、 IMoniker::BindToStorage メソッドを呼び出します。
  5. デバイスを管理する DirectShow フィルターを作成して初期化するには、モニカーで IMoniker::BindToObject を呼び出します。 IFilterGraph::AddFilter を呼び出して、グラフにフィルターを追加します。

このプロセスを説明する図を次に示します。

デバイスの列挙

次の例は、ユーザーのシステムにインストールされているビデオ コンプレッサーを列挙する方法を示しています。 簡潔にするために、この例では最小限のエラー チェックを実行します。

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

デバイス モニカー

デバイス モニカーの場合は、モニカーを IFilterGraph2::AddSourceFilterForMoniker メソッドに渡して、デバイスのキャプチャ フィルターを作成できます。 コード例については、そのメソッドのドキュメントを参照してください。

IMoniker::GetDisplayName メソッドはモニカーの表示名を返します。 表示名は読み取り可能ですが、通常はエンドユーザーに表示しません。 前に説明したように、代わりにプロパティ バッグからフレンドリ名を取得します。

IMoniker::P arseDisplayName メソッドまたは MkParseDisplayName 関数を使用して、特定のフィルター カテゴリの既定のデバイス モニカーを作成できます。 という形式 @device:*:{category-clsid}で表示名を使用します。ここで category-clsid 、 はカテゴリ GUID の文字列表現です。 既定のモニカーは、そのカテゴリのデバイス列挙子によって返される最初のモニカーです。