Share via


시스템 디바이스 열거자 사용

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngineMedia Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드에서 DirectShow 대신 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

시스템 디바이스 열거자는 범주별로 사용자 시스템에 등록된 필터를 열거하는 균일한 방법을 제공합니다. 또한 동일한 필터가 지원하는 경우에도 개별 하드웨어 디바이스를 구분합니다. 이는 WDM(Windows 드라이버 모델) 및 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의 문자열 표현입니다. 기본 모니커는 해당 범주에 대한 디바이스 열거자가 반환한 첫 번째 모니커입니다.