李勇

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

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

2.获取推流地址时,如果频道被占用完,返回值中增加当前频道的所有信息
... ... @@ -34,15 +34,6 @@ let _audio_ape;
let _doc_ape;
let _whiteboard_ape;
////初始化成功回调函数
//let _initSuccessCallBackFun;
//
////加入会议成功回调函数
//let _joinClassSuccessCallBackFun;
//
////监听mcu所有错误异常回调函数
//let _mcuErrorCallBackFun;
//MCUClient 外部实例化主类
export default class MessageEntrance extends Emiter {
constructor() {
... ... @@ -221,7 +212,7 @@ export default class MessageEntrance extends Emiter {
_onClassDeleteRoster(_data){
//{"nodeId":nodeId}
//当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
/* if(_data!=null&&_data.nodeId!=null){
/* if(_data!=null&&_data.nodeId!=null){
loger.log("有人员离开,检查一下离开的人员是否关闭推流");
if(_video_ape){
_video_ape.stopPublishVideo(_data);
... ...
... ... @@ -104,24 +104,65 @@ class AudioApe extends Ape {
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
this.sendTableUpdateHandler(channelInfo);
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"}
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
}
//停止推流,
stopPublishAudio(_param) {
loger.log('stopPublishAudio');
loger.log('stopPublishAudio ->_param',_param);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//_param如果为空或者0,那么默认就是当前自己的nodeId,否则用_param
let nodeId;
//默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId=GlobalConfig.nodeId;
if(_param&&parseInt(_param.nodeId)>0){
nodeId=parseInt(_param.nodeId);
}
//默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
let releaseChannelId=0;
if(_param&&parseInt(_param.mediaId)>0){
releaseChannelId=parseInt(_param.mediaId);
}
//释放channelId 的占用
if(releaseChannelId>0){
//第一种情况,释放nodeId占用的指定mediaId (channelId)
this._releaseChannelForNodeId(nodeId,releaseChannelId);
}else {
nodeId=GlobalConfig.nodeId;
//第二种情况,释放nodeId占用的所有channelId
this._releaseNodeIdAllChannel(nodeId);
}
}
//释放nodeId占用的指定的channelId频道
_releaseChannelForNodeId(nodeId,channelId){
loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId);
let channelInfo=this.mediaModule.mediaChannels[channelId];
if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
if(channelInfo.fromNodeId==nodeId){
let channelInfo={};
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.fromNodeId=0;
channelInfo.channelId=channelId;
channelInfo.timestamp=0;
channelInfo.classId=GlobalConfig.classId;
channelInfo.toNodeId=0;
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
this.sendTableUpdateHandler(channelInfo);
}else {
loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
}
}else {
loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
}
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
loger.log(nodeId,"_releaseNodeIdAllChannel");
let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
if (openingChannel == 0) {
loger.warn(nodeId,"没有占用channel不需要处理");
... ... @@ -138,8 +179,12 @@ class AudioApe extends Ape {
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
setTimeout(function(){
loger.warn(nodeId,"递归检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this),800);
}
sendAudioBroadcastMsg(_param) {
loger.log('sendAudioBroadcastMsg',_param);
if(!this.mcu.connected){
... ...
... ... @@ -79,8 +79,8 @@ class ChatApe extends Ape {
var chatReceivePdu = pdu['RCChatSendDataRequestPdu'].decode(chatBuffer);
var chatMsg = {};
chatMsg.fromNodeID = chatReceivePdu.initiator;
chatMsg.toNodeID = chatReceivePdu.peer;
chatMsg.fromNodeId = chatReceivePdu.initiator;
chatMsg.toNodeId = chatReceivePdu.peer;
chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2);
chatMsg.fromRole = chatReceivePdu.fromRole;
... ...
... ... @@ -246,7 +246,7 @@ class DocApe extends Ape {
docDataModel.action=ApeConsts.DOC_ACTION_SWITCH_DOC;
docDataModel.visible=paramInfo.visible||false;//默认是false
loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
//loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
console.log({"oldDoc":oldDocModel,"nowDoc":docDataModel});
//更新当前选择的文档
this.updaterDoc(docDataModel,docDataModel.itemIdx);
... ...
... ... @@ -53,7 +53,7 @@ class MediaModule {
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.getFreeMediaChannel();
if (freeChannel == 0) {
return {"code":ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
return {"code":ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaChannels};
}
//默认方式推流
... ...
... ... @@ -107,26 +107,64 @@ class VideoApe extends Ape {
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
this.sendTableUpdateHandler(channelInfo);
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!"}
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
}
//停止推流,
stopPublishVideo(_param) {
loger.log('stopPublishVideo ->_param',_param);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId;
//默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId=GlobalConfig.nodeId;
if(_param&&parseInt(_param.nodeId)>0){
nodeId=parseInt(_param.nodeId);
}else {
nodeId=GlobalConfig.nodeId;
}
loger.log('stopPublishVideo ->nodeId',nodeId,' maxVideoChannels', GlobalConfig.maxVideoChannels);
//默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
let releaseChannelId=0;
if(_param&&parseInt(_param.mediaId)>0){
releaseChannelId=parseInt(_param.mediaId);
}
//释放channelId 的占用
if(releaseChannelId>0){
//第一种情况,释放nodeId占用的指定mediaId (channelId)
this._releaseChannelForNodeId(nodeId,releaseChannelId);
}else {
//第二种情况,释放nodeId占用的所有channelId
this._releaseNodeIdAllChannel(nodeId);
}
}
//释放nodeId占用的指定的channelId频道
_releaseChannelForNodeId(nodeId,channelId){
loger.log(nodeId,"_releaseChannelForNodeId-->channelId",channelId);
let channelInfo=this.mediaModule.mediaChannels[channelId];
if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
if(channelInfo.fromNodeId==nodeId){
let channelInfo={};
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.fromNodeId=0;
channelInfo.channelId=channelId;
channelInfo.timestamp=0;
channelInfo.classId=GlobalConfig.classId;
channelInfo.toNodeId=0;
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
this.sendTableUpdateHandler(channelInfo);
}else {
loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
}
}else {
loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
}
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
loger.log(nodeId,"_releaseNodeIdAllChannel");
let openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
if (openingChannel == 0) {
loger.warn(nodeId,"没有占用channel不需要处理");
... ... @@ -143,6 +181,11 @@ class VideoApe extends Ape {
channelInfo.userId=GlobalConfig.userId;
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_DEFAULT;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
setTimeout(function(){
loger.warn(nodeId,"递归检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this),800);
}
sendVideoBroadcastMsg(_param) {
... ... @@ -172,7 +215,7 @@ class VideoApe extends Ape {
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备"};
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
}
}
/* message RCVideoSendDataRequestPdu {
... ...
... ... @@ -87,7 +87,7 @@ class MCU extends Emiter {
let pduType = pduMsg.get("type");
let pduData = pduMsg.get("data");
//loger.data('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
//loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
switch (pduType) {
case PduType.RCPDU_CONNECT_PROVIDER_RESPONSE:
//加入会议请求返回数据处理
... ... @@ -116,7 +116,7 @@ class MCU extends Emiter {
let sessionLabel = ApeConsts(pduMsg.sessionId);
if (ape) {
let subTypeLabel = pdu.id2type(pduMsg.subType);
loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
//loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
//ape广播事件,只要ape中监听就能收到
ape._emit(pduMsg.subType, pduMsg.data);
} else {
... ...