/// <summary> /// 发起视频回传成功后,在状态变化事件中处理视频接收、P2Pvideocall_IND_STATUS_ANSWERED时开始接收视频数据 /// </summary> /// <param name="structResStaIndi"></param> private void P2pStatusDelegateFun(ref strP2pvideocallStatusIndicator structP2pvideocallStaIndi) { NLogEx.LoggerEx logEx = new NLogEx.LoggerEx(log); logEx.Info("Enter: P2pStatusDelegateFun.strP2pvideocallStatusIndicator.Status = {0},Callee = {1}", Enum.GetName(typeof(P2pvideocall_Status_t), structP2pvideocallStaIndi.Status), structP2pvideocallStaIndi.Callee); //P2Pvideocall_IND_STATUS_ANSWERED,表示视频回传请求被成功处理处理 //视频网关需要提取其中的RTP port和对端IP,并负责与摄像头建立RTP连接和读取RTP中的H.264的视频流,然后再调用上层的视频管理系统或视频监控系统中的API //视频从摄像头回传,通过视频网关传入到上层的视频管理系统或视频监控系统 if (structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_ANSWERED) { //摄像机编码 int cameraNo = structP2pvideocallStaIndi.Callee; //源端发送码流IP; string pRemoteSendStreamIp = ip; //源端发送视频码流RTP端口号 uint uiRemoteSendStreamVideoPort = (uint)structP2pvideocallStaIndi.RemoteVideoPort; //源端发送音频端口号 uint uiRemoteSendStreamAudioPort = (uint)structP2pvideocallStaIndi.RemoteAudioPort; //本地视频、音频端口 uint uiLocalAudioPort = (uint)structP2pvideocallStaIndi.CalAudioPort; uint uiLocalVideoPort = (uint)structP2pvideocallStaIndi.LocalVideoPort; //发起视频回传,建立成功 logEx.Trace("P2pStatusDelegateFun.Camera = {0},pRemoteSendStreamIp ={1},uiRemoteSendStreamVideoPort = {2},uiRemoteSendStreamAudioPort ={3},uiLocalAudioPort ={4} ,uiLocalVideoPort ={5} P2Pvideocall_IND_STATUS_ANSWERED OK!", cameraNo, pRemoteSendStreamIp, uiRemoteSendStreamVideoPort, uiRemoteSendStreamAudioPort, uiLocalAudioPort, uiLocalVideoPort); if (uiRemoteSendStreamVideoPort == 0) { logEx.Warn("P2pvideocallStatus uiRemoteSendStreamVideoPort is NULL"); return; } //打开通道,开始接收实况RTP数据流 UInt32 channel = StartRecvStream(cameraNo.ToString(), pRemoteSendStreamIp, uiRemoteSendStreamVideoPort, uiRemoteSendStreamAudioPort == 0 ? uiRemoteSendStreamVideoPort : uiRemoteSendStreamAudioPort, uiLocalVideoPort, uiLocalAudioPort == 0 ? uiLocalVideoPort : uiLocalAudioPort); //如果为0,表示预览失败 if (channel == CgwConst.T28181_ERROR_HANDLE) { logEx.Error("Start Receive camera video data failed.Camera No:{0}.", cameraNo); return; } else { logEx.Info("Start Receive camera video data success.Camera No:{0}", cameraNo); } if (this.videoAutOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { if (videoAutoEvents.ContainsKey(cameraNo.ToString())) { videoAutoEvents[cameraNo.ToString()].VideoSuccess = true; videoAutoEvents[cameraNo.ToString()].eLTEVideoEvent.Set(); logEx.Trace("P2pStatusDelegateFun AutoResetEvent State Set,StartVideo Success"); } } finally { this.videoAutOperateLock.ExitWriteLock(); } } //设置rtp解析回调函数 rtpAdapter.ESDK_RTP_OpenESChannel(frameDataCallBack, channel); if (this.handelOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { this.cameraVideoChannelDic.Add(cameraNo.ToString(), channel); MediaDataSender mediaDataSender = new MediaDataSender(cameraNo.ToString(), this.dataCallBack); this.videoChannelDataSenderDic.Add(channel, mediaDataSender); } finally { this.handelOperateLock.ExitWriteLock(); } } } else if (P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_HANGUPED == structP2pvideocallStaIndi.Status || P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_RELEASED == structP2pvideocallStaIndi.Status || P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_CANCELLED == structP2pvideocallStaIndi.Status) { //2015/3/6 设置信号量不阻塞 if (videoAutOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { int cameraNo = structP2pvideocallStaIndi.Callee; if (videoAutoEvents.ContainsKey(cameraNo.ToString())) { videoAutoEvents[cameraNo.ToString()].VideoSuccess = true; videoAutoEvents[cameraNo.ToString()].eLTEVideoEvent.Set(); logEx.Trace("P2pStatusDelegateFun AutoResetEvent State Set,StartVideo End"); } } finally { this.videoAutOperateLock.ExitWriteLock(); } } //收到呼叫被结束事件、需要停止RTP传输并关闭RTP连接 StopReceiveVideo(structP2pvideocallStaIndi.Callee.ToString()); } //2015/2/5 设备播放失败的错误码状态 else if (structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_REMOTE_NOTCONNECTED || structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_REMOTE_NOTSUPPORTED || structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_REMOTE_NOANSWER || structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_REMOTE_NOTFOUND || structP2pvideocallStaIndi.Status == P2pvideocall_Status_t.P2Pvideocall_IND_STATUS_RELEASED_BUSY ) { if (this.videoAutOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { //摄像机编码 int cameraNo = structP2pvideocallStaIndi.Callee; if (videoAutoEvents.ContainsKey(cameraNo.ToString())) { videoAutoEvents[cameraNo.ToString()].VideoSuccess = false; videoAutoEvents[cameraNo.ToString()].eLTEVideoEvent.Set(); logEx.Trace("P2pStatusDelegateFun AutoResetEvent State Set,StartVideo Remote Failed"); } } finally { this.videoAutOperateLock.ExitWriteLock(); } } } }
/// <summary> /// 启动摄像头预览 /// </summary> /// <param name="cameraNo">摄像头编号</param> /// <returns></returns> public SmcErr StartReceiveVideo(string cameraNo) { NLogEx.LoggerEx logEx = new NLogEx.LoggerEx(log); logEx.Trace("Enter: IvsVideoMonitor.StartReceiveVideo({0}).", cameraNo); SmcErr err = new CgwError(); int handle; logEx.Trace("Call ivsSdkClient.StartRealPlayCBRaw({0}).", cameraNo); int result = this.ivsSdkClient.StartRealPlayCBRaw(cameraNo, out handle); //如果不为0,表示预览失败 if (result != CgwConst.IVS_SDK_SUCCESS_TAG) { err.SetErrorNo(CgwError.START_RECEIVE_VIDEO_FAILED); logEx.Error("Start Receive camera video data failed.Camera No:{0}.Ivs sdk error code:{1}", cameraNo, result); return err; } else { logEx.Info("Start Receive camera video data success.Camera No:{0},Handle:{1}.", cameraNo, handle); } //预览成功,需要停止原来的预览,并将预览句柄添加到缓存 //需要停止的预览句柄 int needToStopHandel = CgwConst.START_RECEIVE_VIDEO_DATA_FAILED; if (this.handelOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { //如果预览句柄已经存在,删除掉原来的句柄,用新的句柄替换 if (this.cameraVideoHandeDic.ContainsKey(cameraNo)) { needToStopHandel = this.cameraVideoHandeDic[cameraNo]; this.videoHandleCameraDic.Remove(needToStopHandel); this.cameraVideoHandeDic.Remove(cameraNo); } this.cameraVideoHandeDic.Add(cameraNo, handle); MediaDataSender mediaDataSender = new MediaDataSender(cameraNo, this.dataCallBack); this.videoHandleCameraDic.Add(handle, mediaDataSender); } finally { this.handelOperateLock.ExitWriteLock(); } } //重新预览后,更新了预览句柄,需要将原来的预览停止,放在handelOperateLock外面,防止长时间占用锁 if (needToStopHandel != CgwConst.START_RECEIVE_VIDEO_DATA_FAILED) { result = this.ivsSdkClient.StopRealPlay(needToStopHandel); //如果不为0,表示停止原来的预览失败,只记录日志,不返回错误,不设置错误码 if (result != CgwConst.IVS_SDK_SUCCESS_TAG) { logEx.Error("Get a new preview success. But stop old preview failed.CameraNo:{0},Ivs sdk error code:{0}", cameraNo, result); return err; } } return err; }
/// <summary> /// 启动摄像头预览 /// </summary> /// <param name="cameraNo">摄像头编号</param> /// <returns></returns> public SmcErr StartReceiveVideo(string cameraNo) { NLogEx.LoggerEx logEx = new NLogEx.LoggerEx(log); logEx.Trace("Enter: T28181VideoMonitor.StartReceiveVideo({0}).", cameraNo); SmcErr err = new CgwError(); //打开通道,开始接收实况RTP数据流 UInt32 channel = sipStack.StartRecvStream(cameraNo, domain, sipPort, localPort); //如果为0,表示预览失败 if (channel == CgwConst.T28181_ERROR_HANDLE) { err.SetErrorNo(CgwError.START_RECEIVE_VIDEO_FAILED); logEx.Error("Start Receive camera video data failed.Camera No:{0}.Handle:{1}.", cameraNo, channel); return err; } else { logEx.Info("Start Receive camera video data success.Camera No:{0},Handle:{1}.", cameraNo, channel); } //设置rtp解析回调函数 rtpAdapter.ESDK_RTP_OpenChannel(frameDataCallBack, channel); //预览成功,需要停止原来的预览,并将预览句柄添加到缓存 //需要停止的预览句柄 UInt32 needToStopChannel = CgwConst.T28181_ERROR_HANDLE; if (this.handelOperateLock.TryEnterWriteLock(CgwConst.ENTER_LOCK_WAIT_TIME)) { try { //如果预览句柄已经存在,删除掉原来的句柄,用新的句柄替换 if (this.cameraVideoChannelDic.ContainsKey(cameraNo)) { needToStopChannel = this.cameraVideoChannelDic[cameraNo]; this.videoChannelDataSenderDic.Remove(needToStopChannel); this.cameraVideoChannelDic.Remove(cameraNo); //用户参数,4字节整数 IntPtr pUser = Marshal.AllocHGlobal(4); NetSourcedInterface.IVS_NETSOURCE_SetDataCallBack(needToStopChannel, null, pUser); //释放NETSOURCE通道资源 IVS_NETSOURCE_RESULT iNet = NetSourcedInterface.IVS_NETSOURCE_CloseNetStream(needToStopChannel); if (iNet != IVS_NETSOURCE_RESULT.SUCCESS) { logEx.Error("IVS_NETSOURCE_CloseNetStream failed channel={0}", needToStopChannel); err.SetErrorNo(CgwError.STOP_RECEIVE_VIDEO_FAILED); } //关闭rtp回调 rtpAdapter.ESDK_RTP_CloseChannel(needToStopChannel); } this.cameraVideoChannelDic.Add(cameraNo, channel); MediaDataSender mediaDataSender = new MediaDataSender(cameraNo, this.dataCallBack); this.videoChannelDataSenderDic.Add(channel, mediaDataSender); } finally { this.handelOperateLock.ExitWriteLock(); } } //重新预览后,更新了预览句柄,需要将原来的预览停止,放在handelOperateLock外面,防止长时间占用锁 if (needToStopChannel != CgwConst.T28181_ERROR_HANDLE) { EM_SIP_RESULT iRet = sipStack.StopRecvStream(needToStopChannel); //如果不为0,表示停止原来的预览失败,只记录日志,不返回错误,不设置错误码 if (iRet != EM_SIP_RESULT.RET_SUCCESS) { err.SetErrorNo(CgwError.START_RECEIVE_VIDEO_FAILED); logEx.Error("Get a new preview success. But stop old preview failed.CameraNo:{0},Ivs sdk error code:{0}", cameraNo, iRet); return err; } } return err; }