#include "stdafx.h" #include "SpBase.h" #include "video_session.h" #include "../../Other/libvideoframework/videoframework.h" #include "memutil.h" #include "../../Other/libvideoqueue/libvideoqueue.h" #include "../../Other/rvcmediacommon/rvc_media_common.h" #include "../../Other/rvcmediacommon/common_video/videocommon.h" #include "../../Other/libvideoframework/videoutil.h" #include "../../Other/libvideoframework/videortp.h" #include "../../Other/libvideoframework/videoclock.h" #include "fileutil.h" #include "Event.h" #ifdef RVC_OS_WIN #include "../../Other/libvideoframework/videoplayer.h" #include "../../Other/libvideoframework/videocap.h" #include #include #include #pragma comment(lib, "dbghelp.lib") #else #include "videorenderobj.h" #include "../../Other/libvideocapture/ivideocaptureinterface.h" #include #include #include #endif // RVC_OS_WIN #include "cv.h" #include "highgui.h" #include "y2k_time.h" #define av_always_inline __inline #define inline __inline #ifndef INT64_C #define INT64_C(c) (c##LL) #define UINT64_C(c) (c##UL) #endif #include extern "C" { #include #include #include } #include "../../Other/libvideoframework/video_common/ffmpeg_api_cpp_adapter.h" BOOL g_bIsSalesRecord = FALSE; BOOL g_bEwsRecord = FALSE; // add by ly@2019/04/18 #ifdef RVC_OS_WIN HWND pg_local_hwnd = NULL; // preview window HWND pg_remote_hwnd = NULL; // remote window #else void* pg_local_render = NULL; // local render void* pg_remote_render = NULL; // remote render #endif // RVC_OS_WIN video_session_t* pg_last_session = NULL; // last used session #define WNDCLS_NAME "sipmedia_video" #define MAX_PATH_SIZE 256 #define DEVICE_STANDARD_TYPE 0 #define DEVICE_PAD_TYPE 1 #define DEVICE_MOBILEPAD_TYPE 2 //#define FPS_KEEP_TIME 3 //动态调整下行帧频,用于移动版,暂时不用,移动版自动将帧频降到1帧/s //int g_nSysFps = 0; //int g_nDynamicFps = 0; //当前动态帧频 //DWORD g_nLastRecFrameTime = 0; //上一秒收到的第一帧视频的时间 //int nRecvFrameNum = 0; //一秒钟内收到的视频帧数 //int nFpsKeepTime = 0; //每个帧频保持时间3s,防止频繁跳动 typedef struct picture_record_s{ #ifdef RVC_OS_WIN HANDLE evt; HANDLE work_thread; #else sem_t sem_evt; pthread_t work_threadid; #endif // RVC_OS_WIN video_session_t* session; video_frame* show_frame; video_frame* record_frame; }picture_record_t; struct video_session_t { video_session_conf_t conf; Clibvideoqueue *video_shm_q_env;// env rtp queue Clibvideoqueue *video_shm_q_opt;// opt rtp queue Clibvideoqueue *video_shm_q_preview; // preview queue Clibvideoqueue *video_shm_q_remote; // preview queue videoq_frame *video_error; videortp_t *rtp; videoclock_t local_clock; struct SwsContext *local_encode_sws_ctx_env; struct SwsContext *local_encode_sws_ctx_opt; IplImage*personimage; IplImage*personmask; IplImage*recordareaimage; IplImage*recordareamask; #ifdef RVC_OS_WIN videoplayer_t* local_player; videoplayer_t* remote_player; HANDLE ui_thread; HANDLE ui_event; HWND local_hwnd; // preview window HWND remote_hwnd; // remote window #else VideoRenderObj* plocal_render; VideoRenderObj* premote_render; pthread_t ui_threadid; sem_t ui_stop_sem; bool bshow_remote; int ilast_windstae; #endif // RVC_OS_WIN picture_record_t* pic_record; bool bvideorecved; bool blocalrender; bool bremoterender; }; static void __dbg(void *user_data, const char *fmt, va_list arg) { vDbg(fmt, arg); } static void __logevent(void* user_data, int itype, const char* strmessage) { if (0 == itype) { LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_VIDEO_RTP_CREATE, strmessage); } else { LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_VIDEO_RTP_DESTROY, strmessage); } } static int translate_image_resolution(video_frame** dstframe,const int iwidth, const int iheight, const video_frame* psrcframe) { int i = -1; if (iwidth == psrcframe->width && iheight == psrcframe->height){ return i; } video_frame* pframe = video_frame_new(iwidth, iheight,VIDEO_FORMAT_RGB24); video_frame_fill_black(pframe); SwsContext* sws = sws_getCachedContext(NULL, psrcframe->width, psrcframe->height, PIX_FMT_BGR24, iwidth, iheight, PIX_FMT_BGR24, SWS_LANCZOS, NULL, NULL, NULL); sws_scale(sws, psrcframe->data, psrcframe->linesize, 0, psrcframe->height, pframe->data, pframe->linesize); sws_freeContext(sws); *dstframe = pframe; i = 0; return i; } static int calc_capture_mode(int width, int height, int *mode) { const struct { int mode; int width; int height; } modes [] = { {VIDEOCAP_FRAME_SQCIF, VIDEOCAP_SQCIF_WIDTH, VIDEOCAP_SQCIF_HEIGHT}, {VIDEOCAP_FRAME_QQVGA, VIDEOCAP_QQVGA_WIDTH, VIDEOCAP_QQVGA_HEIGHT}, {VIDEOCAP_FRAME_QCIF, VIDEOCAP_QCIF_WIDTH, VIDEOCAP_QCIF_HEIGHT}, {VIDEOCAP_FRAME_QVGA, VIDEOCAP_QVGA_WIDTH, VIDEOCAP_QVGA_HEIGHT}, {VIDEOCAP_FRAME_CIF, VIDEOCAP_CIF_WIDTH, VIDEOCAP_CIF_HEIGHT}, {VIDEOCAP_FRAME_VGA, VIDEOCAP_VGA_WIDTH, VIDEOCAP_VGA_HEIGHT}, {VIDEOCAP_FRAME_4CIF, VIDEOCAP_4CIF_WIDTH, VIDEOCAP_4CIF_HEIGHT}, {VIDEOCAP_FRAME_SVGA, VIDEOCAP_SVGA_WIDTH, VIDEOCAP_SVGA_HEIGHT}, {VIDEOCAP_FRAME_NHD, VIDEOCAP_NHD_WIDTH, VIDEOCAP_NHD_HEIGHT}, {VIDEOCAP_FRAME_SXGA, VIDEOCAP_SXGA_WIDTH, VIDEOCAP_SXGA_HEIGHT}, {VIDEOCAP_FRAME_720P, VIDEOCAP_720P_WIDTH, VIDEOCAP_720P_HEIGHT}, {VIDEOCAP_FRAME_1080P, VIDEOCAP_1080P_WIDTH, VIDEOCAP_1080P_HEIGHT}, }; int i; for (i = 0; i < array_size(modes); ++i) { if (modes[i].width == width && modes[i].height == height) { *mode = modes[i].mode; return 0; } } return Error_NotExist; } #ifdef RVC_OS_WIN static void __delete_frame(videoplayer_t *player, void *user_data, video_frame *frame) { video_frame_delete(frame); } #endif static int video_shm_enqueue(Clibvideoqueue *shm_queue, video_frame *frame, int flags) { videoq_frame tmp_frm; tmp_frm.data = frame->data[0]; tmp_frm.framesize = frame->width * frame->height * 3; tmp_frm.format = VIDEOQ_FORMAT_RGB24; tmp_frm.width = frame->width; tmp_frm.height = frame->height; unsigned int nowtime = y2k_time_now(); if (!shm_queue->InsertVideo(&tmp_frm, flags,nowtime)) { Dbg("caution: insert shm video failed!"); return Error_Unexpect; } else { //Dbg("insert shm video ok!"); return Error_Succeed; } } static inline Clibvideoqueue *get_active_videoqueue(video_session_t *session) { int agent_option = *session->conf.ref_camera_switch; int facetracking_option = *session->conf.ref_active_camera; int camera_state = *session->conf.ref_camera_state; Clibvideoqueue *active = NULL; if (agent_option == CAMERA_TYPE_ENV) { if((camera_state!=CAMERA_TYPE_ENV)&&(camera_state!=CAMERA_TYPE_AUTO)) { active = NULL; } else { active = session->video_shm_q_env; } } else if (agent_option == CAMERA_TYPE_OPT) { if((camera_state!=CAMERA_TYPE_OPT)&&(camera_state!=CAMERA_TYPE_AUTO)) { active = NULL; } else { active = session->video_shm_q_opt; } } else if(agent_option == CAMERA_TYPE_ERROR) { active = NULL; } else { // auto if (camera_state == CAMERA_TYPE_AUTO) { if (facetracking_option == CAMERA_TYPE_ENV) { active = session->video_shm_q_env; } else { // opt active = session->video_shm_q_opt; } } else if (camera_state == CAMERA_TYPE_ENV) { active = session->video_shm_q_env; } else if (camera_state == CAMERA_TYPE_OPT) { active = session->video_shm_q_opt; } else if (camera_state == CAMERA_TYPE_ERROR) { active = NULL; } } return active; } static void local_get_frame(void *user_data, video_frame *frame) { video_session_t *session = (video_session_t*)user_data; Clibvideoqueue *q = get_active_videoqueue(session); if (q) { videoq_frame frm; frm.data = frame->data[0]; if (q->GetVideo(&frm, 0)) { //video_frame_fill_black(frame); frame->width = frm.width; frame->height = frm.height; frame->linesize[0] = frm.width * 3; } } else { //video_frame_fill_black(frame); //贴图 Dbg("get active cam is null,load error img"); if (session->video_error != NULL) { frame->width = session->video_error->width; frame->height = session->video_error->height; frame->linesize[0] = session->video_error->width * 3; memcpy(frame->data[0],session->video_error->data,frame->width*frame->height*3); } else { Dbg("video error img is null"); } } } static void local_put_frame(void *user_data, video_frame *frame) { //LOG_FUNCTION(); video_session_t *session = (video_session_t*)user_data; video_frame *tmp_frame_encode = NULL; // send out { tmp_frame_encode = video_frame_new(REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_I420); video_frame_fill_black(tmp_frame_encode); if (frame->width == REC_COMMON_VIDEO_RTP_ENV_WIDTH && frame->height == REC_COMMON_VIDEO_RTP_ENV_HEIGHT) { // env int offset = (REC_COMMON_VIDEO_RTP_HEIGHT - REC_COMMON_VIDEO_RTP_ENV_HEIGHT) / 2; unsigned char *dst_data[4] = {tmp_frame_encode->data[0], tmp_frame_encode->data[1], tmp_frame_encode->data[2], NULL}; dst_data[0] += offset * tmp_frame_encode->linesize[0]; dst_data[1] += offset / 2 * tmp_frame_encode->linesize[1]; dst_data[2] += offset / 2 * tmp_frame_encode->linesize[2]; sws_scale(session->local_encode_sws_ctx_env, frame->data, frame->linesize, 0, frame->height, dst_data, tmp_frame_encode->linesize); } else if (frame->width == REC_COMMON_VIDEO_RTP_OPT_WIDTH && frame->height == REC_COMMON_VIDEO_RTP_OPT_HEIGHT) { // opt video_frame tt; video_frame_alloc(REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, &tt); video_frame_fill_black(&tt); { int offset = (REC_COMMON_VIDEO_RTP_WIDTH - REC_COMMON_VIDEO_RTP_OPT_WIDTH) / 2; unsigned char *dst_data[4] = {tt.data[0], 0, 0, 0}; dst_data[0] += offset * 3; #ifdef RVC_OS_WIN IppiSize size; size.width = frame->width; size.height = frame->height; ippiCopy_8u_C3R(frame->data[0], frame->linesize[0], tt.data[0] + offset * 3, tt.linesize[0], size); #else for (int i = 0; i < frame->height; i++) { memcpy(dst_data[0] + i*tt.linesize[0] , frame->data[0] + i*frame->width*3, frame->width*3); } #endif // RVC_OS_WIN } sws_scale(session->local_encode_sws_ctx_opt, tt.data, tt.linesize, 0, tt.height, tmp_frame_encode->data, tmp_frame_encode->linesize); video_frame_free(&tt); } if (session->conf.local_pt == REC_COMMON_VIDEO_PT){ videortp_send_frame(session->rtp, tmp_frame_encode); } else{ videortp_send_yuvframe(session->rtp, tmp_frame_encode); } } if (tmp_frame_encode) { video_frame_delete(tmp_frame_encode); } } static int on_rx_frame(video_frame *frame, void *user_data) { //LOG_FUNCTION(); video_session_t *session = (video_session_t *)user_data; ////计算当前接收到的视频帧频,用于移动版 //DWORD nCurFrameTime = GetTickCount(); //nRecvFrameNum++; //if ((nCurFrameTime-g_nLastRecFrameTime)>1000) //{ // if((nRecvFrameNum < g_nDynamicFps-2)&&(nRecvFrameNum>=1)) // { // g_nDynamicFps = nRecvFrameNum; // nFpsKeepTime = 0; // //Dbg("adj down stream fps to %d",g_nDynamicFps); // } // else if((nRecvFrameNum >= g_nDynamicFps)&&(g_nDynamicFps < g_nSysFps)&&(nFpsKeepTime>=FPS_KEEP_TIME)) // { // (g_nDynamicFps<(g_nSysFps-2))?g_nDynamicFps=g_nDynamicFps+2:g_nDynamicFps=g_nSysFps; // nFpsKeepTime = 0; // //Dbg("adj down stream fps to %d",g_nDynamicFps); // } // else // { // nFpsKeepTime++; // } // //更新时间、帧数 // nRecvFrameNum = 0; // g_nLastRecFrameTime = GetTickCount(); //} if (session->conf.nCallType == MOBILETOPAD_CALLTYPE) { int rc = video_shm_enqueue(session->video_shm_q_remote, frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP); if (rc != Error_Succeed) { Dbg("mobile mod insert remote video to queue failed."); } //Dbg("remote video queue get video lens:%d.", session->video_shm_q_remote->GetVideoLens()); } else if (DOUBLERECORD_CALLTYPE == session->conf.nCallType) { if (eStand2sType == session->conf.eDeviceType) { //大机对远端视频进行缩放匹配 video_frame* recordframe = NULL; if (0 == translate_image_resolution(&recordframe,/*REC_COMMON_VIDEO_SSM_AGENT_WIDTH*/REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_WIDTH,/*REC_COMMON_VIDEO_SSM_AGENT_HEIGHT*/REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_HEIGHT, frame)) { int rc = video_shm_enqueue(session->video_shm_q_remote, recordframe, VIDEOQUEUE_FLAG_VERTICAL_FLIP); if (rc != Error_Succeed) { Dbg("eStand2sType record call mod insert remote video to queue failed."); } video_frame_delete(recordframe); recordframe = NULL; } } else { int rc = video_shm_enqueue(session->video_shm_q_remote, frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP); if (rc != Error_Succeed) { Dbg("not eStand2sType record call mod insert remote video to queue."); } } } int used = 0; #ifdef RVC_OS_WIN if (session->remote_player) { int rc = videoplayer_queue_frame(session->remote_player, frame, &__delete_frame, NULL); if (rc == 0) { used = 1; } } #else //static int icount = 0; //if (icount == 0){ // video_frame_save_bmpfile("remote_test.bmp", frame); // icount++; //} if (NULL != session->premote_render){ //Dbg("session plocal_render RenderVideoFrame"); video_frame* echoframe = NULL; if (0 == translate_image_resolution(&echoframe,session->conf.remote_video_view_cx,session->conf.remote_video_view_cy, frame)) { session->premote_render->RenderVideoFrame(echoframe); session->bshow_remote = true; video_frame_delete(echoframe); echoframe = NULL; } else { session->premote_render->RenderVideoFrame(frame); session->bshow_remote = true; } used = 1; if (false == session->bremoterender) { LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_REMOTE_VIDEO_RENDER_STARTED, "start remote video render."); session->bremoterender = true; } } #endif return used; } static void on_rx_udp(const char* buf, int size, void* user_data) { video_session_t* session = (video_session_t*)user_data; if (false == session->bvideorecved) { char strmsg[MAX_PATH] = { 0 }; snprintf(strmsg, MAX_PATH, "received first video packet, and packet size is %d.", size); LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_VIDEO_STREAM_RECEIVED, strmsg); session->bvideorecved = true; } } #ifdef RVC_OS_WIN int GetCurrentRunPath(char* pPath) { char* pBuf = new char[MAX_PATH_SIZE]; if (pBuf == NULL) return -1; ZeroMemory(pBuf, MAX_PATH_SIZE); GetModuleFileName(NULL, pBuf, MAX_PATH_SIZE); int len = strnlen_s(pBuf, MAX_PATH_SIZE); if (len <= 0) { delete[]pBuf; return -2; } char* pch; pch = strstr(pBuf, "bin"); if (pch == NULL) return -3; int lenDel = strnlen_s(pch, MAX_PATH_SIZE); if (len <= 0) { delete[]pBuf; return -3; } strncpy_s(pPath, MAX_PATH_SIZE, pBuf, len - lenDel); delete[]pBuf; return strnlen_s(pPath, MAX_PATH_SIZE); } //远端视频窗口状态回调 static int on_remoteWinstate(videoplayer_t *player, void *user_data, video_frame **frame) { video_session_t *session = (video_session_t*)user_data; //if (*session->conf.ref_window_state == 1) //{ // return 1; //} //else if (*session->conf.ref_window_state == 2) //{ // return 2; //} //else //{ // return 0; //} return *session->conf.ref_window_state ; } //本地回显回调 static int on_pull(videoplayer_t *player, void *user_data, video_frame **frame) { video_session_t *session = (video_session_t*)user_data; video_frame *tmp_frame_preview; //Dbg("ref_active_img %d,ref_Is_ActiveInspect %d,ref_camera_switch %d",*session->conf.ref_active_img,*session->conf.ref_Is_ActiveInspect,*session->conf.ref_camera_switch); if((session->conf.ref_active_img == NULL)&&(session->conf.ref_Is_ActiveInspect == NULL)) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; BOOL result = session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); //人形框融合处理 if (result&&session->personimage!=NULL&&session->personmask!=NULL&&*session->conf.ref_Is_showPersonArea==1) { IplImage*img = cvCreateImageHeader(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); img->imageData = (char*)frm.data; if (frm.width!=session->personimage->width) { IplImage*tmp = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); IplImage*tmpmask = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,1); cvResize(session->personimage,tmp); cvResize(session->personmask,tmpmask); cvAdd(img,tmp,img,tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else { cvAdd(img,session->personimage,img,session->personmask); } cvReleaseImageHeader(&img); } } else { if (*session->conf.ref_active_img == 1) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, VIDEO_FORMAT_RGB24); video_frame_fill_black(tmp_frame_preview); if (session->video_error == NULL) { char strPath[MAX_PATH_SIZE] = {0}; #ifdef RVC_OS_WIN GetCurrentRunPath(strPath); sprintf(strPath, "%s\\bin\\looklowerscreen.jpg", strPath); #else #endif // RVC_OS_WIN if (ExistsFile(strPath)) { IplImage*img = cvLoadImage(strPath,1); if (img != NULL) { Dbg("load img success"); session->video_error = new videoq_frame; session->video_error->format = VIDEOQ_FORMAT_RGB24; session->video_error->framesize = img->imageSize; session->video_error->height = img->width; session->video_error->width = img->height; session->video_error->data = new unsigned char[img->imageSize]; memcpy(session->video_error->data,img->imageData,img->imageSize); cvReleaseImage(&img); } } } if (session->video_error != NULL) { SwsContext*sws = sws_getContext(session->video_error->width, session->video_error->height,PIX_FMT_BGR24, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL); uint8_t *src_data[4] = {(unsigned char*)session->video_error->data+(session->video_error->height-1)*session->video_error->width*3,NULL,NULL,NULL}; int src_linesize[4] = {-session->video_error->width*3,0,0,0}; unsigned char *dst[4] = {tmp_frame_preview->data[0],NULL,NULL,NULL}; int dst_linesize[4] = {tmp_frame_preview->linesize[0],0,0,0}; sws_scale(sws, src_data, src_linesize, 0, session->video_error->height, dst, dst_linesize); sws_freeContext(sws); } } else if (*session->conf.ref_Is_ActiveInspect == 1) { if((session->conf.eDeviceType == eMobilePadType)||(session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); } else { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, VIDEO_FORMAT_RGB24); video_frame_fill_black(tmp_frame_preview); if ((*session->conf.ref_camera_switch == CAMERA_TYPE_ENV)||(*session->conf.ref_camera_switch == CAMERA_TYPE_AUTO))//显示上摄像头 { if (session->video_shm_q_env) { videoq_frame frm; int offset = (REC_COMMON_VIDEO_SNAPSHOT_WIDTH - REC_COMMON_VIDEO_SNAPSHOT_HEIGHT) / 2; frm.data = tmp_frame_preview->data[0] + offset * tmp_frame_preview->linesize[0]; session->video_shm_q_env->GetVideo(&frm, VIDEOQUEUE_FLAG_VERTICAL_FLIP); } } else if (*session->conf.ref_camera_switch == CAMERA_TYPE_OPT)//显示下摄像头 { if (session->video_shm_q_opt) { video_frame tt = {0}; int offset = (REC_COMMON_VIDEO_SNAPSHOT_WIDTH-REC_COMMON_VIDEO_SNAPSHOT_HEIGHT) / 2; tt.data[0] = tmp_frame_preview->data[0] + offset *3; tt.format = tmp_frame_preview->format; tt.linesize[0] = tmp_frame_preview->linesize[0]; tt.width = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; tt.height = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; session->video_shm_q_opt->GetVideo2(&tt, VIDEOQUEUE_FLAG_VERTICAL_FLIP); } } } } else { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; BOOL result = session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); //人形框融合处理 if (result&&session->personimage!=NULL&&session->personmask!=NULL&&*session->conf.ref_Is_showPersonArea==1) { IplImage*img = cvCreateImageHeader(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); img->imageData = (char*)frm.data; if (frm.width!=session->personimage->width) { IplImage*tmp = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); IplImage*tmpmask = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,1); cvResize(session->personimage,tmp); cvResize(session->personmask,tmpmask); cvAdd(img,tmp,img,tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else { cvAdd(img,session->personimage,img,session->personmask); } cvReleaseImageHeader(&img); } //双录人形位置框融合处理 if (result&&session->recordareaimage!=NULL&&session->recordareamask!=NULL&&*session->conf.ref_Is_showRecordArea==1) { IplImage*img = cvCreateImageHeader(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); img->imageData = (char*)frm.data; if (frm.width!=session->recordareaimage->width) { IplImage*tmp = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,3); IplImage*tmpmask = cvCreateImage(cvSize(frm.width,frm.height),IPL_DEPTH_8U,1); cvResize(session->recordareaimage,tmp); cvResize(session->recordareamask,tmpmask); cvAdd(img,tmp,img,tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else { cvAdd(img,session->recordareaimage,img,session->recordareamask); } cvReleaseImageHeader(&img); } } } *frame = tmp_frame_preview; //if (*session->conf.ref_window_state == 1) //{ // return 1; //} //else if (*session->conf.ref_window_state == 2) //{ // return 2; //} //else //{ // return 0; //} return *session->conf.ref_window_state; } static void free_frame(videoplayer_t *player, void *user_data, video_frame *frame) { video_frame_delete(frame); } #else //视频窗口显示状态,0:正常大小显示,1:放大一倍显示,2:隐藏全部窗口,3:从隐藏状态恢复为全部显示,4:显示远程窗口,隐藏本地窗口, 5:缩放显示 int set_video_windows(video_session_t* psession, int iwindowstate) { int iret = -1; if (NULL == psession){ return iret; } if (2 == iwindowstate){ psession->plocal_render->HideVideoWindow(); psession->premote_render->HideVideoWindow(); iret = 0; } else if (3 == iwindowstate){ psession->plocal_render->ShowVideoWindow(); psession->premote_render->HideVideoWindow(); psession->premote_render->ShowVideoWindow(); iret = 0; } else if (4 == iwindowstate) { psession->plocal_render->HideVideoWindow(); iret = 0; } return iret; } //本地回显回调 static int get_local_video_frame(void* user_data, video_frame** frame) { video_session_t* session = (video_session_t*)user_data; video_frame* tmp_frame_preview = NULL; //Dbg("ref_active_img %d,ref_Is_ActiveInspect %d,ref_camera_switch %d",*session->conf.ref_active_img,*session->conf.ref_Is_ActiveInspect,*session->conf.ref_camera_switch); if ((session->conf.ref_active_img == NULL) && (session->conf.ref_Is_ActiveInspect == NULL)) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; BOOL result = session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); //人形框融合处理 if (result){ if (session->personimage != NULL && session->personmask != NULL && *session->conf.ref_Is_showPersonArea == 1) { IplImage* img = cvCreateImageHeader(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); img->imageData = (char*)frm.data; if (frm.width != session->personimage->width){ IplImage* tmp = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); IplImage* tmpmask = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 1); cvResize(session->personimage, tmp); cvResize(session->personmask, tmpmask); cvAdd(img, tmp, img, tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else{ cvAdd(img, session->personimage, img, session->personmask); } cvReleaseImageHeader(&img); } } else { video_frame_fill_black(tmp_frame_preview); } } else { if (*session->conf.ref_active_img == 1) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, VIDEO_FORMAT_RGB24); video_frame_fill_black(tmp_frame_preview); if (session->video_error == NULL) { char strPath[MAX_PATH_SIZE] = { 0 }; snprintf(strPath, MAX_PATH_SIZE, "%s", "./bin/looklowerscreen.jpg"); if (ExistsFile(strPath)) { IplImage* img = cvLoadImage(strPath, 1); if (img != NULL) { Dbg("load img success"); session->video_error = new videoq_frame; session->video_error->format = VIDEOQ_FORMAT_RGB24; session->video_error->framesize = img->imageSize; session->video_error->height = img->width; session->video_error->width = img->height; session->video_error->data = new unsigned char[img->imageSize]; memcpy(session->video_error->data, img->imageData, img->imageSize); cvReleaseImage(&img); } } } if (session->video_error != NULL) { SwsContext* sws = sws_getContext(session->video_error->width, session->video_error->height, PIX_FMT_BGR24, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL); uint8_t* src_data[4] = { (unsigned char*)session->video_error->data + (session->video_error->height - 1) * session->video_error->width * 3,NULL,NULL,NULL }; int src_linesize[4] = { -session->video_error->width * 3,0,0,0 }; unsigned char* dst[4] = { tmp_frame_preview->data[0],NULL,NULL,NULL }; int dst_linesize[4] = { tmp_frame_preview->linesize[0],0,0,0 }; sws_scale(sws, src_data, src_linesize, 0, session->video_error->height, dst, dst_linesize); sws_freeContext(sws); } } else if (*session->conf.ref_Is_ActiveInspect == 1) { if ((session->conf.eDeviceType == eMobilePadType) || (session->conf.eDeviceType == ePadtype) || (session->conf.eDeviceType == eDesk2SType) || (session->conf.eDeviceType == eDesk1SType) || (session->conf.eDeviceType == eDesk2SIntegratedType)) { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); } else { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_WIDTH, VIDEO_FORMAT_RGB24); video_frame_fill_black(tmp_frame_preview); if ((*session->conf.ref_camera_switch == CAMERA_TYPE_ENV) || (*session->conf.ref_camera_switch == CAMERA_TYPE_AUTO))//显示上摄像头 { if (session->video_shm_q_env) { videoq_frame frm; int offset = (REC_COMMON_VIDEO_SNAPSHOT_WIDTH - REC_COMMON_VIDEO_SNAPSHOT_HEIGHT) / 2; frm.data = tmp_frame_preview->data[0] + offset * tmp_frame_preview->linesize[0]; session->video_shm_q_env->GetVideo(&frm, VIDEOQUEUE_FLAG_VERTICAL_FLIP); } } else if (*session->conf.ref_camera_switch == CAMERA_TYPE_OPT)//显示下摄像头 { if (session->video_shm_q_opt) { video_frame tt = { 0 }; int offset = (REC_COMMON_VIDEO_SNAPSHOT_WIDTH - REC_COMMON_VIDEO_SNAPSHOT_HEIGHT) / 2; tt.data[0] = tmp_frame_preview->data[0] + offset * 3; tt.format = tmp_frame_preview->format; tt.linesize[0] = tmp_frame_preview->linesize[0]; tt.width = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; tt.height = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; session->video_shm_q_opt->GetVideo2(&tt, VIDEOQUEUE_FLAG_VERTICAL_FLIP); } } } } else { tmp_frame_preview = video_frame_new(REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, VIDEO_FORMAT_RGB24); videoq_frame frm; frm.data = tmp_frame_preview->data[0]; BOOL result = session->video_shm_q_preview->GetVideo(&frm, VIDEOQUEUE_FLAG_HORIZONTAL_FLIP); if (result){ //人形框融合处理 if (session->personimage != NULL && session->personmask != NULL && *session->conf.ref_Is_showPersonArea == 1) { IplImage* img = cvCreateImageHeader(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); img->imageData = (char*)frm.data; if (frm.width != session->personimage->width) { IplImage* tmp = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); IplImage* tmpmask = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 1); cvResize(session->personimage, tmp); cvResize(session->personmask, tmpmask); cvAdd(img, tmp, img, tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else { cvAdd(img, session->personimage, img, session->personmask); } cvReleaseImageHeader(&img); } //双录人形位置框融合处理 if (session->recordareaimage != NULL && session->recordareamask != NULL && *session->conf.ref_Is_showRecordArea == 1) { IplImage* img = cvCreateImageHeader(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); img->imageData = (char*)frm.data; if (frm.width != session->recordareaimage->width) { IplImage* tmp = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 3); IplImage* tmpmask = cvCreateImage(cvSize(frm.width, frm.height), IPL_DEPTH_8U, 1); cvResize(session->recordareaimage, tmp); cvResize(session->recordareamask, tmpmask); cvAdd(img, tmp, img, tmpmask); cvReleaseImage(&tmp); cvReleaseImage(&tmpmask); } else { cvAdd(img, session->recordareaimage, img, session->recordareamask); } cvReleaseImageHeader(&img); } } else { video_frame_fill_black(tmp_frame_preview); } } } *frame = tmp_frame_preview; return *session->conf.ref_window_state; } #endif // RVC_OS_WIN int show_agent_picture_proc(void *arg) { LOG_FUNCTION(); picture_record_t *t_record = (picture_record_t*)arg; if (NULL == t_record){ Dbg("show_agent_picture_proc param valid."); return -1; } #ifdef RVC_OS_WIN SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); #endif for (;;) { #ifdef RVC_OS_WIN DWORD dwRet = WaitForSingleObject(t_record->evt, 200); if (dwRet == WAIT_TIMEOUT){ #else struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long unsec = ts.tv_nsec + (1000 * 1000 * 200); ts.tv_sec += (unsec / 1000000000); ts.tv_nsec = (unsec % 1000000000); if (0 != sem_timedwait(&t_record->sem_evt, &ts)) { #endif if (NULL != t_record->session) { if (NULL != t_record->session->video_shm_q_remote) { int rc = video_shm_enqueue(t_record->session->video_shm_q_remote, t_record->record_frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP); if (rc != Error_Succeed) { Dbg("mobile mod insert remote video to queue."); } } video_frame* showframe = video_frame_new(t_record->show_frame->width, t_record->show_frame->height, VIDEO_FORMAT_RGB24); video_frame_fill_black(showframe); video_frame_copy(showframe, t_record->show_frame); on_rx_frame(showframe, t_record->session); if (NULL != showframe){ video_frame_delete(showframe); showframe = NULL; } } } else { Dbg("show_agent_picture_proc thread exit."); break; } } return 0; } //static void showagentpicdump_exception(PEXCEPTION_POINTERS ExceptionInfo) //{ // char tmp[MAX_PATH]; // HANDLE hDumpFile; // sprintf(tmp, ".\\showagnetpic_%d.dmp", GetCurrentProcessId()); // hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE, // 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); // if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) ) // { // MINIDUMP_EXCEPTION_INFORMATION mdei; // MINIDUMP_TYPE mdt; // // mdei.ThreadId = GetCurrentThreadId(); // mdei.ExceptionPointers = ExceptionInfo; // mdei.ClientPointers = FALSE; // // mdt = MiniDumpWithFullMemory; // // MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), // hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 ); // // CloseHandle( hDumpFile ); // } //} //坐席端图像显示线程 #ifdef RVC_OS_WIN static unsigned int __stdcall agent_picture_show_thread(void* arg) #else void* agent_picture_show_thread(void* arg) #endif { //__try { show_agent_picture_proc(arg); //} //__except(showagentpicdump_exception(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER) //{ // Dbg("show_agent_picture_proc exception."); //} return 0; } static int agent_picture_video_start(picture_record_t* t_record) { LOG_FUNCTION(); #ifdef RVC_OS_WIN t_record->evt = CreateEventA(NULL, FALSE, FALSE, NULL); t_record->work_thread = (HANDLE)_beginthreadex(NULL, 0, &agent_picture_show_thread, t_record, 0, NULL); #else sem_init(&t_record->sem_evt, 0, 0); pthread_attr_t attr; pthread_attr_init(&attr); struct sched_param param; param.sched_priority = sched_get_priority_max(SCHED_RR); pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); int err = pthread_create(&t_record->work_threadid, NULL, agent_picture_show_thread, t_record); if (0 == err) { Dbg("create agent picture show thread success, %u.", t_record->work_threadid); } else { Dbg("create agent picture show thread failed for %s.", strerror(errno)); } #endif // RVC_OS_WIN return 0; } static int agent_picture_video_stop(picture_record_t* t_record) { Dbg("agent picture video stop called, stop static picture show thread."); #ifdef RVC_OS_WIN if (t_record->evt) { SetEvent(t_record->evt); if (t_record->work_thread) { WaitForSingleObject(t_record->work_thread, INFINITE); CloseHandle(t_record->work_thread); t_record->work_thread = NULL; } CloseHandle(t_record->evt); t_record->evt = NULL; } #else sem_post(&t_record->sem_evt); if (t_record->work_threadid > 0) { pthread_join(t_record->work_threadid, NULL); t_record->work_threadid = 0; } sem_destroy(&t_record->sem_evt); #endif // RVC_OS_WIN if (t_record->record_frame){ video_frame_delete(t_record->record_frame); t_record->record_frame = NULL; } if (t_record->show_frame){ video_frame_delete(t_record->show_frame); t_record->show_frame = NULL; } Dbg("stop static picture show thread end."); return 0; } static int record_agent_picture_show_session_destory(video_session_t* session) { if (session->pic_record){ agent_picture_video_stop(session->pic_record); } if (session->video_shm_q_env) { delete session->video_shm_q_env; } if (session->video_shm_q_opt) { delete session->video_shm_q_opt; } if (session->video_error){ delete session->video_error->data; delete session->video_error; } if (session->personimage){ cvReleaseImage(&session->personimage); } if (session->personmask){ cvReleaseImage(&session->personmask); } if (session->recordareaimage){ cvReleaseImage(&session->recordareaimage); } if (session->recordareamask){ cvReleaseImage(&session->recordareamask); } return 0; } static void show_remote_agnet_picture(video_session_t *t_session) { LOG_FUNCTION(); char strPath[MAX_PATH_SIZE]={0}; char strImgPath[MAX_PATH_SIZE]={0}; int irecord_video_frame_width = REC_COMMON_VIDEO_SSM_AGENT_WIDTH; int irecord_video_frame_heigt = REC_COMMON_VIDEO_SSM_AGENT_HEIGHT; if (t_session->conf.eDeviceType == eStand2sType){ irecord_video_frame_width = /*REC_COMMON_VIDEO_DSM_AGENT_WIDTH*/REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_WIDTH; irecord_video_frame_heigt = /*REC_COMMON_VIDEO_DSM_AGENT_HEIGHT*/REC_COMMON_VIDEO_SNAPSHOT_PREVIEW_HEIGHT; } #ifdef RVC_OS_WIN GetCurrentRunPath(strPath); sprintf(strImgPath, "%s\\bin\\agent.jpg", strPath); #else strcpy_s(strImgPath, MAX_PATH_SIZE, "./bin/agent.jpg"); #endif // RVC_OS_WIN video_frame* remote_frame = video_frame_new(irecord_video_frame_width, irecord_video_frame_heigt, VIDEO_FORMAT_RGB24); video_frame_fill_black(remote_frame); if (ExistsFile(strImgPath)) { IplImage*img = cvLoadImage(strImgPath,1); videoq_frame* vframe = new videoq_frame; if (img != NULL) { Dbg("load img success"); vframe->format = VIDEOQ_FORMAT_RGB24; vframe->framesize = img->imageSize; vframe->width = img->width; vframe->height = img->height; vframe->data = new unsigned char[img->imageSize]; memcpy(vframe->data,img->imageData,img->imageSize); cvReleaseImage(&img); } SwsContext*sws = sws_getContext(vframe->width, vframe->height,PIX_FMT_BGR24, irecord_video_frame_width, irecord_video_frame_heigt, PIX_FMT_BGR24, SWS_POINT, NULL, NULL, NULL); uint8_t *src_data[4] = {(unsigned char*)vframe->data+(vframe->height-1)*vframe->width*3,NULL,NULL,NULL}; int src_linesize[4] = {-vframe->width*3,0,0,0}; unsigned char *dst[4] = {remote_frame->data[0],NULL,NULL,NULL}; int dst_linesize[4] = {remote_frame->linesize[0],0,0,0}; sws_scale(sws, src_data, src_linesize, 0, vframe->height, dst, dst_linesize); sws_freeContext(sws); if (vframe){ delete vframe->data; delete vframe; } } if (NULL != t_session->video_shm_q_remote) { int rc = video_shm_enqueue(t_session->video_shm_q_remote, remote_frame, VIDEOQUEUE_FLAG_VERTICAL_FLIP); if (rc != Error_Succeed) { Dbg("insert agent picture to remote video queue."); } } video_frame * showframe = NULL; if (-1 == translate_image_resolution(&showframe,t_session->conf.remote_video_width,t_session->conf.remote_video_height,remote_frame)) { showframe = video_frame_new(t_session->conf.remote_video_width,t_session->conf.remote_video_height, VIDEO_FORMAT_RGB24); video_frame_fill_black(showframe); video_frame_copy(showframe, remote_frame); } t_session->pic_record = new picture_record_t(); t_session->pic_record->record_frame = remote_frame; t_session->pic_record->show_frame = showframe; t_session->pic_record->session = t_session; Dbg("begin agent static picture show thread."); agent_picture_video_start(t_session->pic_record); } static int start_video_rtpsession(video_session_t* session) { int rc = -1; videortp_config_t config = { 0 }; config.fps_den = REC_COMMON_VIDEO_FPS_DEN; if (session->conf.eDeviceType == eMobilePadType) { config.fps_num = REC_COMMON_VIDEO_FPS_MOBILE_AGENT; } else if ((session->conf.eDeviceType == ePadtype) || (session->conf.eDeviceType == eDesk2SType) || (session->conf.eDeviceType == eDesk1SType) || (session->conf.eDeviceType == eDesk2SIntegratedType)) { config.fps_num = REC_COMMON_VIDEO_FPS_MOBILE; } else if (session->conf.eDeviceType == eStand2sType) { config.fps_num = REC_COMMON_VIDEO_FPS_NUM; } config.capture_height = -1; // not use config.capture_width = -1; // not use config.dir = 3; config.tx_width = REC_COMMON_VIDEO_RTP_WIDTH; config.tx_height = REC_COMMON_VIDEO_RTP_HEIGHT; config.rx_width = session->conf.remote_video_width; config.rx_height = session->conf.remote_video_height; config.local_ip = session->conf.local_rtp_ip; config.local_pt = session->conf.local_pt; config.remote_pt = session->conf.local_pt; config.local_rtp_port = session->conf.local_rtp_port; config.mtu = session->conf.mtu; config.quant = session->conf.video_quant; config.remote_ip = session->conf.remote_rtp_ip; config.remote_rtp_port = session->conf.remote_rtp_port; config.user_data = session; config.bit_rate = session->conf.bit_rate; config.on_rx_frame = &on_rx_frame; config.on_rx_udp = &on_rx_udp; config.dbg = &__dbg; config.logevent = &__logevent; videortp_create(&config, &session->rtp); rc = videortp_start(session->rtp); if (rc != 0) { Dbg("start video rtp failed!"); videortp_destroy(session->rtp); session->rtp = NULL; } else { Dbg("videortp_start suc."); } return rc; } static int start_local_video_clock(video_session_t* session) { int rc = -1; if (session->conf.eDeviceType == eMobilePadType){ rc = videoclock_create(REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps, &__dbg); } else if ((session->conf.eDeviceType == ePadtype) || (session->conf.eDeviceType == eDesk2SType) || (session->conf.eDeviceType == eDesk1SType) || (session->conf.eDeviceType == eDesk2SIntegratedType)) { rc = videoclock_create(REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps, &__dbg); } else if (session->conf.eDeviceType == eStand2sType) { rc = videoclock_create(REC_COMMON_VIDEO_FPS_NUM, REC_COMMON_VIDEO_FPS_DEN, REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps, &__dbg); } Dbg("create session->local_clock addr is 0x%08x", session->local_clock); if (0 == rc) { rc = videoclock_start(session->local_clock); if (rc != 0) { Dbg("start video clock failed!"); videoclock_destroy(session->local_clock); session->local_clock = NULL; } else { Dbg("videoclock start success!"); } } else { Dbg("create video clock failed!"); } return rc; } static int start_video(video_session_t *session) { LOG_FUNCTION(); int rc = -1; if (session->video_shm_q_env) { session->local_encode_sws_ctx_env = sws_getContext( REC_COMMON_VIDEO_RTP_ENV_WIDTH, REC_COMMON_VIDEO_RTP_ENV_HEIGHT, PIX_FMT_BGR24, REC_COMMON_VIDEO_RTP_ENV_WIDTH, REC_COMMON_VIDEO_RTP_ENV_HEIGHT, PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL); if (!session->local_encode_sws_ctx_env) goto on_error; else{ Dbg("get session->local_encode_sws_ctx_env succ."); } } else{ Dbg("session->video_shm_q_env is NULL."); } if (session->video_shm_q_opt) { session->local_encode_sws_ctx_opt = sws_getContext( REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, PIX_FMT_BGR24, REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL); if (!session->local_encode_sws_ctx_opt) goto on_error; else{ Dbg("get session->local_encode_sws_ctx_opt succ."); } } else{ Dbg("session->video_shm_q_opt is NULL."); } Dbg("session nCallType is %d, remote_video_view_cx = %d,remote_video_view_cy = %d,remote_video_width = %d,remote_video_height = %d.", session->conf.nCallType,session->conf.remote_video_view_cx,session->conf.remote_video_view_cy,session->conf.remote_video_width,session->conf.remote_video_height); #ifdef RVC_OS_WIN if (DOUBLERECORD_CALLTYPE != session->conf.nCallType){ Dbg("create new remote video player"); if (session->remote_hwnd) { if (session->conf.eDeviceType == eMobilePadType) { rc = videoplayer_create(session->remote_hwnd, 0, 0, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy, REC_COMMON_VIDEO_FPS_MOBILE_AGENT, REC_COMMON_VIDEO_FPS_DEN, session->conf.remote_video_width, session->conf.remote_video_height, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.iremote_wind_flags, "remote", on_remoteWinstate, NULL, session, &session->remote_player); if (rc != 0) { Dbg("create remote video player failed!"); goto on_error; } else{ Dbg("create remote video player suc!"); } } else if((session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { rc = videoplayer_create(session->remote_hwnd, 0, 0, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy, REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, session->conf.remote_video_width, session->conf.remote_video_height, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.iremote_wind_flags, "remote", on_remoteWinstate, NULL, session, &session->remote_player); if (rc != 0) { Dbg("create remote video player failed!"); goto on_error; } else{ Dbg("create remote video player suc!"); } } else if(session->conf.eDeviceType == eStand2sType) { rc = videoplayer_create(session->remote_hwnd, 0, 0, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy, REC_COMMON_VIDEO_FPS_NUM, REC_COMMON_VIDEO_FPS_DEN, session->conf.remote_video_width, session->conf.remote_video_height, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PUSH|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.iremote_wind_flags, "remote", on_remoteWinstate, NULL, session, &session->remote_player); if (rc != 0) { Dbg("create remote video player failed!"); goto on_error; } else{ Dbg("create remote video player suc remote_video_width = %d,remote_video_height = %d.", session->conf.remote_video_width, session->conf.remote_video_height); } } } else { Dbg("remote_hwnd == Null"); } } else{ if (NULL != pg_last_session){ session->remote_player = pg_last_session->remote_player; Dbg("double record call remote_player reuse."); } else{ Dbg("pg_last_session is NULL, and call type is %d.", session->conf.nCallType); } } BOOL bIsActiveInspect = FALSE; if (session->conf.ref_Is_ActiveInspect != NULL) { if (*session->conf.ref_Is_ActiveInspect == 1) { bIsActiveInspect = TRUE; } else { bIsActiveInspect = FALSE; } } else { bIsActiveInspect = FALSE; } if (DOUBLERECORD_CALLTYPE != session->conf.nCallType){ Dbg("create new local video player"); if (session->conf.eDeviceType == eMobilePadType) { rc = videoplayer_create(session->local_hwnd, 0, 0, session->conf.local_video_view_cx, session->conf.local_video_view_cy, REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.ilocal_wind_flags, "local", on_pull, free_frame, session, &session->local_player); if (rc != 0) { Dbg("create local video player failed!"); goto on_error; } else{ Dbg("create local video player suc!"); } } else if((session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { rc = videoplayer_create(session->local_hwnd, 0, 0, session->conf.local_video_view_cx, session->conf.local_video_view_cy, REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, REC_COMMON_VIDEO_PREVIEW_WIDTH, REC_COMMON_VIDEO_PREVIEW_HEIGHT, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.ilocal_wind_flags, "local", on_pull, free_frame, session, &session->local_player); if (rc != 0) { Dbg("create local video player failed!"); goto on_error; } else{ Dbg("create local video player suc!"); } } else if(session->conf.eDeviceType == eStand2sType) { rc = videoplayer_create(session->local_hwnd, 0, 0, session->conf.local_video_view_cx, session->conf.local_video_view_cy, REC_COMMON_VIDEO_FPS_NUM, REC_COMMON_VIDEO_FPS_DEN, bIsActiveInspect?REC_COMMON_VIDEO_SNAPSHOT_WIDTH:REC_COMMON_VIDEO_PREVIEW_WIDTH, bIsActiveInspect?REC_COMMON_VIDEO_SNAPSHOT_WIDTH:REC_COMMON_VIDEO_PREVIEW_HEIGHT, //*VIDEOPLAYER_FLAG_DOUBLESIZE|*/VIDEOPLAYER_FLAG_PULL|VIDEOPLAYER_FLAG_CHECKTOP, session->conf.ilocal_wind_flags, "local", on_pull, free_frame, session, &session->local_player); if (rc != 0) { Dbg("create local video player failed!"); goto on_error; } else{ Dbg("create local video player suc!"); } } } else{ if (NULL != pg_last_session){ session->local_player = pg_last_session->local_player; Dbg("double record call local player reuse."); } } if (session->remote_hwnd) { if (0 != session->conf.remote_rtp_port) { //videortp_config_t config = {0}; //config.fps_den = REC_COMMON_VIDEO_FPS_DEN; //if (session->conf.eDeviceType == eMobilePadType) //{ // config.fps_num = REC_COMMON_VIDEO_FPS_MOBILE_AGENT; //} //else if((session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) //{ // config.fps_num = REC_COMMON_VIDEO_FPS_MOBILE; //} //else if(session->conf.eDeviceType == eStand2sType) //{ // config.fps_num = REC_COMMON_VIDEO_FPS_NUM; //} //config.capture_height = -1; // not use //config.capture_width = -1; // not use //config.dir = 3; //config.tx_width = REC_COMMON_VIDEO_RTP_WIDTH; //config.tx_height = REC_COMMON_VIDEO_RTP_HEIGHT; //config.rx_width = session->conf.remote_video_width; //config.rx_height = session->conf.remote_video_height; //config.local_ip = session->conf.local_rtp_ip; //config.local_pt = session->conf.local_pt; //config.remote_pt = session->conf.local_pt; //config.local_rtp_port = session->conf.local_rtp_port; //config.mtu = session->conf.mtu; //config.quant = session->conf.video_quant; //config.remote_ip = session->conf.remote_rtp_ip; //config.remote_rtp_port = session->conf.remote_rtp_port; //config.user_data = session; //config.bit_rate = session->conf.bit_rate; //config.on_rx_frame = &on_rx_frame; //config.dbg = &__dbg; //videortp_create(&config, &session->rtp); //rc = videortp_start(session->rtp); //if (rc != 0) //{ // Dbg("start video rtp failed!"); // videortp_destroy(session->rtp); // session->rtp = NULL; // goto on_error; //} //else{ // Dbg("videortp_start suc."); //} if (0 != start_video_rtpsession(session)) { goto on_error; } if (DOUBLERECORD_CALLTYPE == session->conf.nCallType){ if (NULL != pg_last_session){ pg_last_session->rtp = session->rtp; } } //if (session->conf.eDeviceType == eMobilePadType) //{ // rc = videoclock_create(REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, // REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, // &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps); //} //else if((session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) //{ // rc = videoclock_create(REC_COMMON_VIDEO_FPS_MOBILE, REC_COMMON_VIDEO_FPS_DEN, // REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, // &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps); //} //else if(session->conf.eDeviceType == eStand2sType) //{ // rc = videoclock_create(REC_COMMON_VIDEO_FPS_NUM, REC_COMMON_VIDEO_FPS_DEN, // REC_COMMON_VIDEO_RTP_WIDTH, REC_COMMON_VIDEO_RTP_HEIGHT, VIDEO_FORMAT_RGB24, // &local_put_frame, session, &local_get_frame, session, &session->local_clock, session->conf.ref_Up_Fps); //} //Dbg("create session->local_clock addr is 0x%08x", session->local_clock); // //if (rc != 0) { // Dbg("create video clock failed!"); // goto on_error; //} //rc = videoclock_start(session->local_clock); //if (rc != 0) { // Dbg("start video clock failed!"); // videoclock_destroy(session->local_clock); // session->local_clock = NULL; // goto on_error; //} if (0 != start_local_video_clock(session)) { goto on_error; } } else{ pg_last_session = session; //保存session信息 Dbg("begin show agent static picture."); show_remote_agnet_picture(session); } } #else if (DOUBLERECORD_CALLTYPE == session->conf.nCallType) { if (NULL != pg_last_session) { session->premote_render = pg_last_session->premote_render; session->plocal_render = pg_last_session->plocal_render; Dbg("double record call local and remote render reuse."); } else { Dbg("pg_last_session is NULL, and call type is %d.", session->conf.nCallType); } } if (session->premote_render) { if (0 != session->conf.remote_rtp_port) { if (0 != start_video_rtpsession(session)) { goto on_error; } if (DOUBLERECORD_CALLTYPE == session->conf.nCallType) { if (NULL != pg_last_session) { pg_last_session->rtp = session->rtp; } } if (0 != start_local_video_clock(session)) { goto on_error; } } else { Dbg("begin show agent static picture."); show_remote_agnet_picture(session); } } #endif // RVC_OS_WIN on_error: return rc; } static void stop_video(video_session_t *session) { LOG_FUNCTION(); #ifdef RVC_OS_WIN Dbg("stop_video param video_session 0x%08x, session->local_clock is 0x%08x, session->remote_hwnd is 0x%08x.", session, session->local_clock, session->remote_hwnd); if (session->local_clock && session->remote_hwnd) { Dbg("videoclock_stop local_clock addr is 0x%08x", session->local_clock); videoclock_stop(session->local_clock); videoclock_destroy(session->local_clock); session->local_clock = NULL; pg_remote_hwnd = NULL; pg_local_hwnd = NULL; } #else if (session->local_clock) { Dbg("videoclock_stop local_clock addr is 0x%08x", session->local_clock); videoclock_stop(session->local_clock); videoclock_destroy(session->local_clock); session->local_clock = NULL; } #endif // RVC_OS_WIN if (session->rtp) { Dbg("begin stop video rtp."); videortp_stop(session->rtp); videortp_destroy(session->rtp); session->rtp = NULL; } else { Dbg("session->rtp == null"); } #ifdef RVC_OS_WIN if (session->local_player) { videoplayer_destroy(session->local_player); session->local_player = NULL; Dbg("local video player destroy."); } if (session->remote_player && session->remote_hwnd) { videoplayer_destroy(session->remote_player); session->remote_player = NULL; Dbg("remote video player destroy."); } #else if (session->plocal_render){ delete session->plocal_render; session->plocal_render = NULL; } if (session->premote_render){ delete session->premote_render; session->premote_render = NULL; } #endif if (session->local_encode_sws_ctx_env) { sws_freeContext(session->local_encode_sws_ctx_env); session->local_encode_sws_ctx_env = NULL; } if (session->local_encode_sws_ctx_opt) { sws_freeContext(session->local_encode_sws_ctx_opt); session->local_encode_sws_ctx_opt = NULL; } } #ifdef RVC_OS_WIN static bool ReMoveOutOfScreenVideoWindow(HWND hWnd, RECT rect) { bool bret = false; int iScreenWidth = GetSystemMetrics(SM_CXSCREEN); int iScreenHight = GetSystemMetrics(SM_CYSCREEN); Dbg("ScreenWidth = %d, ScreenHight = %d.", iScreenWidth, iScreenHight); int iVideoWidth = rect.right - rect.left; int iVideoHight = rect.bottom - rect.top; if (rect.left < 0) { if (rect.bottom <= iScreenHight) { MoveWindow(hWnd, 0, rect.top, iVideoWidth, iVideoHight, TRUE); } else { MoveWindow(hWnd, 0, iScreenHight - iVideoHight, iVideoWidth, iVideoHight, TRUE); } bret = true; } if (rect.right > iScreenWidth) { if (rect.bottom <= iScreenHight) { MoveWindow(hWnd, iScreenWidth - iVideoWidth, rect.top, iVideoWidth, iVideoHight, TRUE); } else { MoveWindow(hWnd, iScreenWidth - iVideoWidth, iScreenHight - iVideoHight, iVideoWidth, iVideoHight, TRUE); } bret = true; } if (rect.bottom > iScreenHight) { if (rect.left >= 0 && rect.right <= iScreenWidth) { MoveWindow(hWnd, rect.left, iScreenHight - iVideoHight, iVideoWidth, iVideoHight, TRUE); bret = true; } } return bret; } static bool ReMoveCenterOtherVideoWindow(HWND hWnd, RECT rect, RECT otherect) { bool bret = false; int iVideoWidth = rect.right - rect.left; int iVideoHight = rect.bottom - rect.top; int iOtherVideoWidth = otherect.right - otherect.left; int iOtherVideoHight = otherect.bottom - otherect.top; if (iVideoWidth > iOtherVideoHight || iVideoHight > iOtherVideoHight) { return bret; } if (rect.left > otherect.left + iVideoWidth && rect.right < otherect.right) { if (rect.top > otherect.top && rect.bottom < otherect.bottom) { if (otherect.right - rect.right <= rect.left - otherect.left) { MoveWindow(hWnd, otherect.right - iVideoWidth, rect.top, iVideoWidth, iVideoHight, TRUE); } else { MoveWindow(hWnd, otherect.left, rect.top, iVideoWidth, iVideoHight, TRUE); } bret = true; } } if (rect.right < otherect.right - iVideoWidth && rect.left > otherect.left) { if (rect.top > otherect.top && rect.bottom < otherect.bottom) { if (otherect.right - rect.right <= rect.left - otherect.left) { MoveWindow(hWnd, otherect.right - iVideoWidth, rect.top, iVideoWidth, iVideoHight, TRUE); } else { MoveWindow(hWnd, otherect.left, rect.top, iVideoWidth, iVideoHight, TRUE); } bret = true; } } return bret; } static bool ReMoveVideoWindow(HWND hWnd, RECT rect, RECT otherect) { LOG_FUNCTION(); bool bret = false; bret = ReMoveOutOfScreenVideoWindow(hWnd, rect); bret = ReMoveCenterOtherVideoWindow(hWnd, rect, otherect); return bret; } static int HandleVideoMoveEvent(int iMessageType, HWND hWnd, video_session_t* pSession) { LOG_FUNCTION(); int iRet = -1; if (NULL == pSession || NULL == hWnd) { return iRet; } HWND hOtherWnd = NULL; //本地和远端标识 1为本地,2为远端 int iVideoType = 2; if (hWnd == pSession->local_hwnd) { iVideoType = 1; hOtherWnd = pSession->remote_hwnd; } else { hOtherWnd = pSession->local_hwnd; } if (NULL == hOtherWnd) { return iRet; } bool bMoved = false; RECT rect; GetWindowRect(hWnd, &rect); Dbg("MessageType = %d, VideoType = %d, rect.left = %d, rect.right = %d, rect.bottom = %d, rect.top = %d", iMessageType, iVideoType, rect.left, rect.right, rect.bottom, rect.top); RECT otherect; GetWindowRect(hOtherWnd, &otherect); Dbg("other video Window left = %d, right = %d, bottom = %d, top = %d", otherect.left, otherect.right, otherect.bottom, otherect.top); bMoved = ReMoveVideoWindow(hWnd, rect, otherect); if (bMoved) { Dbg("has removed video window."); GetWindowRect(hWnd, &rect); } if (NULL != pSession->conf.video_echo_cb && NULL != pSession->conf.video_echo_cb->on_video_box_move) { pSession->conf.video_echo_cb->on_video_box_move(iMessageType, iVideoType, rect.left, rect.bottom, pSession->conf.video_echo_cb->user_data); iRet = 0; } return iRet; } #else #endif // RVC_OS_WIN #ifdef RVC_OS_WIN static LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { video_session_t* session = (video_session_t*)GetWindowLongPtrA(hWnd, GWLP_USERDATA); switch (msg) { case WM_DESTROY: Dbg("WndProc session addr is 0x%08x, and receive WM_DESTROY.", session); if (session->local_hwnd == hWnd) { Dbg("session->local_hwnd = 0"); session->local_hwnd = 0; } else if (session->remote_hwnd == hWnd) { Dbg("session->remote_hwnd = 0"); session->remote_hwnd = 0; } if (session->local_hwnd == 0 && session->remote_hwnd == 0) { Dbg("*****PostQuitMessage****"); PostQuitMessage(0); } return 0; case WM_NCHITTEST: if (((session->local_hwnd == hWnd) && (0 != session->conf.local_move)) || ((session->remote_hwnd == hWnd) && (0 != session->conf.remote_move))) { return HTCAPTION; } else { break; } case WM_ACTIVATE: case WM_TOUCH: case WM_GESTURE: ReleaseCapture(); return 0; #if 1 case WM_WINDOWPOSCHANGED: { LPWINDOWPOS pPos = (LPWINDOWPOS)lParam; if (pPos->hwndInsertAfter != HWND_TOPMOST && pPos->hwndInsertAfter != HWND_TOP) { //BringWindowToTop(hWnd); SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } else { return DefWindowProc(hWnd, msg, wParam, lParam); } } return 0; //return DefWindowProc(hWnd, msg, wParam, lParam); #endif case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: case WM_LBUTTONDBLCLK: case WM_LBUTTONDOWN: case WM_LBUTTONUP: OutputDebugStringA("mouse clicked!"); if (session) { if (session->local_hwnd) { //ReleaseCapture(); } } return 0; case WM_CLOSE: Dbg("WndProc session addr is 0x%08x, and receive WM_CLOSE", session); stop_video(session); Dbg("WndProc SetEvent session addr is 0x%08x.", session); //SetEvent(session->ui_thread); DestroyWindow(session->local_hwnd); DestroyWindow(session->remote_hwnd); return 0; case WM_MOVE: break; case WM_ENTERSIZEMOVE: { Dbg("***WM_ENTERSIZEMOVE***"); HandleVideoMoveEvent(0, hWnd, session); } break; case WM_EXITSIZEMOVE: { Dbg("***WM_EXITSIZEMOVE***"); HandleVideoMoveEvent(1, hWnd, session); } break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } } #endif // #ifdef RVC_OS_WIN static unsigned int __stdcall ui_proc(void *arg) { video_session_t *session = (video_session_t*)arg; Dbg("ui_proc session addr is 0x%08x", session); WNDCLASSA wc = {0}; ATOM a = 0; HWND hWnd = NULL; MSG msg; HINSTANCE hInst = ModuleBase::GetModuleBase()->GetInstance(); bool breuse_local_wnd = false; bool breuse_remote_wnd = false; DWORD dLocal_style = WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOACTIVATE; DWORD dRemote_style = WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOACTIVATE; //双录两阶段视频窗口复用 if (NULL != pg_local_hwnd){ session->local_hwnd = pg_local_hwnd; //SetWindowLongPtrA(session->local_hwnd, GWLP_USERDATA, (LONG_PTR)session); breuse_local_wnd = true; Dbg("local video hwnd reuse."); } else{ Dbg("create local video hwnd and x = %d, y = %d, width = %d, height = %d.", session->conf.local_video_view_x, session->conf.local_video_view_y, session->conf.local_video_view_cx, session->conf.local_video_view_cy); Dbg("local video move flag is %d, remote video move flag is %d.", session->conf.local_move, session->conf.remote_move); if (0 != session->conf.local_move){ dLocal_style -= WS_EX_NOACTIVATE; } if (0 != session->conf.remote_move){ dRemote_style -= WS_EX_NOACTIVATE; } CoInitialize(0); wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.hCursor = NULL; wc.hIcon = NULL; wc.lpfnWndProc = &WndProc; wc.lpszClassName = WNDCLS_NAME; wc.style = CS_HREDRAW | CS_OWNDC | CS_VREDRAW; a = RegisterClassA(&wc); if (a == 0) return 0; session->local_hwnd = CreateWindowExA(dLocal_style, WNDCLS_NAME, NULL, WS_POPUP|WS_VISIBLE, session->conf.local_video_view_x, session->conf.local_video_view_y, session->conf.local_video_view_cx, session->conf.local_video_view_cy, NULL, NULL, hInst, NULL); if (session->local_hwnd) { SetWindowLongPtrA(session->local_hwnd, GWLP_USERDATA, (LONG_PTR)session); if (0 == session->conf.local_move){ SetWindowPos(session->local_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); } pg_local_hwnd = session->local_hwnd; Dbg("restore local video hwnd"); } } if(session->conf.remote_video_view_x||session->conf.remote_video_view_y||session->conf.remote_video_view_cx||session->conf.remote_video_view_cy) { if (NULL != pg_remote_hwnd){ session->remote_hwnd = pg_remote_hwnd; //SetWindowLongPtrA(session->remote_hwnd, GWLP_USERDATA, (LONG_PTR)session); breuse_remote_wnd = true; Dbg("remote video hwnd reuse."); if (NULL != pg_last_session){ Dbg("SetEvent pg_last_session->ui_event and ui_event addr is %8x.", pg_last_session->ui_event); record_agent_picture_show_session_destory(pg_last_session); } } else{ Dbg("create remote video hwnd x = %d, y = %d, width = %d, height = %d.", session->conf.remote_video_view_x, session->conf.remote_video_view_y, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy); session->remote_hwnd = CreateWindowExA(dRemote_style, WNDCLS_NAME, NULL, WS_POPUP|WS_VISIBLE, session->conf.remote_video_view_x, session->conf.remote_video_view_y, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy, NULL, NULL, hInst, NULL); if (session->remote_hwnd) { SetWindowLongPtrA(session->remote_hwnd, GWLP_USERDATA, (LONG_PTR)session); if (0 == session->conf.remote_move){ SetWindowPos(session->remote_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); } pg_remote_hwnd = session->remote_hwnd; Dbg("restore remote video hwnd."); } } } else { Dbg("remote_hwnd == Null"); session->remote_hwnd = NULL; } if (session->local_hwnd/* && session->remote_hwnd*/) { int rc = 0; ShowCursor(FALSE); Dbg("SetEvent1 session addr is 0x%08x.", session); SetEvent(session->ui_event); rc = start_video(session); if (rc != 0) { Dbg("start video failed!"); } else { Dbg("start video ok!"); } if (!breuse_local_wnd && !breuse_remote_wnd) { while (GetMessageA(&msg, NULL, NULL, NULL)) { if (msg.message == WM_CLOSE) { Dbg("session addr is 0x%08x, session->local_hwnd is 0x%08x, rx WM_CLOSE", session, session->local_hwnd); } TranslateMessage(&msg); DispatchMessageA(&msg); } Dbg("SetEvent2 session addr is 0x%08x.", session); SetEvent(session->ui_event); } } if (a) UnregisterClassA(WNDCLS_NAME, hInst); CoUninitialize(); return 0; } #else void* videorender_func(void* arg) { LOG_FUNCTION(); video_session_t* session = (video_session_t*)arg; Dbg("%s:%d session addr is 0x%08x, session->plocal_render = 0x%08x", __FUNCTION__, __LINE__, session, session->plocal_render); char str_local_ip[MAX_PATH_SIZE] = { 0 }; char str_remote_ip[MAX_PATH_SIZE] = { 0 }; translate_ipaddr_from_int(str_local_ip, MAX_PATH_SIZE, session->conf.local_rtp_ip); translate_ipaddr_from_int(str_remote_ip, MAX_PATH_SIZE, session->conf.remote_rtp_ip); Dbg("videorender_func local_pt: %d local_ip: %s local_rtp_port: %d.", session->conf.local_pt, str_local_ip, session->conf.local_rtp_port); Dbg("videorender_func remote_pt: %d remote_ip: %s remote_rtp_port: %d.", session->conf.remote_pt, str_remote_ip, session->conf.remote_rtp_port); Dbg("videorender_func rx_width: %d rx_height: %d.", session->conf.remote_video_width, session->conf.remote_video_height); Dbg("%s:%d local(%d,%d,%d,%d) remote(%d,%d,%d,%d).", __FUNCTION__, __LINE__, session->conf.local_video_view_x, session->conf.local_video_view_y, session->conf.local_video_view_cx, session->conf.local_video_view_cy, session->conf.remote_video_view_x, session->conf.remote_video_view_y, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy); session->plocal_render = new VideoRenderObj(); if (NULL != session->plocal_render){ videorender_param_t tparam = { 0 }; tparam.icx = session->conf.local_video_view_x; tparam.icy = session->conf.local_video_view_y; tparam.uwidth = session->conf.local_video_view_cx; tparam.uheight = session->conf.local_video_view_cy; //tparam.uvideowidth = REC_COMMON_VIDEO_PREVIEW_WIDTH; //tparam.uvideoheight = REC_COMMON_VIDEO_PREVIEW_HEIGHT; tparam.ivideoformat = VIDEO_FORMAT_RGB24; if (0 == session->plocal_render->SetVideoRenderParam(&tparam)){ session->plocal_render->HideVideoWindow(); } else { Dbg("%s:%d set video render param failed!", __FUNCTION__, __LINE__); return 0; } } if (session->conf.remote_video_view_x || session->conf.remote_video_view_y || session->conf.remote_video_view_cx || session->conf.remote_video_view_cy){ Dbg("%s:%d create remote video hwnd x = %d, y = %d, width = %d, height = %d.", __FUNCTION__, __LINE__, session->conf.remote_video_view_x, session->conf.remote_video_view_y, session->conf.remote_video_view_cx, session->conf.remote_video_view_cy); session->premote_render = new VideoRenderObj(); if (session->premote_render){ videorender_param_t tparam_remote = { 0 }; tparam_remote.icx = session->conf.remote_video_view_x; tparam_remote.icy = session->conf.remote_video_view_y; tparam_remote.uwidth = session->conf.remote_video_view_cx; tparam_remote.uheight = session->conf.remote_video_view_cy; //tparam_remote.uvideowidth = REC_COMMON_VIDEO_DSM_AGENT_WIDTH; //tparam_remote.uvideoheight = REC_COMMON_VIDEO_DSM_AGENT_HEIGHT; tparam_remote.ivideoformat = VIDEO_FORMAT_RGB24; if (0 == session->premote_render->SetVideoRenderParam(&tparam_remote)) { //session->premote_render->ShowVideoWindow(); } } else { Dbg("session remote video render is null."); } } if (session->plocal_render){ start_video(session); //session->plocal_render->ShowVideoWindow(); bool bshow_local = false; bool bset = true; //session->premote_render->ShowVideoWindow(); for (; ; ) { struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long unsec = ts.tv_nsec + (1000 * 1000 * 500); ts.tv_sec += (unsec / 1000000000); ts.tv_nsec = (unsec % 1000000000); if (0 != sem_timedwait(&session->ui_stop_sem, &ts) && (ETIMEDOUT == errno)) { video_frame* local_video_frame = NULL; int iwindowstate = get_local_video_frame(session, &local_video_frame); if (iwindowstate != session->ilast_windstae){ set_video_windows(session, iwindowstate); session->ilast_windstae = iwindowstate; Dbg("%s:%d, window state is %d.", __FUNCTION__, __LINE__, iwindowstate); } if (NULL != local_video_frame) { //Dbg("%s:%d, video size is (%d,%d), showPersonArea flag is %d.", __FUNCTION__, __LINE__, local_video_frame->width, local_video_frame->height, *session->conf.ref_Is_showPersonArea); video_frame* localframe = NULL; if (0 == translate_image_resolution(&localframe, session->conf.local_video_view_cx, session->conf.local_video_view_cy, local_video_frame)) { session->plocal_render->RenderVideoFrame(localframe); video_frame_delete(localframe); localframe = NULL; } else { session->plocal_render->RenderVideoFrame(local_video_frame); } if (false == session->blocalrender){ LogWarn(Severity_Middle, Error_Debug, EVENT_MOD_SIP_LOCAL_VIDEO_RENDER_STARTED, "start local video render."); session->blocalrender = true; } bshow_local = true; video_frame_delete(local_video_frame); local_video_frame = NULL; } else { //Dbg("%s:%d,get video from shm preview queue failed!", __FUNCTION__, __LINE__); } } else { Dbg("%s:%d videorender_func exit!", __FUNCTION__, __LINE__); session->plocal_render->HideVideoWindow(); break; } if (bset){ if (bshow_local && session->bshow_remote) { session->plocal_render->ShowVideoWindow(); session->premote_render->ShowVideoWindow(); bset = false; } } } } return 0; } #endif // RVC_OS_WIN static int start_ui(video_session_t *session) { LOG_FUNCTION(); Dbg("start ui session addr is 0x%08x", session); #ifdef RVC_OS_WIN session->ui_event = CreateEventA(NULL, FALSE, FALSE, NULL); if (!session->ui_event) { Dbg("phonemedia_start create ui event failed!"); return Error_Resource; } else{ Dbg("session->ui_event = 0x%8x", session->ui_event); } session->ui_thread = (HANDLE)_beginthreadex(NULL, 0, &ui_proc, session, 0, NULL); if (!session->ui_thread) { Dbg("phonemedia_start create ui thread failed!"); CloseHandle(session->ui_event); session->ui_event = NULL; return Error_Resource; } else{ Dbg("session %8x create session->ui_thread = %8x", session, session->ui_thread); } Dbg("ui thread created ok!"); { HANDLE hs[] = {session->ui_event, session->ui_thread}; DWORD dwRet = WaitForMultipleObjects(array_size(hs), hs, FALSE, INFINITE); if (dwRet == WAIT_OBJECT_0) { // Dbg("wait for ui ready event ok!"); } else if (dwRet == WAIT_OBJECT_0 + 1) { // thread exit Dbg("ui thread aborted unexpected!"); Dbg("CloseHandle ui_thread 0x%08x", session->ui_thread); CloseHandle(session->ui_thread); session->ui_thread = NULL; Dbg("CloseHandle ui_event 0x%08x", session->ui_event); CloseHandle(session->ui_event); session->ui_event = NULL; return Error_Resource; } } return 0; #else if (0 != sem_init(&session->ui_stop_sem, 0, 0)) { Dbg("%s:%d create ui stop event failed!", __FUNCTION__, __LINE__); return Error_Resource; } else{ Dbg("%s:%d create ui stop event success!", __FUNCTION__, __LINE__); } int err = pthread_create(&session->ui_threadid, NULL, videorender_func, session); if (0 == err) { Dbg("create video render thread success, thread id is %u.", session->ui_threadid); } else { Dbg("create video render thread failed."); return Error_Resource; } return err; #endif // RVC_OS_WIN } static void stop_ui(video_session_t *session) { LOG_FUNCTION(); Dbg("%s:%d session addr is 0x%08x.", __FUNCTION__, __LINE__, session); #ifdef RVC_OS_WIN if (DOUBLERECORD_CALLTYPE == session->conf.nCallType) { if (NULL != pg_last_session) { pg_last_session->rtp = session->rtp; pg_last_session->local_clock = session->local_clock; CloseHandle(session->ui_thread); session->ui_thread = NULL; CloseHandle(session->ui_event); session->ui_event = NULL; session = pg_last_session; } } if (NULL != session->pic_record) { if (NULL != session->pic_record->work_thread) { SetEvent(session->pic_record->evt); Dbg("CloseHandle pic_record ui_thread 0x%08x", session->pic_record->work_thread); CloseHandle(session->pic_record->work_thread); session->pic_record->work_thread = NULL; Dbg("CloseHandle pic_record ui_event 0x%08x", session->pic_record->evt); CloseHandle(session->pic_record->evt); session->pic_record->evt = NULL; } } if (session->local_hwnd) { Dbg("PostMessageA WM_CLOSE session addr is 0x%08x, session->local_hwnd = 0x%08x", session, session->local_hwnd); BOOL bRet = PostMessageA(session->local_hwnd, WM_CLOSE, 0, 0); Dbg("WaitForSingleObject session addr is %8x, and session->ui_thread is %8x.", session, session->ui_thread); DWORD dCode = WaitForSingleObject(session->ui_thread, INFINITE); Dbg("After WaitForSingleObject (session->ui_thread, INFINITE) session addr is %8x, and session->ui_thread = 0x%08x.", session, session->ui_thread); Dbg("CloseHandle ui_thread 0x%08x", session->ui_thread); CloseHandle(session->ui_thread); session->ui_thread = NULL; Dbg("CloseHandle ui_event 0x%08x", session->ui_event); CloseHandle(session->ui_event); session->ui_event = NULL; } pg_last_session = NULL; pg_local_hwnd = NULL; pg_remote_hwnd = NULL; Dbg("set pg_last_session to null."); #else sem_post(&session->ui_stop_sem); if (session->ui_threadid > 0) { if (0 == pthread_join(session->ui_threadid, NULL)){ Dbg("video render thread %u pthread join success.", session->ui_threadid); session->ui_threadid = 0; } else{ Dbg("video render thread pthread join error for %s", strerror(errno)); } } Dbg("ui thread exit!"); stop_video(session); #endif // RVC_OS_WIN } static int load_record_area_png(video_session_t *session) { int iret = -1; if (NULL == session){ return iret; } //加载双录人形背景框 char strPath[MAX_PATH_SIZE]={0}; char strRecordAreaPath[MAX_PATH_SIZE] = { 0 }; #ifdef RVC_OS_WIN GetCurrentRunPath(strPath); sprintf(strRecordAreaPath, "%s\\bin\\recordarea.png", strPath); if (ExistsFile(strRecordAreaPath)) { if (session->recordareaimage == NULL) { if((session->conf.eDeviceType == eMobilePadType)||(session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { //pad版对人形区域放大处理 session->recordareaimage = cvLoadImage(strRecordAreaPath); IplImage* tmp = cvCreateImage(cvSize(session->recordareaimage->width,session->recordareaimage->height),IPL_DEPTH_8U,3); cvResize(session->recordareaimage ,tmp); cvSetImageROI(tmp,cvRect(0,0,session->recordareaimage->width,session->recordareaimage->height)); //cvSetImageROI(tmp,cvRect(0,0,session->recordareaimage->width,session->recordareaimage->height)); cvCopy(tmp,session->recordareaimage); cvReleaseImage(&tmp); } else { session->recordareaimage = cvLoadImage(strRecordAreaPath); } } if (session->recordareamask == NULL ) { if((session->conf.eDeviceType == eMobilePadType)||(session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { //pad版对人形区域放大处理 session->recordareamask = cvLoadImage(strRecordAreaPath,0); IplImage* tmp = cvCreateImage(cvSize(session->recordareamask->width,session->recordareamask->height),IPL_DEPTH_8U,1); cvResize(session->recordareamask ,tmp); cvSetImageROI(tmp,cvRect(0,0,session->recordareamask->width,session->recordareamask->height)); cvCopy(tmp,session->recordareamask); cvReleaseImage(&tmp); } else { session->recordareamask = cvLoadImage(strRecordAreaPath,0); } } Dbg("Load record area img Success"); iret = 0; } else { Dbg("Load record area img Fail"); session->recordareaimage = NULL; session->recordareamask = NULL; } #endif // RVC_OS_WIN return iret; } int Local_video_session_create(const video_session_conf_t *conf, video_session_t **p_session, const bool bremote) { LOG_FUNCTION(); video_session_t *session = ZALLOC_T(video_session_t); if (session) { memcpy(&session->conf, conf, sizeof(video_session_conf_t)); session->bshow_remote = false; session->ilast_windstae = 0; if ((conf->eDeviceType == eDesk2SType||conf->eDeviceType == eDesk1SType||conf->eDeviceType == eDesk2SIntegratedType) && g_bIsSalesRecord) { //modify by clp 20191011 低柜区分是否远程连线模式双录 if (g_bEwsRecord) { session->video_shm_q_preview = new Clibvideoqueue(REC_COMMON_VIDEO_EWS_SHM_PREVIEW_QUEUE); Dbg("[dbg] use ews preview share memory."); } else { session->video_shm_q_preview = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE); Dbg("[dbg] use env preview share memory."); } } else if ((conf->eDeviceType == ePadtype || conf->eDeviceType == eMobilePadType) && g_bEwsRecord) { session->video_shm_q_preview = new Clibvideoqueue(REC_COMMON_VIDEO_EWS_SHM_PREVIEW_QUEUE); Dbg("[dbg] use ews preview share memory"); } else { session->video_shm_q_preview = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE); Dbg("[dbg] use env preview share memory"); } if (bremote){ if (eStand2sType == conf->eDeviceType){ session->video_shm_q_remote = new Clibvideoqueue(REC_COMMON_VIDEO_REMOTE_SHM_RTP_QUEUE); Dbg("[dbg] stand2s device, record remote video use 320*240, and video_shm_q_remote addr is 0x%08x.", session->video_shm_q_remote); } else{ session->video_shm_q_remote = new Clibvideoqueue(REC_COMMON_VIDEO_REMOTE_SHM_RTP_QUEUE); Dbg("[dbg] not stand2s device, record remote video use 320*240, and video_shm_q_remote addr is 0x%08x.", session->video_shm_q_remote); } } if (conf->ref_Is_ActiveInspect != NULL) { if (*conf->ref_Is_ActiveInspect == 1) { session->video_error = NULL; session->video_shm_q_env = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE); if (conf->camera_count == 2) { session->video_shm_q_opt = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE); } } } session->local_clock = NULL; if (false == bremote){ if (0 == load_record_area_png(session)){ Dbg("load record area picture success."); } else{ Dbg("load record area picture failed."); } } *p_session = session; } return 0; } int video_session_create(const video_session_conf_t *conf, video_session_t **p_session) { LOG_FUNCTION(); video_session_t *session = ZALLOC_T(video_session_t); if (session) { char str_local[MAX_PATH_SIZE] = {0}; char str_remote[MAX_PATH_SIZE] = {0}; translate_ipaddr_from_int(str_local, MAX_PATH_SIZE, conf->local_rtp_ip); translate_ipaddr_from_int(str_remote, MAX_PATH_SIZE, conf->remote_rtp_ip); Dbg("video_session_create session addr = 0x%08x,local_rtp_ip = %s,local_rtp_port = %d, local_pt = %d, remote_rtp_ip = %s,remote_rtp_port=%d, remote_pt = %d, call type = %d.", session, str_local, conf->local_rtp_port,conf->local_pt, str_remote, conf->remote_rtp_port, conf->remote_pt, conf->nCallType); memcpy(&session->conf, conf, sizeof(video_session_conf_t)); session->bshow_remote = false; session->ilast_windstae = 0; session->video_shm_q_env = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_RTP_QUEUE); if (DOUBLERECORD_CALLTYPE != conf->nCallType){ session->video_shm_q_remote = new Clibvideoqueue(REC_COMMON_VIDEO_REMOTE_SHM_RTP_QUEUE); session->video_shm_q_preview = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_PREVIEW_QUEUE); } else{ if (NULL != pg_last_session){ session->video_shm_q_remote = (pg_last_session)->video_shm_q_remote; session->video_shm_q_preview = (pg_last_session)->video_shm_q_preview; Dbg("double record the second period, reuse record video queue."); } } char strPath[MAX_PATH_SIZE]={0}; char strImgPath[MAX_PATH_SIZE]={0}; #ifdef RVC_OS_WIN GetCurrentRunPath(strPath); sprintf(strImgPath, "%s\\bin\\error.jpg", strPath); #else strcpy_s(strImgPath, MAX_PATH_SIZE, "./bin/error.jpg"); #endif // RVC_OS_WIN if (ExistsFile(strImgPath)) { IplImage*img = cvLoadImage(strImgPath,1); if (img != NULL) { Dbg("load img success"); session->video_error = new videoq_frame; session->video_error->format = VIDEOQ_FORMAT_RGB24; session->video_error->framesize = 320*180*3; session->video_error->height = 180; session->video_error->width = 320; session->video_error->data = new unsigned char[320*180*3]; memcpy(session->video_error->data,img->imageData,320*180*3); cvReleaseImage(&img); } } else { Dbg("Load error img Fail"); session->video_error = NULL; } //加载人形背景框 char strPersonPath[MAX_PATH_SIZE] = {0}; #ifdef RVC_OS_WIN sprintf(strPersonPath, "%s\\bin\\rxk.jpg", strPath); #else strcpy_s(strPersonPath, MAX_PATH_SIZE, "./bin/rxk.jpg"); #endif // RVC_OS_WIN if (ExistsFile(strPersonPath)) { if (session->personimage == NULL) { if((session->conf.eDeviceType == eMobilePadType)||(session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { //pad版对人形区域放大处理 session->personimage = cvLoadImage(strPersonPath); IplImage*tmp = cvCreateImage(cvSize(session->personimage->width*3/2,session->personimage->height*3/2),IPL_DEPTH_8U,3); cvResize(session->personimage ,tmp); cvSetImageROI(tmp,cvRect(session->personimage->width/4,50,session->personimage->width,session->personimage->height)); cvCopy(tmp,session->personimage); cvReleaseImage(&tmp); } else { session->personimage = cvLoadImage(strPersonPath); } } if (session->personmask == NULL ) { if((session->conf.eDeviceType == eMobilePadType)||(session->conf.eDeviceType == ePadtype)||(session->conf.eDeviceType == eDesk2SType)||(session->conf.eDeviceType == eDesk1SType)||(session->conf.eDeviceType == eDesk2SIntegratedType)) { //pad版对人形区域放大处理 session->personmask = cvLoadImage(strPersonPath,0); IplImage*tmp = cvCreateImage(cvSize(session->personmask->width*3/2,session->personmask->height*3/2),IPL_DEPTH_8U,1); cvResize(session->personmask ,tmp); cvSetImageROI(tmp,cvRect(session->personmask->width/4,50,session->personmask->width,session->personmask->height)); cvCopy(tmp,session->personmask); cvReleaseImage(&tmp); } else { session->personmask = cvLoadImage(strPersonPath,0); } } //IplImage*persongrey = cvLoadImage(strPersonPath,CV_LOAD_IMAGE_GRAYSCALE); //二值化提取人形框掩码 //cvThreshold(persongrey,session->personmask,150, 255, CV_THRESH_BINARY); Dbg("Load person img Success"); } else { Dbg("Load person img Fail"); session->personimage = NULL; session->personmask = NULL; } #if 0 video_frame frame; video_frame_alloc(320, 180, VIDEO_FORMAT_RGB24, &frame); video_frame_fill_black(&frame); videoq_frame frm; frm.data = frame.data[0]; session->video_shm_q_env->GetVideo(&frm, 0); video_frame_save_bmpfile("d:\\a.bmp", &frame); #endif if (conf->camera_count == 2) { session->video_shm_q_opt = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_RTP_QUEUE); } session->bvideorecved = false; session->blocalrender = false; session->bremoterender = false; *p_session = session; } return 0; } int video_session_start(video_session_t *session) { LOG_FUNCTION(); Dbg("video_session_start session addr is 0x%08x, session call type is %d.", session, session->conf.nCallType); int rc = start_ui(session); return rc; } void video_session_stop(video_session_t *session) { LOG_FUNCTION(); Dbg("video session stop session addr is 0x%08x", session); stop_ui(session); } void double_record_broadcast_video_session_stop() { LOG_FUNCTION(); #ifdef RVC_OS_WIN if (NULL != pg_last_session){ if (NULL != pg_last_session->pic_record){ if (NULL != pg_last_session->pic_record->work_thread){ SetEvent(pg_last_session->pic_record->evt); Dbg("CloseHandle pic_record ui_thread 0x%08x", pg_last_session->pic_record->work_thread); CloseHandle(pg_last_session->pic_record->work_thread); pg_last_session->pic_record->work_thread = NULL; Dbg("CloseHandle pic_record ui_event 0x%08x", pg_last_session->pic_record->evt); CloseHandle(pg_last_session->pic_record->evt); pg_last_session->pic_record->evt = NULL; } } } if (pg_last_session && pg_last_session->local_hwnd) { Dbg("PostMessageA WM_CLOSE session addr is 0x%08x, session->local_hwnd = 0x%08x", pg_last_session, pg_last_session->local_hwnd); BOOL bRet = PostMessageA(pg_last_session->local_hwnd, WM_CLOSE, 0, 0); Dbg("WaitForSingleObject session addr is %8x, and session->ui_thread is %8x.", pg_last_session, pg_last_session->ui_thread); DWORD dCode = WaitForSingleObject(pg_last_session->ui_thread, INFINITE); Dbg("After WaitForSingleObject (session->ui_thread, INFINITE) session addr is %8x, and session->ui_thread = 0x%08x.",pg_last_session, pg_last_session->ui_thread); Dbg("CloseHandle ui_thread 0x%08x", pg_last_session->ui_thread); CloseHandle(pg_last_session->ui_thread); pg_last_session->ui_thread = NULL; Dbg("CloseHandle ui_event 0x%08x", pg_last_session->ui_event); CloseHandle(pg_last_session->ui_event); pg_last_session->ui_event = NULL; } pg_last_session = NULL; pg_local_hwnd = NULL; pg_remote_hwnd = NULL; Dbg("set pg_last_session, pg_local_hwnd, pg_remote_hwnd to null."); #else #endif // RVC_OS_WIN } void video_session_destroy(video_session_t *session) { LOG_FUNCTION(); #ifdef RVC_OS_WIN if (NULL != session) { if (NULL != session->pic_record) { if (NULL != session->pic_record->work_thread) { SetEvent(session->pic_record->evt); Dbg("CloseHandle pic_record ui_thread 0x%08x", session->pic_record->work_thread); CloseHandle(session->pic_record->work_thread); session->pic_record->work_thread = NULL; Dbg("CloseHandle pic_record ui_event 0x%08x", session->pic_record->evt); CloseHandle(session->pic_record->evt); session->pic_record->evt = NULL; } } if (session->video_shm_q_env) { delete session->video_shm_q_env; session->video_shm_q_env = NULL; } if (session->video_shm_q_opt) { delete session->video_shm_q_opt; session->video_shm_q_opt = NULL; } if (session->video_shm_q_preview) { delete session->video_shm_q_preview; session->video_shm_q_preview = NULL; } } #else #endif // RVC_OS_WIN if (session->video_error){ delete session->video_error->data; delete session->video_error; } if (session->video_shm_q_remote) { delete session->video_shm_q_remote; session->video_shm_q_remote = NULL; } if (session->personimage){ cvReleaseImage(&session->personimage); } if (session->personmask){ cvReleaseImage(&session->personmask); } if (session->recordareaimage){ cvReleaseImage(&session->recordareaimage); } if (session->recordareamask){ cvReleaseImage(&session->recordareamask); } free(session); } void av_log_cb(void*ptr, int level, const char*fmt, va_list list) { vDbg(fmt, list); } int video_lib_init() { #ifdef RVC_OS_WIN CoInitialize(NULL); { int i, n; n = videocap_get_device_count(); for (i = 0; i < n; ++i) { WCHAR tmp[128]; char t[128]; videocap_get_device_name(i, tmp, ARRAYSIZE(tmp)); WideCharToMultiByte(CP_ACP, 0, tmp, -1, t, sizeof(t), 0, NULL); Dbg("%d = %s", i, t); } } videoframework_init(); av_log_set_callback(&av_log_cb); //av_log_set_level(AV_LOG_DEBUG); av_log_set_level(AV_LOG_QUIET); #else videoframework_init(); if (0 == VideoRender_Init()){ Dbg("sdl init success."); } else { Dbg("sdl init failed."); } //av_log_set_callback(&av_log_cb); //av_log_set_level(AV_LOG_TRACE); //av_log_set_level(AV_LOG_QUIET); #endif // RVC_OS_WIN return 0; } void video_lib_deinit() { #ifdef RVC_OS_WIN CoUninitialize(); #else #endif // RVC_OS_WIN videoframework_term(); VideoRender_Term(); }