Преглед изворни кода

Z991239-6031 #comment 支持上下摄像头同时回显

80274480 пре 7 месеци
родитељ
комит
5be95c68c0

+ 17 - 11
Module/mod_mediacontroller/capture.cpp

@@ -32,6 +32,7 @@ using namespace MediaController;
 #define RVC_AUDIO_BUFFER_LEN 320
 #endif
 
+#ifdef RVC_OS_WIN
 static void __dbg(const char *fmt, va_list arg)
 {
 	int n = vsnprintf(NULL, 0, fmt, arg);
@@ -47,6 +48,7 @@ static void __dbg(const char *fmt, va_list arg)
 		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("%s", strlog);
 	}
 }
+#endif
 
 
 static void __logevent(int ilogtype, int idevid, const char* strmessage)
@@ -841,8 +843,8 @@ static void env_cap_on_frame(void *user_data, video_frame *frame)
 	if (video_cap->bsavephoto) {
 		if ((video_cap->isaveinterval > 0) && (0 == video_cap->frame_id % (video_cap->isaveinterval * cap->config.video_env_fps)))
 		{
-			char strFileName[2 * MAX_PATH] = { 0 };
-			snprintf(strFileName, 2 * MAX_PATH, "%s%s_%d.bmp", video_cap->strsavedir, video_cap->strphotoname, isnapshot_count++);
+			char strFileName[3 * MAX_PATH] = { 0 };
+			snprintf(strFileName, 3 * MAX_PATH, "%s%s_%d%s", video_cap->strsavedir, video_cap->strphotoname, isnapshot_count++, ".bmp");
 			video_frame_save_bmpfile(strFileName, frame);
 		}
 	}
@@ -1195,6 +1197,8 @@ static void video_capture_destroy(video_capture_t *video_cap)
 }
 
 
+#ifdef RVC_OS_WIN
+#else
 static int get_video_capture_fps(int icapfps)
 {
 	int ifps = REC_COMMON_VIDEO_RAW_FPS;
@@ -1205,6 +1209,8 @@ static int get_video_capture_fps(int icapfps)
 
 	return ifps;
 }
+#endif
+
 
 #ifdef RVC_OS_WIN
 static int video_capture_start_win(video_capture_t* video_cap)
