DirectShow 对系统中不可预知性硬件提供了良好的支持,其方法是使用系统枚举,系统枚举的一般过程如下所示:
(1)使用CoCreateInstance函数创建系统枚举器组建对象(CLSID为CLSID_SystemDeviceEnum),并获得ICreateDevEnum接口;
(2)使用接口方法ICreateDevEnum::CreateClassEnumerator为指定的Filter注册类型目录创建一个枚举器,并获得IEnumMoniker接口;
(3)使用IEnumMoniker接口方法枚举指定类型目录下所有设备标识(DeviceMoniker);
(4)调用IMoniker::BindTOStorage之后,可以访问设备标识的属性集,比如得到Display Name、Friendly Name等;
(5)调用IMoniker::BindToObject可以将设备标识生成一个DirectShow Filter,随后调用IFilterGraph::AddFilter,并将之加入到FilterGraph中就可以参与工作了。
下面是这个过程的代码:
//创建一个系统枚举组建 HRESULT hr; ICreateDevEnum* pSysDevEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pSysDevEnum); if(FAILED(hr)) { return hr; } // 指定枚举的类型目录,获得IEnumMoniker接口 IEnumMoniker* pEnumCat = NULL; hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); if(hr == S_OK) { // 使用IEnumMoniker接口枚举所有的设备标识 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)) { // get Friendly Name of Filter VARIANT varName; VariantInit(&varName); hr = pPropBag->Read(L"FriendlyName", &varName, 0); if(SUCCEEDED(hr)) { // Display the name in your UI somehow } VariantClear(&varName); // Create Filter instance 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();