Capture.cpp 26 KB

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