CaptureVideo.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #include "StdAfx.h"
  2. #include "CaptureVideo.h"
  3. CCaptureVideo::CCaptureVideo()
  4. {
  5. //COM Library Intialization
  6. if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
  7. {
  8. AfxMessageBox("CoInitialize Failed!\r\n");
  9. return;
  10. }
  11. m_hWnd = NULL;
  12. m_pVW = NULL;
  13. m_pMC = NULL;
  14. m_pGB = NULL;
  15. m_pBF = NULL;
  16. m_pGrabber = NULL;
  17. m_pCapture = NULL;
  18. }
  19. CCaptureVideo::~CCaptureVideo()
  20. {
  21. // Stop media playback
  22. if(m_pMC)m_pMC->Stop();
  23. if(m_pVW){
  24. m_pVW->put_Visible(OAFALSE);
  25. m_pVW->put_Owner(NULL);
  26. }
  27. SAFE_RELEASE(m_pCapture);
  28. SAFE_RELEASE(m_pMC);
  29. SAFE_RELEASE(m_pGB);
  30. SAFE_RELEASE(m_pBF);
  31. SAFE_RELEASE(m_pVW);
  32. SAFE_RELEASE(m_pGrabber);
  33. CoUninitialize( );
  34. }
  35. int CCaptureVideo::EnumDevices(CMFCRibbonComboBox *pCombobox)
  36. {
  37. if (!pCombobox)
  38. return -1;
  39. int id = 0;
  40. // 建立系统设备枚举实例;
  41. ICreateDevEnum *pCreateDevEnum;
  42. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  43. if (hr != NOERROR)
  44. {
  45. //CoUninitialize();
  46. return -1;
  47. }
  48. // 获取设备类枚举器;
  49. IEnumMoniker *pEnum;
  50. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);
  51. if (hr != NOERROR)
  52. {
  53. //CoUninitialize();
  54. return -1;
  55. }
  56. CString strCurName;
  57. int nIndex = pCombobox->GetCurSel();
  58. if ( nIndex != -1 )
  59. strCurName = pCombobox->GetItem(nIndex);
  60. // 枚举设备名称;
  61. pEnum->Reset();
  62. ULONG cFetched;
  63. IMoniker *pM;
  64. pCombobox->RemoveAllItems();
  65. while(hr = pEnum->Next(1, &pM, &cFetched), hr==S_OK)
  66. {
  67. IPropertyBag *pBag;
  68. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  69. if(SUCCEEDED(hr))
  70. {
  71. VARIANT var;
  72. var.vt = VT_BSTR;
  73. hr = pBag->Read(L"FriendlyName", &var, NULL);
  74. if (hr == NOERROR)
  75. {
  76. TCHAR str[2048];
  77. id++;
  78. WideCharToMultiByte(CP_ACP,0,var.bstrVal, -1, str, 2048, NULL, NULL);
  79. //::SendMessage(hList, CB_ADDSTRING, 0,(LPARAM)str);
  80. pCombobox->AddItem(str);
  81. SysFreeString(var.bstrVal);
  82. }
  83. pBag->Release();
  84. }
  85. pM->Release();
  86. }
  87. pEnum->Release();
  88. pEnum = NULL;
  89. // 如果之前有选择,恢复;
  90. if ( nIndex != -1 )
  91. pCombobox->SelectItem(strCurName);
  92. return id;
  93. }
  94. HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
  95. {
  96. HRESULT hr;
  97. hr = InitCaptureGraphBuilder();
  98. if (FAILED(hr)){
  99. AfxMessageBox("Failed to get video interfaces!");
  100. return hr;
  101. }
  102. // Bind Device Filter. We know the device because the id was passed in
  103. if(!BindFilter(iDeviceID, &m_pBF))
  104. return S_FALSE;
  105. hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
  106. // hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
  107. // m_pBF, NULL, NULL);
  108. // create a sample grabber
  109. //hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
  110. hr = CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void**)&m_pGrabber );
  111. if( !m_pGrabber )
  112. {
  113. AfxMessageBox("Fail to create SampleGrabber, maybe qedit.dll is not registered?");
  114. return hr;
  115. }
  116. CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
  117. //设置视频格式
  118. AM_MEDIA_TYPE mt;
  119. IAMStreamConfig *pSC = NULL;
  120. m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pBF, IID_IAMStreamConfig, (void **)&pSC);
  121. ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
  122. mt.majortype = MEDIATYPE_Video;
  123. mt.subtype = MEDIASUBTYPE_RGB32;
  124. mt.bTemporalCompression = FALSE;
  125. hr = m_pGrabber->SetMediaType(&mt);
  126. if( FAILED( hr ) )
  127. {
  128. AfxMessageBox("Fail to set media type!");
  129. return hr;
  130. }
  131. hr = m_pGB->AddFilter( pGrabBase, L"Grabber" );
  132. if( FAILED( hr ) )
  133. {
  134. AfxMessageBox("Fail to put sample grabber in graph");
  135. return hr;
  136. }
  137. // try to render preview/capture pin
  138. hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
  139. if( FAILED( hr ) )
  140. hr = m_pCapture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,m_pBF,pGrabBase,NULL);
  141. if( FAILED( hr ) )
  142. {
  143. AfxMessageBox("Can’t build the graph");
  144. return hr;
  145. }
  146. hr = m_pGrabber->GetConnectedMediaType( &mt );
  147. if ( FAILED( hr) )
  148. {
  149. AfxMessageBox("Failt to read the connected media type");
  150. return hr;
  151. }
  152. VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
  153. mCB.lWidth = vih->bmiHeader.biWidth;
  154. mCB.lHeight = vih->bmiHeader.biHeight;
  155. // 单位为100ns,所以每帧(10^7/p3)*100ns
  156. vih->AvgTimePerFrame = 10000000 / 50;
  157. FreeMediaType(mt);
  158. hr = m_pGrabber->SetBufferSamples( FALSE );
  159. hr = m_pGrabber->SetOneShot( FALSE );
  160. hr = m_pGrabber->SetCallback( &mCB, 1 );
  161. //设置视频捕捉窗口
  162. m_hWnd = hWnd ;
  163. SetupVideoWindow();
  164. hr = m_pMC->Run();//开始视频捕捉
  165. if ( FAILED( hr) )
  166. {
  167. AfxMessageBox("Couldn’t run the graph!");
  168. return hr;
  169. }
  170. return S_OK;
  171. }
  172. bool CCaptureVideo::BindFilter(int deviceId, IBaseFilter **pFilter)
  173. {
  174. if (deviceId < 0)
  175. return false;
  176. // enumerate all video capture devices
  177. ICreateDevEnum* pCreateDevEnum;
  178. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  179. if (hr != NOERROR)
  180. {
  181. return false;
  182. }
  183. IEnumMoniker* pEm;
  184. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEm, 0);
  185. if (hr != NOERROR)
  186. {
  187. return false;
  188. }
  189. pEm->Reset();
  190. ULONG cFetched;
  191. IMoniker *pM;
  192. int index = 0;
  193. while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= deviceId)
  194. {
  195. IPropertyBag *pBag;
  196. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  197. if(SUCCEEDED(hr))
  198. {
  199. VARIANT var;
  200. var.vt = VT_BSTR;
  201. hr = pBag->Read(L"FriendlyName", &var, NULL);
  202. if (hr == NOERROR)
  203. {
  204. if (index == deviceId)
  205. {
  206. pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);
  207. }
  208. SysFreeString(var.bstrVal);
  209. }
  210. pBag->Release();
  211. }
  212. pM->Release();
  213. index++;
  214. }
  215. pEm->Release();
  216. pEm = NULL;
  217. return true;
  218. }
  219. HRESULT CCaptureVideo::InitCaptureGraphBuilder()
  220. {
  221. HRESULT hr;
  222. // 创建IGraphBuilder接口
  223. hr=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB);
  224. // 创建ICaptureGraphBuilder2接口
  225. hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC,
  226. IID_ICaptureGraphBuilder2, (void **) &m_pCapture);
  227. if (FAILED(hr))return hr;
  228. m_pCapture->SetFiltergraph(m_pGB);
  229. hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  230. if (FAILED(hr))return hr;
  231. hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *) &m_pVW);
  232. if (FAILED(hr))return hr;
  233. return hr;
  234. }
  235. HRESULT CCaptureVideo::SetupVideoWindow()
  236. {
  237. HRESULT hr;
  238. hr = m_pVW->put_Owner((OAHWND)m_hWnd);
  239. if (FAILED(hr))return hr;
  240. hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
  241. if (FAILED(hr))return hr;
  242. ResizeVideoWindow();
  243. hr = m_pVW->put_Visible(OATRUE);
  244. return hr;
  245. }
  246. void CCaptureVideo::ResizeVideoWindow()
  247. {
  248. if (m_pVW){
  249. //让图像充满整个窗口
  250. CRect rc;
  251. ::GetClientRect(m_hWnd,&rc);
  252. m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
  253. }
  254. }
  255. void CCaptureVideo::GrabOneFrame(BOOL bGrab)
  256. {
  257. bOneShot = bGrab;
  258. }
  259. void CCaptureVideo::FreeMediaType(AM_MEDIA_TYPE& mt)
  260. {
  261. if (mt.cbFormat != 0) {
  262. CoTaskMemFree((PVOID)mt.pbFormat);
  263. // Strictly unnecessary but tidier
  264. mt.cbFormat = 0;
  265. mt.pbFormat = NULL;
  266. }
  267. if (mt.pUnk != NULL) {
  268. mt.pUnk->Release();
  269. mt.pUnk = NULL;
  270. }
  271. }