DirectShow 方式列举和捕捉设备接口

列举视频设备:

1、建立系统硬件设备的列表首先,申明一个列表指针,然后通过 CoCreateInstance 建立。CLSID_SystemDeviceEnum是我们想建立对象的类型,IID_ICreateDevEnum是接口的GUID。

 

[cpp] view plain copy

  1. ICreateDevEnum *pCreateDevEnum;  
  2. CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum);  


        CoCreateInstance 函数用来创建一个Com对象:

 

        第一个参数用来创建的Com对象的类标识符(CLSID),CLSID是指windows系统对于不同的应用程序,文件类型,OLE对象,特殊文件夹以及各种系统组件分配一个唯一表示它的ID代码,用于对其身份的标示和与其他对象进行区分。先得说下GUID,它是Globally Unique Identifier的简称,中文翻译为“全局唯一标示符”,在Windows系统中也称之为Class ID,缩写为CLSID。

        第二个参数,如果为NULL,,表明此对象不是聚合式对象一部分。如果不是NULL, 则指针指向一个聚合式对象的IUnknown接口。

        第三个参数,组件类别.,可使用CLSCTX枚举器中预定义的值。

        第四个参数,引用接口标识符,用来与对象通信。

        第五个参数,用来接收指向Com对象接口地址的指针变量。

 

2、其次,建立一个特别类型的硬件设备的列表(例如视频捕捉卡)申明一个IEnumMoniker接口,并把他传给ICreateDevEnum::CreateClassEnumerator 方法。你就可以使用他访问新得到的列表了。

 

[cpp] view plain copy

  1. IEnumMoniker *pEnumMon;  
  2. pCreateDevEnum->CreateClassEnumerator( [specify device GUID here], &pEnumMon, 0);  

 

 

第一个参数,任然是CLSID标识符:

第二个参数,用来接收指向 IEnumMoniker 接口地址的指针变量。

第三个参数,位标识符,若为0,则列举所有的过滤器目录,其他的标识符如下:

 

3、最后,列举列表直到你得到你想要的设备为止。

如果先前的CreateClassEnumerator调用成功了,你可以用IEnumMoniker::Next得到设备。调用IMoniker::BindToObject建立一个和选择的device联合的filter,并且装载filter的属性(CLSID,FriendlyName, and DevicePath)。不需要为if语句的(1 == cFetched) 困惑,在测试合法性之前,pEnumMon->Next(1, &pMon, &cFetched)方法会设置他为返回对象的数字(如果成功了为1)。

 

[cpp] view plain copy

  1. ULONG cFetched = 0;    
  2. IMoniker *pMon ;    
  3.     
  4. if (S_OK == (pEnumMon->Next(1, &pMon, &cFetched))  &&  (1 == cFetched))    
  5. {    
  6.     pMon->BindToObject(0, 0, IID_IBaseFilter, (void **)&[desired interface here]) ;    
  7.     pGraph->AddFilter([desired interface here], L"[filter name here]") ;    
  8.     pMon->Release() ;  // Release moniker    
  9. }    
  10. pEnumMon->Release() ; // Release the class enumerator  
  11. pCreateDevEnum->Release();  

 

 

好,现在你有了一个IMoniker指针,你可以添加设备的filter到filter graph。一旦你添加了filter,你就不需要IMoniker指针,设备列表,或系统设备列表。现在需要实际的设备了,调用IEnumMoniker::Next ,然后用得到的指针pM调用IMoniker::BindToObject,绑定filter到设备。如果你不想建立联合的filter,使用IMoniker::BindToStorage 代替IMoniker::BindToObject。例如以下这段代码是 WebTRC 的视频捕捉模块中的一段(GetDeviceFilter):

 

[cpp] view plain copy

  1. IEnumMoniker* _dsMonikerDevEnum;  
  2. _dsMonikerDevEnum->Reset();  
  3. ULONG cFetched;  
  4. IMoniker *pM;  
  5.   
  6. IBaseFilter *captureFilter = NULL;  
  7. bool deviceFound = false;  
  8. while (S_OK == _dsMonikerDevEnum->Next(1, &pM, &cFetched) && !deviceFound)  
  9. {  
  10.     IPropertyBag *pBag;  
  11.     hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **) &pBag);  
  12.     if (S_OK == hr)  
  13.     {  
  14.         // Find the description or friendly name.  
  15.         VARIANT varName;  
  16.         VariantInit(&varName);  
  17.         if (deviceUniqueIdUTF8Length > 0)  
  18.         {  
  19.             hr = pBag->Read(L"DevicePath", &varName, 0);  
  20.             if (FAILED(hr))  
  21.             {  
  22.                 hr = pBag->Read(L"Description", &varName, 0);  
  23.                 if (FAILED(hr))  
  24.                 {  
  25.                     hr = pBag->Read(L"FriendlyName", &varName, 0);  
  26.                 }  
  27.             }  
  28.             if (SUCCEEDED(hr))  
  29.             {  
  30.                 char tempDevicePathUTF8[256];  
  31.                 tempDevicePathUTF8[0] = 0;  
  32.                 WideCharToMultiByte(CP_UTF8, 0, varName.bstrVal, -1,  
  33.                                     tempDevicePathUTF8,  
  34.                                     sizeof(tempDevicePathUTF8), NULL,  
  35.                                     NULL);  
  36.                 if (strncmp(tempDevicePathUTF8,  
  37.                             (const char*) deviceUniqueIdUTF8,  
  38.                             deviceUniqueIdUTF8Length) == 0)  
  39.                 {  
  40.                     // We have found the requested device  
  41.                     deviceFound = true;  
  42.                     hr = pM->BindToObject(0, 0, IID_IBaseFilter,  
  43.                                           (void**) &captureFilter);  
  44.                     if FAILED(hr)  
  45.                     {  
  46.                         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture,  
  47.                                      _id, "Failed to bind to the selected capture device %d",hr);  
  48.                     }  
  49.                     if (productUniqueIdUTF8  
  50.                         && productUniqueIdUTF8Length > 0) // Get the device name  
  51.                     {  
  52.                         GetProductId(deviceUniqueIdUTF8,  
  53.                                      productUniqueIdUTF8,  
  54.                                      productUniqueIdUTF8Length);  
  55.                     }  
  56.                 }  
  57.             }  
  58.         }  
  59.         VariantClear(&varName);  
  60.         pBag->Release();  
  61.         pM->Release();  
  62.     } }  


