Capture.cpp 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  1. #include "stdafx.h"
  2. #include <locale.h>
  3. #include <memutil.h>
  4. #include <md5.h>
  5. #include <ipp.h>
  6. #include <intrin.h>
  7. #include "y2k_time.h"
  8. #include "rec_common.h"
  9. #include "videohorflip.h"
  10. #include "Event.h"
  11. #include "capture.h"
  12. using namespace CameraConfigManage;
  13. #define av_always_inline __inline
  14. #define inline __inline
  15. static int Bin2Str(unsigned char *x, int xlen, char *str, int str_size)
  16. {
  17. static const char *hex2char = "0123456789ABCDEF";
  18. int i, k = 0;
  19. if (str_size <= xlen * 2)
  20. return -1;
  21. for (i = 0; i < xlen; ++i) {
  22. int h = x[i] >> 4;
  23. int l = x[i] & 0xf;
  24. str[k++] = hex2char[h];
  25. str[k++] = hex2char[l];
  26. }
  27. str[k] = 0;
  28. return k;
  29. }
  30. static int translate_id(int in_direction, int idx)
  31. {
  32. int i, n, ii;
  33. n = Pa_GetDeviceCount();
  34. for (i = 0, ii = 0; i < n; ++i) {
  35. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  36. if (in_direction) {
  37. if (info->maxInputChannels) {
  38. if (ii == idx) {
  39. return i;
  40. }
  41. ii++;
  42. }
  43. } else {
  44. if (info->maxOutputChannels) {
  45. if (ii == idx) {
  46. return i;
  47. }
  48. ii++;
  49. }
  50. }
  51. }
  52. return -1;
  53. }
  54. static int StreamCallback(const void *input,
  55. void *output,
  56. unsigned long frameCount,
  57. const PaStreamCallbackTimeInfo* timeInfo,
  58. PaStreamCallbackFlags statusFlags,
  59. void *userData)
  60. {
  61. audio_capture_t *audio_cap = (audio_capture_t*)userData;
  62. if (input) {
  63. audio_frame frm;
  64. frm.bitspersample = 16;
  65. frm.format = 1;
  66. frm.data = (char*)const_cast<void*>(input);
  67. frm.framesize = frameCount << 1;
  68. frm.nchannels = 1;
  69. frm.samplespersec = CAPTURE_CLOCK;
  70. if (!audio_cap->shm_queue->InsertAudio(&frm)) {
  71. Dbg("Insert audio for video echo failed! frameCount:%d", frameCount);
  72. }
  73. }
  74. if (output) {
  75. memset(output, 0, frameCount<<1);
  76. }
  77. return paContinue;
  78. }
  79. static audio_capture_t *audio_capture_create(capture_t *cap)
  80. {
  81. audio_capture_t *audio_cap = ZALLOC_T(audio_capture_t);
  82. if (audio_cap) {
  83. audio_cap->parent = cap;
  84. audio_cap->shm_queue = new Clibaudioqueue(REC_COMMON_AUDIO_SHM_QUEUE);
  85. }
  86. return audio_cap;
  87. }
  88. static void audio_capture_destroy(audio_capture_t *audio_cap)
  89. {
  90. delete audio_cap->shm_queue;
  91. free(audio_cap);
  92. }
  93. static int audio_capture_start(audio_capture_t *audio_cap)
  94. {
  95. capture_t *cap = audio_cap->parent;
  96. PaStreamParameters inParam = {0};
  97. PaStreamParameters outParam = {0};
  98. PaError paError;
  99. const PaDeviceInfo *info;
  100. int nId = capture_get_audio_device_id(true, cap->config.strAudioIn);
  101. if (nId == -1)
  102. {
  103. return Error_AudioIN;
  104. }
  105. int in_dev_id = translate_id(TRUE, nId);
  106. if (in_dev_id < 0) {
  107. Dbg("audio in dev translate failed!");
  108. return Error_AudioIN;
  109. }
  110. info = Pa_GetDeviceInfo(in_dev_id);
  111. if (!info) {
  112. Dbg("get device info failed!");
  113. return Error_AudioIN;
  114. }
  115. inParam.channelCount = 1;
  116. inParam.device = in_dev_id;
  117. inParam.suggestedLatency = info->defaultLowInputLatency;
  118. inParam.sampleFormat = paInt16;
  119. inParam.hostApiSpecificStreamInfo = NULL;
  120. if (Pa_IsFormatSupported(&inParam, NULL, CAPTURE_CLOCK) != paNoError) {
  121. Dbg("audio capture create error, cannot open audio input device");
  122. return Error_AudioIN;
  123. }
  124. //打开流设备,可以用以下代码替换paError = Pa_OpenStream(&audio_cap->stream, &inParam, &outParam, CAPTURE_CLOCK,
  125. //CAPTURE_FRAME_TIME * CAPTURE_CLOCK/1000, paClipOff|paDitherOff, &StreamCallback, audio_cap);
  126. paError = Pa_OpenStream(&audio_cap->stream, &inParam, NULL, CAPTURE_CLOCK,
  127. CAPTURE_FRAME_TIME * CAPTURE_CLOCK/1000, paClipOff|paDitherOff, &StreamCallback, audio_cap);
  128. if (paError != paNoError) {
  129. Dbg("portaudio open stream failed! paError = %d", paError);
  130. return Error_AudioIN;
  131. }
  132. paError = Pa_StartStream(audio_cap->stream);
  133. if (paError != paNoError) {
  134. Dbg("portaudio start stream failed! paError = %d", paError);
  135. return Error_AudioIN;
  136. }
  137. return Error_Succeed;
  138. }
  139. static void audio_capture_stop(audio_capture_t *audio_cap)
  140. {
  141. if (audio_cap->stream) {
  142. Pa_AbortStream(audio_cap->stream);
  143. Pa_CloseStream(audio_cap->stream);
  144. audio_cap->stream = NULL;
  145. }
  146. }
  147. static int calc_capture_mode(int width, int height, int *mode)
  148. {
  149. const struct {
  150. int mode;
  151. int width;
  152. int height;
  153. } modes [] = {
  154. {VIDEOCAP_FRAME_SQCIF, VIDEOCAP_SQCIF_WIDTH, VIDEOCAP_SQCIF_HEIGHT},
  155. {VIDEOCAP_FRAME_QQVGA, VIDEOCAP_QQVGA_WIDTH, VIDEOCAP_QQVGA_HEIGHT},
  156. {VIDEOCAP_FRAME_QCIF, VIDEOCAP_QCIF_WIDTH, VIDEOCAP_QCIF_HEIGHT},
  157. {VIDEOCAP_FRAME_QVGA, VIDEOCAP_QVGA_WIDTH, VIDEOCAP_QVGA_HEIGHT},
  158. {VIDEOCAP_FRAME_CIF, VIDEOCAP_CIF_WIDTH, VIDEOCAP_CIF_HEIGHT},
  159. {VIDEOCAP_FRAME_VGA, VIDEOCAP_VGA_WIDTH, VIDEOCAP_VGA_HEIGHT},
  160. {VIDEOCAP_FRAME_4CIF, VIDEOCAP_4CIF_WIDTH, VIDEOCAP_4CIF_HEIGHT},
  161. {VIDEOCAP_FRAME_SVGA, VIDEOCAP_SVGA_WIDTH, VIDEOCAP_SVGA_HEIGHT},
  162. {VIDEOCAP_FRAME_NHD, VIDEOCAP_NHD_WIDTH, VIDEOCAP_NHD_HEIGHT},
  163. {VIDEOCAP_FRAME_SXGA, VIDEOCAP_SXGA_WIDTH, VIDEOCAP_SXGA_HEIGHT},
  164. {VIDEOCAP_FRAME_720P, VIDEOCAP_720P_WIDTH, VIDEOCAP_720P_HEIGHT},
  165. {VIDEOCAP_FRAME_1080P, VIDEOCAP_1080P_WIDTH, VIDEOCAP_1080P_HEIGHT},
  166. };
  167. int i;
  168. for (i = 0; i < array_size(modes); ++i) {
  169. if (modes[i].width == width && modes[i].height == height) {
  170. *mode = modes[i].mode;
  171. return 0;
  172. }
  173. }
  174. return Error_NotExist;
  175. }
  176. static int video_shm_enqueue(Clibvideoqueue *shm_queue, video_frame *frame, int flags)
  177. {
  178. videoq_frame tmp_frm;
  179. tmp_frm.data = frame->data[0];
  180. tmp_frm.framesize = frame->width * frame->height * 3;
  181. tmp_frm.format = VIDEOQ_FORMAT_RGB24;
  182. tmp_frm.width = frame->width;
  183. tmp_frm.height = frame->height;
  184. unsigned int nowtime = y2k_time_now();
  185. if (!shm_queue->InsertVideo(&tmp_frm, flags,nowtime)) {
  186. Dbg("caution: insert shm video failed!");
  187. return Error_Unexpect;
  188. } else {
  189. //Dbg("insert shm video ok!");
  190. return Error_Succeed;
  191. }
  192. }
  193. static void cap_on_frame(void *user_data, video_frame *frame)
  194. {
  195. video_capture_t *video_cap = (video_capture_t *)user_data;
  196. capture_t *cap = video_cap->parent;
  197. int rc;
  198. int flip = -1;
  199. if (cap->config.video_rotate == 0){
  200. flip = 0;
  201. }
  202. else if (cap->config.video_rotate == 180){
  203. flip = (VIDEOQUEUE_FLAG_VERTICAL_FLIP|VIDEOQUEUE_FLAG_HORIZONTAL_FLIP);
  204. }
  205. else {
  206. return;
  207. }
  208. video_cap->frame_id++;
  209. //Dbg("start echo on frame, id=%d, tick=%d", video_cap->frame_id, GetTickCount());
  210. /*IplImage*img = NULL;
  211. img = cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,3);
  212. img->imageData = (char*)frame->data[0];
  213. cvSaveImage("c:\\echo.jpg", img,0);
  214. cvReleaseImageHeader(&img);*/
  215. //// snapshot
  216. //if (rc==Error_Succeed)
  217. //{
  218. // if (*cap->config.ref_capture_count)
  219. // {
  220. // Dbg("echo camera ref_env_capture_count=%d",*cap->config.ref_capture_count);
  221. // InterlockedDecrement(cap->config.ref_capture_count);
  222. // LogEvent(Severity_Middle, MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENV, "agent capture env ok, and capture env finished!");
  223. // }
  224. //}
  225. // preview 320x240
  226. {
  227. video_frame preview_frame;
  228. video_frame_alloc(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24, &preview_frame);
  229. memset(preview_frame.data[0], 0, preview_frame.height*preview_frame.linesize[0]);
  230. uint8_t *dst_data[4] = {preview_frame.data[0] + 30 * preview_frame.linesize[0], 0, 0, 0}; // 320x180 paste to 320x240
  231. sws_scale(video_cap->preview_sws_ctx, frame->data, frame->linesize, 0, frame->height, dst_data, preview_frame.linesize);
  232. video_shm_enqueue(video_cap->preview_shm_queue, &preview_frame, flip);
  233. video_frame_free(&preview_frame);
  234. }
  235. //Dbg("end echo on frame, id=%d, tick=%d", video_cap->frame_id, GetTickCount());;
  236. }
  237. static video_capture_t *video_capture_create(capture_t *cap, int camera_type)
  238. {
  239. video_capture_t *video_cap = ZALLOC_T(video_capture_t);
  240. if (video_cap) {
  241. video_cap->parent = cap;
  242. video_cap->camera_type = camera_type;
  243. video_cap->frame_id = 0;
  244. if (camera_type == CAMERA_TYPE_ENV) { // need to be edited
  245. video_cap->preview_shm_queue = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE);
  246. video_cap->preview_sws_ctx = sws_getContext(REC_COMMON_VIDEO_SNAPSHOT_WIDTH,
  247. REC_COMMON_VIDEO_SNAPSHOT_HEIGHT,
  248. PIX_FMT_BGR24,
  249. REC_COMMON_VIDEO_RTP_ENV_WIDTH,
  250. REC_COMMON_VIDEO_RTP_ENV_HEIGHT,
  251. PIX_FMT_BGR24,
  252. SWS_FAST_BILINEAR, NULL, NULL, NULL);
  253. }
  254. }
  255. return video_cap;
  256. }
  257. static void video_capture_destroy(video_capture_t *video_cap)
  258. {
  259. if (video_cap) {
  260. if (video_cap->preview_sws_ctx) {
  261. sws_freeContext(video_cap->preview_sws_ctx);
  262. video_cap->preview_sws_ctx = NULL;
  263. }
  264. if (video_cap->preview_shm_queue) {
  265. delete video_cap->preview_shm_queue;
  266. video_cap->preview_shm_queue = NULL;
  267. }
  268. free(video_cap);
  269. }
  270. }
  271. static int video_capture_start(video_capture_t *video_cap)
  272. {
  273. capture_config_t *conf = &video_cap->parent->config;
  274. int dev_id;
  275. if (video_cap->camera_type == CAMERA_TYPE_ENV)
  276. {
  277. capture_camera_t tmp;
  278. dev_id = capture_get_video_device_id(conf->strVideo,tmp);
  279. if (dev_id == -1)
  280. {
  281. Dbg("No echo camera,please check config file or device!");
  282. return -1;
  283. }
  284. }
  285. videocap_param param = {0};
  286. int cap_mode;
  287. int rc = -1;
  288. rc = calc_capture_mode(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_HEIGHT, &cap_mode);
  289. if (rc != 0)
  290. {
  291. Dbg("calc cap_mode failed!");
  292. return rc;
  293. }
  294. param.cap_mode = cap_mode;
  295. param.dev_id = dev_id;
  296. param.frame_fmt = VIDEO_FORMAT_RGB24;
  297. if ((ePadtype == g_eDeviceType)||(eDesk2SType == g_eDeviceType))
  298. {
  299. param.fps = REC_COMMON_VIDEO_FPS_MOBILE;
  300. }
  301. else
  302. {
  303. param.fps = REC_COMMON_VIDEO_RAW_FPS;
  304. }
  305. param.on_frame = &cap_on_frame;
  306. param.user_data = video_cap;
  307. param.option = 0;
  308. rc = videocap_create(&video_cap->cap, &param);
  309. if (rc != 0)
  310. {
  311. Dbg("videocap create failed!");
  312. return rc;
  313. }
  314. rc = videocap_start(video_cap->cap);
  315. if (rc != 0)
  316. {
  317. Dbg("videocap start failed!");
  318. videocap_destroy(video_cap->cap);
  319. video_cap->cap = NULL;
  320. return rc;
  321. }
  322. return 0;
  323. }
  324. static void video_capture_stop(video_capture_t *video_cap)
  325. {
  326. if (video_cap->cap) {
  327. videocap_stop(video_cap->cap);
  328. videocap_destroy(video_cap->cap);
  329. video_cap->cap = NULL;
  330. }
  331. }
  332. static int audio_get_dev_count(int *in_cnt, int *out_cnt)
  333. {
  334. int icnt = 0, ocnt = 0;
  335. int cnt = Pa_GetDeviceCount();
  336. for (int i = 0; i < cnt; ++i) {
  337. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  338. if (info->maxInputChannels)
  339. icnt ++;
  340. if (info->maxOutputChannels)
  341. ocnt ++;
  342. }
  343. if (in_cnt)
  344. *in_cnt = icnt;
  345. if (out_cnt)
  346. *out_cnt = ocnt;
  347. return 0;
  348. }
  349. static CSimpleStringA audio_get_dev_name(bool in_direction, int idx)
  350. {
  351. int cnt = Pa_GetDeviceCount();
  352. int ii, i;
  353. for (i = 0, ii = 0; i < cnt; ++i) {
  354. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  355. if (in_direction) {
  356. if (info->maxInputChannels) {
  357. if (idx == ii) {
  358. return CSimpleStringA(info->name);
  359. }
  360. ii++;
  361. }
  362. } else {
  363. if (info->maxOutputChannels) {
  364. if (idx == ii) {
  365. return CSimpleStringA(info->name);
  366. }
  367. ii++;
  368. }
  369. }
  370. }
  371. return CSimpleStringA();
  372. }
  373. namespace CameraConfigManage {
  374. DeviceTypeEnum g_eDeviceType;
  375. int capture_create( const capture_config_t *config, capture_t **p_cap )
  376. {
  377. capture_t *cap = ZALLOC_T(capture_t);
  378. cap->audio = NULL;
  379. cap->video = NULL;
  380. memcpy(&cap->config, config, sizeof(capture_config_t));
  381. cap->audio = audio_capture_create(cap);
  382. if (!cap->audio) {
  383. Dbg("create audio capture object failed!");
  384. return Error_Unexpect;
  385. }
  386. capture_camera_t tmp;
  387. int dev_id = capture_get_video_device_id(config->strVideo,tmp);
  388. if (dev_id != -1)
  389. {
  390. cap->video = video_capture_create(cap, CAMERA_TYPE_ENV);
  391. if (!cap->video) {
  392. Dbg("create echo video object failed!");
  393. return Error_Unexpect;
  394. }
  395. }
  396. if(dev_id == -1)
  397. {
  398. Dbg("echo camera deviceid error!");
  399. capture_destroy(cap);
  400. return Error_Unexpect;
  401. }
  402. else
  403. {
  404. *p_cap = cap;
  405. return 0;
  406. }
  407. }
  408. // 重启摄像头用到
  409. ErrorCodeEnum capture_create( const capture_config_t *config,capture_t *cap )
  410. {
  411. capture_camera_t tmp;
  412. int dev_id = capture_get_video_device_id(config->strVideo,tmp);
  413. if((dev_id != -1)&&(cap->video == NULL))
  414. {
  415. cap->video = video_capture_create(cap, CAMERA_TYPE_ENV);
  416. if (!cap->video)
  417. {
  418. Dbg("create echo video object failed!");
  419. return Error_Unexpect;
  420. }
  421. }
  422. else
  423. {
  424. return Error_Unexpect;
  425. }
  426. return Error_Succeed;
  427. }
  428. void capture_destroy( capture_t *cap )
  429. {
  430. if (cap) {
  431. if (cap->video) {
  432. video_capture_destroy(cap->video);
  433. cap->video = NULL;
  434. }
  435. if (cap->audio) {
  436. audio_capture_destroy(cap->audio);
  437. cap->audio = NULL;
  438. }
  439. free(cap);
  440. }
  441. }
  442. ErrorCodeEnum capture_start( capture_t *cap )
  443. {
  444. int rc = 0;
  445. if (cap->audio)
  446. {
  447. rc = audio_capture_start(cap->audio);
  448. if (rc != Error_Succeed)
  449. {
  450. ErrorCodeEnum rslt = (ErrorCodeEnum)rc;
  451. if (rslt == Error_AudioIN)
  452. {
  453. Dbg("start audio In object failed! rc:%d", rc);
  454. }
  455. return rslt;
  456. }
  457. }
  458. else
  459. {
  460. Dbg("start echo audio Error_Unexpect");
  461. return Error_Unexpect;
  462. }
  463. if (cap->video)
  464. {
  465. rc = video_capture_start(cap->video);
  466. if (rc != Error_Succeed)
  467. {
  468. Dbg("start echo video capture object failed! rc:%d", rc);
  469. //LogError(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_ENVCAM_OPEN,"open echo camera fail,please check device");
  470. return Error_EnvCamera;
  471. }
  472. }
  473. else
  474. {
  475. Dbg("start echo video Error_Unexpect");
  476. return Error_Unexpect;
  477. }
  478. return (ErrorCodeEnum)rc;
  479. }
  480. void capture_stop( capture_t *cap )
  481. {
  482. if (cap->audio) {
  483. audio_capture_stop(cap->audio);
  484. }
  485. if (cap->video) {
  486. video_capture_stop(cap->video);
  487. }
  488. }
  489. int capture_detect_camera_bug( capture_t *cap, int *n )
  490. {
  491. *n = 0;
  492. if (cap->video)
  493. {
  494. if (cap->video->preview_shm_queue)
  495. {
  496. *n = cap->video->preview_shm_queue->GetVideoLens();
  497. }
  498. }
  499. else
  500. {
  501. *n = -1;
  502. }
  503. return 0;
  504. }
  505. int capture_get_last_frametime( capture_t *cap, DWORD *n )
  506. {
  507. *n = 0;
  508. if (cap->video)
  509. {
  510. if (cap->video->preview_shm_queue)
  511. {
  512. *n = cap->video->preview_shm_queue->GetLastFrameTime();
  513. }
  514. }
  515. else
  516. {
  517. *n = 0;
  518. }
  519. return 0;
  520. }
  521. int capture_lib_init()
  522. {
  523. HRESULT hr = CoInitialize(NULL);
  524. int rc;
  525. {
  526. HMODULE hModule = GetModuleHandleA("MSVCR100.dll");
  527. if (hModule) {
  528. typedef char *(*f_setlocale)(int, const char*);
  529. f_setlocale f = (f_setlocale)GetProcAddress(hModule, "setlocale");
  530. (*f)(LC_ALL, "chs");
  531. }
  532. }
  533. if (SUCCEEDED(hr)) {
  534. PaError Error;
  535. Error = Pa_Initialize();
  536. if (Error == paNoError) {
  537. rc = videoframework_init();
  538. if (rc != 0) {
  539. Dbg("videoframework_init failed, rc=%d", rc);
  540. return Error_Resource;
  541. }
  542. } else {
  543. Dbg("PaInitialize failed, rc=%d", Error);
  544. return Error_Resource;
  545. }
  546. } else {
  547. Dbg("coinitialze failed! hr:%d", hr);
  548. return Error_Resource;
  549. }
  550. {
  551. int i, n;
  552. n = videocap_get_device_count();
  553. for (i = 0; i < n; ++i) {
  554. WCHAR tmp[256];
  555. char t[256];
  556. WCHAR tmp1[256];
  557. char t1[256];
  558. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  559. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  560. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  561. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  562. capture_md5(t1);
  563. Dbg("%d = %s;%s", i, t, t1);
  564. }
  565. }
  566. {
  567. int icnt, ocnt;
  568. rc = audio_get_dev_count(&icnt, &ocnt);
  569. if (rc == 0) {
  570. int i;
  571. Dbg("audio input devices(%d):", icnt);
  572. for (i = 0; i < icnt; ++i) {
  573. CSimpleStringA str = audio_get_dev_name(true, i);
  574. Dbg("%d = %s", i, (LPCSTR)str);
  575. }
  576. Dbg("audio output devices(%d):", ocnt);
  577. for (i = 0; i < ocnt; ++i) {
  578. CSimpleStringA str = audio_get_dev_name(false, i);
  579. Dbg("%d = %s", i, (LPCSTR)str);
  580. }
  581. }
  582. }
  583. return Error_Succeed;
  584. }
  585. void capture_lib_term()
  586. {
  587. videoframework_term();
  588. Pa_Terminate();
  589. CoUninitialize();
  590. }
  591. int capture_get_audio_device_id( bool in_direction, const char *dev_name )
  592. {
  593. int cnt = Pa_GetDeviceCount();
  594. int ii, i;
  595. for (i = 0, ii = 0; i < cnt; ++i) {
  596. const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
  597. if (in_direction) {
  598. if (info->maxInputChannels) {
  599. if (strstr(info->name, dev_name) != NULL) {
  600. return ii;
  601. }
  602. ii++;
  603. }
  604. } else {
  605. if (info->maxOutputChannels) {
  606. if (strstr(info->name, dev_name) != NULL) {
  607. return ii;
  608. }
  609. ii++;
  610. }
  611. }
  612. }
  613. return -1;
  614. }
  615. //int capture_get_video_device_id( const char *dev_name )
  616. //{
  617. // int i, n;
  618. //
  619. // n = videocap_get_device_count();
  620. // for (i = 0; i < n; ++i) {
  621. // WCHAR tmp[256];
  622. // char t[256];
  623. // WCHAR tmp1[256];
  624. // char t1[256];
  625. // videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  626. // WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  627. // videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  628. // WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  629. // capture_md5(t1);
  630. // strcat(t, ";");
  631. // strcat(t, t1);
  632. // if (strcmp(dev_name, t) == 0)
  633. // return i;
  634. // }
  635. // return -1; // not found
  636. //}
  637. int capture_get_video_device_id(const char *dev_name, capture_camera_t &camera)
  638. {
  639. int i, n;
  640. n = videocap_get_device_count();
  641. for (i = 0; i < n; ++i) {
  642. WCHAR tmp[256];
  643. char t[256];
  644. WCHAR tmp1[256];
  645. char t1[256];
  646. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  647. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  648. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  649. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  650. // save DevicePath (add by ly at 20160725)
  651. char t2[256];
  652. strcpy(t2,t1);
  653. for (int j = 0; j < strlen(t2); ++j)
  654. {
  655. t2[j] = toupper(t2[j]);
  656. if (t2[j] == '#') t2[j] = '\\';
  657. }
  658. capture_md5(t1);
  659. if (dev_name != NULL && strlen(dev_name) > 1
  660. && strstr(dev_name, ";") == NULL) // 外接摄像头 add by ly at 20160531
  661. {
  662. if (strstr(t2,dev_name) != NULL) // 判断外接摄像头DeviceLocationPaths是否是DevicePath的子串
  663. {
  664. camera.strFriendlyName = t;
  665. camera.strDevPath = t2;
  666. camera.strMd5Val = t1;
  667. return i;
  668. }
  669. if (strcmp(dev_name, t) == 0) // 如果是直接用友好名称查询(适用于高拍仪) add by ly 2017/11/08
  670. return i;
  671. }
  672. else
  673. {
  674. char t3[256];
  675. strcpy(t3,t);
  676. strcat(t3, ";");
  677. strcat(t3, t1);
  678. if (strcmp(dev_name, t3) == 0){
  679. camera.strFriendlyName = t;
  680. camera.strDevPath = t2;
  681. camera.strMd5Val = t1;
  682. return i;
  683. }
  684. }
  685. }
  686. return -1; // not found
  687. }
  688. bool capture_check_video_device_match( const char *dev_name, const char*dev_inst_path )
  689. {
  690. int i, n;
  691. n = videocap_get_device_count();
  692. for (i = 0; i < n; ++i) {
  693. WCHAR tmp[256];
  694. char t[256];
  695. WCHAR tmp1[256];
  696. char t1[256];
  697. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  698. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  699. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  700. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  701. // save DevicePath (add by ly at 20160725)
  702. char t2[256];
  703. strcpy(t2,t1);
  704. for (int j = 0; j < strlen(t2); ++j)
  705. {
  706. t2[j] = toupper(t2[j]);
  707. if (t2[j] == '#') t2[j] = '\\';
  708. }
  709. capture_md5(t1);
  710. strcat(t, ";");
  711. strcat(t, t1);
  712. if (strstr(t2,dev_inst_path) != NULL)
  713. {
  714. Dbg("[dbg] %s founded in %d cameras.", dev_inst_path, n);
  715. if (strcmp(dev_name, t) == 0)
  716. return true;
  717. }
  718. }
  719. return false; // not match
  720. }
  721. bool capture_adj_brightness( capture_t *cap,int nvalue,ErrorCodeEnum nCode )
  722. {
  723. HRESULT rst = S_OK;
  724. if (cap->video&&(nCode!=Error_EnvCamera)&&(nCode!=Error_AllCamera))
  725. {
  726. rst = videocap_adj_brightness(cap->video->cap,nvalue);
  727. }
  728. if (SUCCEEDED(rst))
  729. return true;
  730. return false;
  731. }
  732. bool capture_set_autobrightness( capture_t *cap,ErrorCodeEnum nCode )
  733. {
  734. HRESULT rst = S_OK;
  735. if (cap->video&&(nCode!=Error_EnvCamera)&&(nCode!=Error_AllCamera))
  736. {
  737. rst = videocap_set_autobrightness(cap->video->cap);
  738. }
  739. if (SUCCEEDED(rst))
  740. return true;
  741. return false;
  742. }
  743. int capture_get_brightness( capture_t *cap,ErrorCodeEnum nCode )
  744. {
  745. int nValue=0;
  746. HRESULT rst = S_OK;
  747. if (cap->video&&(nCode!=Error_EnvCamera)&&(nCode!=Error_AllCamera))
  748. {
  749. HRESULT rst = videocap_get_brightness(cap->video->cap,&nValue);
  750. }
  751. else
  752. {
  753. return -1;
  754. }
  755. if (SUCCEEDED(rst))
  756. {
  757. return nValue;
  758. }
  759. else
  760. {
  761. return -1;
  762. }
  763. }
  764. int stop_camera( capture_t *cap )
  765. {
  766. if (cap->video)
  767. {
  768. video_capture_stop(cap->video);
  769. video_capture_destroy(cap->video);
  770. cap->video = NULL;
  771. return 0;
  772. }
  773. else
  774. {
  775. return -1;
  776. }
  777. }
  778. void capture_enum_cameras( std::vector<capture_camera_t> &cams, CAutoArray<CSimpleStringA> &hspcams)
  779. {
  780. int i, n;
  781. cams.clear();
  782. n = videocap_get_device_count();
  783. if (n <= 0) return;
  784. int m = hspcams.GetCount(); // 高拍仪的个数
  785. for (i = 0; i < n; ++i) {
  786. WCHAR tmp[256];
  787. char t[256];
  788. WCHAR tmp1[256];
  789. char t1[256],t2[256];
  790. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  791. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  792. // 检查是否为高拍仪摄像头,若是则直接枚举下一个摄像头
  793. bool isHspCam = false;
  794. for (int k = 0; k < m; ++k) {
  795. if (!stricmp((LPCTSTR)hspcams[k],t)) {
  796. isHspCam = true;
  797. break;
  798. }
  799. }
  800. if (isHspCam) {
  801. continue;
  802. }
  803. capture_camera_t camera;
  804. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  805. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  806. // save DevicePath
  807. strcpy(t2,t1);
  808. for (int j = 0; j < strlen(t2); ++j)
  809. {
  810. t2[j] = toupper(t2[j]);
  811. if (t2[j] == '#') t2[j] = '\\';
  812. }
  813. capture_md5(t1);
  814. camera.strFriendlyName = t;
  815. camera.strDevPath = t2;
  816. camera.strMd5Val = t1;
  817. cams.push_back(camera);
  818. }
  819. }
  820. void capture_md5( char *dev_path )
  821. {
  822. if (dev_path&&strlen(dev_path)>0)
  823. {
  824. unsigned char x[MD5_DIGESTSIZE];
  825. md5_ctx_t ctx;
  826. md5_init(&ctx);
  827. md5(x, dev_path, strlen(dev_path));
  828. Bin2Str(x, sizeof(x), dev_path, strlen(dev_path));
  829. }
  830. }
  831. bool capture_get_only_video_device_by_friendlyname(const CSimpleStringA friendlyname,
  832. CAutoArray<CSimpleStringA> &excludecams, const CAutoArray<CSimpleStringA> &hspcams, capture_camera_t &camera)
  833. {
  834. int i, n;
  835. n = videocap_get_device_count();
  836. if (n <= 0) return false;
  837. int cnt = 0;
  838. int m = hspcams.GetCount(); // 高拍仪的个数
  839. for (i = 0; i < n; ++i) {
  840. WCHAR tmp[256];
  841. char t[256];
  842. WCHAR tmp1[256];
  843. char t1[256], t2[256];
  844. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  845. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  846. Dbg("[capture_get_only_video_device_by_friendlyname]%d, %s excludecams:%d.", i, t, excludecams.GetCount());
  847. // 检查是否为高拍仪摄像头,若是则直接枚举下一个摄像头
  848. bool isHspCam = false;
  849. for (int k = 0; k < m; ++k) {
  850. if (!stricmp((LPCTSTR)hspcams[k], t)) {
  851. isHspCam = true;
  852. break;
  853. }
  854. }
  855. if (isHspCam) {
  856. Dbg("[get_only_video_device_by_friendlyname]%d, %s isHspCam.", i, t);
  857. continue;
  858. }
  859. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  860. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  861. // save DevicePath
  862. strcpy(t2, t1);
  863. for (int j = 0; j < strlen(t2); ++j)
  864. {
  865. t2[j] = toupper(t2[j]);
  866. if (t2[j] == '#') t2[j] = '\\';
  867. }
  868. capture_md5(t1);
  869. // 检查是否为排除摄像头,若是则直接枚举下一个摄像头
  870. bool isExcludeCam = false;
  871. for (int k = 0; k < excludecams.GetCount(); ++k) {
  872. if (!strcmp((LPCTSTR)excludecams[k], t1)) {
  873. isExcludeCam = true;
  874. break;
  875. }
  876. }
  877. if (isExcludeCam) {
  878. Dbg("[get_only_video_device_by_friendlyname]%d, %s Md5:%s isExcludeCam.", i, t, t1);
  879. continue;
  880. }
  881. if (strcmp((LPCTSTR)friendlyname, t) == 0)
  882. {
  883. if (0 == cnt)
  884. {
  885. camera.strFriendlyName = t;
  886. camera.strDevPath = t2;
  887. camera.strMd5Val = t1;
  888. }
  889. cnt++;
  890. Dbg("[get_only_video_device_by_friendlyname]%d, %s Md5:%s DevPath:%s isFoundCam.", i, t, t1, t2);
  891. }
  892. }
  893. if (1 != cnt) // 未找到唯一摄像头
  894. {
  895. camera.strFriendlyName = "$";
  896. camera.strDevPath = "$";
  897. camera.strMd5Val = "$";
  898. return false; // not found
  899. }
  900. return true;
  901. }
  902. bool capture_get_only_video_device(CAutoArray<CSimpleStringA> &excludecams, const CAutoArray<CSimpleStringA> &hspcams, capture_camera_t &camera)
  903. {
  904. int i, n;
  905. n = videocap_get_device_count();
  906. if (n <= 0) return false;
  907. int cnt = 0;
  908. int m = hspcams.GetCount(); // 高拍仪的个数
  909. for (i = 0; i < n; ++i) {
  910. WCHAR tmp[256];
  911. char t[256];
  912. WCHAR tmp1[256];
  913. char t1[256], t2[256];
  914. videocap_get_device_name(i, tmp, ARRAYSIZE(tmp));
  915. WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL);
  916. Dbg("[capture_get_only_video_device]%d, %s excludecams:%d.", i, t, excludecams.GetCount());
  917. // 检查是否为高拍仪摄像头,若是则直接枚举下一个摄像头
  918. bool isHspCam = false;
  919. for (int k = 0; k < m; ++k) {
  920. if (!stricmp((LPCTSTR)hspcams[k], t)) {
  921. isHspCam = true;
  922. break;
  923. }
  924. }
  925. if (isHspCam) {
  926. Dbg("[capture_get_only_video_device]%d, %s isHspCam.", i, t);
  927. continue;
  928. }
  929. videocap_get_device_path(i, tmp1, ARRAYSIZE(tmp1));
  930. WideCharToMultiByte(CP_ACP, 0, tmp1, -1, t1, sizeof(t1), 0, NULL);
  931. // save DevicePath
  932. strcpy(t2, t1);
  933. for (int j = 0; j < strlen(t2); ++j)
  934. {
  935. t2[j] = toupper(t2[j]);
  936. if (t2[j] == '#') t2[j] = '\\';
  937. }
  938. capture_md5(t1);
  939. // 检查是否为排除摄像头,若是则直接枚举下一个摄像头
  940. bool isExcludeCam = false;
  941. for (int k = 0; k < excludecams.GetCount(); ++k) {
  942. if (!strcmp((LPCTSTR)excludecams[k], t1)) {
  943. isExcludeCam = true;
  944. break;
  945. }
  946. }
  947. if (isExcludeCam) {
  948. Dbg("[capture_get_only_video_device]%d, %s Md5:%s isExcludeCam.", i, t, t1);
  949. continue;
  950. }
  951. if (0 == cnt)
  952. {
  953. camera.strFriendlyName = t;
  954. camera.strDevPath = t2;
  955. camera.strMd5Val = t1;
  956. }
  957. cnt++;
  958. Dbg("[capture_get_only_video_device]%d, %s Md5:%s DevPath:%s isFoundCam.", i, t, t1, t2);
  959. }
  960. if (1 != cnt) // 未找到唯一摄像头
  961. {
  962. camera.strFriendlyName = "$";
  963. camera.strDevPath = "$";
  964. camera.strMd5Val = "$";
  965. return false; // not found
  966. }
  967. return true;
  968. }
  969. }