李勇

1.音视频模块停止推流接口增加参数字段,根据字段来做停止推流是否频道占用;分4种情况

A.停止自己占用的所有流
B.停止自己占用的指定id流
C.停止其他人(nodeId)占用的所有流;
D停止其他人(nodeId)占用的指定id流;

2.获取推流地址时,如果频道被占用完,返回值中增加当前频道的所有信息
@@ -34,15 +34,6 @@ let _audio_ape; @@ -34,15 +34,6 @@ let _audio_ape;
34 let _doc_ape; 34 let _doc_ape;
35 let _whiteboard_ape; 35 let _whiteboard_ape;
36 36
37 -////初始化成功回调函数  
38 -//let _initSuccessCallBackFun;  
39 -//  
40 -////加入会议成功回调函数  
41 -//let _joinClassSuccessCallBackFun;  
42 -//  
43 -////监听mcu所有错误异常回调函数  
44 -//let _mcuErrorCallBackFun;  
45 -  
46 //MCUClient 外部实例化主类 37 //MCUClient 外部实例化主类
47 export default class MessageEntrance extends Emiter { 38 export default class MessageEntrance extends Emiter {
48 constructor() { 39 constructor() {
@@ -221,7 +212,7 @@ export default class MessageEntrance extends Emiter { @@ -221,7 +212,7 @@ export default class MessageEntrance extends Emiter {
221 _onClassDeleteRoster(_data){ 212 _onClassDeleteRoster(_data){
222 //{"nodeId":nodeId} 213 //{"nodeId":nodeId}
223 //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel; 214 //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
224 -/* if(_data!=null&&_data.nodeId!=null){ 215 + /* if(_data!=null&&_data.nodeId!=null){
225 loger.log("有人员离开,检查一下离开的人员是否关闭推流"); 216 loger.log("有人员离开,检查一下离开的人员是否关闭推流");
226 if(_video_ape){ 217 if(_video_ape){
227 _video_ape.stopPublishVideo(_data); 218 _video_ape.stopPublishVideo(_data);
@@ -104,24 +104,65 @@ class AudioApe extends Ape { @@ -104,24 +104,65 @@ class AudioApe extends Ape {
104 channelInfo.userId=GlobalConfig.userId; 104 channelInfo.userId=GlobalConfig.userId;
105 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO; 105 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
106 this.sendTableUpdateHandler(channelInfo); 106 this.sendTableUpdateHandler(channelInfo);
107 - return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"} 107 + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
108 } 108 }
109 109
110 //停止推流, 110 //停止推流,
111 stopPublishAudio(_param) { 111 stopPublishAudio(_param) {
112 - loger.log('stopPublishAudio'); 112 + loger.log('stopPublishAudio ->_param',_param);
113 if(!this.mcu.connected){ 113 if(!this.mcu.connected){
114 loger.warn(GlobalConfig.getCurrentStatus()); 114 loger.warn(GlobalConfig.getCurrentStatus());
115 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 115 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
116 } 116 }
117 - //_param如果为空或者0,那么默认就是当前自己的nodeId,否则用_param  
118 - let nodeId; 117 +
  118 + //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
  119 + let nodeId=GlobalConfig.nodeId;
119 if(_param&&parseInt(_param.nodeId)>0){ 120 if(_param&&parseInt(_param.nodeId)>0){
120 nodeId=parseInt(_param.nodeId); 121 nodeId=parseInt(_param.nodeId);
  122 + }
  123 +
  124 + //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
  125 + let releaseChannelId=0;
  126 + if(_param&&parseInt(_param.mediaId)>0){
  127 + releaseChannelId=parseInt(_param.mediaId);
  128 + }
  129 +
  130 + //释放channelId 的占用
  131 + if(releaseChannelId>0){
  132 + //第一种情况,释放nodeId占用的指定mediaId (channelId)
  133 + this._releaseChannelForNodeId(nodeId,releaseChannelId);
121 }else { 134 }else {
122 - nodeId=GlobalConfig.nodeId; 135 + //第二种情况,释放nodeId占用的所有channelId
  136 + this._releaseNodeIdAllChannel(nodeId);
123 } 137 }
  138 + }
124 139
  140 + //释放nodeId占用的指定的channelId频道
  141 + _releaseChannelForNodeId(nodeId,channelId){
  142 + loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId);
  143 + let channelInfo=this.mediaModule.mediaChannels[channelId];
  144 + if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
  145 + if(channelInfo.fromNodeId==nodeId){
  146 + let channelInfo={};
  147 + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
  148 + channelInfo.fromNodeId=0;
  149 + channelInfo.channelId=channelId;
  150 + channelInfo.timestamp=0;
  151 + channelInfo.classId=GlobalConfig.classId;
  152 + channelInfo.toNodeId=0;
  153 + channelInfo.userId=GlobalConfig.userId;
  154 + channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
  155 + this.sendTableUpdateHandler(channelInfo);
  156 + }else {
  157 + loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
  158 + }
  159 + }else {
  160 + loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
  161 + }
  162 + }
  163 + //释放nodeId占用的所有频道
  164 + _releaseNodeIdAllChannel(nodeId){
  165 + loger.log(nodeId,"_releaseNodeIdAllChannel");
125 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); 166 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
126 if (openingChannel == 0) { 167 if (openingChannel == 0) {
127 loger.warn(nodeId,"没有占用channel不需要处理"); 168 loger.warn(nodeId,"没有占用channel不需要处理");
@@ -138,8 +179,12 @@ class AudioApe extends Ape { @@ -138,8 +179,12 @@ class AudioApe extends Ape {
138 channelInfo.userId=GlobalConfig.userId; 179 channelInfo.userId=GlobalConfig.userId;
139 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT; 180 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
140 this.sendTableUpdateHandler(channelInfo); 181 this.sendTableUpdateHandler(channelInfo);
  182 + //递归检查,800毫秒之后执行
  183 + setTimeout(function(){
  184 + loger.warn(nodeId,"递归检查频道是否占用");
  185 + this._releaseNodeIdAllChannel(nodeId);
  186 + }.bind(this),800);
141 } 187 }
142 -  
143 sendAudioBroadcastMsg(_param) { 188 sendAudioBroadcastMsg(_param) {
144 loger.log('sendAudioBroadcastMsg',_param); 189 loger.log('sendAudioBroadcastMsg',_param);
145 if(!this.mcu.connected){ 190 if(!this.mcu.connected){
@@ -79,8 +79,8 @@ class ChatApe extends Ape { @@ -79,8 +79,8 @@ class ChatApe extends Ape {
79 var chatReceivePdu = pdu['RCChatSendDataRequestPdu'].decode(chatBuffer); 79 var chatReceivePdu = pdu['RCChatSendDataRequestPdu'].decode(chatBuffer);
80 80
81 var chatMsg = {}; 81 var chatMsg = {};
82 - chatMsg.fromNodeID = chatReceivePdu.initiator;  
83 - chatMsg.toNodeID = chatReceivePdu.peer; 82 + chatMsg.fromNodeId = chatReceivePdu.initiator;
  83 + chatMsg.toNodeId = chatReceivePdu.peer;
84 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2); 84 chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
85 chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2); 85 chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2);
86 chatMsg.fromRole = chatReceivePdu.fromRole; 86 chatMsg.fromRole = chatReceivePdu.fromRole;
@@ -246,7 +246,7 @@ class DocApe extends Ape { @@ -246,7 +246,7 @@ class DocApe extends Ape {
246 docDataModel.action=ApeConsts.DOC_ACTION_SWITCH_DOC; 246 docDataModel.action=ApeConsts.DOC_ACTION_SWITCH_DOC;
247 docDataModel.visible=paramInfo.visible||false;//默认是false 247 docDataModel.visible=paramInfo.visible||false;//默认是false
248 248
249 - loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态'); 249 + //loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
250 console.log({"oldDoc":oldDocModel,"nowDoc":docDataModel}); 250 console.log({"oldDoc":oldDocModel,"nowDoc":docDataModel});
251 //更新当前选择的文档 251 //更新当前选择的文档
252 this.updaterDoc(docDataModel,docDataModel.itemIdx); 252 this.updaterDoc(docDataModel,docDataModel.itemIdx);
@@ -53,7 +53,7 @@ class MediaModule { @@ -53,7 +53,7 @@ class MediaModule {
53 //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启 53 //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
54 let freeChannel = this.getFreeMediaChannel(); 54 let freeChannel = this.getFreeMediaChannel();
55 if (freeChannel == 0) { 55 if (freeChannel == 0) {
56 - return {"code":ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; 56 + return {"code":ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaChannels};
57 } 57 }
58 58
59 //默认方式推流 59 //默认方式推流
@@ -107,26 +107,64 @@ class VideoApe extends Ape { @@ -107,26 +107,64 @@ class VideoApe extends Ape {
107 channelInfo.userId=GlobalConfig.userId; 107 channelInfo.userId=GlobalConfig.userId;
108 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO; 108 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
109 this.sendTableUpdateHandler(channelInfo); 109 this.sendTableUpdateHandler(channelInfo);
110 - return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"} 110 + return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
111 } 111 }
112 112
113 //停止推流, 113 //停止推流,
114 stopPublishVideo(_param) { 114 stopPublishVideo(_param) {
  115 + loger.log('stopPublishVideo ->_param',_param);
115 if(!this.mcu.connected){ 116 if(!this.mcu.connected){
116 loger.warn(GlobalConfig.getCurrentStatus()); 117 loger.warn(GlobalConfig.getCurrentStatus());
117 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"}; 118 return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
118 } 119 }
119 120
120 - //_param如果为空,那么默认就是当前自己的nodeId,否则用_param  
121 - let nodeId; 121 + //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
  122 + let nodeId=GlobalConfig.nodeId;
122 if(_param&&parseInt(_param.nodeId)>0){ 123 if(_param&&parseInt(_param.nodeId)>0){
123 nodeId=parseInt(_param.nodeId); 124 nodeId=parseInt(_param.nodeId);
124 - }else {  
125 - nodeId=GlobalConfig.nodeId;  
126 } 125 }
127 126
128 - loger.log('stopPublishVideo ->nodeId',nodeId,' maxVideoChannels', GlobalConfig.maxVideoChannels); 127 + //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
  128 + let releaseChannelId=0;
  129 + if(_param&&parseInt(_param.mediaId)>0){
  130 + releaseChannelId=parseInt(_param.mediaId);
  131 + }
129 132
  133 + //释放channelId 的占用
  134 + if(releaseChannelId>0){
  135 + //第一种情况,释放nodeId占用的指定mediaId (channelId)
  136 + this._releaseChannelForNodeId(nodeId,releaseChannelId);
  137 + }else {
  138 + //第二种情况,释放nodeId占用的所有channelId
  139 + this._releaseNodeIdAllChannel(nodeId);
  140 + }
  141 + }
  142 + //释放nodeId占用的指定的channelId频道
  143 + _releaseChannelForNodeId(nodeId,channelId){
  144 + loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId);
  145 + let channelInfo=this.mediaModule.mediaChannels[channelId];
  146 + if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
  147 + if(channelInfo.fromNodeId==nodeId){
  148 + let channelInfo={};
  149 + channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
  150 + channelInfo.fromNodeId=0;
  151 + channelInfo.channelId=channelId;
  152 + channelInfo.timestamp=0;
  153 + channelInfo.classId=GlobalConfig.classId;
  154 + channelInfo.toNodeId=0;
  155 + channelInfo.userId=GlobalConfig.userId;
  156 + channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
  157 + this.sendTableUpdateHandler(channelInfo);
  158 + }else {
  159 + loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
  160 + }
  161 + }else {
  162 + loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
  163 + }
  164 + }
  165 + //释放nodeId占用的所有频道
  166 + _releaseNodeIdAllChannel(nodeId){
  167 + loger.log(nodeId,"_releaseNodeIdAllChannel");
130 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId); 168 let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
131 if (openingChannel == 0) { 169 if (openingChannel == 0) {
132 loger.warn(nodeId,"没有占用channel不需要处理"); 170 loger.warn(nodeId,"没有占用channel不需要处理");
@@ -143,6 +181,11 @@ class VideoApe extends Ape { @@ -143,6 +181,11 @@ class VideoApe extends Ape {
143 channelInfo.userId=GlobalConfig.userId; 181 channelInfo.userId=GlobalConfig.userId;
144 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT; 182 channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
145 this.sendTableUpdateHandler(channelInfo); 183 this.sendTableUpdateHandler(channelInfo);
  184 + //递归检查,800毫秒之后执行
  185 + setTimeout(function(){
  186 + loger.warn(nodeId,"递归检查频道是否占用");
  187 + this._releaseNodeIdAllChannel(nodeId);
  188 + }.bind(this),800);
146 } 189 }
147 190
148 sendVideoBroadcastMsg(_param) { 191 sendVideoBroadcastMsg(_param) {
@@ -172,7 +215,7 @@ class VideoApe extends Ape { @@ -172,7 +215,7 @@ class VideoApe extends Ape {
172 let freeChannel = this.mediaModule.getFreeMediaChannel(); 215 let freeChannel = this.mediaModule.getFreeMediaChannel();
173 if (freeChannel == 0) { 216 if (freeChannel == 0) {
174 loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param); 217 loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param);
175 - return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"}; 218 + return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
176 } 219 }
177 } 220 }
178 /* message RCVideoSendDataRequestPdu { 221 /* message RCVideoSendDataRequestPdu {
@@ -87,7 +87,7 @@ class MCU extends Emiter { @@ -87,7 +87,7 @@ class MCU extends Emiter {
87 let pduType = pduMsg.get("type"); 87 let pduType = pduMsg.get("type");
88 let pduData = pduMsg.get("data"); 88 let pduData = pduMsg.get("data");
89 //loger.data('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId); 89 //loger.data('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
90 - loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId); 90 + //loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
91 switch (pduType) { 91 switch (pduType) {
92 case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE: 92 case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
93 //加入会议请求返回数据处理 93 //加入会议请求返回数据处理
@@ -116,7 +116,7 @@ class MCU extends Emiter { @@ -116,7 +116,7 @@ class MCU extends Emiter {
116 let sessionLabel = ApeConsts(pduMsg.sessionId); 116 let sessionLabel = ApeConsts(pduMsg.sessionId);
117 if (ape) { 117 if (ape) {
118 let subTypeLabel = pdu.id2type(pduMsg.subType); 118 let subTypeLabel = pdu.id2type(pduMsg.subType);
119 - loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType); 119 + //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
120 //ape广播事件,只要ape中监听就能收到 120 //ape广播事件,只要ape中监听就能收到
121 ape._emit(pduMsg.subType, pduMsg.data); 121 ape._emit(pduMsg.subType, pduMsg.data);
122 } else { 122 } else {