先用BindToStorage 绑定 IPropertyBag,找到匹配的设备友好名之后,再用 BindToObject 来绑定 IBaseFilter,并且建立联合的 filter。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DirectShow是Windows平台上的一个多媒体框架,用于处理音频和视频流。使用DirectShow捕捉摄像头视频数据需要以下步骤: 1. 枚举可用的视频捕捉设备并选择需要使用的设备。 2. 创建一个Filter Graph Manager对象,用于管理DirectShow图形。 3. 创建一个视频捕捉设备的Filter对象,并添加到Filter Graph Manager中。 4. 创建一个Sample Grabber Filter对象,用于获取视频数据。 5. 创建一个Null Renderer对象,用于显示视频数据。 6. 将Sample Grabber Filter对象和Null Renderer对象添加到Filter Graph Manager中,并建立连接。 7. 设置Sample Grabber Filter对象的回调函数,用于处理视频数据。 8. 开始视频捕捉。 以下是C++代码示例: ```cpp #include <dshow.h> // 枚举可用的视频捕捉设备 HRESULT EnumerateDevices(REFGUID category, IEnumMoniker** ppEnum) { // 创建系统设备枚举器 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum); if (FAILED(hr)) { return hr; } // 枚举视频捕捉设备 hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); if (hr == S_FALSE) { hr = VFW_E_NOT_FOUND; } pDevEnum->Release(); return hr; } // 创建Filter Graph Manager对象 IGraphBuilder* pGraphBuilder = NULL; IMediaControl* pMediaControl = NULL; IMediaEventEx* pMediaEvent = NULL; HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraphBuilder); if (FAILED(hr)) { return hr; } // 创建视频捕捉设备的Filter对象 IEnumMoniker* pEnumMoniker = NULL; hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnumMoniker); if (FAILED(hr)) { return hr; } IMoniker* pMoniker = NULL; ULONG cFetched; while (pEnumMoniker->Next(1, &pMoniker, &cFetched) == S_OK) { IBaseFilter* pFilter = NULL; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr)) { // 添加到Filter Graph Manager中 pGraphBuilder->AddFilter(pFilter, L"Video Capture"); pFilter->Release(); } pMoniker->Release(); } pEnumMoniker->Release(); // 创建Sample Grabber Filter对象 ISampleGrabber* pSampleGrabber = NULL; hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSampleGrabber); if (FAILED(hr)) { return hr; } // 设置Sample Grabber Filter对象的回调函数 hr = pSampleGrabber->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber); if (FAILED(hr)) { return hr; } AM_MEDIA_TYPE mt; ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB24; mt.formattype = FORMAT_VideoInfo; hr = pGrabber->SetMediaType(&mt); if (FAILED(hr)) { return hr; } hr = pGrabber->SetCallback(&SampleGrabberCallback, 0); if (FAILED(hr)) { return hr; } // 创建Null Renderer对象 IBaseFilter* pNullRenderer = NULL; hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pNullRenderer); if (FAILED(hr)) { return hr; } // 将Sample Grabber Filter对象和Null Renderer对象添加到Filter Graph Manager中,并建立连接 hr = pGraphBuilder->AddFilter(pSampleGrabber, L"Sample Grabber"); if (FAILED(hr)) { return hr; } hr = pGraphBuilder->AddFilter(pNullRenderer, L"Null Renderer"); if (FAILED(hr)) { return hr; } IPin* pGrabberOut = GetPin(pSampleGrabber, PINDIR_OUTPUT); IPin* pRendererIn = GetPin(pNullRenderer, PINDIR_INPUT); hr = pGraphBuilder->Connect(pGrabberOut, pRendererIn); if (FAILED(hr)) { return hr; } // 开始视频捕捉 hr = pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pMediaControl); if (FAILED(hr)) { return hr; } hr = pMediaControl->Run(); if (FAILED(hr)) { return hr; } // 处理视频数据的回调函数 HRESULT SampleGrabberCallback::SampleCB(double Time, IMediaSample *pSample) { BYTE* pData = NULL; pSample->GetPointer(&pData); long lDataLen = pSample->GetActualDataLength(); // 处理视频数据 return S_OK; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值