@@ -1579,9 +1585,9 @@ namespace MediaController {
 					if (rc != Error_Succeed) 
 					{
 						cap->opt_video->ustarttime = 0;
-						char strMessage[MAX_PATH*2] = {0};
-						get_camera_exception_message(strMessage, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail, please check device.");
-						LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN, strMessage);
+						char stroptMessage[MAX_PATH*2] = {0};
+						get_camera_exception_message(stroptMessage, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail, please check device.");
+						LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN, stroptMessage);
 						return Error_AllCamera;
 					}
 					else
@@ -1611,9 +1617,9 @@ namespace MediaController {
 					if (rc != Error_Succeed) 
 					{
 						cap->opt_video->ustarttime = 0;
-						char strMessage[MAX_PATH*2] = {0};
-						get_camera_exception_message(strMessage, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail, please check device.");
-						LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN,strMessage);
+						char strMsg[MAX_PATH*2] = {0};
+						get_camera_exception_message(strMsg, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail, please check device.");
+						LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN, strMsg);
 						return Error_OptCamera;
 					}
 					else
@@ -1641,9 +1647,9 @@ namespace MediaController {
 				if (rc != Error_Succeed) 
 				{
 					cap->opt_video->ustarttime = 0;
-					char strMessage[MAX_PATH*2] = {0};
-					get_camera_exception_message(strMessage, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail,please check device.");
-					LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN,strMessage);
+					char stroptMsg[MAX_PATH*2] = {0};
+					get_camera_exception_message(stroptMsg, MAX_PATH*2, cap->config.strVideoOpt, "open operate camera fail, please check device.");
+					LogWarn(Severity_Middle,Error_NotInit,ERROR_MOD_MEDIACONTROLLER_OPTCAM_OPEN, stroptMsg);
 					return Error_AllCamera;
 				}
 				else

+ 49 - 0
Module/mod_sipphone/SIPPhone_client_g.h

@@ -910,6 +910,55 @@ public:
 		return Error;
 	}
 
+	ErrorCodeEnum StartBothCameraRender(PhoneService_StartBothCameraRender_Req &Req, CSmartPointer<IAsynWaitSp> &spAsyncWait, DWORD dwTimeout)
+	{
+		CSmartPointer<IClientSessionFunction> pFunc = GetFunction();
+		CAutoBuffer Buf = SpObject2Buffer(Req);
+		if (m_context.checkEmpty())
+		{
+			m_context.AutoGenerate();
+			DbgToBeidou(m_context, m_pEntityBase != NULL ? m_pEntityBase->GetEntityName() : "")();
+			m_context = m_context.upgradeLink();
+		}
+		auto ret = pFunc->AsyncRequest(PhoneService_Method_StartBothCameraRender, PhoneService_MethodSignature_StartBothCameraRender, Buf, spAsyncWait, m_context, dwTimeout);
+		m_context.clear();
+		return ret;
+	}
+	ErrorCodeEnum StartBothCameraRender(PhoneService_StartBothCameraRender_Req &Req, PhoneService_StartBothCameraRender_Ans &Ans, DWORD dwTimeout)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = StartBothCameraRender(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+	ErrorCodeEnum StartBothCameraRender(PhoneService_StartBothCameraRender_Req &Req, PhoneService_StartBothCameraRender_Ans &Ans, DWORD dwTimeout, DWORD &dwUserError, CSimpleString &str)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = StartBothCameraRender(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+	ErrorCodeEnum StartBothCameraRender(PhoneService_StartBothCameraRender_Req &Req, PhoneService_StartBothCameraRender_Ans &Ans, DWORD dwTimeout, DWORD &dwUserError)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = StartBothCameraRender(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			CSimpleString str;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+
 
 	bool SafeDelete()
 	{

+ 32 - 0
Module/mod_sipphone/SIPPhone_def_g.h

@@ -43,6 +43,7 @@ namespace SIPPhone {
 #define PhoneService_Method_StartCameraRender 21
 #define PhoneService_Method_StopCameraRender 22
 #define PhoneService_Method_IsCameraRender 23
+#define PhoneService_Method_StartBothCameraRender 24
 
 #define PhoneService_MethodSignature_MakeCall -1045574280
 #define PhoneService_MethodSignature_HangupCall 507892508
@@ -68,6 +69,7 @@ namespace SIPPhone {
 #define PhoneService_MethodSignature_StartCameraRender -1962833445
 #define PhoneService_MethodSignature_StopCameraRender 6416978
 #define PhoneService_MethodSignature_IsCameraRender 325255993
+#define PhoneService_MethodSignature_StartBothCameraRender -1631336261
 
 #define PhoneService_LogCode_MakeCall "QLR040230100"
 #define PhoneService_LogCode_HangupCall "QLR040230101"
@@ -90,6 +92,7 @@ namespace SIPPhone {
 #define PhoneService_LogCode_StartCameraRender "QLR040230121"
 #define PhoneService_LogCode_StopCameraRender "QLR040230122"
 #define PhoneService_LogCode_IsCameraRender "QLR040230123"
+#define PhoneService_LogCode_StartBothCameraRender "QLR040230124"
 
 struct PhoneService_MakeCall_Req
 {
@@ -522,6 +525,35 @@ struct PhoneService_IsCameraRender_Ans
 
 };
 
+struct PhoneService_StartBothCameraRender_Req
+{
+	int env_view_x;
+	int env_view_y;
+	int env_view_cx;
+	int env_view_cy;
+	int opt_view_x;
+	int opt_view_y;
+	int opt_view_cx;
+	int opt_view_cy;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		auto & buf = Buf & env_view_x & env_view_y & env_view_cx & env_view_cy & opt_view_x & opt_view_y & opt_view_cx & opt_view_cy;
+	}
+
+};
+
+struct PhoneService_StartBothCameraRender_Ans
+{
+	int result;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		auto & buf = Buf & result;
+	}
+
+};
+
 
 ///////////////////////////
 

+ 27 - 0
Module/mod_sipphone/SIPPhone_server_g.h

@@ -191,6 +191,13 @@ public:
 				Error = Error_MethodSignatureFailed;
 			}
 			break;
+		case PhoneService_Method_StartBothCameraRender:
+			if (dwSignature == PhoneService_MethodSignature_StartBothCameraRender) {
+				bOverlap = true;
+			} else {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
 		default:
 			Error = Error_MethodNotFound;
 			break;
@@ -317,6 +324,11 @@ public:
 				Error = Error_MethodSignatureFailed;
 			}
 			break;
+		case PhoneService_Method_StartBothCameraRender:
+			if (dwSignature != PhoneService_MethodSignature_StartBothCameraRender) {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
 		default:
 			Error = Error_MethodNotFound;
 			break;
@@ -439,6 +451,11 @@ public:
 	/// override by user
 	}
 
+	virtual void Handle_StartBothCameraRender(SpReqAnsContext<PhoneService_StartBothCameraRender_Req, PhoneService_StartBothCameraRender_Ans>::Pointer ctx)
+	{
+	/// override by user
+	}
+
 	virtual void OnRequest(CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		CAutoBuffer Buf;
@@ -681,6 +698,16 @@ public:
 						Handle_IsCameraRender(ctx);
 					}
 					break;
+				case PhoneService_Method_StartBothCameraRender:
+					{
+						SpReqAnsContext<PhoneService_StartBothCameraRender_Req,PhoneService_StartBothCameraRender_Ans>::Pointer ctx;
+						ctx.Attach(new SpReqAnsContext<PhoneService_StartBothCameraRender_Req,PhoneService_StartBothCameraRender_Ans>(pTransactionContext));
+						SpBuffer2Object(Buf, ctx->Req);
+						pTransactionContext->GetLinkContext(ctx->link);
+						EntityResource::setLink(ctx->link);
+						Handle_StartBothCameraRender(ctx);
+					}
+					break;
 				default:
 					assert(0);
 					break;

+ 15 - 0
Module/mod_sipphone/SipService.xml

@@ -172,6 +172,21 @@
         <param name="result" type="bool"/>
       </res>
     </twoway>
+    <twoway name="StartBothCameraRender" overlap="true" method_id="24">
+      <req>
+        <param name="env_view_x" type="int"/>
+        <param name="env_view_y" type="int"/>
+        <param name="env_view_cx" type="int"/>
+        <param name="env_view_cy" type="int"/>
+        <param name="opt_view_x" type="int"/>
+        <param name="opt_view_y" type="int"/>
+        <param name="opt_view_cx" type="int"/>
+        <param name="opt_view_cy" type="int"/>
+      </req>
+      <res>
+        <param name="result" type="int"/>
+      </res>
+    </twoway>
   </class>
 	<!-- ÊÓÆµ¿ò¿ªÊ¼Òƶ¯ÏûÏ¢ -->
 	<message name="VideoBoxStartMove">

+ 73 - 19
Module/mod_sipphone/mod_sipphone.cpp

@@ -2468,7 +2468,7 @@ int CSIPEntity::StartCameraRender(int icamid, int ivideoview_x, int ivideoview_y
 	memcpy(&m_render->cb, &t_window_type_callback, sizeof(rvc_video_render_window_type_callback_t));
 	m_stVideoParam.bShowPersonArea = 0;
 
-	if (Error_Succeed == rvc_start_video_render(m_render, false, &t_render_callback)) {
+	if (Error_Succeed == rvc_start_video_render(m_render, eRender_Local_Single, &t_render_callback)) {
 		m_bIsCameraRender = true;
 	}
 
@@ -2492,16 +2492,9 @@ int CSIPEntity::StopCameraRender()
 		DestroyVideoRenderObj(m_render->plocal_render);
 	}
 
-#ifdef RVC_OS_WIN
-	if (NULL != m_render->local_render_stop_event) {
-		CloseHandle(m_render->local_render_stop_event);
-		m_render->local_render_stop_event = NULL;
-	}
-#else
-	if (NULL != &m_render->local_render_stop_sem) {
-		sem_destroy(&m_render->local_render_stop_sem);
+	if (NULL != m_render->premote_render) {
+		DestroyVideoRenderObj(m_render->premote_render);
 	}
-#endif // RVC_OS_WIN
 
 	if (NULL != m_render) {
 		delete(m_render);
@@ -2515,6 +2508,65 @@ int CSIPEntity::StopCameraRender()
 	return iRet;
 }
 
+int CSIPEntity::StartBothCameraRender(SpReqAnsContext<PhoneService_StartBothCameraRender_Req, PhoneService_StartBothCameraRender_Ans>::Pointer ctx)
+{
+	int iRet = -1;
+
+	if (m_bIsCameraRender) {
+		return iRet;
+	}
+
+	m_render = new rvc_video_render_t();
+	videorender_callback_t t_callback = { 0 };
+	t_callback.debug = &__video_render_log;
+	rvc_video_render_params_t render_param = { 0 };
+	render_param.ilocal_view_cx = ctx->Req.env_view_cx;
+	render_param.ilocal_view_cy = ctx->Req.env_view_cy;
+	render_param.ilocal_view_x = ctx->Req.env_view_x;
+	render_param.ilocal_view_y = ctx->Req.env_view_y;
+	render_param.iremote_view_cx = ctx->Req.opt_view_cx;
+	render_param.iremote_view_cy = ctx->Req.opt_view_cy;
+	render_param.iremote_view_x = ctx->Req.opt_view_x;
+	render_param.iremote_view_y = ctx->Req.opt_view_y;
+	render_param.erender_queue = eSnapshot_Queue;
+
+	m_render->plocal_render = CreateVideoRenderObj(&t_callback);
+	LogWarn(Severity_Low, Error_Debug, EVENT_MOD_SIP_LOCAL_VIDEO_RENDER_CREATE, "local video render create.");
+
+	m_render->premote_render = CreateVideoRenderObj(&t_callback);
+	LogWarn(Severity_Low, Error_Debug, EVENT_MOD_SIP_REMOTE_VIDEO_RENDER_CREATE, "remote video render create.");
+
+	memcpy(&m_render->render_param, &render_param, sizeof(rvc_video_render_params_t));
+
+#ifdef RVC_OS_WIN
+	m_render->local_render_stop_event = NULL;
+	m_render->remote_render_stop_event = NULL;
+	m_render->local_render_thread = NULL;
+	m_render->remote_render_thread = NULL;
+#else
+	m_render->local_render_threadid = 0;
+	m_render->remote_render_threadid = 0;
+#endif // RVC_OS_WIN
+
+	rvc_video_box_move_callback_t t_render_callback = { 0 };
+	t_render_callback.on_video_box_move = &__on_video_box_move;
+	t_render_callback.user_data = this;
+
+	rvc_video_render_window_type_callback_t t_window_type_callback = { 0 };
+	t_window_type_callback.on_window_type = &__on_window_type_callback;
+	t_window_type_callback.user_data = this;
+	memcpy(&m_render->cb, &t_window_type_callback, sizeof(rvc_video_render_window_type_callback_t));
+	m_stVideoParam.bShowPersonArea = 0;
+
+	if (Error_Succeed == rvc_start_video_render(m_render, eRender_Local_Both, &t_render_callback)) {
+		m_bIsCameraRender = true;
+	}
+
+	iRet = 0;
+
+	return iRet;
+}
+
 //
 // CSIPPhoneSession
 //
@@ -2865,6 +2917,15 @@ void CSIPPhoneSession::Handle_IsCameraRender(SpReqAnsContext<PhoneService_IsCame
 	ctx->Answer(Error_Succeed);
 }
 
+
+void CSIPPhoneSession::Handle_StartBothCameraRender(SpReqAnsContext<PhoneService_StartBothCameraRender_Req, PhoneService_StartBothCameraRender_Ans>::Pointer ctx)
+{
+	int iRet = m_pEntity->StartBothCameraRender(ctx);
+	ctx->Ans.result = iRet;
+	ctx->Answer(Error_Succeed);
+}
+
+
 void CSIPPhoneSession::Handle_BeginState( SpSubscribeContext<PhoneService_BeginState_Sub, PhoneService_PhoneState_Info>::Pointer ctx )
 {
 	m_spCallbackContext = ctx;
@@ -3200,7 +3261,7 @@ int CSIPPhoneSession::start_video_render(rvc_video_render_params_t* render_param
 	memcpy(&m_pEntity->m_render->cb, &t_window_type_callback, sizeof(rvc_video_render_window_type_callback_t));
 	m_pEntity->m_stVideoParam.bShowPersonArea = 0;
 
-	if (Error_Succeed != rvc_start_video_render(m_pEntity->m_render, bremote, &t_render_callback)) {
+	if (Error_Succeed != rvc_start_video_render(m_pEntity->m_render, eRender_LocalRemote, &t_render_callback)) {
 		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("start video render failed!");
 	}
 
@@ -3212,17 +3273,10 @@ int CSIPPhoneSession::stop_video_render()
 	if (Error_Succeed != rvc_stop_video_render(m_pEntity->m_render)) {
 		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("stop video render failed.");
 	}
+
 	DestroyVideoRenderObj(m_pEntity->m_render->plocal_render);
 	DestroyVideoRenderObj(m_pEntity->m_render->premote_render);
 
-	if (NULL != &m_pEntity->m_render->local_render_stop_sem) {
-		sem_destroy(&m_pEntity->m_render->local_render_stop_sem);
-	}
-
-	if (NULL != &m_pEntity->m_render->remote_render_stop_sem) {
-		sem_destroy(&m_pEntity->m_render->remote_render_stop_sem);
-	}
-
 	delete(m_pEntity->m_render);
 	m_pEntity->m_render = NULL;
 

+ 2 - 0
Module/mod_sipphone/mod_sipphone.h

@@ -240,6 +240,7 @@ public:
 	virtual void Handle_StartCameraRender(SpReqAnsContext<PhoneService_StartCameraRender_Req, PhoneService_StartCameraRender_Ans>::Pointer ctx);
 	virtual void Handle_StopCameraRender(SpReqAnsContext<PhoneService_StopCameraRender_Req, PhoneService_StopCameraRender_Ans>::Pointer ctx);
 	virtual void Handle_IsCameraRender(SpReqAnsContext<PhoneService_IsCameraRender_Req, PhoneService_IsCameraRender_Ans>::Pointer ctx);
+	virtual void Handle_StartBothCameraRender(SpReqAnsContext<PhoneService_StartBothCameraRender_Req, PhoneService_StartBothCameraRender_Ans>::Pointer ctx);
 
 public:
 	void on_call_state(int state, const char *state_desc, const char *phrase);
@@ -325,6 +326,7 @@ public:
 	void HandleSendBroadcastMsg(bool bHandfreeError);
 	int StartCameraRender(int icamid, int ivideoview_x, int ivideoview_y, int ivideoview_cx, int ivideoview_cy);
 	int StopCameraRender();
+	int StartBothCameraRender(SpReqAnsContext<PhoneService_StartBothCameraRender_Req, PhoneService_StartBothCameraRender_Ans>::Pointer ctx);
 
 private:
 	ErrorCodeEnum LoadConfig(endpoint_conf_t *conf);

+ 89 - 8
Module/mod_sipphone/video_render.cpp

@@ -220,7 +220,7 @@ static void* rvc_videorender_func(void* arg)
 	int ivideo_width = 0;
 	int ivideo_height = 0;
 	int isize = local_video_queue->GetFrameSize(ivideo_width, ivideo_height);
-	DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s:%d isize = %d, ivideo_width = %d, ivideo_height = %d.",__FUNCTION__, __LINE__, isize, ivideo_width, ivideo_height);
+	
 	if (ivideo_width > 0 && ivideo_height > 0) {
 		iwidth = ivideo_width;
 		iheight = ivideo_height;
@@ -449,7 +449,59 @@ static void* rvc_remote_videorender_func(void* arg)
 }
 
 
-int rvc_start_video_render(rvc_video_render_t* prender, bool bremote, rvc_video_box_move_callback_t* cb)
+#ifdef RVC_OS_WIN
+static unsigned int __stdcall rvc_optcam_videorender_func(void* arg)
+#else
+static void* rvc_optcam_videorender_func(void* arg)
+#endif
+{
+	rvc_video_render_t* param = (rvc_video_render_t*)arg;
+	int iremote_video_fresh_time = param->render_param.iremote_fresh_time;
+	
+	Clibvideoqueue* local_optvideo_queue = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE);
+	int iwidth = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT;
+	int iheight = REC_COMMON_VIDEO_SNAPSHOT_WIDTH;
+	RVC_RendererFlip renderflip = RVC_FLIP_NONE;
+
+	for (; ; ) {
+#ifdef RVC_OS_WIN
+		DWORD dwRet = WaitForSingleObject(param->remote_render_stop_event, iremote_video_fresh_time);
+		if (WAIT_TIMEOUT == dwRet) {
+#else
+		struct timespec ts;
+		clock_gettime(CLOCK_REALTIME, &ts);
+		long unsec = ts.tv_nsec + (1000 * 1000 * iremote_video_fresh_time);
+		ts.tv_sec += (unsec / 1000000000);
+		ts.tv_nsec = (unsec % 1000000000);
+		if (0 != sem_timedwait(&param->remote_render_stop_sem, &ts) && (ETIMEDOUT == errno)) {
+#endif // RVC_OS_WIN
+			video_frame* local_video_frame = NULL;
+			get_local_video_frame(&local_video_frame, 0, local_optvideo_queue, iwidth, iheight, NULL, NULL);
+
+			if (NULL != local_video_frame) {
+				video_frame* localframe = NULL;
+				if (0 == translate_image_resolution(&localframe, param->render_param.iremote_view_cx, param->render_param.iremote_view_cy, local_video_frame)) {
+					param->premote_render->RenderVideoFrame(localframe, renderflip);
+					video_frame_delete(localframe);
+					localframe = NULL;
+				}
+				else {
+					param->premote_render->RenderVideoFrame(local_video_frame, renderflip);
+				}
+
+				video_frame_delete(local_video_frame);
+				local_video_frame = NULL;
+			}
+		}
+		else {
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int rvc_start_video_render(rvc_video_render_t* prender, eVideoRenderMode eMode, rvc_video_box_move_callback_t* cb)
 {
 	int errcode = -1;
 	if (NULL == prender) {
@@ -469,14 +521,20 @@ int rvc_start_video_render(rvc_video_render_t* prender, bool bremote, rvc_video_
 		return Error_Resource;
 	}
 
-	if (bremote) {
+	if (eRender_LocalRemote == eMode || eRender_Local_Both == eMode) {
 		prender->remote_render_stop_event = CreateEventA(NULL, false, false, NULL);
-		if (NULL == prender->local_render_stop_event) {
+		if (NULL == prender->remote_render_stop_event) {
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote stop event failed!");
 			return Error_Resource;
 		}
 
-		prender->remote_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_remote_videorender_func, prender, 0, NULL);
+		if (eRender_LocalRemote == eMode) {
+			prender->remote_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_remote_videorender_func, prender, 0, NULL);
+		}
+		else {
+			prender->remote_render_thread = (HANDLE)_beginthreadex(NULL, 0, rvc_optcam_videorender_func, prender, 0, NULL);
+		}
+
 		if (NULL == prender->remote_render_thread) {
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote video render thread failed.");
 			return Error_Resource;
@@ -495,13 +553,19 @@ int rvc_start_video_render(rvc_video_render_t* prender, bool bremote, rvc_video_
 		return Error_Resource;
 	}
 
-	if (bremote) {
+	if (eRender_LocalRemote == eMode || eRender_Local_Both == eMode) {
 		if (0 != sem_init(&prender->remote_render_stop_sem, 0, 0)) {
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote stop sem failed!");
 			return Error_Resource;
 		}
 
-		errcode = pthread_create(&prender->remote_render_threadid, NULL, rvc_remote_videorender_func, prender);
+		if (eRender_LocalRemote == eMode) {
+			errcode = pthread_create(&prender->remote_render_threadid, NULL, rvc_remote_videorender_func, prender);
+		}
+		else {
+			errcode = pthread_create(&prender->remote_render_threadid, NULL, rvc_videorender_func, prender);
+		}
+
 		if (Error_Succeed != errcode) {
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create remote video render thread failed.");
 			return Error_Resource;
@@ -529,6 +593,11 @@ int rvc_stop_video_render(rvc_video_render_t* prender)
 		CloseHandle(prender->local_render_thread);
 		prender->local_render_thread = NULL;
 	}
+
+	if (NULL != prender->local_render_stop_event) {
+		CloseHandle(prender->local_render_stop_event);
+		prender->local_render_stop_event = NULL;
+	}
 #else
 	sem_post(&prender->local_render_stop_sem);
 	rvc_stop_remote_video_render(prender);
@@ -540,6 +609,10 @@ int rvc_stop_video_render(rvc_video_render_t* prender)
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("video render thread pthread join error for %s.", strerror(errno));
 		}
 	}
+
+	if (NULL != &prender->local_render_stop_sem) {
+		sem_destroy(&prender->local_render_stop_sem);
+	}
 #endif // RVC_OS_WIN
 
 	return Error_Succeed;
@@ -554,6 +627,10 @@ int rvc_stop_remote_video_render(rvc_video_render_t* prender)
 		CloseHandle(prender->remote_render_thread);
 		prender->remote_render_thread = NULL;
 	}
+	if (NULL != prender->remote_render_stop_event) {
+		CloseHandle(prender->remote_render_stop_event);
+		prender->remote_render_stop_event = NULL;
+	}
 #else
 	if (prender->remote_render_threadid > 0) {
 		sem_post(&prender->remote_render_stop_sem);
@@ -564,7 +641,11 @@ int rvc_stop_remote_video_render(rvc_video_render_t* prender)
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("remote video render thread pthread join error for %s.", strerror(errno));
 		}
 	}
-#endif
 
+	if (NULL != &prender->remote_render_stop_sem) {
+		sem_destroy(&prender->remote_render_stop_sem);
+	}
+
+#endif
 	return Error_Succeed;
 }

+ 8 - 1
Module/mod_sipphone/video_render.h

@@ -26,6 +26,13 @@ enum eVideoRenderQueue {
 	eSnapshot_Queue
 };
 
+
+enum eVideoRenderMode {
+	eRender_Local_Single,
+	eRender_LocalRemote,
+	eRender_Local_Both
+};
+
 typedef struct rvc_video_box_move_callback_s {
 	void (*on_video_box_move)(int imessagetype, int ivideotype, int ileft, int ibottom, void* user_data);
 	void* user_data;
@@ -80,7 +87,7 @@ typedef struct rvc_video_render_s {
 }rvc_video_render_t;
 
 
-int rvc_start_video_render(rvc_video_render_t* prender, bool bremote, rvc_video_box_move_callback_t* cb);
+int rvc_start_video_render(rvc_video_render_t* prender, eVideoRenderMode eMode, rvc_video_box_move_callback_t* cb);
 int rvc_stop_video_render(rvc_video_render_t* prender);
 int rvc_remote_video_render(rvc_video_render_t* prender, void* videoframe);
 int rvc_stop_remote_video_render(rvc_video_render_t* prender);

+ 1 - 1
Other/libfacecapture/libfacecapture.cpp

@@ -344,13 +344,13 @@ public:
 	int m_nCameraState;		//0:无故障1:env故障,2:opt故障,3:全部故障
 
 private:
+
 #ifdef _WIN32
 	HANDLE m_hStopEventWait; // CreateEvent
 	CRITICAL_SECTION CS;
 #else
 	pthread_mutex_t cs_mutex;
 	sem_t m_semt;
-
 #endif
 	bool* m_pResult;
 	MonitorEnum m_eType;