/// <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); //如果为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); //关闭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) { int result = sipStack.StopRecvStream(needToStopChannel); //如果不为0,表示停止原来的预览失败,只记录日志,不返回错误,不设置错误码 if (result != CgwConst.IVS_SDK_SUCCESS_TAG) { 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, result); return err; } } return err; }