video_render.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. #include "video_render.h"
  2. #include "SpBase.h"
  3. #include "Event.h"
  4. #include "../../Other/libvideoframework/videoutil.h"
  5. #include "../../Other/libvideoqueue/libvideoqueue.h"
  6. #include "../../Other/rvcmediacommon/rvc_media_common.h"
  7. #include "fileutil.h"
  8. extern "C"{
  9. #include <libavutil/avutil.h>
  10. #include <libavcodec/avcodec.h>
  11. #include <libswscale/swscale.h>
  12. }
  13. #include "../../Other/libvideoframework/video_common/ffmpeg_api_cpp_adapter.h"
  14. #include "cv.h"
  15. #include "highgui.h"
  16. #include "y2k_time.h"
  17. static int translate_image_resolution(video_frame** dstframe, const int iwidth, const int iheight, const video_frame* psrcframe)
  18. {
  19. int i = -1;
  20. if (iwidth == psrcframe->width && iheight == psrcframe->height) {
  21. return i;
  22. }
  23. video_frame* pframe = video_frame_new(iwidth, iheight, VIDEO_FORMAT_RGB24);
  24. video_frame_fill_black(pframe);
  25. SwsContext* sws = sws_getCachedContext(NULL, psrcframe->width, psrcframe->height,
  26. PIX_FMT_BGR24,
  27. iwidth,
  28. iheight,
  29. PIX_FMT_BGR24,
  30. SWS_LANCZOS,
  31. NULL,
  32. NULL,
  33. NULL);
  34. sws_scale(sws, psrcframe->data, psrcframe->linesize, 0, psrcframe->height, pframe->data, pframe->linesize);
  35. sws_freeContext(sws);
  36. *dstframe = pframe;
  37. i = 0;
  38. return i;
  39. }
  40. static int rvc_video_shm_enqueue(Clibvideoqueue* shm_queue, video_frame* frame, int flags)
  41. {
  42. videoq_frame tmp_frm;
  43. tmp_frm.data = frame->data[0];
  44. tmp_frm.framesize = frame->width * frame->height * 3;
  45. tmp_frm.format = VIDEOQ_FORMAT_RGB24;
  46. tmp_frm.width = frame->width;
  47. tmp_frm.height = frame->height;
  48. unsigned int nowtime = y2k_time_now();
  49. if (!shm_queue->InsertVideo(&tmp_frm, flags, nowtime)){
  50. Dbg("caution: insert shm video failed!");
  51. return Error_Unexpect;
  52. }
  53. else
  54. {
  55. //Dbg("insert shm video ok!");
  56. return Error_Succeed;
  57. }
  58. }
  59. static int get_local_video_frame(video_frame** frame, int itype, Clibvideoqueue* local_video_queue, IplImage* personimage, IplImage* personmask)
  60. {
  61. video_frame* tmp_frame_preview = NULL;
  62. tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24);
  63. videoq_frame frm;
  64. frm.data = tmp_frame_preview->data[0];
  65. //Dbg("%s:%d, session->video_shm_q_preview = 0x%08x.", __FUNCTION__, __LINE__, local_video_queue);
  66. bool result = local_video_queue->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP);
  67. if (result){
  68. if (1 == itype) {
  69. if (NULL != personimage && NULL != personmask)
  70. {
  71. IplImage* img = cvCreateImageHeader(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3);
  72. img->imageData = (char*)frm.data;
  73. if (frm.width != personimage->width) {
  74. IplImage* tmp = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3);
  75. IplImage* tmpmask = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 1);
  76. cvResize(personimage, tmp);
  77. cvResize(personmask, tmpmask);
  78. cvAdd(img, tmp, img, tmpmask);
  79. cvReleaseImage(&tmp);
  80. cvReleaseImage(&tmpmask);
  81. }
  82. else {
  83. cvAdd(img, personimage, img, personmask);
  84. }
  85. cvReleaseImageHeader(&img);
  86. }
  87. }
  88. *frame = tmp_frame_preview;
  89. }
  90. return 0;
  91. }
  92. int rvc_remote_video_render(rvc_video_render_t* prender, void* videoframe)
  93. {
  94. if (NULL != prender->premote_render) {
  95. video_frame* echoframe = NULL;
  96. if (0 == translate_image_resolution(&echoframe, prender->location_param.iremote_view_cx, prender->location_param.iremote_view_cy, (const video_frame*)videoframe)) {
  97. prender->premote_render->RenderVideoFrame(echoframe, RVC_FLIP_VERTICAL);
  98. video_frame_delete(echoframe);
  99. echoframe = NULL;
  100. }
  101. else {
  102. prender->premote_render->RenderVideoFrame((video_frame*)videoframe, RVC_FLIP_VERTICAL);
  103. }
  104. }
  105. return 0;
  106. }
  107. void* rvc_videorender_func(void* arg)
  108. {
  109. LOG_FUNCTION();
  110. rvc_video_render_t* param = (rvc_video_render_t*)arg;
  111. int ilocal_video_fresh_time = param->location_param.ilocal_fresh_time;
  112. Clibvideoqueue* local_video_queue = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE);
  113. char strPersonPath[MAX_PATH] = { 0 };
  114. snprintf(strPersonPath, MAX_PATH, "./bin/rxk.jpg");
  115. IplImage* personimage = NULL;
  116. IplImage* personmask = NULL;
  117. if (ExistsFile(strPersonPath)){
  118. personimage = cvLoadImage(strPersonPath);
  119. personmask = cvLoadImage(strPersonPath, 0);
  120. Dbg("Load person img Success");
  121. }
  122. if (NULL != param->plocal_render) {
  123. videorender_param_t tparam = { 0 };
  124. tparam.icx = param->location_param.ilocal_view_x;
  125. tparam.icy = param->location_param.ilocal_view_y;
  126. tparam.uwidth = param->location_param.ilocal_view_cx;
  127. tparam.uheight = param->location_param.ilocal_view_cy;
  128. tparam.ivideoformat = VIDEO_FORMAT_RGB24;
  129. if (0 == param->plocal_render->VideoRenderSetParam(&tparam)) {
  130. param->plocal_render->HideVideoWindow();
  131. }
  132. else {
  133. Dbg("%s:%d set video render param failed!", __FUNCTION__, __LINE__);
  134. return 0;
  135. }
  136. }
  137. if (0 != param->location_param.iremote_view_cx && 0 != param->location_param.iremote_view_cy) {
  138. Dbg("%s:%d create remote video width = %d, height = %d.", __FUNCTION__, __LINE__, param->location_param.iremote_view_cx, param->location_param.iremote_view_cy);
  139. if (NULL != param->premote_render) {
  140. videorender_param_t tparam_remote = { 0 };
  141. tparam_remote.icx = param->location_param.iremote_view_x;
  142. tparam_remote.icy = param->location_param.iremote_view_y;
  143. tparam_remote.uwidth = param->location_param.iremote_view_cx;
  144. tparam_remote.uheight = param->location_param.iremote_view_cy;
  145. tparam_remote.ivideoformat = VIDEO_FORMAT_RGB24;
  146. if (0 == param->premote_render->VideoRenderSetParam(&tparam_remote)) {
  147. Dbg("%s:%d video render set param success.",__FUNCTION__, __LINE__);
  148. }
  149. }
  150. else {
  151. Dbg("remote video render is null.");
  152. }
  153. }
  154. if (NULL != param->plocal_render) {
  155. bool bshow_local = false;
  156. bool bset = true;
  157. param->plocal_render->StartVideoRender();
  158. for (; ; ) {
  159. struct timespec ts;
  160. clock_gettime(CLOCK_REALTIME, &ts);
  161. long unsec = ts.tv_nsec + (1000 * 1000 * ilocal_video_fresh_time);
  162. ts.tv_sec += (unsec / 1000000000);
  163. ts.tv_nsec = (unsec % 1000000000);
  164. if (0 != sem_timedwait(&param->ui_stop_sem, &ts) && (ETIMEDOUT == errno))
  165. {
  166. video_frame* local_video_frame = NULL;
  167. int iwindowstate = param->cb.on_window_type(param->cb.user_data);
  168. get_local_video_frame(&local_video_frame, iwindowstate, local_video_queue, personimage, personmask);
  169. if (NULL != local_video_frame) {
  170. video_frame* localframe = NULL;
  171. if (0 == translate_image_resolution(&localframe, param->location_param.ilocal_view_cx, param->location_param.ilocal_view_cy, local_video_frame)) {
  172. param->plocal_render->RenderVideoFrame(localframe, RVC_FLIP_VERTICAL);
  173. video_frame_delete(localframe);
  174. localframe = NULL;
  175. }
  176. else {
  177. param->plocal_render->RenderVideoFrame(local_video_frame, RVC_FLIP_VERTICAL);
  178. }
  179. bshow_local = true;
  180. video_frame_delete(local_video_frame);
  181. local_video_frame = NULL;
  182. }
  183. else {
  184. Dbg("%s:%d,get video from shm preview queue failed!", __FUNCTION__, __LINE__);
  185. }
  186. }
  187. else {
  188. Dbg("%s:%d videorender_func exit!", __FUNCTION__, __LINE__);
  189. param->plocal_render->HideVideoWindow();
  190. break;
  191. }
  192. if (bset) {
  193. if (bshow_local) {
  194. param->plocal_render->ShowVideoWindow();
  195. param->premote_render->ShowVideoWindow();
  196. bset = false;
  197. }
  198. }
  199. }
  200. param->plocal_render->StopVideoRender();
  201. }
  202. if (NULL != personimage) {
  203. cvReleaseImage(&personimage);
  204. }
  205. if (NULL != personmask) {
  206. cvReleaseImage(&personmask);
  207. }
  208. return 0;
  209. }
  210. void* rvc_remote_videorender_func(void* arg)
  211. {
  212. LOG_FUNCTION();
  213. rvc_video_render_t* param = (rvc_video_render_t*)arg;
  214. int iremote_video_fresh_time = param->location_param.iremote_fresh_time;
  215. char strImgPath[MAX_PATH] = { 0 };
  216. int irecord_video_frame_width = REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_WIDTH;
  217. int irecord_video_frame_heigt = REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_HEIGHT;
  218. Clibvideoqueue* video_shm_q_remote = new Clibvideoqueue(REC_COMMON_VIDEO_REMOTE_SHM_RTP_QUEUE);
  219. _snprintf(strImgPath, MAX_PATH, "%s", "./bin/agent.jpg");
  220. video_frame* remote_frame = video_frame_new(irecord_video_frame_width, irecord_video_frame_heigt, VIDEO_FORMAT_RGB24);
  221. video_frame_fill_black(remote_frame);
  222. if (ExistsFile(strImgPath)){
  223. IplImage* img = cvLoadImage(strImgPath, 1);
  224. videoq_frame* vframe = new videoq_frame;
  225. if (NULL != img) {
  226. Dbg("load img success");
  227. vframe->format = VIDEOQ_FORMAT_RGB24;
  228. vframe->framesize = img->imageSize;
  229. vframe->width = img->width;
  230. vframe->height = img->height;
  231. vframe->data = new unsigned char[img->imageSize];
  232. memcpy(vframe->data, img->imageData, img->imageSize);
  233. cvReleaseImage(&img);
  234. }
  235. SwsContext* sws = sws_getContext(vframe->width, vframe->height, PIX_FMT_BGR24,
  236. irecord_video_frame_width,
  237. irecord_video_frame_heigt,
  238. PIX_FMT_BGR24,
  239. SWS_POINT, NULL, NULL, NULL);
  240. uint8_t* src_data[4] = { (unsigned char*)vframe->data + (vframe->height - 1) * vframe->width * 3, NULL, NULL, NULL };
  241. int src_linesize[4] = { -vframe->width * 3,0,0,0 };
  242. unsigned char* dst[4] = { remote_frame->data[0],NULL,NULL,NULL };
  243. int dst_linesize[4] = { remote_frame->linesize[0],0,0,0 };
  244. sws_scale(sws, src_data, src_linesize, 0, vframe->height, dst, dst_linesize);
  245. sws_freeContext(sws);
  246. if (vframe) {
  247. delete vframe->data;
  248. delete vframe;
  249. vframe = NULL;
  250. }
  251. }
  252. video_frame* showframe = NULL;
  253. if (-1 == translate_image_resolution(&showframe, param->location_param.iremote_view_cx, param->location_param.iremote_view_cy, remote_frame)) {
  254. showframe = video_frame_new(param->location_param.iremote_view_cx, param->location_param.iremote_view_cy, VIDEO_FORMAT_RGB24);
  255. video_frame_fill_black(showframe);
  256. video_frame_copy(showframe, remote_frame);
  257. }
  258. for (; ; ) {
  259. struct timespec ts;
  260. clock_gettime(CLOCK_REALTIME, &ts);
  261. long unsec = ts.tv_nsec + (1000 * 1000 * iremote_video_fresh_time);
  262. ts.tv_sec += (unsec / 1000000000);
  263. ts.tv_nsec = (unsec % 1000000000);
  264. if (0 != sem_timedwait(&param->remote_render_stop_sem, &ts) && (ETIMEDOUT == errno)){
  265. rvc_remote_video_render(param, showframe);
  266. if (NULL != video_shm_q_remote){
  267. int rc = rvc_video_shm_enqueue(video_shm_q_remote, remote_frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP);
  268. if (rc != Error_Succeed){
  269. Dbg("insert agent picture to remote video queue.");
  270. }
  271. }
  272. }
  273. else {
  274. Dbg("%s:%d record remote video render_func exit!", __FUNCTION__, __LINE__);
  275. break;
  276. }
  277. }
  278. video_frame_delete(showframe);
  279. showframe = NULL;
  280. video_frame_delete(remote_frame);
  281. remote_frame = NULL;
  282. return 0;
  283. }
  284. int rvc_start_video_render(rvc_video_render_t* prender, bool bremote, rvc_video_box_move_callback_t* cb)
  285. {
  286. if (0 != sem_init(&prender->ui_stop_sem, 0, 0)) {
  287. Dbg("%s:%d create stop sem failed!", __FUNCTION__, __LINE__);
  288. return Error_Resource;
  289. }
  290. else {
  291. Dbg("%s:%d create stop sem success!", __FUNCTION__, __LINE__);
  292. }
  293. int err = pthread_create(&prender->ui_threadid, NULL, rvc_videorender_func, prender);
  294. if (Error_Succeed == err) {
  295. Dbg("create video render thread success, thread id is %u.", prender->ui_threadid);
  296. }
  297. else {
  298. Dbg("create video render thread failed.");
  299. return Error_Resource;
  300. }
  301. if (bremote) {
  302. if (0 != sem_init(&prender->remote_render_stop_sem, 0, 0)) {
  303. Dbg("%s:%d create remote stop sem failed!", __FUNCTION__, __LINE__);
  304. return Error_Resource;
  305. }
  306. else {
  307. Dbg("%s:%d create remote stop sem success!", __FUNCTION__, __LINE__);
  308. }
  309. err = pthread_create(&prender->remote_render_threadid, NULL, rvc_remote_videorender_func, prender);
  310. if (Error_Succeed == err) {
  311. Dbg("create video render thread success, thread id is %u.", prender->ui_threadid);
  312. }
  313. else {
  314. Dbg("create video render thread failed.");
  315. return Error_Resource;
  316. }
  317. }
  318. return err;
  319. }
  320. int rvc_stop_video_render(rvc_video_render_t* prender)
  321. {
  322. sem_post(&prender->ui_stop_sem);
  323. rvc_stop_remote_video_render(prender);
  324. if (prender->ui_threadid > 0) {
  325. if (0 == pthread_join(prender->ui_threadid, NULL)) {
  326. Dbg("video render thread %u pthread join success.", prender->ui_threadid);
  327. prender->ui_threadid = 0;
  328. }
  329. else {
  330. Dbg("video render thread pthread join error for %s.", strerror(errno));
  331. }
  332. }
  333. Dbg("video render thread exit!");
  334. return Error_Succeed;
  335. }
  336. int rvc_stop_remote_video_render(rvc_video_render_t* prender)
  337. {
  338. if (prender->remote_render_threadid > 0) {
  339. sem_post(&prender->remote_render_stop_sem);
  340. if (0 == pthread_join(prender->remote_render_threadid, NULL)) {
  341. Dbg("remote video render thread %u pthread join success.", prender->remote_render_threadid);
  342. prender->remote_render_threadid = 0;
  343. }
  344. else {
  345. Dbg("remote video render thread pthread join error for %s.", strerror(errno));
  346. }
  347. Dbg("remote video render thread exit!");
  348. }
  349. return Error_Succeed;
  350. }