CameraDS.cpp
上传用户:wjt888999
上传日期:2022-08-11
资源大小:5225k
文件大小:11k
源码类别:

OpenCV

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////
  2. // Video Capture using DirectShow
  3. // Author: Shiqi Yu (shiqi.yu@gmail.com)
  4. // Thanks to:
  5. // HardyAI@OpenCV China
  6. // flymanbox@OpenCV China (for his contribution to function CameraName, and frame width/height setting)
  7. // Last modification: April 9, 2009
  8. //////////////////////////////////////////////////////////////////////
  9. //////////////////////////////////////////////////////////////////////
  10. // 使用说明:
  11. //   1. 将CameraDS.h CameraDS.cpp以及目录DirectShow复制到你的项目中
  12. //   2. 菜单 Project->Settings->Settings for:(All configurations)->C/C++->Category(Preprocessor)->Additional include directories
  13. //      设置为 DirectShow/Include
  14. //   3. 菜单 Project->Settings->Settings for:(All configurations)->Link->Category(Input)->Additional library directories
  15. //      设置为 DirectShow/Lib
  16. //////////////////////////////////////////////////////////////////////
  17. // CameraDS.cpp: implementation of the CCameraDS class.
  18. //
  19. //////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "CameraDS.h"
  22. #pragma comment(lib,"Strmiids.lib") 
  23. //////////////////////////////////////////////////////////////////////
  24. // Construction/Destruction
  25. //////////////////////////////////////////////////////////////////////
  26. CCameraDS::CCameraDS()
  27. {
  28. m_bConnected = false;
  29. m_nWidth = 0;
  30. m_nHeight = 0;
  31. m_bLock = false;
  32. m_bChanged = false;
  33. m_pFrame = NULL;
  34. m_nBufferSize = 0;
  35. m_pNullFilter = NULL;
  36. m_pMediaEvent = NULL;
  37. m_pSampleGrabberFilter = NULL;
  38. m_pGraph = NULL;
  39. CoInitialize(NULL);
  40. }
  41. CCameraDS::~CCameraDS()
  42. {
  43. CloseCamera();
  44. CoUninitialize();
  45. }
  46. void CCameraDS::CloseCamera()
  47. {
  48. if(m_bConnected)
  49. m_pMediaControl->Stop();
  50. m_pGraph = NULL;
  51. m_pDeviceFilter = NULL;
  52. m_pMediaControl = NULL;
  53. m_pSampleGrabberFilter = NULL;
  54. m_pSampleGrabber = NULL;
  55. m_pGrabberInput = NULL;
  56. m_pGrabberOutput = NULL;
  57. m_pCameraOutput = NULL;
  58. m_pMediaEvent = NULL;
  59. m_pNullFilter = NULL;
  60. m_pNullInputPin = NULL;
  61. if (m_pFrame)
  62. cvReleaseImage(&m_pFrame);
  63. m_bConnected = false;
  64. m_nWidth = 0;
  65. m_nHeight = 0;
  66. m_bLock = false;
  67. m_bChanged = false;
  68. m_nBufferSize = 0;
  69. }
  70. bool CCameraDS::OpenCamera(int nCamID, bool bDisplayProperties, int nWidth, int nHeight)
  71. {
  72. HRESULT hr = S_OK;
  73. CoInitialize(NULL);
  74. // Create the Filter Graph Manager.
  75. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
  76. IID_IGraphBuilder, (void **)&m_pGraph);
  77. hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, 
  78. IID_IBaseFilter, (LPVOID *)&m_pSampleGrabberFilter);
  79. hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &m_pMediaControl);
  80. hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &m_pMediaEvent);
  81. hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,
  82. IID_IBaseFilter, (LPVOID*) &m_pNullFilter);
  83. hr = m_pGraph->AddFilter(m_pNullFilter, L"NullRenderer");
  84. hr = m_pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&m_pSampleGrabber);
  85. AM_MEDIA_TYPE   mt;
  86. ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
  87. mt.majortype = MEDIATYPE_Video;
  88. mt.subtype = MEDIASUBTYPE_RGB24;
  89. mt.formattype = FORMAT_VideoInfo; 
  90. hr = m_pSampleGrabber->SetMediaType(&mt);
  91. MYFREEMEDIATYPE(mt);
  92. m_pGraph->AddFilter(m_pSampleGrabberFilter, L"Grabber");
  93.  
  94. // Bind Device Filter.  We know the device because the id was passed in
  95. BindFilter(nCamID, &m_pDeviceFilter);
  96. m_pGraph->AddFilter(m_pDeviceFilter, NULL);
  97. CComPtr<IEnumPins> pEnum;
  98. m_pDeviceFilter->EnumPins(&pEnum);
  99.  
  100. hr = pEnum->Reset();
  101. hr = pEnum->Next(1, &m_pCameraOutput, NULL); 
  102. pEnum = NULL; 
  103. m_pSampleGrabberFilter->EnumPins(&pEnum);
  104. pEnum->Reset();
  105. hr = pEnum->Next(1, &m_pGrabberInput, NULL); 
  106. pEnum = NULL;
  107. m_pSampleGrabberFilter->EnumPins(&pEnum);
  108. pEnum->Reset();
  109. pEnum->Skip(1);
  110. hr = pEnum->Next(1, &m_pGrabberOutput, NULL); 
  111. pEnum = NULL;
  112. m_pNullFilter->EnumPins(&pEnum);
  113. pEnum->Reset();
  114. hr = pEnum->Next(1, &m_pNullInputPin, NULL);
  115. //SetCrossBar();
  116. if (bDisplayProperties) 
  117. {
  118. CComPtr<ISpecifyPropertyPages> pPages;
  119. HRESULT hr = m_pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);
  120. if (SUCCEEDED(hr))
  121. {
  122. PIN_INFO PinInfo;
  123. m_pCameraOutput->QueryPinInfo(&PinInfo);
  124. CAUUID caGUID;
  125. pPages->GetPages(&caGUID);
  126. OleCreatePropertyFrame(NULL, 0, 0,
  127. L"Property Sheet", 1,
  128. (IUnknown **)&(m_pCameraOutput.p),
  129. caGUID.cElems,
  130. caGUID.pElems,
  131. 0, 0, NULL);
  132. CoTaskMemFree(caGUID.pElems);
  133. PinInfo.pFilter->Release();
  134. }
  135. pPages = NULL;
  136. }
  137. else 
  138. {
  139. //////////////////////////////////////////////////////////////////////////////
  140. // 加入由 lWidth和lHeight设置的摄像头的宽和高 的功能,默认320*240
  141. // by flymanbox @2009-01-24
  142. //////////////////////////////////////////////////////////////////////////////
  143.    int _Width = nWidth, _Height = nHeight;
  144.    IAMStreamConfig*   iconfig; 
  145.    iconfig = NULL;
  146.    hr = m_pCameraOutput->QueryInterface(IID_IAMStreamConfig,   (void**)&iconfig);   
  147.       
  148.    AM_MEDIA_TYPE* pmt;    
  149.    if(iconfig->GetFormat(&pmt) !=S_OK) 
  150.    {
  151.   //printf("GetFormat Failed ! n");
  152.   return   false;   
  153.    }
  154.       
  155.    VIDEOINFOHEADER*   phead;
  156.    if ( pmt->formattype == FORMAT_VideoInfo)   
  157.    {   
  158. phead=( VIDEOINFOHEADER*)pmt->pbFormat;   
  159. phead->bmiHeader.biWidth = _Width;   
  160. phead->bmiHeader.biHeight = _Height;   
  161. if(( hr=iconfig->SetFormat(pmt)) != S_OK )   
  162. {
  163. return   false;
  164. }
  165. }   
  166. iconfig->Release();   
  167. iconfig=NULL;   
  168. MYFREEMEDIATYPE(*pmt);
  169. }
  170. hr = m_pGraph->Connect(m_pCameraOutput, m_pGrabberInput);
  171. hr = m_pGraph->Connect(m_pGrabberOutput, m_pNullInputPin);
  172. if (FAILED(hr))
  173. {
  174. switch(hr)
  175. {
  176. case VFW_S_NOPREVIEWPIN :
  177. break;
  178. case E_FAIL :
  179. break;
  180. case E_INVALIDARG :
  181. break;
  182. case E_POINTER :
  183. break;
  184. }
  185. }
  186. m_pSampleGrabber->SetBufferSamples(TRUE);
  187. m_pSampleGrabber->SetOneShot(TRUE);
  188.     
  189. hr = m_pSampleGrabber->GetConnectedMediaType(&mt);
  190. if(FAILED(hr))
  191. return false;
  192. VIDEOINFOHEADER *videoHeader;
  193. videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);
  194. m_nWidth = videoHeader->bmiHeader.biWidth;
  195. m_nHeight = videoHeader->bmiHeader.biHeight;
  196. m_bConnected = true;
  197. pEnum = NULL;
  198. return true;
  199. }
  200. bool CCameraDS::BindFilter(int nCamID, IBaseFilter **pFilter)
  201. {
  202. if (nCamID < 0)
  203. return false;
  204.  
  205.     // enumerate all video capture devices
  206. CComPtr<ICreateDevEnum> pCreateDevEnum;
  207. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  208. IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  209. if (hr != NOERROR)
  210. {
  211. return false;
  212. }
  213.     CComPtr<IEnumMoniker> pEm;
  214.     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
  215.         &pEm, 0);
  216.     if (hr != NOERROR) 
  217. {
  218. return false;
  219.     }
  220.     pEm->Reset();
  221.     ULONG cFetched;
  222.     IMoniker *pM;
  223. int index = 0;
  224.     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= nCamID)
  225.     {
  226. IPropertyBag *pBag;
  227. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  228. if(SUCCEEDED(hr)) 
  229. {
  230. VARIANT var;
  231. var.vt = VT_BSTR;
  232. hr = pBag->Read(L"FriendlyName", &var, NULL);
  233. if (hr == NOERROR) 
  234. {
  235. if (index == nCamID)
  236. {
  237. pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
  238. }
  239. SysFreeString(var.bstrVal);
  240. }
  241. pBag->Release();
  242. }
  243. pM->Release();
  244. index++;
  245.     }
  246. pCreateDevEnum = NULL;
  247. return true;
  248. }
  249. //将输入crossbar变成PhysConn_Video_Composite
  250. void CCameraDS::SetCrossBar()
  251. {
  252. int i;
  253. IAMCrossbar *pXBar1 = NULL;
  254. ICaptureGraphBuilder2 *pBuilder = NULL;
  255.  
  256. HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
  257. CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, 
  258. (void **)&pBuilder);
  259. if (SUCCEEDED(hr))
  260. {
  261. hr = pBuilder->SetFiltergraph(m_pGraph);
  262. }
  263. hr = pBuilder->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, 
  264. m_pDeviceFilter,IID_IAMCrossbar, (void**)&pXBar1);
  265. if (SUCCEEDED(hr)) 
  266. {
  267.    long OutputPinCount;
  268. long InputPinCount;
  269. long PinIndexRelated;
  270. long PhysicalType;
  271. long inPort = 0;
  272. long outPort = 0;
  273. pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
  274. for( i =0;i<InputPinCount;i++)
  275. {
  276. pXBar1->get_CrossbarPinInfo(TRUE,i,&PinIndexRelated,&PhysicalType);
  277. if(PhysConn_Video_Composite==PhysicalType) 
  278. {
  279. inPort = i;
  280. break;
  281. }
  282. }
  283. for( i =0;i<OutputPinCount;i++)
  284. {
  285. pXBar1->get_CrossbarPinInfo(FALSE,i,&PinIndexRelated,&PhysicalType);
  286. if(PhysConn_Video_VideoDecoder==PhysicalType) 
  287. {
  288. outPort = i;
  289. break;
  290. }
  291. }
  292.   
  293. if(S_OK==pXBar1->CanRoute(outPort,inPort))
  294. {
  295. pXBar1->Route(outPort,inPort);
  296. }
  297. pXBar1->Release();  
  298. }
  299. pBuilder->Release();
  300. }
  301. /*
  302. The returned image can not be released.
  303. */
  304. IplImage* CCameraDS::QueryFrame()
  305. {
  306. long evCode;
  307. long size = 0;
  308. m_pMediaControl->Run();
  309. m_pMediaEvent->WaitForCompletion(INFINITE, &evCode);
  310.  
  311. m_pSampleGrabber->GetCurrentBuffer(&size, NULL);
  312. //if the buffer size changed
  313. if (size != m_nBufferSize)
  314. {
  315. if (m_pFrame)
  316. cvReleaseImage(&m_pFrame);
  317. m_nBufferSize = size;
  318. m_pFrame = cvCreateImage(cvSize(m_nWidth, m_nHeight), IPL_DEPTH_8U, 3);
  319. }
  320. m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (long*)m_pFrame->imageData);
  321. cvFlip(m_pFrame);
  322. return m_pFrame;
  323. }
  324. int CCameraDS::CameraCount()
  325. {
  326. int count = 0;
  327.   CoInitialize(NULL);
  328.    // enumerate all video capture devices
  329. CComPtr<ICreateDevEnum> pCreateDevEnum;
  330.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  331. IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  332.     CComPtr<IEnumMoniker> pEm;
  333.     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
  334.         &pEm, 0);
  335.     if (hr != NOERROR) 
  336. {
  337. return count;
  338.     }
  339.     pEm->Reset();
  340.     ULONG cFetched;
  341.     IMoniker *pM;
  342.     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
  343.     {
  344. count++;
  345.     }
  346. pCreateDevEnum = NULL;
  347. pEm = NULL;
  348. return count;
  349. }
  350. int CCameraDS::CameraName(int nCamID, char* sName, int nBufferSize)
  351. {
  352. int count = 0;
  353.   CoInitialize(NULL);
  354.    // enumerate all video capture devices
  355. CComPtr<ICreateDevEnum> pCreateDevEnum;
  356.     HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
  357. IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  358.     CComPtr<IEnumMoniker> pEm;
  359.     hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
  360.         &pEm, 0);
  361.     if (hr != NOERROR) return 0;
  362.     pEm->Reset();
  363.     ULONG cFetched;
  364.     IMoniker *pM;
  365.     while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
  366.     {
  367. if (count == nCamID)
  368. {
  369. IPropertyBag *pBag=0;
  370. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  371. if(SUCCEEDED(hr))
  372. {
  373. VARIANT var;
  374. var.vt = VT_BSTR;
  375. hr = pBag->Read(L"FriendlyName", &var, NULL); //还有其他属性,像描述信息等等...
  376.             if(hr == NOERROR)
  377.         {
  378.         //获取设备名称
  379. WideCharToMultiByte(CP_ACP,0,var.bstrVal,-1,sName, nBufferSize ,"",NULL);
  380.                 SysFreeString(var.bstrVal);
  381.         }
  382.     pBag->Release();
  383. }
  384. pM->Release();
  385. break;
  386. }
  387. count++;
  388.     }
  389. pCreateDevEnum = NULL;
  390. pEm = NULL;
  391. return 1;
  392. }