Directshow_驱动摄像头预览视频

https://blog.csdn.net/li_chihang/article/details/43378429?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

出于兴趣一直以来都断断续续看过dshow的东西,可没怎么系统地总结过(学习还是要多实践,多总结啊).

dshow预览摄像头捕捉的视频比较简单基础,网上相关的资料很多,简单的思路由下面代码所示:

 

 
  1. ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder

  2. // Initialize pBuild (not shown).

  3. IBaseFilter *pCap; // Video capture filter.

  4. /* Initialize pCap and add it to the filter graph (not shown). */

  5. hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,

  6. pCap, NULL, NULL);

   dshow 提供了一个 Capture Graph Builder COM 组件使得捕捉graph 图的生成更加简单。 Capture Graph Builder 提供了一 ICaptureGraphBuilder2接口 ,这个接口提供了一些方法用来构建和控制捕捉 graph。video capture filter则由系统设备枚举得到可用视频设备,并生成filter;最后智能连接graph即可.具体见代码和注释:

 

 

 
  1. #include <dshow.h>

  2. #include <stdio.h>

  3. #include <atlconv.h>

  4. #pragma comment(lib,"quartz.lib")

  5. #pragma comment(lib, "strmiids.lib")

  6. void main()

  7. {

  8. IGraphBuilder *pGraph = NULL;

  9. IMediaControl *pControl = NULL;

  10. IMediaEvent *pEvent = NULL;

  11. IVideoWindow *pVideoWindow = NULL;

  12. ICaptureGraphBuilder2 *pBuild = NULL;

  13. // Initialize the COM library.

  14. HRESULT hr = CoInitialize(NULL);

  15. if (FAILED(hr)){

  16. printf("ERROR - Could not initialize COM library");

  17. return;

  18. }

  19. //创建Capture Graph Builder 对象

  20. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,

  21. CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);

  22. if (SUCCEEDED(hr)){

  23. // 创建 graph manger 对象.

  24. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,

  25. IID_IGraphBuilder, (void**)&pGraph);

  26. if (SUCCEEDED(hr))

  27. // 初始化 Capture Graph Builder.

  28. pBuild->SetFiltergraph(pGraph);

  29. }

  30. //各个查询接口.

  31. hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

  32. hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

  33. hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow);

  34.  
  35. ICreateDevEnum *pDevEnum = NULL;

  36. IEnumMoniker *pEnum = NULL;

  37. //创建一个系统设备枚举对象

  38. hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,

  39. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,reinterpret_cast<void**>(&pDevEnum));

  40. if (SUCCEEDED(hr))

  41. //创建一个枚举器,用来枚举视频设备

  42. hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);

  43.  
  44. IMoniker *pMoniker = NULL;

  45. //开始枚举设备

  46. while (pEnum->Next(1, &pMoniker, NULL) == S_OK)

  47. {

  48. IBaseFilter *pCap = NULL;

  49. hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);//为设备生成 filter

  50. if (SUCCEEDED(hr))

  51. {

  52. hr = pGraph->AddFilter(pCap, L"Capture Filter");//将filter加入到graph

  53. }

  54. if (SUCCEEDED(hr))

  55. {

  56. //PIN_CATEGORY_PREVIEW: specifying a pin category;

  57. //MEDIATYPE_Video: the major media types.

  58. //pCap: pointer to the starting filter for the connection

  59. hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video, pCap, NULL, NULL);//连接graph

  60. break;

  61. }

  62. else{

  63. pMoniker->Release();

  64. continue; //尝试下一个

  65. }

  66. }

  67. pVideoWindow->put_AutoShow(OATRUE);//graph自动显示视频窗口

  68. //pVideoWindow->put_Visible(OATRUE/*OAFALSE*/);

  69. if (SUCCEEDED(hr))

  70. {

  71. // Run the graph.

  72. hr = pControl->Run();

  73. if (SUCCEEDED(hr)){

  74. long evCode;

  75. pEvent->WaitForCompletion(INFINITE, &evCode);//一直阻塞在这边;

  76. }

  77. }

  78. pBuild->Release();

  79. pMoniker->Release();

  80. pControl->Release();

  81. pEvent->Release();

  82. pGraph->Release();

  83. CoUninitialize();

  84. }

 

参考资料:

 

  1. 《Directshow开发指南》
  2. 《directshow SDK 学习笔记》
//指定视频采集设备的友好名字,为它创建一个Filter IBaseFilter * CTestPreviewDlg::CreateVideoDevice(const char * inFriendlyName) { return CreateHardwareFilter(CLSID_VideoInputDeviceCategory,inFriendlyName); } //根据设备的友好名字,创建一个代表该设备的Filter IBaseFilter * CTestPreviewDlg::CreateHardwareFilter(GUID inCategory,const char * inFriendlyName) { //创建一个系统枚举组件对象 ICreateDevEnum * enumHardware = NULL; HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL, IID_ICreateDevEnum,(void**)&enumHardware); if(FAILED(hr)) { return NULL; } IBaseFilter * hardwareFilter = NULL; IEnumMoniker * enumMoniker = NULL; //为指定的目录创建枚举器 hr = enumHardware->CreateClassEnumerator(inCategory,&enumMoniker,0); if(enumMoniker) { enumMoniker->Reset(); ULONG fetched = 0; IMoniker * moniker = NULL; char friendlyName[256]; //枚举得到该目录下所有的设备,逐个进行名字匹配 while(!hardwareFilter && SUCCEEDED(enumMoniker->Next(1,&moniker, &fetched)) && fetched) { if(moniker) { IPropertyBag * propertyBag = NULL; VARIANT name; friendlyName[0] = 0; hr = moniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&propertyBag); //读取设备的友好名字 if(SUCCEEDED(hr)) { name.vt = VT_BSTR; hr = propertyBag->Read(L"Friendlyname",&name,NULL); } if(SUCCEEDED(hr)) { WideCharToMultiByte(CP_ACP,0,name.bstrVal,-1, friendlyName,256,NULL,NULL); //如果当前设备的友好名字与用户指定的设备名字相同, //则将当前设备标识绑定为Filter形式 if(strcmp(friendlyName,inFriendlyName) == 0) { moniker->BindToObject(0,0,IID_IBaseFilter, (void**)&hardwareFilter); } } //释放使用过的接口 if(propertyBag) { propertyBag->Release(); propertyBag = NULL; } moniker->Release(); } } enumMoniker->Release(); } enumHardware->Release(); return hardwareFilter; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值