video_render.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. #include "video_render.h"
  2. #include "SpBase.h"
  3. #include "Event.h"
  4. #include "videoutil.h"
  5. #include "libvideoqueue.h"
  6. #include "rvc_media_common.h"
  7. #include "fileutil.h"
  8. #include "video_common/ffmpeg_api_cpp_adapter.h"
  9. #include "cv.h"
  10. #include "highgui.h"
  11. #include "y2k_time.h"
  12. static int translate_image_resolution(video_frame** dstframe, const int iwidth, const int iheight, const video_frame* psrcframe)
  13. {
  14. int i = -1;
  15. if (iwidth == psrcframe->width && iheight == psrcframe->height) {
  16. return i;
  17. }
  18. video_frame* pframe = video_frame_new(iwidth, iheight, VIDEO_FORMAT_RGB24);
  19. video_frame_fill_black(pframe);
  20. SwsContext* sws = sws_getCachedContext(NULL, psrcframe->width, psrcframe->height,
  21. PIX_FMT_BGR24,
  22. iwidth,
  23. iheight,
  24. PIX_FMT_BGR24,
  25. SWS_LANCZOS,
  26. NULL,
  27. NULL,
  28. NULL);
  29. sws_scale(sws, psrcframe->data, psrcframe->linesize, 0, psrcframe->height, pframe->data, pframe->linesize);
  30. sws_freeContext(sws);
  31. *dstframe = pframe;
  32. i = 0;
  33. return i;
  34. }
  35. static int rvc_video_shm_enqueue(Clibvideoqueue* shm_queue, video_frame* frame, int flags, int iframeid)
  36. {
  37. videoq_frame tmp_frm;
  38. tmp_frm.data = frame->data[0];
  39. tmp_frm.framesize = frame->width * frame->height * 3;
  40. tmp_frm.format = VIDEOQ_FORMAT_RGB24;
  41. tmp_frm.width = frame->width;
  42. tmp_frm.height = frame->height;
  43. tmp_frm.iframeid = iframeid;
  44. unsigned int nowtime = y2k_time_now();
  45. if (!shm_queue->InsertVideo(&tmp_frm, flags, nowtime)){
  46. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("caution: rvc render shm_queue video insert shm video failed!");
  47. return Error_Unexpect;
  48. }
  49. else{
  50. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("video render shm_queue video insert shm video ok, and nowtime is %d, and frame id is %d.", nowtime, iframeid);
  51. return Error_Succeed;
  52. }
  53. }
  54. static bool get_local_video_frame(video_frame** frame, int itype, Clibvideoqueue* local_video_queue, int iwidth, int iheight, IplImage* personimage, IplImage* personmask)
  55. {
  56. bool result = false;
  57. video_frame* tmp_frame_preview = NULL;
  58. tmp_frame_preview = video_frame_new(iwidth, iheight, VIDEO_FORMAT_RGB24);
  59. if (NULL == tmp_frame_preview) {
  60. return result;
  61. }
  62. videoq_frame frm;
  63. frm.data = tmp_frame_preview->data[0];
  64. //static bool blog = true;
  65. //if (blog) {
  66. // int ivideo_width = 0;
  67. // int ivideo_height = 0;
  68. // int isize = local_video_queue->GetFrameSize(ivideo_width, ivideo_height);
  69. // blog = false;
  70. //}
  71. result = local_video_queue->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP);
  72. if (result){
  73. if (1 == itype) {
  74. if (NULL != personimage && NULL != personmask)
  75. {
  76. IplImage* img = cvCreateImageHeader(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3);
  77. img->imageData = (char*)frm.data;
  78. if (frm.width != personimage->width) {
  79. IplImage* tmp = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3);
  80. IplImage* tmpmask = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 1);
  81. cvResize(personimage, tmp);
  82. cvResize(personmask, tmpmask);
  83. cvAdd(img, tmp, img, tmpmask);
  84. cvReleaseImage(&tmp);
  85. cvReleaseImage(&tmpmask);
  86. }
  87. else {
  88. cvAdd(img, personimage, img, personmask);
  89. }
  90. cvReleaseImageHeader(&img);
  91. }
  92. }
  93. *frame = tmp_frame_preview;
  94. }
  95. else {
  96. video_frame_delete(tmp_frame_preview);
  97. tmp_frame_preview = NULL;
  98. }
  99. return result;
  100. }
  101. int rvc_remote_video_render(rvc_video_render_t* prender, void* videoframe)
  102. {
  103. if (NULL != prender && NULL != videoframe) {
  104. if (NULL != prender->premote_render) {
  105. video_frame* echoframe = NULL;
  106. if (0 == translate_image_resolution(&echoframe, prender->render_param.iremote_view_cx, prender->render_param.iremote_view_cy, (const video_frame*)videoframe)) {
  107. prender->premote_render->RenderVideoFrame(echoframe, RVC_FLIP_VERTICAL);
  108. video_frame_delete(echoframe);
  109. echoframe = NULL;
  110. }
  111. else {
  112. prender->premote_render->RenderVideoFrame((video_frame*)videoframe, RVC_FLIP_VERTICAL);
  113. }
  114. }
  115. }
  116. return 0;
  117. }
  118. static int rvc_getrender_videoqueue(Clibvideoqueue** render_video_queue, int* render_width, int* render_height, RVC_RendererFlip* renderflip, rvc_video_render_t* param)
  119. {
  120. int iret = -1;
  121. int irender_camera = CAMERA_TYPE_ENV;
  122. if (param->render_param.ilocal_view_cx < param->render_param.ilocal_view_cy) {
  123. irender_camera = CAMERA_TYPE_OPT;
  124. }
  125. if (CAMERA_TYPE_ENV == irender_camera) {
  126. if (ePreview_Queue == param->render_param.erender_queue) {
  127. *render_video_queue = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE);
  128. *render_width = REC_COMMON_VIDEO_PREVIEW_WIDTH;
  129. *render_height = REC_COMMON_VIDEO_PREVIEW_HEIGHT;
  130. }
  131. else {
  132. *render_video_queue = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE);
  133. *render_width = REC_COMMON_VIDEO_SNAPSHOT_WIDTH;
  134. *render_height = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT;
  135. }
  136. #ifdef RVC_OS_WIN
  137. *renderflip = RVC_FLIP_HORIZONTAL;
  138. #endif // RVC_OS_WIN
  139. }
  140. else {
  141. if (ePreview_Queue == param->render_param.erender_queue) {
  142. *render_video_queue = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_PREVIEW_QUEUE);
  143. *render_width = REC_COMMON_VIDEO_PREVIEW_HEIGHT;
  144. *render_height = REC_COMMON_VIDEO_PREVIEW_WIDTH;
  145. }
  146. else {
  147. *render_video_queue = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE);
  148. *render_width = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT;
  149. *render_height = REC_COMMON_VIDEO_SNAPSHOT_WIDTH;
  150. }
  151. #ifdef RVC_OS_WIN
  152. *renderflip = RVC_FLIP_NONE;
  153. #else
  154. *renderflip = RVC_FLIP_HORIZONTAL;
  155. #endif
  156. }
  157. iret = 0;
  158. return iret;
  159. }
  160. static int rvc_getrxkimage(IplImage** personimage, IplImage** personmask)
  161. {
  162. int iret = -1;
  163. char strPersonPath[MAX_PATH] = { 0 };
  164. _snprintf(strPersonPath, MAX_PATH, "./bin/rxk.jpg");
  165. if (ExistsFile(strPersonPath)) {
  166. *personimage = cvLoadImage(strPersonPath);
  167. *personmask = cvLoadImage(strPersonPath, 0);
  168. iret = 0;
  169. }
  170. return iret;
  171. }
  172. static int rvc_setrender_property(IVideoRender* pRender, rvc_video_render_params_t* param, bool blocal)
  173. {
  174. int iret = -1;
  175. if (NULL == pRender || NULL == param) {
  176. return iret;
  177. }
  178. videorender_param_t tparam = { 0 };
  179. if (blocal) {
  180. tparam.icx = param->ilocal_view_x;
  181. tparam.icy = param->ilocal_view_y;
  182. tparam.uwidth = param->ilocal_view_cx;
  183. tparam.uheight = param->ilocal_view_cy;
  184. }
  185. else {
  186. tparam.icx = param->iremote_view_x;
  187. tparam.icy = param->iremote_view_y;
  188. tparam.uwidth = param->iremote_view_cx;
  189. tparam.uheight = param->iremote_view_cy;
  190. }
  191. tparam.ivideoformat = VIDEO_FORMAT_RGB24;
  192. if (0 == pRender->VideoRenderSetParam(&tparam)) {
  193. pRender->HideVideoWindow();
  194. iret = 0;
  195. }
  196. return iret;
  197. }
  198. #ifdef RVC_OS_WIN
  199. static unsigned int __stdcall rvc_videorender_func(void* arg)
  200. #else
  201. static void* rvc_videorender_func(void* arg)
  202. #endif
  203. {
  204. rvc_video_render_t* param = (rvc_video_render_t*)arg;
  205. int ilocal_video_fresh_time = param->render_param.ilocal_fresh_time;
  206. bool bremote_video = false;
  207. Clibvideoqueue* local_video_queue = NULL;
  208. RVC_RendererFlip renderflip = RVC_FLIP_VERTICAL;
  209. int iwidth = 0;
  210. int iheight = 0;
  211. rvc_getrender_videoqueue(&local_video_queue, &iwidth, &iheight, &renderflip, param);
  212. int ivideo_width = 0;
  213. int ivideo_height = 0;
  214. int isize = local_video_queue->GetFrameSize(ivideo_width, ivideo_height);
  215. if (ivideo_width > 0 && ivideo_height > 0) {
  216. iwidth = ivideo_width;
  217. iheight = ivideo_height;
  218. }
  219. IplImage* personimage = NULL;
  220. IplImage* personmask = NULL;
  221. rvc_getrxkimage(&personimage, &personmask);
  222. if (NULL != param->plocal_render) {
  223. videorender_param_t tparam = { 0 };
  224. tparam.icx = param->render_param.ilocal_view_x;
  225. tparam.icy = param->render_param.ilocal_view_y;
  226. tparam.uwidth = param->render_param.ilocal_view_cx;
  227. tparam.uheight = param->render_param.ilocal_view_cy;
  228. tparam.ivideoformat = VIDEO_FORMAT_RGB24;
  229. if (0 == param->plocal_render->VideoRenderSetParam(&tparam)) {
  230. param->plocal_render->HideVideoWindow();
  231. }
  232. else {
  233. return 0;
  234. }
  235. }
  236. if (0 != param->render_param.iremote_view_cx && 0 != param->render_param.iremote_view_cy) {
  237. if (NULL != param->premote_render) {
  238. videorender_param_t tparam_remote = { 0 };
  239. tparam_remote.icx = param->render_param.iremote_view_x;
  240. tparam_remote.icy = param->render_param.iremote_view_y;
  241. tparam_remote.uwidth = param->render_param.iremote_view_cx;
  242. tparam_remote.uheight = param->render_param.iremote_view_cy;
  243. tparam_remote.ivideoformat = VIDEO_FORMAT_RGB24;
  244. if (0 != param->premote_render->VideoRenderSetParam(&tparam_remote)) {
  245. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("video render set param failed.");
  246. }
  247. bremote_video = true;
  248. }
  249. else {
  250. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("remote video render is null.");
  251. }
  252. }
  253. if (NULL != param->plocal_render) {
  254. bool bshow_local = false;
  255. bool bset = true;
  256. param->plocal_render->StartVideoRender();
  257. ivideo_width = 0;
  258. ivideo_height = 0;
  259. isize = local_video_queue->GetFrameSize(ivideo_width, ivideo_height);
  260. for (; ; ) {
  261. #ifdef RVC_OS_WIN
  262. DWORD dwRet = WaitForSingleObject(param->local_render_stop_event, ilocal_video_fresh_time);
  263. if (WAIT_TIMEOUT == dwRet) {
  264. #else
  265. struct timespec ts;
  266. clock_gettime(CLOCK_REALTIME, &ts);
  267. long unsec = ts.tv_nsec + (1000 * 1000 * ilocal_video_fresh_time);
  268. ts.tv_sec += (unsec / 1000000000);
  269. ts.tv_nsec = (unsec % 1000000000);
  270. if (0 != sem_timedwait(&param->local_render_stop_sem, &ts) && (ETIMEDOUT == errno)){
  271. #endif
  272. video_frame* local_video_frame = NULL;
  273. int iwindowstate = param->cb.on_window_type(param->cb.user_data);
  274. get_local_video_frame(&local_video_frame, iwindowstate, local_video_queue, iwidth, iheight, personimage, personmask);
  275. if (NULL != local_video_frame) {
  276. video_frame* localframe = NULL;
  277. if (0 == translate_image_resolution(&localframe, param->render_param.ilocal_view_cx, param->render_param.ilocal_view_cy, local_video_frame)) {
  278. param->plocal_render->RenderVideoFrame(localframe, renderflip);
  279. video_frame_delete(localframe);
  280. localframe = NULL;
  281. }
  282. else {
  283. param->plocal_render->RenderVideoFrame(local_video_frame, renderflip);
  284. }
  285. bshow_local = true;
  286. video_frame_delete(local_video_frame);
  287. local_video_frame = NULL;
  288. }
  289. }
  290. else {
  291. param->plocal_render->HideVideoWindow();
  292. break;
  293. }
  294. if (bset) {
  295. if (bshow_local) {
  296. param->plocal_render->ShowVideoWindow();
  297. if (bremote_video) {
  298. param->premote_render->ShowVideoWindow();
  299. }
  300. bset = false;
  301. }
  302. }
  303. }
  304. param->plocal_render->StopVideoRender();
  305. }
  306. if (NULL != personimage) {
  307. cvReleaseImage(&personimage);
  308. }
  309. if (NULL != personmask) {
  310. cvReleaseImage(&personmask);
  311. }
  312. return 0;
  313. }
  314. static int rvc_get_agent_videoframe(video_frame** remote_frame)
  315. {
  316. int iret = -1;
  317. char strImgPath[MAX_PATH] = { 0 };
  318. _snprintf(strImgPath, MAX_PATH, "%s", "./bin/agent.jpg");
  319. int irecord_video_frame_width = REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_WIDTH;
  320. int irecord_video_frame_heigt = REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_HEIGHT;
  321. *remote_frame = video_frame_new(irecord_video_frame_width, irecord_video_frame_heigt, VIDEO_FORMAT_RGB24);
  322. video_frame_fill_black(*remote_frame);
  323. if (ExistsFileA(strImgPath)) {
  324. IplImage* img = cvLoadImage(strImgPath, 1);
  325. videoq_frame* vframe = new videoq_frame;
  326. if (NULL != img) {
  327. vframe->format = VIDEOQ_FORMAT_RGB24;
  328. vframe->framesize = img->imageSize;
  329. vframe->width = img->width;
  330. vframe->height = img->height;
  331. vframe->data = new unsigned char[img->imageSize];
  332. memcpy(vframe->data, img->imageData, img->imageSize);
  333. cvReleaseImage(&img);
  334. }
  335. SwsContext* sws = sws_getContext(vframe->width, vframe->height, PIX_FMT_BGR24,
  336. irecord_video_frame_width,
  337. irecord_video_frame_heigt,
  338. PIX_FMT_BGR24,
  339. SWS_POINT, NULL, NULL, NULL);
  340. uint8_t* src_data[4] = { (unsigned char*)vframe->data + (vframe->height - 1) * vframe->width * 3, NULL, NULL, NULL };
  341. int src_linesize[4] = { -vframe->width * 3, 0, 0, 0 };
  342. unsigned char* dst[4] = { (*remote_frame)->data[0],NULL,NULL,NULL };
  343. int dst_linesize[4] = { (*remote_frame)->linesize[0], 0, 0, 0 };
  344. sws_scale(sws, src_data, src_linesize, 0, vframe->height, dst, dst_linesize);
  345. sws_freeContext(sws);
  346. if (vframe) {
  347. delete vframe->data;
  348. delete vframe;
  349. vframe = NULL;
  350. }
  351. iret = 0;
  352. }
  353. return iret;
  354. }
  355. #ifdef RVC_OS_WIN
  356. static unsigned int __stdcall rvc_remote_videorender_func(void* arg)
  357. #else
  358. static void* rvc_remote_videorender_func(void* arg)
  359. #endif
  360. {
  361. rvc_video_render_t* param = (rvc_video_render_t*)arg;
  362. int iremote_video_fresh_time = param->render_param.iremote_fresh_time;
  363. Clibvideoqueue* video_shm_q_remote = new Clibvideoqueue(REC_COMMON_VIDEO_REMOTE_SHM_RTP_QUEUE);
  364. video_frame* remote_frame = NULL;
  365. rvc_get_agent_videoframe(&remote_frame);
  366. video_frame* showframe = NULL;
  367. if (-1 == translate_image_resolution(&showframe, param->render_param.iremote_view_cx, param->render_param.iremote_view_cy, remote_frame)) {
  368. showframe = video_frame_new(param->render_param.iremote_view_cx, param->render_param.iremote_view_cy, VIDEO_FORMAT_RGB24);
  369. video_frame_fill_black(showframe);
  370. video_frame_copy(showframe, remote_frame);
  371. }
  372. int iframeid = 0;
  373. int rc = rvc_video_shm_enqueue(video_shm_q_remote, remote_frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP, iframeid++);
  374. if (rc != Error_Succeed) {
  375. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("insert agent picture to remote video queue failed.");
  376. }
  377. for (; ; ) {
  378. #ifdef RVC_OS_WIN
  379. DWORD dwRet = WaitForSingleObject(param->remote_render_stop_event, iremote_video_fresh_time);
  380. if (WAIT_TIMEOUT == dwRet){
  381. #else
  382. struct timespec ts;
  383. clock_gettime(CLOCK_REALTIME, &ts);
  384. long unsec = ts.tv_nsec + (1000 * 1000 * iremote_video_fresh_time);
  385. ts.tv_sec += (unsec / 1000000000);
  386. ts.tv_nsec = (unsec % 1000000000);
  387. if (0 != sem_timedwait(&param->remote_render_stop_sem, &ts) && (ETIMEDOUT == errno)){
  388. #endif // RVC_OS_WIN
  389. rvc_remote_video_render(param, showframe);
  390. if (NULL != video_shm_q_remote){
  391. rc = rvc_video_shm_enqueue(video_shm_q_remote, remote_frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP, iframeid++);
  392. if (rc != Error_Succeed){
  393. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("insert agent picture to remote video queue failed.");
  394. }
  395. }
  396. }
  397. else {
  398. break;
  399. }
  400. }
  401. video_frame_delete(showframe);
  402. showframe = NULL;
  403. video_frame_delete(remote_frame);
  404. remote_frame = NULL;
  405. return 0;
  406. }
  407. #ifdef RVC_OS_WIN
  408. static unsigned int __stdcall rvc_optcam_videorender_func(void* arg)
  409. #else
  410. static void* rvc_optcam_videorender_func(void* arg)
  411. #endif
  412. {
  413. rvc_video_render_t* param = (rvc_video_render_t*)arg;
  414. int iremote_video_fresh_time = param->render_param.iremote_fresh_time;
  415. Clibvideoqueue* local_optvideo_queue = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE);
  416. int iwidth = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT;
  417. int iheight = REC_COMMON_VIDEO_SNAPSHOT_WIDTH;
  418. RVC_RendererFlip renderflip = RVC_FLIP_NONE;
  419. #ifdef RVC_OS_WIN
  420. #else
  421. renderflip = RVC_FLIP_HORIZONTAL;
  422. #endif
  423. for (; ; ) {
  424. #ifdef RVC_OS_WIN
  425. DWORD dwRet = WaitForSingleObject(param->remote_render_stop_event, iremote_video_fresh_time);
  426. if (WAIT_TIMEOUT == dwRet) {
  427. #else
  428. struct timespec ts;
  429. clock_gettime(CLOCK_REALTIME, &ts);
  430. long unsec = ts.tv_nsec + (1000 * 1000 * iremote_video_fresh_time);
  431. ts.tv_sec += (unsec / 1000000000);
  432. ts.tv_nsec = (unsec % 1000000000);
  433. if (0 != sem_timedwait(&param->remote_render_stop_sem, &ts) && (ETIMEDOUT == errno)) {
  434. #endif // RVC_OS_WIN
  435. video_frame* local_video_frame = NULL;
  436. get_local_video_frame(&local_video_frame, 0, local_optvideo_queue, iwidth, iheight, NULL, NULL);
  437. if (NULL != local_video_frame) {
  438. video_frame* localframe = NULL;
  439. if (0 == translate_image_resolution(&localframe, param->render_param.iremote_view_cx, param->render_param.iremote_view_cy, local_video_frame)) {
  440. param->premote_render->RenderVideoFrame(localframe, renderflip);
  441. video_frame_delete(localframe);
  442. localframe = NULL;
  443. }
  444. else {
  445. param->premote_render->RenderVideoFrame(local_video_frame, renderflip);
  446. }
  447. video_frame_delete(local_video_frame);
  448. local_video_frame = NULL;
  449. }
  450. }
  451. else {
  452. break;
  453. }
  454. }
  455. return 0;
  456. }
  457. int rvc_start_video_render(rvc_video_render_t* prender, eVideoRenderMode eMode, rvc_video_box_move_callback_t* cb)
  458. {
  459. int errcode = -1;
  460. if (NULL == prender) {
  461. return errcode;
  462. }
  463. #ifdef RVC_OS_WIN
  464. prender->local_render_stop_event = CreateEventA(NULL, false, false, NULL);
  465. if (NULL == prender->local_render_stop_event) {
  466. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create local stop event failed!");
  467. return Error_Resource;
  468. }
  469. prender->local_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_videorender_func, prender, 0, NULL);
  470. if (NULL == prender->local_render_thread) {
  471. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create local video render thread failed.");
  472. return Error_Resource;
  473. }
  474. if (eRender_LocalRemote == eMode || eRender_Local_Both == eMode) {
  475. prender->remote_render_stop_event = CreateEventA(NULL, false, false, NULL);
  476. if (NULL == prender->remote_render_stop_event) {
  477. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote stop event failed!");
  478. return Error_Resource;
  479. }
  480. if (eRender_LocalRemote == eMode) {
  481. prender->remote_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_remote_videorender_func, prender, 0, NULL);
  482. }
  483. else {
  484. prender->remote_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_optcam_videorender_func, prender, 0, NULL);
  485. }
  486. if (NULL == prender->remote_render_thread) {
  487. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote video render thread failed.");
  488. return Error_Resource;
  489. }
  490. }
  491. errcode = 0;
  492. #else
  493. if (0 != sem_init(&prender->local_render_stop_sem, 0, 0)) {
  494. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create local stop sem failed!");
  495. return Error_Resource;
  496. }
  497. errcode = pthread_create(&prender->local_render_threadid, NULL, rvc_videorender_func, prender);
  498. if (Error_Succeed != errcode) {
  499. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create local video render thread failed.");
  500. return Error_Resource;
  501. }
  502. if (eRender_LocalRemote == eMode || eRender_Local_Both == eMode) {
  503. if (0 != sem_init(&prender->remote_render_stop_sem, 0, 0)) {
  504. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote stop sem failed!");
  505. return Error_Resource;
  506. }
  507. if (eRender_LocalRemote == eMode) {
  508. errcode = pthread_create(&prender->remote_render_threadid, NULL, rvc_remote_videorender_func, prender);
  509. }
  510. else {
  511. errcode = pthread_create(&prender->remote_render_threadid, NULL, rvc_optcam_videorender_func, prender);
  512. }
  513. if (Error_Succeed != errcode) {
  514. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote video render thread failed.");
  515. return Error_Resource;
  516. }
  517. }
  518. #endif // RVC_OS_WIN
  519. return errcode;
  520. }
  521. int rvc_stop_video_render(rvc_video_render_t* prender)
  522. {
  523. if (NULL == prender) {
  524. return Error_Param;
  525. }
  526. #ifdef RVC_OS_WIN
  527. if (prender->local_render_stop_event) {
  528. SetEvent(prender->local_render_stop_event);
  529. }
  530. rvc_stop_remote_video_render(prender);
  531. if (NULL != prender->local_render_thread) {
  532. WaitForSingleObject(prender->local_render_thread, INFINITE);
  533. CloseHandle(prender->local_render_thread);
  534. prender->local_render_thread = NULL;
  535. }
  536. if (NULL != prender->local_render_stop_event) {
  537. CloseHandle(prender->local_render_stop_event);
  538. prender->local_render_stop_event = NULL;
  539. }
  540. #else
  541. sem_post(&prender->local_render_stop_sem);
  542. rvc_stop_remote_video_render(prender);
  543. if (prender->local_render_threadid > 0) {
  544. if (0 == pthread_join(prender->local_render_threadid, NULL)) {
  545. prender->local_render_threadid = 0;
  546. }
  547. else {
  548. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("video render thread pthread join error for %s.", strerror(errno));
  549. }
  550. }
  551. if (NULL != &prender->local_render_stop_sem) {
  552. sem_destroy(&prender->local_render_stop_sem);
  553. }
  554. #endif // RVC_OS_WIN
  555. return Error_Succeed;
  556. }
  557. int rvc_stop_remote_video_render(rvc_video_render_t* prender)
  558. {
  559. #ifdef RVC_OS_WIN
  560. if (NULL != prender->remote_render_thread) {
  561. SetEvent(prender->remote_render_stop_event);
  562. WaitForSingleObject(prender->remote_render_thread, INFINITE);
  563. CloseHandle(prender->remote_render_thread);
  564. prender->remote_render_thread = NULL;
  565. }
  566. if (NULL != prender->remote_render_stop_event) {
  567. CloseHandle(prender->remote_render_stop_event);
  568. prender->remote_render_stop_event = NULL;
  569. }
  570. #else
  571. if (prender->remote_render_threadid > 0) {
  572. sem_post(&prender->remote_render_stop_sem);
  573. if (0 == pthread_join(prender->remote_render_threadid, NULL)) {
  574. prender->remote_render_threadid = 0;
  575. }
  576. else {
  577. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("remote video render thread pthread join error for %s.", strerror(errno));
  578. }
  579. }
  580. if (NULL != &prender->remote_render_stop_sem) {
  581. sem_destroy(&prender->remote_render_stop_sem);
  582. }
  583. #endif
  584. return Error_Succeed;
  585. }