李勇

1.修改视频和音频模块的推流和播流接口

2.文档模块修改了获取pdf图片序列的接口
@@ -549,10 +549,12 @@ export default class MessageEntrance extends Emiter { @@ -549,10 +549,12 @@ export default class MessageEntrance extends Emiter {
549 549
550 //保存会态信息成功 550 //保存会态信息成功
551 _sassSaveClassStatusInfoSuccessHandler(_data) { 551 _sassSaveClassStatusInfoSuccessHandler(_data) {
552 - loger.log('保存会议状态信息成功.', _data); 552 + loger.log('保存会议状态信息成功.');
  553 + console.log(_data);
553 } 554 }
554 _sassSaveClassRecordInfoSuccessHandler(_data){ 555 _sassSaveClassRecordInfoSuccessHandler(_data){
555 - loger.log('保存会议录制信息成功.', _data); 556 + loger.log('保存会议录制信息成功.');
  557 + console.log(_data);
556 } 558 }
557 559
558 //Sass校验流程结束之后,开始加入MCU 560 //Sass校验流程结束之后,开始加入MCU
@@ -42,7 +42,11 @@ class EverSocket extends Emiter { @@ -42,7 +42,11 @@ class EverSocket extends Emiter {
42 42
43 send(data) { 43 send(data) {
44 if (this._connected) { 44 if (this._connected) {
  45 + if(data){
  46 + loger.log('SEND MESSAGE,byteLength---->',data.byteLength);
  47 + }else {
45 loger.log('SEND MESSAGE---->'); 48 loger.log('SEND MESSAGE---->');
  49 + }
46 this.websocket.send(data); 50 this.websocket.send(data);
47 } else { 51 } else {
48 loger.warn('WebSocket未建立连接.消息忽略'); 52 loger.warn('WebSocket未建立连接.消息忽略');
@@ -34,10 +34,14 @@ MessageTypes.CLASS_RECORD_START='class.record.start';//开始录制 @@ -34,10 +34,14 @@ MessageTypes.CLASS_RECORD_START='class.record.start';//开始录制
34 MessageTypes.CHAT_RECEIVE = 'chat.receive'; 34 MessageTypes.CHAT_RECEIVE = 'chat.receive';
35 35
36 //视频模块事件定义 36 //视频模块事件定义
  37 +MessageTypes.VIDEO_PLAY = 'video.play';//播放视频
  38 +MessageTypes.VIDEO_STOP = 'video.stop';//停止视频
37 MessageTypes.VIDEO_UPDATE = 'video.update'; 39 MessageTypes.VIDEO_UPDATE = 'video.update';
38 MessageTypes.VIDEO_BROADCAST= 'video.broadcast'; 40 MessageTypes.VIDEO_BROADCAST= 'video.broadcast';
39 41
40 //音频模块事件定义 42 //音频模块事件定义
  43 +MessageTypes.AUDIO_PLAY = 'audio.play';//播放
  44 +MessageTypes.AUDIO_STOP = 'audio.stop';//停止
41 MessageTypes.AUDIO_UPDATE = 'audio.update'; 45 MessageTypes.AUDIO_UPDATE = 'audio.update';
42 MessageTypes.AUDIO_BROADCAST= 'audio.broadcast'; 46 MessageTypes.AUDIO_BROADCAST= 'audio.broadcast';
43 47
@@ -57,15 +57,21 @@ class AudioApe extends Ape { @@ -57,15 +57,21 @@ class AudioApe extends Ape {
57 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 57 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
58 } 58 }
59 59
60 - if (_param == null||_param.channelId == null||  
61 - _param.classId == null||_param.userId == null||  
62 - _param.siteId == null|| _param.timestamp==null) 60 + if (_param == null||_param.publishUrl == null)
63 { 61 {
64 loger.warn('publishAudio,参数错误', _param); 62 loger.warn('publishAudio,参数错误', _param);
65 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 63 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
66 return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; 64 return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
67 } 65 }
68 66
  67 + //根据推流的地址获取对应的频道信息
  68 + let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
  69 + if(needPublishChannelInfo==null){
  70 + loger.warn('publishVideo,推流数据已经无效', _param);
  71 + return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
  72 + }
  73 +
  74 +
69 //同一个nodeId只允许推一个流,如果已经推了就不能再推 75 //同一个nodeId只允许推一个流,如果已经推了就不能再推
70 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ 76 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
71 loger.warn("publishAudio,已经存在一个流,不能再推"); 77 loger.warn("publishAudio,已经存在一个流,不能再推");
@@ -80,18 +86,19 @@ class AudioApe extends Ape { @@ -80,18 +86,19 @@ class AudioApe extends Ape {
80 } 86 }
81 87
82 //判断当前的频道是否已经占用 88 //判断当前的频道是否已经占用
83 - if(this.mediaModule.checkChannelIsOpening(_param.channelId)){  
84 - loger.warn(_param.channelId,"频道已经被占用"); 89 + if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){
  90 + loger.warn(needPublishChannelInfo.channelId,"频道已经被占用");
85 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; 91 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
86 } 92 }
87 93
88 let channelInfo={}; 94 let channelInfo={};
89 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; 95 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
90 channelInfo.fromNodeId=GlobalConfig.nodeId; 96 channelInfo.fromNodeId=GlobalConfig.nodeId;
91 - channelInfo.channelId=_param.channelId;//freeChannel  
92 - channelInfo.timestamp=_param.timestamp;//EngineUtils.creatTimestamp();  
93 - channelInfo.classId=_param.classId;//GlobalConfig.classId;  
94 - channelInfo.siteId=_param.siteId;//GlobalConfig.siteId; 97 + channelInfo.channelId=needPublishChannelInfo.channelId;//freeChannel
  98 + channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称
  99 + channelInfo.timestamp=needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp();
  100 + channelInfo.classId=GlobalConfig.classId;//GlobalConfig.classId;
  101 + channelInfo.siteId=GlobalConfig.siteId;//GlobalConfig.siteId;
95 channelInfo.toNodeId=0; 102 channelInfo.toNodeId=0;
96 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO; 103 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
97 this.sendTableUpdateHandler(channelInfo); 104 this.sendTableUpdateHandler(channelInfo);
@@ -105,9 +112,9 @@ class AudioApe extends Ape { @@ -105,9 +112,9 @@ class AudioApe extends Ape {
105 loger.warn(GlobalConfig.getCurrentStatus()); 112 loger.warn(GlobalConfig.getCurrentStatus());
106 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 113 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
107 } 114 }
108 - //_param如果为空,那么默认就是当前自己的nodeId,否则用_param 115 + //_param如果为空或者0,那么默认就是当前自己的nodeId,否则用_param
109 let nodeId; 116 let nodeId;
110 - if(_param&&parseInt(_param.nodeId)>=0){ 117 + if(_param&&parseInt(_param.nodeId)>0){
111 nodeId=parseInt(_param.nodeId); 118 nodeId=parseInt(_param.nodeId);
112 }else { 119 }else {
113 nodeId=GlobalConfig.nodeId; 120 nodeId=GlobalConfig.nodeId;
@@ -115,8 +122,8 @@ class AudioApe extends Ape { @@ -115,8 +122,8 @@ class AudioApe extends Ape {
115 122
116 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); 123 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
117 if (openingChannel == 0) { 124 if (openingChannel == 0) {
118 - loger.warn(nodeId,"stopPublishAudio,没有占用channel,不需要关闭");  
119 - return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"}; 125 + loger.warn(nodeId,"没有占用channel不需要处理");
  126 + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
120 } 127 }
121 128
122 let channelInfo={}; 129 let channelInfo={};
@@ -243,11 +250,47 @@ class AudioApe extends Ape { @@ -243,11 +250,47 @@ class AudioApe extends Ape {
243 250
244 tableUpdateHandler(owner, itemIdx, itemData) { 251 tableUpdateHandler(owner, itemIdx, itemData) {
245 // debugger; 252 // debugger;
246 - let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData); 253 + /* let updateChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
247 254
248 this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo; 255 this.mediaModule.mediaChannels[itemIdx] = updateChannelInfo;
249 256
250 - this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo); 257 + this._emit(MessageTypes.AUDIO_UPDATE, updateChannelInfo);*/
  258 + let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
  259 + this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
  260 +
  261 + if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){
  262 + let receiveChannelInfo={};
  263 + receiveChannelInfo.mediaId=unpackChannelInfo.channelId;
  264 +
  265 + //消息不是自己同步的,需要处理
  266 + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
  267 + //正在推流
  268 + receiveChannelInfo.m3u8Url="";
  269 + receiveChannelInfo.rtmpUrl="";
  270 + let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
  271 + let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId});
  272 +
  273 + if(m3u8Stream.code==0){
  274 + receiveChannelInfo.m3u8Url=m3u8Stream.playUrl;
  275 + }
  276 + if(rtmpStream.code==0){
  277 + receiveChannelInfo.rtmpUrl=rtmpStream.playUrl;
  278 + }
  279 + loger.log("AUDIO_PLAY");
  280 + console.log(receiveChannelInfo);
  281 + //广播播放视频的消息
  282 + this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo);
  283 + }else {
  284 + loger.log("AUDIO_STOP");
  285 + console.log(receiveChannelInfo);
  286 + //流已经停止
  287 + this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo);
  288 + }
  289 + }else {
  290 + loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:");
  291 + console.log(unpackChannelInfo);
  292 +
  293 + }
251 } 294 }
252 295
253 ///////数据的封包和解包///////////////////////////////////////// 296 ///////数据的封包和解包/////////////////////////////////////////
@@ -263,6 +306,7 @@ class AudioApe extends Ape { @@ -263,6 +306,7 @@ class AudioApe extends Ape {
263 let packPduModel = new pdu['RCAudioChannelInfoPdu']; 306 let packPduModel = new pdu['RCAudioChannelInfoPdu'];
264 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; 307 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
265 packPduModel.channelId = _itemIdx; 308 packPduModel.channelId = _itemIdx;
  309 + packPduModel.streamId = _param.streamId||"";
266 packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; 310 packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
267 packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); 311 packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
268 packPduModel.userId =_param.userId||"0"; 312 packPduModel.userId =_param.userId||"0";
@@ -282,7 +326,7 @@ class AudioApe extends Ape { @@ -282,7 +326,7 @@ class AudioApe extends Ape {
282 } 326 }
283 try { 327 try {
284 let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData); 328 let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData);
285 - loger.log("unPackPdu",packChannelInfo); 329 + console.log(packChannelInfo);
286 return packChannelInfo; 330 return packChannelInfo;
287 } catch (err) { 331 } catch (err) {
288 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); 332 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
@@ -171,7 +171,8 @@ class DocApe extends Ape { @@ -171,7 +171,8 @@ class DocApe extends Ape {
171 if(lastIndex>0){ 171 if(lastIndex>0){
172 let newPath=fullPath.substr(0,lastIndex); 172 let newPath=fullPath.substr(0,lastIndex);
173 let pathArr=[]; 173 let pathArr=[];
174 - for(let i=1;i<_param.pageNum;i++){ 174 + //页数从1开始
  175 + for(let i=1;i<=_param.pageNum;i++){
175 pathArr.push(newPath+"/"+i+"."+fileType); 176 pathArr.push(newPath+"/"+i+"."+fileType);
176 } 177 }
177 return pathArr; 178 return pathArr;
@@ -210,6 +211,8 @@ class DocApe extends Ape { @@ -210,6 +211,8 @@ class DocApe extends Ape {
210 211
211 //切换文档 212 //切换文档
212 documentSwitchDoc(paramInfo){ 213 documentSwitchDoc(paramInfo){
  214 + loger.log('切换文档,documentSwitchDoc');
  215 + console.log(paramInfo);
213 if(paramInfo==null||paramInfo.itemIdx==null){ 216 if(paramInfo==null||paramInfo.itemIdx==null){
214 loger.warn('documentSwitch失败,参数错误',paramInfo); 217 loger.warn('documentSwitch失败,参数错误',paramInfo);
215 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 218 this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -257,6 +260,8 @@ class DocApe extends Ape { @@ -257,6 +260,8 @@ class DocApe extends Ape {
257 260
258 //文档翻页 261 //文档翻页
259 documentSwitchPage(paramInfo){ 262 documentSwitchPage(paramInfo){
  263 + loger.log('文档翻页,documentSwitchPage');
  264 + console.log(paramInfo);
260 //console.log(this.docList); 265 //console.log(this.docList);
261 //获取已经存在的数据 266 //获取已经存在的数据
262 let docDataModel= this.docList[paramInfo.itemIdx]; 267 let docDataModel= this.docList[paramInfo.itemIdx];
@@ -12,6 +12,7 @@ let loger = Loger.getLoger('MediaModule'); @@ -12,6 +12,7 @@ let loger = Loger.getLoger('MediaModule');
12 12
13 class MediaModule { 13 class MediaModule {
14 constructor() { 14 constructor() {
  15 + this.needPublishMediaChannel={};//记录准备推流的频道信息
15 this.mediaChannels = {}; 16 this.mediaChannels = {};
16 this.maxMediaChannel=0; 17 this.maxMediaChannel=0;
17 this.MEDIA_OBJ_TABLE_ID=0; 18 this.MEDIA_OBJ_TABLE_ID=0;
@@ -20,9 +21,7 @@ class MediaModule { @@ -20,9 +21,7 @@ class MediaModule {
20 //获取播流地址 21 //获取播流地址
21 getMediaPlayPath(_param) { 22 getMediaPlayPath(_param) {
22 loger.log('getMediaPlayPath'); 23 loger.log('getMediaPlayPath');
23 - if (_param == null||_param.siteId == null||  
24 - _param.classId == null||_param.userId == null||  
25 - _param.channelId == null|| _param.timestamp==null) 24 + if (_param == null||_param.streamId == null)
26 { 25 {
27 loger.warn('getMediaPlayPath,参数错误', _param); 26 loger.warn('getMediaPlayPath,参数错误', _param);
28 //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 27 //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
@@ -37,21 +36,13 @@ class MediaModule { @@ -37,21 +36,13 @@ class MediaModule {
37 port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort; 36 port = (GlobalConfig.RSServerPort == "" || GlobalConfig.RSServerPort == null) ? "":":" + GlobalConfig.RSServerPort;
38 path = "http://" + GlobalConfig.RSServerIP 37 path = "http://" + GlobalConfig.RSServerIP
39 + port + "/live/" 38 + port + "/live/"
40 - + _param.siteId  
41 - + "_" + _param.classId  
42 - + "_" + _param.userId  
43 - + "_" + _param.channelId  
44 - + "_" + _param.timestamp 39 + + _param.streamId
45 + "/index.m3u8"; 40 + "/index.m3u8";
46 } else { 41 } else {
47 port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort; 42 port = (GlobalConfig.MSServerPort == "" || GlobalConfig.MSServerPort == null) ? "":":" + GlobalConfig.MSServerPort;
48 path = "rtmp://" + GlobalConfig.MSServerIP 43 path = "rtmp://" + GlobalConfig.MSServerIP
49 + port + "/live/" 44 + port + "/live/"
50 - + _param.siteId  
51 - + "_" + _param.classId  
52 - + "_" + _param.userId  
53 - + "_" + _param.channelId  
54 - + "_" + _param.timestamp; 45 + + _param.streamId;
55 } 46 }
56 return {"code": ApeConsts.RETURN_SUCCESS, "data": "","playUrl": path}; 47 return {"code": ApeConsts.RETURN_SUCCESS, "data": "","playUrl": path};
57 } 48 }
@@ -77,18 +68,21 @@ class MediaModule { @@ -77,18 +68,21 @@ class MediaModule {
77 //时间戳 68 //时间戳
78 let timestamp = EngineUtils.creatTimestamp(); 69 let timestamp = EngineUtils.creatTimestamp();
79 70
80 - //生成推流地址和推流数据(同步数据的时候用)  
81 - let publishUrl = "rtmp://" + GlobalConfig.MSServerIP  
82 - + port + "/"+pubType+"/" +GlobalConfig.siteId+"_" 71 + let streamId=GlobalConfig.siteId+"_"
83 + GlobalConfig.classId + "_"+GlobalConfig.userId 72 + GlobalConfig.classId + "_"+GlobalConfig.userId
84 +"_" + freeChannel + "_" + timestamp; 73 +"_" + freeChannel + "_" + timestamp;
  74 +
  75 + //生成推流地址和推流数据(同步数据的时候用)
  76 + let publishUrl = "rtmp://" + GlobalConfig.MSServerIP
  77 + + port + "/"+pubType+"/" +streamId;
  78 +
  79 + this.needPublishMediaChannel[publishUrl]={
  80 + "channelId":freeChannel,
  81 + "publishUrl":publishUrl,
  82 + "streamId":streamId
  83 + };
85 return {"code": ApeConsts.RETURN_SUCCESS, 84 return {"code": ApeConsts.RETURN_SUCCESS,
86 "data":"", 85 "data":"",
87 - "siteId":GlobalConfig.siteId,  
88 - "classId":GlobalConfig.classId,  
89 - "userId":GlobalConfig.userId,  
90 - "channelId": freeChannel,  
91 - "timestamp": timestamp,  
92 "publishUrl": publishUrl 86 "publishUrl": publishUrl
93 }; 87 };
94 } 88 }
@@ -111,6 +105,11 @@ class MediaModule { @@ -111,6 +105,11 @@ class MediaModule {
111 return 0;//没有空闲的 105 return 0;//没有空闲的
112 } 106 }
113 107
  108 + //获取准备推流的频道信息
  109 + getNeedPublishMediaChannel(_publishUrl){
  110 + return this.needPublishMediaChannel[_publishUrl];
  111 + }
  112 +
114 //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId 113 //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
115 getOpeningMediaChannel(_nodeId){ 114 getOpeningMediaChannel(_nodeId){
116 if(_nodeId==null||_nodeId==0){ 115 if(_nodeId==null||_nodeId==0){
@@ -58,16 +58,19 @@ class VideoApe extends Ape { @@ -58,16 +58,19 @@ class VideoApe extends Ape {
58 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 58 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
59 } 59 }
60 60
61 - if (_param == null||_param.channelId == null||  
62 - _param.classId == null||_param.userId == null||  
63 - _param.siteId == null|| _param.timestamp==null) 61 + if (_param == null||_param.publishUrl == null)
64 { 62 {
65 loger.warn('publishVideo,参数错误', _param); 63 loger.warn('publishVideo,参数错误', _param);
66 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG); 64 this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
67 return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"}; 65 return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
68 } 66 }
69 67
70 - loger.log('publishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); 68 + //根据推流的地址获取对应的频道信息
  69 + let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
  70 + if(needPublishChannelInfo==null){
  71 + loger.warn('publishVideo,推流数据已经无效', _param);
  72 + return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
  73 + }
71 74
72 //同一个nodeId只允许推一个流,如果已经推了就不能再推 75 //同一个nodeId只允许推一个流,如果已经推了就不能再推
73 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){ 76 if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
@@ -82,19 +85,20 @@ class VideoApe extends Ape { @@ -82,19 +85,20 @@ class VideoApe extends Ape {
82 return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; 85 return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
83 } 86 }
84 87
  88 +
85 //判断当前的频道是否已经占用 89 //判断当前的频道是否已经占用
86 - if(this.mediaModule.checkChannelIsOpening(_param.channelId)){  
87 - loger.warn(_param.channelId,"频道已经被占用"); 90 + if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){
  91 + loger.warn(needPublishChannelInfo.channelId,"频道已经被占用");
88 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"}; 92 return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
89 } 93 }
90 94
91 let channelInfo={}; 95 let channelInfo={};
92 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING; 96 channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
93 channelInfo.fromNodeId=GlobalConfig.nodeId; 97 channelInfo.fromNodeId=GlobalConfig.nodeId;
94 - channelInfo.channelId=_param.channelId;//freeChannel  
95 - channelInfo.timestamp=_param.timestamp;//EngineUtils.creatTimestamp();  
96 - channelInfo.classId=_param.classId;//GlobalConfig.classId;  
97 - channelInfo.siteId=_param.siteId;//GlobalConfig.siteId; 98 + channelInfo.channelId=needPublishChannelInfo.channelId;
  99 + channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称
  100 + channelInfo.classId=GlobalConfig.classId;
  101 + channelInfo.siteId=GlobalConfig.siteId;
98 channelInfo.toNodeId=0; 102 channelInfo.toNodeId=0;
99 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; 103 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
100 this.sendTableUpdateHandler(channelInfo); 104 this.sendTableUpdateHandler(channelInfo);
@@ -111,7 +115,7 @@ class VideoApe extends Ape { @@ -111,7 +115,7 @@ class VideoApe extends Ape {
111 loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels); 115 loger.log('stopPublishVideo -> maxVideoChannels', GlobalConfig.maxVideoChannels);
112 //_param如果为空,那么默认就是当前自己的nodeId,否则用_param 116 //_param如果为空,那么默认就是当前自己的nodeId,否则用_param
113 let nodeId; 117 let nodeId;
114 - if(_param&&parseInt(_param.nodeId)>=0){ 118 + if(_param&&parseInt(_param.nodeId)>0){
115 nodeId=parseInt(_param.nodeId); 119 nodeId=parseInt(_param.nodeId);
116 }else { 120 }else {
117 nodeId=GlobalConfig.nodeId; 121 nodeId=GlobalConfig.nodeId;
@@ -119,8 +123,8 @@ class VideoApe extends Ape { @@ -119,8 +123,8 @@ class VideoApe extends Ape {
119 123
120 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); 124 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
121 if (openingChannel == 0) { 125 if (openingChannel == 0) {
122 - loger.warn(nodeId,"stopPublishVideo,没有占用channel,不需要关闭");  
123 - return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel,不需要关闭"}; 126 + loger.warn(nodeId,"没有占用channel不需要处理");
  127 + return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
124 } 128 }
125 129
126 let channelInfo={}; 130 let channelInfo={};
@@ -265,9 +269,44 @@ class VideoApe extends Ape { @@ -265,9 +269,44 @@ class VideoApe extends Ape {
265 269
266 tableUpdateHandler(owner, itemIdx, itemData) { 270 tableUpdateHandler(owner, itemIdx, itemData) {
267 // debugger; 271 // debugger;
268 - let videoChannelInfo = this.unPackPdu(owner, itemIdx, itemData);  
269 - this.mediaModule.mediaChannels[itemIdx] = videoChannelInfo;  
270 - this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo); 272 + let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
  273 + this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
  274 +
  275 + if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){
  276 + let receiveChannelInfo={};
  277 + receiveChannelInfo.mediaId=unpackChannelInfo.channelId;
  278 +
  279 + //消息不是自己同步的,需要处理
  280 + if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
  281 + //正在推流
  282 + receiveChannelInfo.m3u8Url="";
  283 + receiveChannelInfo.rtmpUrl="";
  284 + let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
  285 + let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId});
  286 +
  287 + if(m3u8Stream.code==0){
  288 + receiveChannelInfo.m3u8Url=m3u8Stream.playUrl;
  289 + }
  290 + if(rtmpStream.code==0){
  291 + receiveChannelInfo.rtmpUrl=rtmpStream.playUrl;
  292 + }
  293 + loger.log("VIDEO_PLAY");
  294 + console.log(receiveChannelInfo);
  295 + //广播播放视频的消息
  296 + this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo);
  297 + }else {
  298 + loger.log("VIDEO_STOP");
  299 + console.log(receiveChannelInfo);
  300 + //流已经停止
  301 + this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo);
  302 + }
  303 + }else {
  304 + loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:");
  305 + console.log(unpackChannelInfo);
  306 +
  307 + }
  308 +
  309 + //this._emit(MessageTypes.VIDEO_UPDATE, videoChannelInfo);
271 } 310 }
272 311
273 ///////数据的封包和解包///////////////////////////////////////// 312 ///////数据的封包和解包/////////////////////////////////////////
@@ -283,6 +322,7 @@ class VideoApe extends Ape { @@ -283,6 +322,7 @@ class VideoApe extends Ape {
283 let packPduModel = new pdu['RCVideoChannelInfoPdu']; 322 let packPduModel = new pdu['RCVideoChannelInfoPdu'];
284 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED; 323 packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
285 packPduModel.channelId = _itemIdx; 324 packPduModel.channelId = _itemIdx;
  325 + packPduModel.streamId = _param.streamId||"";
286 packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId; 326 packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
287 packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId); 327 packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
288 packPduModel.userId =_param.userId||"0"; 328 packPduModel.userId =_param.userId||"0";
@@ -303,7 +343,7 @@ class VideoApe extends Ape { @@ -303,7 +343,7 @@ class VideoApe extends Ape {
303 try { 343 try {
304 344
305 let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData); 345 let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData);
306 - loger.log("unPackPdu",videoChannelInfo); 346 + console.log(videoChannelInfo);
307 return videoChannelInfo; 347 return videoChannelInfo;
308 } catch (err) { 348 } catch (err) {
309 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message); 349 loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
@@ -776,6 +776,7 @@ message RCAudioChannelInfoPdu { @@ -776,6 +776,7 @@ message RCAudioChannelInfoPdu {
776 optional uint32 class_id = 7;//课堂号 776 optional uint32 class_id = 7;//课堂号
777 optional string site_id = 8;//站点号 777 optional string site_id = 8;//站点号
778 optional string user_id = 9;//用户的userId 778 optional string user_id = 9;//用户的userId
  779 + optional string stream_id = 10;//流名称
779 } 780 }
780 781
781 message RCVideoChannelInfoPdu { 782 message RCVideoChannelInfoPdu {
@@ -788,6 +789,7 @@ message RCVideoChannelInfoPdu { @@ -788,6 +789,7 @@ message RCVideoChannelInfoPdu {
788 optional uint32 class_id = 7;//课堂号 789 optional uint32 class_id = 7;//课堂号
789 optional string site_id = 8;//站点号 790 optional string site_id = 8;//站点号
790 optional string user_id = 9;//用户的userId 791 optional string user_id = 9;//用户的userId
  792 + optional string stream_id = 10;//流名称
791 } 793 }
792 794
793 message RCVideoChannelInfoRecordPdu { 795 message RCVideoChannelInfoRecordPdu {