李勇

增加一个录制回放时专门解析数据的APE;开始录制的时候把录制消息广播给其他模块

此 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
  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 +