CameraImpl.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #include "stdafx.h"
  2. #include "CameraImpl.h"
  3. #include "Dshow.h"
  4. #include "smartptr.h"
  5. static int Bin2Str(unsigned char *x, int xlen, char *str, int str_size)
  6. {
  7. static const char *hex2char = "0123456789ABCDEF";
  8. int i, k = 0;
  9. if (str_size <= xlen * 2)
  10. return -1;
  11. for (i = 0; i < xlen; ++i) {
  12. int h = x[i] >> 4;
  13. int l = x[i] & 0xf;
  14. str[k++] = hex2char[h];
  15. str[k++] = hex2char[l];
  16. }
  17. str[k] = 0;
  18. return k;
  19. }
  20. int GetCameraInfors(CAMERA_BUCKET& vtCameraList)
  21. {
  22. LOG_FUNCTION();
  23. DestoryCamereBuckets(vtCameraList);
  24. SmartPtr<ICreateDevEnum> pDevEnum = NULL;
  25. int deviceCounter = 0;
  26. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  27. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
  28. reinterpret_cast<void**>(&pDevEnum));
  29. if (SUCCEEDED(hr)) {
  30. // Create an enumerator for the video capture category.
  31. IEnumMoniker *pEnum = NULL;
  32. hr = pDevEnum->CreateClassEnumerator(
  33. CLSID_VideoInputDeviceCategory,
  34. &pEnum, 0);
  35. if (hr == S_OK) {
  36. //if (!silent)printf("SETUP: Looking For Capture Devices\n");
  37. IMoniker *pMoniker = NULL;
  38. while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
  39. IPropertyBag *pPropBag;
  40. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
  41. if (FAILED(hr)) {
  42. SAFE_RELEASE_IDEV(pPropBag);
  43. SAFE_RELEASE_IDEV(pMoniker);
  44. continue; // Skip this one, maybe the next one will work.
  45. }
  46. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  47. if(item != NULL) {
  48. item->Cleanup();
  49. // Find the description or friendly name.
  50. VARIANT varName;
  51. VariantInit(&varName);
  52. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  53. if (SUCCEEDED(hr)) {
  54. int maxLen = sizeof(item->szDevName) - 2;
  55. int nLen = WrapW2A(varName, &(item->szDevName[0]), maxLen);
  56. }
  57. VariantClear(&varName);
  58. VARIANT varCLSID;
  59. VariantInit(&varCLSID);
  60. hr = pPropBag->Read(L"CLSID", &varCLSID, 0);
  61. if (SUCCEEDED(hr)) {
  62. int maxLen = sizeof(item->szCLSID) - 2;
  63. int nLen = WrapW2A(varCLSID, &(item->szCLSID[0]), maxLen);
  64. }
  65. VariantClear(&varCLSID);
  66. VARIANT varDevPath;
  67. VariantInit(&varDevPath);
  68. hr = pPropBag->Read(L"DevicePath", &varDevPath, 0);
  69. if (SUCCEEDED(hr)) {
  70. int maxLen = sizeof(item->szDevPath) - 2;
  71. int nLen = WrapW2A(varDevPath, &(item->szDevPath[0]), maxLen);
  72. }
  73. VariantClear(&varDevPath);
  74. VARIANT varWaveID;
  75. VariantInit(&varWaveID);
  76. hr = pPropBag->Read(L"WaveInID", &varWaveID, 0);
  77. if (SUCCEEDED(hr)) {
  78. item->uWaveInID = varWaveID.lVal;
  79. }
  80. VariantClear(&varWaveID);
  81. vtCameraList.push_back(item);
  82. }
  83. SAFE_RELEASE_IDEV(pPropBag);
  84. SAFE_RELEASE_IDEV(pMoniker);
  85. deviceCounter++;
  86. }
  87. SAFE_RELEASE_IDEV(pMoniker);
  88. }
  89. SAFE_RELEASE_IDEV(pEnum);
  90. }
  91. else {
  92. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CoCreateInstance failed, hr=%d(0x%x)", hr, hr);
  93. }
  94. return deviceCounter;
  95. }
  96. int GetCameraCount()
  97. {
  98. ICreateDevEnum *pDevEnum = NULL;
  99. int deviceCounter = 0;
  100. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  101. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
  102. reinterpret_cast<void**>(&pDevEnum));
  103. if (SUCCEEDED(hr)) {
  104. IEnumMoniker *pEnum = NULL;
  105. hr = pDevEnum->CreateClassEnumerator(
  106. CLSID_VideoInputDeviceCategory,
  107. &pEnum, 0);
  108. if(hr == S_OK){
  109. IMoniker *pMoniker = NULL;
  110. while (pEnum->Next(1, &pMoniker, NULL) == S_OK){
  111. IPropertyBag *pPropBag;
  112. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
  113. (void**)(&pPropBag));
  114. SAFE_RELEASE_IDEV(pPropBag);
  115. SAFE_RELEASE_IDEV(pMoniker);
  116. if (FAILED(hr)){
  117. continue; // Skip this one, maybe the next one will work.
  118. }
  119. deviceCounter++;
  120. }
  121. }
  122. SAFE_RELEASE_IDEV(pEnum);
  123. }
  124. SAFE_RELEASE_IDEV(pDevEnum);
  125. return deviceCounter;
  126. }
  127. //usually consumes 300ms
  128. int IsDeviceBusy(const char* lpcszDeviceName)
  129. {
  130. LOG_FUNCTION();
  131. return 0;
  132. int nRet = -2;
  133. ICreateDevEnum *pDevEnum = NULL;
  134. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
  135. CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum);
  136. IEnumMoniker *pEnum = NULL;
  137. hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
  138. if (SUCCEEDED(hr)) {
  139. // Create an enumerator for the video capture category.
  140. IMoniker *pMoniker = NULL;
  141. nRet = -1;
  142. while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
  143. IPropertyBag *pPropBag = NULL;
  144. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
  145. if(SUCCEEDED(hr)) {
  146. VARIANT varName;
  147. varName.vt = VT_BSTR;
  148. hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  149. if (SUCCEEDED(hr)) {
  150. int count = 0;
  151. char tmp[256] = {0};
  152. WrapW2A(varName, tmp, 255);
  153. SysFreeString(varName.bstrVal);
  154. if(!strcmp(lpcszDeviceName, tmp)) {
  155. //Deal the specific device
  156. nRet = 0;
  157. LPBC* pbc = NULL;
  158. CreateBindCtx(0, pbc);
  159. SmartPtr<IBaseFilter> pCap = NULL;
  160. hr = pMoniker->BindToObject((IBindCtx*)pbc, 0, IID_IBaseFilter,(void **)&pCap);
  161. IGraphBuilder *m_pGB = NULL;
  162. hr = CoCreateInstance(CLSID_FilterGraph, NULL,
  163. CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
  164. if (FAILED(hr)) {
  165. nRet = -2;
  166. SAFE_RELEASE_IDEV(m_pGB);
  167. SAFE_RELEASE_IDEV(pPropBag);
  168. SAFE_RELEASE_IDEV(pMoniker);
  169. goto PEnd;
  170. }
  171. m_pGB->AddFilter(pCap, NULL);
  172. ICaptureGraphBuilder2 *m_pCapGB = NULL;
  173. hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
  174. CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
  175. if (FAILED(hr)) {
  176. nRet = -2;
  177. SAFE_RELEASE_IDEV(m_pCapGB);
  178. SAFE_RELEASE_IDEV(m_pGB);
  179. SAFE_RELEASE_IDEV(pPropBag);
  180. SAFE_RELEASE_IDEV(pMoniker);
  181. goto PEnd;
  182. }
  183. m_pCapGB->SetFiltergraph(m_pGB);
  184. IAMCrossbar *pXBar1 = NULL;
  185. hr = m_pCapGB->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pCap,
  186. IID_IAMCrossbar,(void **)&pXBar1);
  187. if (SUCCEEDED(hr)) {
  188. long OutputPinCount;
  189. long InputPinCount;
  190. long PinIndexRelated;
  191. long PhysicalType;
  192. long inPort = 0;
  193. long outPort = 0;
  194. pXBar1->get_PinCounts(&OutputPinCount,&InputPinCount);
  195. int videoBusy = 1;
  196. for (int i=0; i<InputPinCount; i++) {
  197. pXBar1->get_CrossbarPinInfo(TRUE, i, &PinIndexRelated, &PhysicalType);
  198. if(PhysConn_Video_Composite == PhysicalType) {
  199. inPort = i;
  200. break;
  201. }
  202. }
  203. for (int j=0; j<OutputPinCount; j++) {
  204. pXBar1->get_CrossbarPinInfo(FALSE, j, &PinIndexRelated, &PhysicalType);
  205. if(PhysConn_Video_Composite == PhysicalType) {
  206. outPort = j;
  207. break;
  208. }
  209. }
  210. for (int i=0; i<InputPinCount; i++) {
  211. for (int j=0; j<OutputPinCount; j++) {
  212. hr = pXBar1->CanRoute(j, i);
  213. if(S_OK == hr) {
  214. pXBar1->Route(j,i);
  215. IMediaControl *m_pMC = NULL;
  216. IVideoWindow *m_pVW = NULL;
  217. IBaseFilter *P_VCamTrans = NULL;
  218. m_pGB->AddFilter(pCap, L"Capture Filter");
  219. hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  220. hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
  221. hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
  222. hr = m_pVW->put_Owner((OAHWND)NULL);
  223. hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
  224. hr = m_pVW->put_Visible(OAFALSE);
  225. hr = m_pVW->put_AutoShow(OAFALSE);
  226. HRESULT innhr = m_pMC->StopWhenReady();
  227. if (SUCCEEDED(innhr)){
  228. videoBusy = 0;
  229. } else {
  230. LogWarn(Severity_Low, Error_DevCommFailed, DETECT_CAMERA_BUSY_ONE,
  231. CSimpleStringA::Format("%s stop failed: 0x%08X", lpcszDeviceName, innhr));
  232. }
  233. SAFE_RELEASE_IDEV(m_pVW);
  234. SAFE_RELEASE_IDEV(m_pMC);
  235. SAFE_RELEASE_IDEV(P_VCamTrans);
  236. }
  237. else {
  238. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CanRoute failed: 0x%08X", hr);
  239. }
  240. }
  241. }
  242. if (videoBusy == 1)
  243. {
  244. nRet = 1; //视频设备占用
  245. }
  246. SAFE_RELEASE_IDEV(pXBar1);
  247. }
  248. else //pXBar1
  249. {
  250. IMediaControl *m_pMC = NULL;
  251. IVideoWindow *m_pVW = NULL;
  252. IBaseFilter *P_VCamTrans = NULL;
  253. m_pGB->AddFilter(pCap, L"Capture Filter");
  254. m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
  255. hr = m_pGB->QueryInterface(IID_IVideoWindow,(LPVOID*)&m_pVW);
  256. hr = m_pCapGB->RenderStream(NULL, NULL, pCap, NULL, P_VCamTrans);
  257. hr = m_pVW->put_Owner((OAHWND)NULL);
  258. hr = m_pVW->put_WindowStyle( WS_CHILD | WS_CLIPCHILDREN);
  259. hr = m_pVW->put_Visible(OAFALSE);
  260. hr = m_pVW->put_AutoShow(OAFALSE);
  261. HRESULT innhr = m_pMC->StopWhenReady();
  262. if (FAILED(innhr))
  263. {
  264. LogWarn(Severity_Low, Error_DevCommFailed, DETECT_CAMERA_BUSY_TWO,
  265. CSimpleStringA::Format("%s stop failed: 0x%08X", lpcszDeviceName, innhr));
  266. nRet = 1; //视频设备占用
  267. }
  268. SAFE_RELEASE_IDEV(m_pVW);
  269. SAFE_RELEASE_IDEV(m_pMC);
  270. SAFE_RELEASE_IDEV(P_VCamTrans);
  271. }
  272. SAFE_RELEASE_IDEV(pXBar1);
  273. SAFE_RELEASE_IDEV(m_pCapGB);
  274. SAFE_RELEASE_IDEV(m_pGB);
  275. break;
  276. }
  277. }
  278. VariantClear(&varName);
  279. }
  280. SAFE_RELEASE_IDEV(pPropBag);
  281. SAFE_RELEASE_IDEV(pMoniker);
  282. }
  283. SAFE_RELEASE_IDEV(pMoniker);
  284. }
  285. PEnd:
  286. SAFE_RELEASE_IDEV(pEnum);
  287. SAFE_RELEASE_IDEV(pDevEnum);
  288. if(nRet != 1) {
  289. nRet = 0;
  290. }
  291. return nRet;
  292. }
  293. int UpdateCameraInfors(CAMERA_BUCKET& vtCameraList)
  294. {
  295. LOG_FUNCTION();
  296. int old_count = vtCameraList.size();
  297. if(old_count > 0) {
  298. DestoryCamereBuckets(vtCameraList);
  299. }
  300. GetCameraInfors(vtCameraList);
  301. return old_count;
  302. }
  303. int ExclusiveCameraBuckes(const CAMERA_BUCKET& lhs, const CAMERA_BUCKET& rhs, CAMERA_BUCKET& diff)
  304. {
  305. int count = 0;
  306. const size_t l_size = lhs.size();
  307. const size_t r_size = rhs.size();
  308. if(!diff.empty()) {
  309. DestoryCamereBuckets(diff);
  310. }
  311. //Is it necessary to sort before doing comparation job ?
  312. if(l_size > r_size) {
  313. for(CAMERA_BUCKET_CITER citer=lhs.cbegin(); citer!=lhs.cend(); ++citer) {
  314. auto aim = std::find_if(rhs.cbegin(), rhs.cend(), [citer](PCAMERA_INFOR_ITEM const item){
  315. return !strcmp(item->szDevPath, (*citer)->szDevPath);
  316. });
  317. if(aim == rhs.cend()) {
  318. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  319. if(item != NULL) {
  320. item->Copy((*citer));
  321. diff.push_back(item);
  322. count++;
  323. }
  324. }
  325. }
  326. } else if(l_size < r_size) {
  327. for(CAMERA_BUCKET_CITER citer=rhs.cbegin(); citer!=rhs.cend(); ++citer) {
  328. auto aim = std::find_if(lhs.cbegin(), lhs.cend(), [citer](PCAMERA_INFOR_ITEM const item){
  329. return !strcmp(item->szDevPath, (*citer)->szDevPath);
  330. });
  331. if(aim == lhs.cend()) {
  332. PCAMERA_INFOR_ITEM item = new CAMERA_INFOR_ITEM();
  333. if(item != NULL) {
  334. item->Copy((*citer));
  335. diff.push_back(item);
  336. count++;
  337. }
  338. }
  339. }
  340. }
  341. return count;
  342. }
  343. void DisplayCameraInfos(const CAMERA_BUCKET& vtCameraList)
  344. {
  345. for(CAMERA_BUCKET_CITER it=vtCameraList.cbegin(); it!=vtCameraList.cend(); ++it) {
  346. if(*it) {
  347. (*it)->Display();
  348. }else {
  349. LOG_ASSERT(!"Empty elememt occurs !!");
  350. }
  351. }
  352. }