正在显示
4 个修改的文件
包含
474 行增加
和
1 行删除
此 diff 太大无法显示。
| @@ -28,7 +28,7 @@ import MediaModule from 'apes/MediaModule'; | @@ -28,7 +28,7 @@ import MediaModule from 'apes/MediaModule'; | ||
| 28 | import UTF8 from 'utf-8'; | 28 | import UTF8 from 'utf-8'; |
| 29 | 29 | ||
| 30 | let loger = Loger.getLoger('McuClient'); | 30 | let loger = Loger.getLoger('McuClient'); |
| 31 | -let _sdkInfo = {"version": "v1.21.5.201705017", "author": "www.3mang.com"}; | 31 | +let _sdkInfo = {"version": "v1.22.0.201705017", "author": "www.3mang.com"}; |
| 32 | 32 | ||
| 33 | //APE | 33 | //APE |
| 34 | let _sass; | 34 | let _sass; |
| @@ -255,6 +255,7 @@ class ConferApe extends Ape { | @@ -255,6 +255,7 @@ class ConferApe extends Ape { | ||
| 255 | GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); | 255 | GlobalConfig.classStopTime = EngineUtils.creatTimestampStr(); |
| 256 | this.sendConferRecordMsg({"recordStatus": true}); | 256 | this.sendConferRecordMsg({"recordStatus": true}); |
| 257 | this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); | 257 | this._emit(MessageTypes.CLASS_STATUS_INFO_CHANGE); |
| 258 | + this._emit(MessageTypes.CLASS_RECORD_START);//课堂开始录制 | ||
| 258 | } | 259 | } |
| 259 | } | 260 | } |
| 260 | 261 |
src/apes/RecordApe.js
0 → 100644
| 1 | +// ////////////////////////////////////////////////////////////////////////////// | ||
| 2 | +//视频模块 | ||
| 3 | +// ////////////////////////////////////////////////////////////////////////////// | ||
| 4 | + | ||
| 5 | +import Ape from './Ape'; | ||
| 6 | +import ApeConsts from './ApeConsts'; | ||
| 7 | +import pdu from 'pdus'; | ||
| 8 | +import Loger from 'Loger'; | ||
| 9 | +import MessageTypes from 'MessageTypes'; | ||
| 10 | +import GlobalConfig from 'GlobalConfig'; | ||
| 11 | +import EngineUtils from 'EngineUtils'; | ||
| 12 | +import MediaModule from "./MediaModule"; | ||
| 13 | + | ||
| 14 | +let loger = Loger.getLoger('RecordApe'); | ||
| 15 | + | ||
| 16 | +class RecordApe extends Ape { | ||
| 17 | + constructor() { | ||
| 18 | + super( | ||
| 19 | + ApeConsts.VIDEO_SESSION_ID, | ||
| 20 | + ApeConsts.VIDEO_SESSION_NAME, | ||
| 21 | + ApeConsts.VIDEO_SESSION_TAG | ||
| 22 | + ); | ||
| 23 | + | ||
| 24 | + this.mediaModule=new MediaModule(); | ||
| 25 | + this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.VIDEO_OBJ_TABLE_ID; | ||
| 26 | + this.mediaModule.mediaChannels={}; | ||
| 27 | + this.mediaModule.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; | ||
| 28 | + | ||
| 29 | + // Ape Models | ||
| 30 | + this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer); | ||
| 31 | + this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.VIDEO_OBJ_TABLE_ID, ApeConsts.VIDEO_OBJ_TABLE_NAME, ApeConsts.VIDEO_OBJ_TABLE_TAG, 0, new ArrayBuffer); | ||
| 32 | + | ||
| 33 | + // videoApe 监听视频控制消息,用户之间的消息传递 | ||
| 34 | + this.on(pdu.RCPDU_SEND_VIDEO_DATA_REQUEST, this.receiveVideoCommandHandler.bind(this)); | ||
| 35 | + } | ||
| 36 | + //ape加入成功 | ||
| 37 | + onJoinChannelHandlerSuccess(){ | ||
| 38 | + //这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据 | ||
| 39 | + this.mediaModule.maxMediaChannel=GlobalConfig.maxVideoChannels; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /////////////发送数据操作//////////////////////////////////////////// | ||
| 43 | + //获取播流地址 | ||
| 44 | + getPlayVideoPath(_param) { | ||
| 45 | + loger.log('getPlayVideoPath'); | ||
| 46 | + return this.mediaModule.getMediaPlayPath(_param); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + //获取推流地址 | ||
| 50 | + getPublishVideoPath(_param) { | ||
| 51 | + loger.log('获取推流地址->'); | ||
| 52 | + if(!this.mcu.connected){ | ||
| 53 | + loger.warn(GlobalConfig.getCurrentStatus()); | ||
| 54 | + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | ||
| 55 | + } | ||
| 56 | + //监课比较特殊,不占用课堂内的音视频路数,额外创建 | ||
| 57 | + if(GlobalConfig.userRole==ApeConsts.invisible){ | ||
| 58 | + let result=this.mediaModule.getMediaPublishPathForInVisible(_param); | ||
| 59 | + //this._emit( MessageTypes.VIDEO_GET_PUBLISH_PATH,result); | ||
| 60 | + return result; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + //非监课的身份,需要判断是否可以继续推流 | ||
| 64 | + //需要判断当前已经使用的流路数 | ||
| 65 | + let openChannel=0; | ||
| 66 | + let allChannels= MediaModule.allMediaChannelsList; | ||
| 67 | + for(let i in allChannels){ | ||
| 68 | + let channel=allChannels[i]; | ||
| 69 | + if(channel&&channel.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 70 | + openChannel++; | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + //如果已经开启的数量大于等于最大允许开启的数量,不允许再推流 | ||
| 74 | + if(openChannel>=GlobalConfig.maxMediaChannels){ | ||
| 75 | + loger.warn('不能再打开设备->当前开启的设备数量->',openChannel); | ||
| 76 | + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开设备,当前开启的设备数量"}; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + let result=this.mediaModule.getMediaPublishPath(_param); | ||
| 80 | + //this._emit( MessageTypes.VIDEO_GET_PUBLISH_PATH,result); | ||
| 81 | + return result; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + //获取当前所有频道信息 | ||
| 85 | + getAllChannelInfo(_param){ | ||
| 86 | + loger.log('获取当前所有频道信息->'); | ||
| 87 | + return this.mediaModule.getAllMediaChannelInfo(); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + //推流 | ||
| 91 | + publishVideo(_param) { | ||
| 92 | + if(!this.mcu.connected){ | ||
| 93 | + loger.warn(GlobalConfig.getCurrentStatus()); | ||
| 94 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"已经断开连接!","mediaId":0}); | ||
| 95 | + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + if (_param == null||_param.publishUrl == null) | ||
| 99 | + { | ||
| 100 | + loger.warn('推流->参数错误', _param); | ||
| 101 | + //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | ||
| 102 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"参数错误!","mediaId":0}); | ||
| 103 | + return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + //根据推流的地址获取对应的频道信息 | ||
| 107 | + let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl); | ||
| 108 | + if(needPublishChannelInfo==null){ | ||
| 109 | + loger.warn('推流->推流数据已经无效', _param); | ||
| 110 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"推流数据已经无效!","mediaId":0}); | ||
| 111 | + return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"}; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + //判断当前是否还有空闲的channle | ||
| 115 | + let freeChannel = this.mediaModule.getFreeMediaChannel(); | ||
| 116 | + if (freeChannel == 0) { | ||
| 117 | + loger.warn("推流->不能再打开更多的设备 "); | ||
| 118 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"不能再打开更多的设备!","mediaId":0}); | ||
| 119 | + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels}; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + | ||
| 123 | + //判断当前的频道是否已经占用 | ||
| 124 | + if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){ | ||
| 125 | + if(needPublishChannelInfo.nodeId==GlobalConfig.nodeId){ | ||
| 126 | + loger.warn(needPublishChannelInfo.channelId,"已经推送过消息,不需要再次推送"); | ||
| 127 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId}); | ||
| 128 | + return {"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId}; | ||
| 129 | + }else { | ||
| 130 | + loger.warn(needPublishChannelInfo.channelId,"频道已经被占用"); | ||
| 131 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!","mediaId":0}); | ||
| 132 | + return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!","mediaChannels":this.mediaModule.mediaChannels}; | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + let channelInfo=this.mediaModule.getDefaultChannelInfo(); | ||
| 137 | + channelInfo.owner=GlobalConfig.nodeId; | ||
| 138 | + channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; | ||
| 139 | + channelInfo.channelId=needPublishChannelInfo.channelId; | ||
| 140 | + channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称 | ||
| 141 | + channelInfo.timestamp=needPublishChannelInfo.timestamp;//时间戳 | ||
| 142 | + channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; | ||
| 143 | + this.sendTableUpdateHandler(channelInfo); | ||
| 144 | + | ||
| 145 | + //this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId}); | ||
| 146 | + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId}; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + //停止推流, | ||
| 150 | + stopPublishVideo(_param) { | ||
| 151 | + loger.log('停止推流->',_param); | ||
| 152 | + if(!this.mcu.connected){ | ||
| 153 | + loger.warn(GlobalConfig.getCurrentStatus()); | ||
| 154 | + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param | ||
| 158 | + let nodeId=GlobalConfig.nodeId; | ||
| 159 | + if(_param&&parseInt(_param.nodeId)>0){ | ||
| 160 | + nodeId=parseInt(_param.nodeId); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道 | ||
| 164 | + let releaseChannelId=0; | ||
| 165 | + if(_param&&parseInt(_param.mediaId)>0){ | ||
| 166 | + releaseChannelId=parseInt(_param.mediaId); | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + //释放channelId 的占用 | ||
| 170 | + if(releaseChannelId>0){ | ||
| 171 | + //第一种情况,释放nodeId占用的指定mediaId (channelId) | ||
| 172 | + this._releaseChannelForNodeId(nodeId,releaseChannelId); | ||
| 173 | + }else { | ||
| 174 | + //第二种情况,释放nodeId占用的所有channelId | ||
| 175 | + this._releaseNodeIdAllChannel(nodeId); | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | + //释放nodeId占用的指定的channelId频道 | ||
| 179 | + _releaseChannelForNodeId(nodeId,channelId){ | ||
| 180 | + loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId); | ||
| 181 | + let channelInfo=this.mediaModule.mediaChannels[channelId]; | ||
| 182 | + if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 183 | + if(channelInfo.fromNodeId==nodeId){ | ||
| 184 | + | ||
| 185 | + let channelInfo=this.mediaModule.getDefaultChannelInfo(); | ||
| 186 | + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED; | ||
| 187 | + channelInfo.channelId=channelId; | ||
| 188 | + | ||
| 189 | + this.sendTableUpdateHandler(channelInfo); | ||
| 190 | + }else { | ||
| 191 | + loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo); | ||
| 192 | + } | ||
| 193 | + }else { | ||
| 194 | + loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo); | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | + //释放nodeId占用的所有频道 | ||
| 198 | + _releaseNodeIdAllChannel(nodeId){ | ||
| 199 | + loger.log(nodeId,"_releaseNodeIdAllChannel",this.mcu.connected); | ||
| 200 | + if(!this.mcu.connected){ | ||
| 201 | + clearTimeout(this.releaseTimeId); | ||
| 202 | + loger.warn(GlobalConfig.getCurrentStatus()); | ||
| 203 | + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); | ||
| 207 | + if (openingChannel == 0) { | ||
| 208 | + loger.warn(nodeId,"没有占用channel不需要处理"); | ||
| 209 | + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"}; | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + let channelInfo=this.mediaModule.getDefaultChannelInfo(); | ||
| 213 | + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED; | ||
| 214 | + channelInfo.channelId=openingChannel; | ||
| 215 | + | ||
| 216 | + this.sendTableUpdateHandler(channelInfo); | ||
| 217 | + //递归检查,800毫秒之后执行 | ||
| 218 | + this.releaseTimeId=setTimeout(function(){ | ||
| 219 | + loger.warn(nodeId,"检查频道是否占用"); | ||
| 220 | + this._releaseNodeIdAllChannel(nodeId); | ||
| 221 | + }.bind(this),800); | ||
| 222 | + } | ||
| 223 | + | ||
| 224 | + sendVideoBroadcastMsg(_param) { | ||
| 225 | + if(!this.mcu.connected){ | ||
| 226 | + loger.warn(GlobalConfig.getCurrentStatus()); | ||
| 227 | + return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; | ||
| 228 | + } | ||
| 229 | + | ||
| 230 | + if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) { | ||
| 231 | + loger.log('不能发送Video消息.McuClient还未初始化数据!'); | ||
| 232 | + if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) { | ||
| 233 | + //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN); | ||
| 234 | + return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"}; | ||
| 235 | + } | ||
| 236 | + return {"code": ApeConsts.RETURN_FAILED, "data": "不能发送Video消息.McuClient还未初始化数据"}; | ||
| 237 | + } | ||
| 238 | + if (_param == null) { | ||
| 239 | + loger.warn('sendVideoCommandMsg失败,参数错误', _param); | ||
| 240 | + //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | ||
| 241 | + return {"code": ApeConsts.RETURN_FAILED, "data": "sendVideoCommandMsg失败,参数错误"}; | ||
| 242 | + } | ||
| 243 | + // to, message | ||
| 244 | + loger.log('发送Video消息.', _param); | ||
| 245 | + | ||
| 246 | + if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) { | ||
| 247 | + //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启 | ||
| 248 | + let freeChannel = this.mediaModule.getFreeMediaChannel(); | ||
| 249 | + if (freeChannel == 0) { | ||
| 250 | + loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param); | ||
| 251 | + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels}; | ||
| 252 | + } | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + let videoSendPdu = new pdu['RCVideoSendDataRequestPdu']; | ||
| 256 | + videoSendPdu.type = pdu.RCPDU_SEND_VIDEO_DATA_REQUEST; | ||
| 257 | + videoSendPdu.isPublic = true; | ||
| 258 | + | ||
| 259 | + videoSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人 | ||
| 260 | + videoSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人 | ||
| 261 | + videoSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT; | ||
| 262 | + | ||
| 263 | + let dataStr=''; | ||
| 264 | + try{ | ||
| 265 | + dataStr=JSON.stringify(_param.data); | ||
| 266 | + }catch (err){ | ||
| 267 | + loger.warn('控制消息->JSON转换失败'); | ||
| 268 | + dataStr=_param.data; | ||
| 269 | + } | ||
| 270 | + videoSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + dataStr);//开头两个字会乱码 | ||
| 271 | + | ||
| 272 | + if (!videoSendPdu.isPublic && 0 != videoSendPdu.toNodeId) { | ||
| 273 | + //发送给制定的人 | ||
| 274 | + //loger.log('发送私聊Video消息.'); | ||
| 275 | + this.send(videoSendPdu); | ||
| 276 | + } else { | ||
| 277 | + //发送给所有人 | ||
| 278 | + //loger.log('发送公聊Video消息.'); | ||
| 279 | + this.sendChatUniform(videoSendPdu); | ||
| 280 | + } | ||
| 281 | + return {"code": ApeConsts.RETURN_SUCCESS, "data": ""}; | ||
| 282 | + } | ||
| 283 | + //发送到mcu同步(更新数据) | ||
| 284 | + sendTableUpdateHandler(_channelInfo) { | ||
| 285 | + loger.log("video===sendTableUpdateHandler "); | ||
| 286 | + let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);//let updateModelPdu=this.packPdu({},ApeConsts.VIDEO_OBJ_TABLE_ID+2); | ||
| 287 | + | ||
| 288 | + if(updateModelPdu==null){ | ||
| 289 | + loger.warn("sendTableUpdateHandler error,updateModelPdu=null"); | ||
| 290 | + return; | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + let tableItemPdu = new pdu['RCRegistryTableItemPdu']; | ||
| 294 | + tableItemPdu.itemIdx = _channelInfo.channelId;//tableItemPdu.itemIdx=ApeConsts.VIDEO_OBJ_TABLE_ID+2; | ||
| 295 | + tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0 | ||
| 296 | + tableItemPdu.itemData = updateModelPdu.toArrayBuffer(); | ||
| 297 | + | ||
| 298 | + //insert | ||
| 299 | + let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu']; | ||
| 300 | + tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;// | ||
| 301 | + tableInsertItemPdu.items.push(tableItemPdu); | ||
| 302 | + | ||
| 303 | + let updateObjPdu = new pdu['RCRegistryUpdateObjPdu']; | ||
| 304 | + updateObjPdu.objId = ApeConsts.VIDEO_OBJ_TABLE_ID;// | ||
| 305 | + updateObjPdu.subType = tableInsertItemPdu.type; | ||
| 306 | + updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer(); | ||
| 307 | + | ||
| 308 | + //同步 | ||
| 309 | + let adapterItemPdu = new pdu['RCAdapterItemPdu']; | ||
| 310 | + adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ; | ||
| 311 | + adapterItemPdu.itemData = updateObjPdu.toArrayBuffer(); | ||
| 312 | + | ||
| 313 | + let adapterPdu = new pdu['RCAdapterPdu']; | ||
| 314 | + adapterPdu.type = pdu.RCPDU_REG_ADAPTER; | ||
| 315 | + adapterPdu.item.push(adapterItemPdu); | ||
| 316 | + | ||
| 317 | + loger.log("发送更新VIDEO.itemIdx=" + tableItemPdu.itemIdx); | ||
| 318 | + this.sendUniform(adapterPdu, true); | ||
| 319 | + } | ||
| 320 | + | ||
| 321 | + /////收到消息处理////////////////////////////////////////////////// | ||
| 322 | + | ||
| 323 | + // 视频消息处理,内部处理,不需要告诉应用层 | ||
| 324 | + receiveVideoCommandHandler(_data) { | ||
| 325 | + let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(_data); | ||
| 326 | + if (videoReceivePdu == null) { | ||
| 327 | + loger.warn("视频控制消息处理,收到的消息为null,不做处理"); | ||
| 328 | + return; | ||
| 329 | + } | ||
| 330 | + videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码 | ||
| 331 | + | ||
| 332 | + let dataObj= {}; | ||
| 333 | + try{ | ||
| 334 | + dataObj=JSON.parse(videoReceivePdu.data); | ||
| 335 | + }catch (err){ | ||
| 336 | + loger.warn('控制消息->JSON转换失败'); | ||
| 337 | + dataObj= videoReceivePdu.data; | ||
| 338 | + } | ||
| 339 | + videoReceivePdu.data=dataObj; | ||
| 340 | + //判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理 | ||
| 341 | + if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != GlobalConfig.nodeId) { | ||
| 342 | + loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId); | ||
| 343 | + } else { | ||
| 344 | + loger.log('视频控制消息处理 .',videoReceivePdu); | ||
| 345 | + //this._emit(MessageTypes.VIDEO_BROADCAST, videoReceivePdu); | ||
| 346 | + } | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + | ||
| 350 | + | ||
| 351 | + tableUpdateHandler(owner, itemIdx, itemData,seek) { | ||
| 352 | + // debugger; | ||
| 353 | + let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData); | ||
| 354 | + loger.log("tableUpdateHandler->channel",itemIdx,'status->',unpackChannelInfo.status,"seek->",seek); | ||
| 355 | + | ||
| 356 | + //****很重要******** | ||
| 357 | + //如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0) | ||
| 358 | + if(owner==0){ | ||
| 359 | + loger.log("释放占用的频道,channel",itemIdx); | ||
| 360 | + unpackChannelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED; | ||
| 361 | + unpackChannelInfo.streamId=""; | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo; | ||
| 365 | + | ||
| 366 | + if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){ | ||
| 367 | + let receiveChannelInfo={}; | ||
| 368 | + receiveChannelInfo.mediaId=unpackChannelInfo.channelId; | ||
| 369 | + receiveChannelInfo.fromNodeId=unpackChannelInfo.fromNodeId; | ||
| 370 | + receiveChannelInfo.userName=unpackChannelInfo.userName||""; | ||
| 371 | + receiveChannelInfo.userRole=unpackChannelInfo.userRole||ApeConsts.normal; | ||
| 372 | + //消息不是自己同步的,需要处理 | ||
| 373 | + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 374 | + //正在推流 | ||
| 375 | + receiveChannelInfo.m3u8Url=""; | ||
| 376 | + receiveChannelInfo.rtmpUrl=""; | ||
| 377 | + receiveChannelInfo.replay=""; | ||
| 378 | + | ||
| 379 | + receiveChannelInfo.seek=seek||0;//这个是录制回放时使用的seek | ||
| 380 | + | ||
| 381 | + let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId}); | ||
| 382 | + let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId}); | ||
| 383 | + let replay=this.mediaModule.getMediaRecordPlaybackPath({"type":"m3u8","streamId": unpackChannelInfo.streamId}); | ||
| 384 | + | ||
| 385 | + if(m3u8Stream.code==0){ | ||
| 386 | + receiveChannelInfo.m3u8Url=m3u8Stream.playUrl; | ||
| 387 | + } | ||
| 388 | + if(rtmpStream.code==0){ | ||
| 389 | + receiveChannelInfo.rtmpUrl=rtmpStream.playUrl; | ||
| 390 | + } | ||
| 391 | + if(replay.code==0){ | ||
| 392 | + receiveChannelInfo.replay=replay.playUrl; | ||
| 393 | + } | ||
| 394 | + loger.log("VIDEO_PLAY",receiveChannelInfo); | ||
| 395 | + //广播播放视频的消息 | ||
| 396 | + //this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo); | ||
| 397 | + }else { | ||
| 398 | + loger.log("VIDEO_STOP",receiveChannelInfo); | ||
| 399 | + //流已经停止 | ||
| 400 | + //this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo); | ||
| 401 | + } | ||
| 402 | + }else { | ||
| 403 | + loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:"); | ||
| 404 | + loger.log(unpackChannelInfo); | ||
| 405 | + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){ | ||
| 406 | + GlobalConfig.openCamera=EngineUtils.creatTimestamp(); | ||
| 407 | + GlobalConfig.openMicrophones=GlobalConfig.openCamera; | ||
| 408 | + }else { | ||
| 409 | + GlobalConfig.openCamera=0; | ||
| 410 | + GlobalConfig.openMicrophones=0; | ||
| 411 | + } | ||
| 412 | + //this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE,{ | ||
| 413 | + // nodeId:GlobalConfig.nodeId, | ||
| 414 | + // userRole:GlobalConfig.userRole, | ||
| 415 | + // userName:GlobalConfig.userName, | ||
| 416 | + // userId:GlobalConfig.userId, | ||
| 417 | + // openCamera:GlobalConfig.openCamera, | ||
| 418 | + // openMicrophones:GlobalConfig.openMicrophones | ||
| 419 | + // }); | ||
| 420 | + } | ||
| 421 | + | ||
| 422 | + MediaModule.allMediaChannelsList[itemIdx]=unpackChannelInfo; | ||
| 423 | + console.log('MediaModule.allMediaChannelsList',MediaModule.allMediaChannelsList); | ||
| 424 | + //this._emit(MessageTypes.VIDEO_UPDATE, unpackChannelInfo); | ||
| 425 | + } | ||
| 426 | + | ||
| 427 | + ///////数据的封包和解包///////////////////////////////////////// | ||
| 428 | + packPdu(_param, _itemIdx) { | ||
| 429 | + loger.log("packPdu "); | ||
| 430 | + //验证坐标点集合数组是否合法 | ||
| 431 | + if (_param == null || _itemIdx == null) { | ||
| 432 | + //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | ||
| 433 | + return null; | ||
| 434 | + } | ||
| 435 | + | ||
| 436 | + //判断type类型,根据type设置不同的参数 | ||
| 437 | + let packPduModel = new pdu['RCVideoChannelInfoPdu']; | ||
| 438 | + packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; | ||
| 439 | + packPduModel.channelId = _itemIdx; | ||
| 440 | + packPduModel.streamId = _param.streamId||""; | ||
| 441 | + packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; | ||
| 442 | + packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); | ||
| 443 | + packPduModel.userId =_param.userId||"0"; | ||
| 444 | + packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_VIDEO; | ||
| 445 | + packPduModel.timestamp =_param.timestamp||0; | ||
| 446 | + packPduModel.fromNodeId = GlobalConfig.nodeId; | ||
| 447 | + packPduModel.userName=GlobalConfig.userName||""; | ||
| 448 | + packPduModel.toNodeId = 0; | ||
| 449 | + packPduModel.userRole=GlobalConfig.userRole||ApeConsts.normal; | ||
| 450 | + loger.log(packPduModel); | ||
| 451 | + return packPduModel; | ||
| 452 | + } | ||
| 453 | + | ||
| 454 | + unPackPdu(owner, itemIdx, itemData) { | ||
| 455 | + loger.log("unPackPdu->owner:",owner,"itemIdx->",itemIdx); | ||
| 456 | + if (owner == null || itemIdx == null || itemData == null) { | ||
| 457 | + //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); | ||
| 458 | + return null; | ||
| 459 | + } | ||
| 460 | + try { | ||
| 461 | + let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData); | ||
| 462 | + loger.log(videoChannelInfo); | ||
| 463 | + return videoChannelInfo; | ||
| 464 | + } catch (err) { | ||
| 465 | + loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); | ||
| 466 | + } | ||
| 467 | + return null; | ||
| 468 | + } | ||
| 469 | +} | ||
| 470 | + | ||
| 471 | +export default RecordApe; | ||
| 472 | + |
-
请 注册 或 登录 后发表评论