李勇

1.音视频模块推流接口增加optionJsonData:{"bufferTime":0}} 用于设置播放流的时候的bufferTime

... ... @@ -58,7 +58,7 @@ export default class MessageEntrance extends Emiter {
constructor() {
super();
//sdk 信息
GlobalConfig.sdkVersion = "v1.79.4.20170821";
GlobalConfig.sdkVersion = "v1.79.5.20170821";
loger.warn("sdkVersion:" + GlobalConfig.sdkVersion);
//设置
... ... @@ -1796,7 +1796,6 @@ export default class MessageEntrance extends Emiter {
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
if (_video_ape) {
GlobalConfig.optionJsonData=_param.optionJsonData||"";
return _video_ape.publishVideo(_param);
}
}
... ... @@ -1853,7 +1852,6 @@ export default class MessageEntrance extends Emiter {
return {"code": ApeConsts.RETURN_FAILED, "data": ""};
}
if (_audio_ape) {
GlobalConfig.optionJsonData=_param.optionJsonData||"";
return _audio_ape.publishAudio(_param);
}
}
... ...
... ... @@ -14,484 +14,521 @@ import MediaModule from "./MediaModule";
let loger = Loger.getLoger('AudioApe');
class AudioApe extends Ape {
constructor() {
super(
ApeConsts.AUDIO_SESSION_ID,
ApeConsts.AUDIO_SESSION_NAME,
ApeConsts.AUDIO_SESSION_TAG
);
this.releaseTimeId=0
this.mediaModule=new MediaModule();
this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.AUDIO_OBJ_TABLE_ID;
this.mediaModule.mediaChannels={};
this.mediaModule.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.AUDIO_OBJ_TABLE_ID, ApeConsts.AUDIO_OBJ_TABLE_NAME, ApeConsts.AUDIO_OBJ_TABLE_TAG, 0, new ArrayBuffer);
// 广播消息,用户之间的消息传递
this.on(pdu.RCPDU_SEND_AUDIO_DATA_REQUEST, this.receiveAudiooCommandHandler.bind(this));
}
//ape加入成功
onJoinChannelHandlerSuccess(){
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this.mediaModule.maxMediaChannel=GlobalConfig.maxAudioChannels;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getAudioPlayPath(_param) {
loger.log('获取播流地址->');
return this.mediaModule.getMediaPlayPath(_param);
}
//获取推流地址
getAudioPublishPath(_param) {
loger.log('获取推流地址->');
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};;
}
//监课比较特殊,不占用课堂内的音视频路数,额外创建
if(GlobalConfig.userRole==ApeConsts.invisible){
let result=this.mediaModule.getMediaPublishPathForInVisible(_param);
this._emit( MessageTypes.AUDIO_GET_PUBLISH_PATH,result);
return result;
}
//非监课的身份,需要判断是否可以继续推流
//需要判断当前已经使用的流路数
let openChannel=0;
let allChannels= MediaModule.allMediaChannelsList;
for(let i in allChannels){
let channel=allChannels[i];
if(channel&&channel.status==ApeConsts.CHANNEL_STATUS_OPENING&&channel.userRole!=ApeConsts.invisible){
//正在开启的才计数,监课开启的不计算在内
openChannel++;
}
}
//如果已经开启的数量大于等于最大允许开启的数量,不允许再推流
if(openChannel>=GlobalConfig.maxMediaChannels){
loger.warn('不能再打开设备->当前开启的设备数量->',openChannel);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开设备,当前开启的设备数量"};
}
let result=this.mediaModule.getMediaPublishPath(_param);
this._emit( MessageTypes.AUDIO_GET_PUBLISH_PATH,result);
return result;
constructor() {
super(
ApeConsts.AUDIO_SESSION_ID,
ApeConsts.AUDIO_SESSION_NAME,
ApeConsts.AUDIO_SESSION_TAG
);
this.releaseTimeId = 0
this.mediaModule = new MediaModule();
this.mediaModule.MEDIA_OBJ_TABLE_ID = ApeConsts.AUDIO_OBJ_TABLE_ID;
this.mediaModule.mediaChannels = {};
this.mediaModule.mediaType = ApeConsts.MEDIA_TYPE_AUDIO;
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.AUDIO_OBJ_TABLE_ID, ApeConsts.AUDIO_OBJ_TABLE_NAME, ApeConsts.AUDIO_OBJ_TABLE_TAG, 0, new ArrayBuffer);
// 广播消息,用户之间的消息传递
this.on(pdu.RCPDU_SEND_AUDIO_DATA_REQUEST, this.receiveAudiooCommandHandler.bind(this));
}
//ape加入成功
onJoinChannelHandlerSuccess() {
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this.mediaModule.maxMediaChannel = GlobalConfig.maxAudioChannels;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getAudioPlayPath(_param) {
loger.log('获取播流地址->');
return this.mediaModule.getMediaPlayPath(_param);
}
//获取推流地址
getAudioPublishPath(_param) {
loger.log('获取推流地址->');
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
;
}
//获取当前所有频道信息
getAllChannelInfo(_param){
loger.log('获取当前所有频道信息->');
return this.mediaModule.getAllMediaChannelInfo();
//监课比较特殊,不占用课堂内的音视频路数,额外创建
if (GlobalConfig.userRole == ApeConsts.invisible) {
let result = this.mediaModule.getMediaPublishPathForInVisible(_param);
this._emit(MessageTypes.AUDIO_GET_PUBLISH_PATH, result);
return result;
}
//推流
publishAudio(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"已经断开连接!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接","mediaId":0};
}
if (_param == null||_param.publishUrl == null)
{
loger.warn('推流->参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"参数错误!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
}
//根据推流的地址获取对应的频道信息
let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
if(needPublishChannelInfo==null){
loger.warn('推流->推流数据已经无效', _param);
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"推流数据已经无效!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
}
//非监课的身份,需要判断是否可以继续推流
//需要判断当前已经使用的流路数
let openChannel = 0;
let allChannels = MediaModule.allMediaChannelsList;
for (let i in allChannels) {
let channel = allChannels[i];
if (channel && channel.status == ApeConsts.CHANNEL_STATUS_OPENING && channel.userRole != ApeConsts.invisible) {
//正在开启的才计数,监课开启的不计算在内
openChannel++;
}
}
//如果已经开启的数量大于等于最大允许开启的数量,不允许再推流
if (openChannel >= GlobalConfig.maxMediaChannels) {
loger.warn('不能再打开设备->当前开启的设备数量->', openChannel);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开设备,当前开启的设备数量"};
}
//判断当前是否还有空闲的channle
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn("推流->不能再打开更多的设备");
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
}
let result = this.mediaModule.getMediaPublishPath(_param);
this._emit(MessageTypes.AUDIO_GET_PUBLISH_PATH, result);
return result;
}
//获取当前所有频道信息
getAllChannelInfo(_param) {
loger.log('获取当前所有频道信息->');
return this.mediaModule.getAllMediaChannelInfo();
}
//推流
publishAudio(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接!", "mediaId": 0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接", "mediaId": 0};
}
//判断当前的频道是否已经占用
if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){
if(needPublishChannelInfo.nodeId==GlobalConfig.nodeId){
loger.warn(needPublishChannelInfo.channelId,"已经推送过消息,不需要再次推送!");
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId});
return {"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId};
}else {
loger.warn(needPublishChannelInfo.channelId,"频道已经被占用");
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!"};
}
if (_param == null || _param.publishUrl == null) {
loger.warn('推流->参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {"code": ApeConsts.RETURN_FAILED, "data": "参数错误!", "mediaId": 0});
return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
}
//获取可选参数,转换为JSON字符串
try {
GlobalConfig.optionJsonData = JSON.stringify(_param.optionJsonData) || ""
} catch (err) {
GlobalConfig.optionJsonData = "";
}
}
//根据推流的地址获取对应的频道信息
let needPublishChannelInfo = this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
if (needPublishChannelInfo == null) {
loger.warn('推流->推流数据已经无效', _param);
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "推流数据已经无效!",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
}
let channelInfo=this.mediaModule.getDefaultChannelInfo();
channelInfo.owner=GlobalConfig.nodeId;
channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
channelInfo.channelId=needPublishChannelInfo.channelId;//freeChannel
channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称
channelInfo.timestamp=needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp();
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_AUDIO;
this.sendTableUpdateHandler(channelInfo);
this._emit( MessageTypes.AUDIO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId});
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
//判断当前是否还有空闲的channle
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn("推流->不能再打开更多的设备");
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "不能再打开更多的设备",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels};
}
//停止推流,
stopPublishAudio(_param) {
loger.log('停止推流 ->',_param);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//判断当前的频道是否已经占用
if (this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)) {
if (needPublishChannelInfo.nodeId == GlobalConfig.nodeId) {
loger.warn(needPublishChannelInfo.channelId, "已经推送过消息,不需要再次推送!");
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_SUCCESS,
"data": "已经推送过消息,不需要再次推送!",
"mediaId": needPublishChannelInfo.channelId
});
return {
"code": ApeConsts.RETURN_SUCCESS,
"data": "已经推送过消息,不需要再次推送!",
"mediaId": needPublishChannelInfo.channelId
};
} else {
loger.warn(needPublishChannelInfo.channelId, "频道已经被占用");
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "频道已经被占用!",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "频道已经被占用!"};
}
//默认为自己的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占用的所有channelId
this._releaseNodeIdAllChannel(nodeId);
}
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.owner = GlobalConfig.nodeId;
channelInfo.status = ApeConsts.CHANNEL_STATUS_OPENING;
channelInfo.channelId = needPublishChannelInfo.channelId;//freeChannel
channelInfo.streamId = needPublishChannelInfo.streamId;//按规则拼接的流名称
channelInfo.timestamp = needPublishChannelInfo.timestamp;//EngineUtils.creatTimestamp();
channelInfo.mediaType = ApeConsts.MEDIA_TYPE_AUDIO;
this.sendTableUpdateHandler(channelInfo);
this._emit(MessageTypes.AUDIO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_SUCCESS,
"data": "推流成功!",
"mediaId": needPublishChannelInfo.channelId
});
return {"code": ApeConsts.RETURN_SUCCESS, "data": "推流成功!", "mediaId": needPublishChannelInfo.channelId};
}
//停止推流,
stopPublishAudio(_param) {
loger.log('停止推流 ->', _param);
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//释放nodeId占用的指定的channelId频道
_releaseChannelForNodeId(nodeId,channelId){
loger.log(nodeId,"释放占用的频道-->",channelId);
let channelInfo=this.mediaModule.mediaChannels[channelId];
if(channelInfo&&channelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
if(channelInfo.fromNodeId==nodeId){
//默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId = GlobalConfig.nodeId;
if (_param && parseInt(_param.nodeId) > 0) {
nodeId = parseInt(_param.nodeId);
}
let channelInfo=this.mediaModule.getDefaultChannelInfo();
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId=channelId;
//默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
let releaseChannelId = 0;
if (_param && parseInt(_param.mediaId) > 0) {
releaseChannelId = parseInt(_param.mediaId);
}
this.sendTableUpdateHandler(channelInfo);
}else {
loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
}
}else {
loger.warn(nodeId,"要释放的频道不存在或者已经释放-->channelId",channelInfo);
}
//释放channelId 的占用
if (releaseChannelId > 0) {
//第一种情况,释放nodeId占用的指定mediaId (channelId)
this._releaseChannelForNodeId(nodeId, releaseChannelId);
} else {
//第二种情况,释放nodeId占用的所有channelId
this._releaseNodeIdAllChannel(nodeId);
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
loger.log(nodeId,"_releaseNodeIdAllChannel",this.mcu.connected);
if(!this.mcu.connected){
clearTimeout(this.releaseTimeId);
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
}
let openingChannelInfo = this.mediaModule.getOpeningMediaChannelForNodeId(nodeId);
if (openingChannelInfo.channelId == 0) {
loger.warn(nodeId,"没有占用频道不需要处理");
return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
}
//释放nodeId占用的指定的channelId频道
_releaseChannelForNodeId(nodeId, channelId) {
loger.log(nodeId, "释放占用的频道-->", channelId);
let channelInfo = this.mediaModule.mediaChannels[channelId];
if (channelInfo && channelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
if (channelInfo.fromNodeId == nodeId) {
let channelInfo=this.mediaModule.getDefaultChannelInfo();
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId=openingChannelInfo.channelId;
channelInfo.nodeId=openingChannelInfo.fromNodeId;
channelInfo.userRole=openingChannelInfo.userRole;
channelInfo.userName=openingChannelInfo.userName;
channelInfo.userId=openingChannelInfo.userId;
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId = channelId;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
this.releaseTimeId=setTimeout(function(){
loger.warn(nodeId,"检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this),800);
} else {
loger.warn(channelId, "不属于nodeId", nodeId, "不能释放", channelInfo);
}
} else {
loger.warn(nodeId, "要释放的频道不存在或者已经释放-->channelId", channelInfo);
}
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId) {
loger.log(nodeId, "_releaseNodeIdAllChannel", this.mcu.connected);
if (!this.mcu.connected) {
clearTimeout(this.releaseTimeId);
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
sendAudioBroadcastMsg(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('音频模块广播->失败->还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
}
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
}
if (_param == null) {
loger.warn('音频模块广播->失败->,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg,参数错误"};
}
// to, message
loger.log('音频模块广播->',_param);
if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn('不能再打开更多的设备', _param);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
}
}
let audioSendPdu = new pdu['RCAudioSendDataRequestPdu'];
audioSendPdu.type = pdu.RCPDU_SEND_AUDIO_DATA_REQUEST;
audioSendPdu.isPublic = true;
audioSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
audioSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人
audioSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
let dataStr='';
try{
dataStr=JSON.stringify(_param.data);
}catch (err){
loger.warn('控制消息->JSON转换失败');
dataStr=_param.data;
}
audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" +dataStr);//开头两个字会乱码,需要加上h5两个字符
let openingChannelInfo = this.mediaModule.getOpeningMediaChannelForNodeId(nodeId);
if (openingChannelInfo.channelId == 0) {
loger.warn(nodeId, "没有占用频道不需要处理");
return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
}
if (!audioSendPdu.isPublic && 0 != audioSendPdu.toNodeId) {
//发送给制定的人
//loger.log('发送私聊消息.');
this.send(audioSendPdu);
} else {
//发送给所有人
//loger.log('音频模块广播->.');
this.sendChatUniform(audioSendPdu);
}
return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId = openingChannelInfo.channelId;
channelInfo.nodeId = openingChannelInfo.fromNodeId;
channelInfo.userRole = openingChannelInfo.userRole;
channelInfo.userName = openingChannelInfo.userName;
channelInfo.userId = openingChannelInfo.userId;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
this.releaseTimeId = setTimeout(function () {
loger.warn(nodeId, "检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this), 800);
}
sendAudioBroadcastMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('音频模块广播->失败->还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
}
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据"};
}
if (_param == null) {
loger.warn('音频模块广播->失败->,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendAudioBroadcastMsg,参数错误"};
}
// to, message
loger.log('音频模块广播->', _param);
if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn('不能再打开更多的设备', _param);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels};
}
}
sendTableUpdateHandler(_channelInfo) {
//loger.log("audio,sendTableUpdateHandler ");
let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);
if(updateModelPdu==null){
loger.warn("音频模块更新数据-> 失败->数据无效",_channelInfo);
return;
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = _channelInfo.channelId;
tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
let audioSendPdu = new pdu['RCAudioSendDataRequestPdu'];
audioSendPdu.type = pdu.RCPDU_SEND_AUDIO_DATA_REQUEST;
audioSendPdu.isPublic = true;
//insert
let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;
tableInsertItemPdu.items.push(tableItemPdu);
audioSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
audioSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人
audioSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.AUDIO_OBJ_TABLE_ID;//
updateObjPdu.subType = tableInsertItemPdu.type;
updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
let dataStr = '';
try {
dataStr = JSON.stringify(_param.data);
} catch (err) {
loger.warn('控制消息->JSON转换失败');
dataStr = _param.data;
}
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + dataStr);//开头两个字会乱码,需要加上h5两个字符
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
if (!audioSendPdu.isPublic && 0 != audioSendPdu.toNodeId) {
//发送给制定的人
//loger.log('发送私聊消息.');
this.send(audioSendPdu);
} else {
//发送给所有人
//loger.log('音频模块广播->.');
this.sendChatUniform(audioSendPdu);
}
return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
}
sendTableUpdateHandler(_channelInfo) {
//loger.log("audio,sendTableUpdateHandler ");
let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);
if (updateModelPdu == null) {
loger.warn("音频模块更新数据-> 失败->数据无效", _channelInfo);
return;
}
loger.log("音频模块更新数据->itemIdx=" + tableItemPdu.itemIdx);
this.sendUniform(adapterPdu, true);
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = _channelInfo.channelId;
tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
//insert
let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;
tableInsertItemPdu.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.AUDIO_OBJ_TABLE_ID;//
updateObjPdu.subType = tableInsertItemPdu.type;
updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
loger.log("音频模块更新数据->itemIdx=" + tableItemPdu.itemIdx);
this.sendUniform(adapterPdu, true);
}
/////收到消息处理//////////////////////////////////////////////////
// 消息处理,内部处理,不需要告诉应用层
receiveAudiooCommandHandler(_data) {
let audioReceivePdu = pdu['RCAudioSendDataRequestPdu'].decode(_data);
if (audioReceivePdu == null) {
loger.warn("音频消息处理,收到的消息为null,不做处理");
return;
}
audioReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(audioReceivePdu.data, 2);//开头两个字会乱码
let dataObj = {};
try {
dataObj = JSON.parse(audioReceivePdu.data);
} catch (err) {
loger.warn('控制消息->JSON转换失败');
dataObj = audioReceivePdu.data;
}
audioReceivePdu.data = dataObj;
//判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
if (audioReceivePdu.toNodeId != 0 && audioReceivePdu.toNodeId != GlobalConfig.nodeId) {
loger.log('音频消息不处理 toNodeId=', audioReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
} else {
loger.log('音频控制消息处理 .', audioReceivePdu);
this._emit(MessageTypes.AUDIO_BROADCAST, audioReceivePdu);
}
}
tableUpdateHandler(owner, itemIdx, itemData, seek) {
let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
loger.log("tableUpdateHandler->channel", itemIdx, 'status->', unpackChannelInfo.status, "seek->", seek);
//****很重要********
//如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
if (owner == 0) {
loger.log("释放占用的频道,channel", itemIdx);
unpackChannelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
unpackChannelInfo.streamId = "";
}
/////收到消息处理//////////////////////////////////////////////////
this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
if (unpackChannelInfo && unpackChannelInfo.fromNodeId != GlobalConfig.nodeId) {
let receiveChannelInfo = {};
receiveChannelInfo.mediaId = unpackChannelInfo.channelId;
receiveChannelInfo.fromNodeId = unpackChannelInfo.fromNodeId;
receiveChannelInfo.userName = unpackChannelInfo.userName || "";
receiveChannelInfo.userRole = unpackChannelInfo.userRole || ApeConsts.normal;
receiveChannelInfo.mediaType = unpackChannelInfo.mediaType || ApeConsts.MEDIA_TYPE_DEFAULT;
receiveChannelInfo.screenWidth = unpackChannelInfo.screenWidth || GlobalConfig.screenWidth;
receiveChannelInfo.screenHeight = unpackChannelInfo.screenHeight || GlobalConfig.screenHeight;
receiveChannelInfo.deviceType = unpackChannelInfo.deviceType || 0;
receiveChannelInfo.optionJsonData = unpackChannelInfo.optionJsonData || "";
//消息不是自己同步的,需要处理
if (unpackChannelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
//正在推流
receiveChannelInfo.m3u8Url = "";
receiveChannelInfo.rtmpUrl = "";
receiveChannelInfo.replay = "";
receiveChannelInfo.seek = seek || 0;//这个是录制回放时使用的seek
let m3u8Stream = this.mediaModule.getMediaPlayPath({"type": "m3u8", "streamId": unpackChannelInfo.streamId});
let rtmpStream = this.mediaModule.getMediaPlayPath({"type": "rtmp", "streamId": unpackChannelInfo.streamId});
let replay = this.mediaModule.getMediaRecordPlaybackPath({
"type": "m3u8",
"streamId": unpackChannelInfo.streamId
});
if (m3u8Stream.code == 0) {
receiveChannelInfo.m3u8Url = m3u8Stream.playUrl;
}
if (rtmpStream.code == 0) {
receiveChannelInfo.rtmpUrl = rtmpStream.playUrl;
}
if (replay.code == 0) {
receiveChannelInfo.replay = replay.playUrl;
}
loger.log("AUDIO_PLAY->", receiveChannelInfo);
//广播播放视频的消息
this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo);
} else {
loger.log("AUDIO_STOP->", receiveChannelInfo);
//流已经停止
this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo);
}
} else {
loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:");
loger.log(unpackChannelInfo);
if (unpackChannelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
GlobalConfig.openMicrophones = EngineUtils.creatTimestamp();
GlobalConfig.openCamera = 0;
} else {
GlobalConfig.openCamera = 0;
GlobalConfig.openMicrophones = 0;
}
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
userName: GlobalConfig.userName,
userId: GlobalConfig.userId,
openCamera: GlobalConfig.openCamera,
openMicrophones: GlobalConfig.openMicrophones
});
}
// 消息处理,内部处理,不需要告诉应用层
receiveAudiooCommandHandler(_data) {
let audioReceivePdu = pdu['RCAudioSendDataRequestPdu'].decode(_data);
if (audioReceivePdu == null) {
loger.warn("音频消息处理,收到的消息为null,不做处理");
return;
}
audioReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(audioReceivePdu.data, 2);//开头两个字会乱码
let dataObj= {};
try{
dataObj=JSON.parse(audioReceivePdu.data);
}catch (err){
loger.warn('控制消息->JSON转换失败');
dataObj= audioReceivePdu.data;
}
audioReceivePdu.data=dataObj;
//判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
if (audioReceivePdu.toNodeId != 0 && audioReceivePdu.toNodeId != GlobalConfig.nodeId) {
loger.log('音频消息不处理 toNodeId=', audioReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList);
this._emit(MessageTypes.AUDIO_UPDATE, unpackChannelInfo);
}
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param) {
console.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels) {
let channelInfo = this.mediaModule.mediaChannels[i];
if (channelInfo) {
if (channelInfo.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
channelInfo.owner = 0;
} else {
loger.log('音频控制消息处理 .',audioReceivePdu);
this._emit(MessageTypes.AUDIO_BROADCAST, audioReceivePdu);
channelInfo.owner = channelInfo.fromNodeId;
}
this.sendTableUpdateHandler(channelInfo);
}
}
tableUpdateHandler(owner, itemIdx, itemData,seek) {
let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
loger.log("tableUpdateHandler->channel",itemIdx,'status->',unpackChannelInfo.status,"seek->",seek);
//****很重要********
//如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
if(owner==0){
loger.log("释放占用的频道,channel",itemIdx);
unpackChannelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
unpackChannelInfo.streamId="";
}
this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){
let receiveChannelInfo={};
receiveChannelInfo.mediaId=unpackChannelInfo.channelId;
receiveChannelInfo.fromNodeId=unpackChannelInfo.fromNodeId;
receiveChannelInfo.userName=unpackChannelInfo.userName||"";
receiveChannelInfo.userRole=unpackChannelInfo.userRole||ApeConsts.normal;
receiveChannelInfo.mediaType=unpackChannelInfo.mediaType||ApeConsts.MEDIA_TYPE_DEFAULT;
receiveChannelInfo.screenWidth=unpackChannelInfo.screenWidth||GlobalConfig.screenWidth;
receiveChannelInfo.screenHeight=unpackChannelInfo.screenHeight||GlobalConfig.screenHeight;
receiveChannelInfo.deviceType=unpackChannelInfo.deviceType||0;
receiveChannelInfo.optionJsonData=unpackChannelInfo.optionJsonData||"";
//消息不是自己同步的,需要处理
if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
//正在推流
receiveChannelInfo.m3u8Url="";
receiveChannelInfo.rtmpUrl="";
receiveChannelInfo.replay="";
receiveChannelInfo.seek=seek||0;//这个是录制回放时使用的seek
let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId});
let replay=this.mediaModule.getMediaRecordPlaybackPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
if(m3u8Stream.code==0){
receiveChannelInfo.m3u8Url=m3u8Stream.playUrl;
}
if(rtmpStream.code==0){
receiveChannelInfo.rtmpUrl=rtmpStream.playUrl;
}
if(replay.code==0){
receiveChannelInfo.replay=replay.playUrl;
}
loger.log("AUDIO_PLAY->",receiveChannelInfo);
//广播播放视频的消息
this._emit(MessageTypes.AUDIO_PLAY, receiveChannelInfo);
}else {
loger.log("AUDIO_STOP->",receiveChannelInfo);
//流已经停止
this._emit(MessageTypes.AUDIO_STOP, receiveChannelInfo);
}
}else {
loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:");
loger.log(unpackChannelInfo);
if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
GlobalConfig.openMicrophones=EngineUtils.creatTimestamp();
GlobalConfig.openCamera=0;
}else {
GlobalConfig.openCamera=0;
GlobalConfig.openMicrophones=0;
}
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE,{
nodeId:GlobalConfig.nodeId,
userRole:GlobalConfig.userRole,
userName:GlobalConfig.userName,
userId:GlobalConfig.userId,
openCamera:GlobalConfig.openCamera,
openMicrophones:GlobalConfig.openMicrophones
});
}
MediaModule.allMediaChannelsList[itemIdx]=unpackChannelInfo;
console.log('MediaModule.allMediaChannelsList',MediaModule.allMediaChannelsList);
this._emit(MessageTypes.AUDIO_UPDATE, unpackChannelInfo);
}
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param){
console.warn("录制状态发送改变->更新当前的状态->",this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels){
let channelInfo=this.mediaModule.mediaChannels[i];
if(channelInfo){
if(channelInfo.status==ApeConsts.CHANNEL_STATUS_RELEASED){
channelInfo.owner=0;
}else {
channelInfo.owner=channelInfo.fromNodeId;
}
this.sendTableUpdateHandler(channelInfo);
}
}
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
loger.warn("packPdu->失败");
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
loger.warn("packPdu->失败");
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
//判断type类型,根据type设置不同的参数
let packPduModel = new pdu['RCAudioChannelInfoPdu'];
packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
packPduModel.channelId = _itemIdx;
packPduModel.streamId = _param.streamId||"";
packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
packPduModel.userId =_param.userId||"0";
packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_AUDIO;
packPduModel.timestamp =_param.timestamp||EngineUtils.creatTimestamp();
packPduModel.fromNodeId =_param.nodeId|| GlobalConfig.nodeId;
packPduModel.userName=_param.userName||GlobalConfig.userName||"";
packPduModel.toNodeId = 0;
packPduModel.userRole=_param.userRole||GlobalConfig.userRole;
packPduModel.screenWidth=_param.screenWidth||GlobalConfig.screenWidth;
packPduModel.screenHeight=_param.screenHeight||GlobalConfig.screenHeight;
packPduModel.deviceType=_param.deviceType||GlobalConfig.deviceType;
packPduModel.optionJsonData=_param.optionJsonData||GlobalConfig.optionJsonData;
loger.log("packPdu->",packPduModel);
return packPduModel;
}
unPackPdu(owner, itemIdx, itemData) {
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData);
loger.log("unPackPdu->",packChannelInfo);
return packChannelInfo;
} catch (err) {
loger.log("unPackPdu error->itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
//判断type类型,根据type设置不同的参数
let packPduModel = new pdu['RCAudioChannelInfoPdu'];
packPduModel.status = _param.status || ApeConsts.CHANNEL_STATUS_RELEASED;
packPduModel.channelId = _itemIdx;
packPduModel.streamId = _param.streamId || "";
packPduModel.siteId = _param.siteId || GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId = parseInt(_param.classId) || parseInt(GlobalConfig.classId);
packPduModel.userId = _param.userId || "0";
packPduModel.mediaType = _param.mediaType || ApeConsts.MEDIA_TYPE_AUDIO;
packPduModel.timestamp = _param.timestamp || EngineUtils.creatTimestamp();
packPduModel.fromNodeId = _param.nodeId || GlobalConfig.nodeId;
packPduModel.userName = _param.userName || GlobalConfig.userName || "";
packPduModel.toNodeId = 0;
packPduModel.userRole = _param.userRole || GlobalConfig.userRole;
packPduModel.screenWidth = _param.screenWidth || GlobalConfig.screenWidth;
packPduModel.screenHeight = _param.screenHeight || GlobalConfig.screenHeight;
packPduModel.deviceType = _param.deviceType || GlobalConfig.deviceType;
packPduModel.optionJsonData = GlobalConfig.optionJsonData;
loger.log("packPdu->", packPduModel);
return packPduModel;
}
unPackPdu(owner, itemIdx, itemData) {
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let packChannelInfo = pdu['RCAudioChannelInfoPdu'].decode(itemData);
loger.log("unPackPdu->", packChannelInfo);
return packChannelInfo;
} catch (err) {
loger.log("unPackPdu error->itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
}
... ...
... ... @@ -14,609 +14,656 @@ import ShareApe from './ShareApe';
let loger = Loger.getLoger('VideoApe');
class VideoApe extends Ape {
constructor() {
super(
ApeConsts.VIDEO_SESSION_ID,
ApeConsts.VIDEO_SESSION_NAME,
ApeConsts.VIDEO_SESSION_TAG
);
this.mediaModule=new MediaModule();
this.mediaModule.MEDIA_OBJ_TABLE_ID=ApeConsts.VIDEO_OBJ_TABLE_ID;
this.mediaModule.mediaChannels={};
this.mediaModule.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
this.shareApe=new ShareApe();
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_SUCCESS,this.onPublishScreenShareSuccess.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_FAILE,this.onPublishScreenShareFaile.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_CLOSE,this.onPublishScreenShareClose.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_DISCONNECT,this.onPublishScreenShareDisconnect.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_CONNECTED,this.onPublishScreenShareConnected.bind(this));
this.shareApe.on( MessageTypes.PUBLISH_SCREEN_MOVIE_INFO_CHANGE,this.onPublishScreenMovieInfoChange.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_VIDEO_INFO_CHANGE,this.onPublishScreenVideoInfoChange.bind(this));
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
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);
// videoApe 监听视频控制消息,用户之间的消息传递
this.on(pdu.RCPDU_SEND_VIDEO_DATA_REQUEST, this.receiveVideoCommandHandler.bind(this));
}
//ape加入成功
onJoinChannelHandlerSuccess(){
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this.mediaModule.maxMediaChannel=GlobalConfig.maxVideoChannels;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getPlayVideoPath(_param) {
loger.log('getPlayVideoPath');
return this.mediaModule.getMediaPlayPath(_param);
}
//获取推流地址
getPublishVideoPath(_param) {
loger.log('获取推流地址->');
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//监课比较特殊,不占用课堂内的音视频路数,额外创建
if(GlobalConfig.userRole==ApeConsts.invisible){
let result=this.mediaModule.getMediaPublishPathForInVisible(_param);
this._emit( MessageTypes.VIDEO_GET_PUBLISH_PATH,result);
return result;
}
//非监课的身份,需要判断是否可以继续推流
//需要判断当前已经使用的流路数
let openChannel=0;
let allChannels= MediaModule.allMediaChannelsList;
for(let i in allChannels){
let channel=allChannels[i];
if(channel&&channel.status==ApeConsts.CHANNEL_STATUS_OPENING&&channel.userRole!=ApeConsts.invisible){
//正在开启的才计数,监课开启的不计算在内
openChannel++;
}
}
//如果已经开启的数量大于等于最大允许开启的数量,不允许再推流
if(openChannel>=GlobalConfig.maxMediaChannels){
loger.warn('不能再打开设备->当前开启的设备数量->',openChannel);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开设备,当前开启的设备数量"};
}
let result=this.mediaModule.getMediaPublishPath(_param);
this._emit( MessageTypes.VIDEO_GET_PUBLISH_PATH,result);
return result;
constructor() {
super(
ApeConsts.VIDEO_SESSION_ID,
ApeConsts.VIDEO_SESSION_NAME,
ApeConsts.VIDEO_SESSION_TAG
);
this.mediaModule = new MediaModule();
this.mediaModule.MEDIA_OBJ_TABLE_ID = ApeConsts.VIDEO_OBJ_TABLE_ID;
this.mediaModule.mediaChannels = {};
this.mediaModule.mediaType = ApeConsts.MEDIA_TYPE_VIDEO;
this.shareApe = new ShareApe();
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_SUCCESS, this.onPublishScreenShareSuccess.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_FAILE, this.onPublishScreenShareFaile.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_CLOSE, this.onPublishScreenShareClose.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_DISCONNECT, this.onPublishScreenShareDisconnect.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_SHARE_CONNECTED, this.onPublishScreenShareConnected.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_MOVIE_INFO_CHANGE, this.onPublishScreenMovieInfoChange.bind(this));
this.shareApe.on(MessageTypes.PUBLISH_SCREEN_VIDEO_INFO_CHANGE, this.onPublishScreenVideoInfoChange.bind(this));
// Ape Models
this.registerKey(this._session_id, this._session_name, this._session_tag, new ArrayBuffer);
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);
// videoApe 监听视频控制消息,用户之间的消息传递
this.on(pdu.RCPDU_SEND_VIDEO_DATA_REQUEST, this.receiveVideoCommandHandler.bind(this));
}
//ape加入成功
onJoinChannelHandlerSuccess() {
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this.mediaModule.maxMediaChannel = GlobalConfig.maxVideoChannels;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getPlayVideoPath(_param) {
loger.log('getPlayVideoPath');
return this.mediaModule.getMediaPlayPath(_param);
}
//获取推流地址
getPublishVideoPath(_param) {
loger.log('获取推流地址->');
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//获取当前所有频道信息
getAllChannelInfo(_param){
loger.log('获取当前所有频道信息->');
return this.mediaModule.getAllMediaChannelInfo();
//监课比较特殊,不占用课堂内的音视频路数,额外创建
if (GlobalConfig.userRole == ApeConsts.invisible) {
let result = this.mediaModule.getMediaPublishPathForInVisible(_param);
this._emit(MessageTypes.VIDEO_GET_PUBLISH_PATH, result);
return result;
}
//推流
publishVideo(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"已经断开连接!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (_param == null||_param.publishUrl == null)
{
loger.warn('推流->参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"参数错误!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
}
//根据推流的地址获取对应的频道信息
let needPublishChannelInfo=this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
if(needPublishChannelInfo==null){
loger.warn('推流->推流数据已经无效', _param);
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"推流数据已经无效!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
}
//判断当前是否还有空闲的channle
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn("推流->不能再打开更多的设备 ");
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"不能再打开更多的设备!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
}
//非监课的身份,需要判断是否可以继续推流
//需要判断当前已经使用的流路数
let openChannel = 0;
let allChannels = MediaModule.allMediaChannelsList;
for (let i in allChannels) {
let channel = allChannels[i];
if (channel && channel.status == ApeConsts.CHANNEL_STATUS_OPENING && channel.userRole != ApeConsts.invisible) {
//正在开启的才计数,监课开启的不计算在内
openChannel++;
}
}
//如果已经开启的数量大于等于最大允许开启的数量,不允许再推流
if (openChannel >= GlobalConfig.maxMediaChannels) {
loger.warn('不能再打开设备->当前开启的设备数量->', openChannel);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开设备,当前开启的设备数量"};
}
//判断当前的频道是否已经占用
if(this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)){
if(needPublishChannelInfo.nodeId==GlobalConfig.nodeId){
loger.warn(needPublishChannelInfo.channelId,"已经推送过消息,不需要再次推送");
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId});
return {"code": ApeConsts.RETURN_SUCCESS, "data":"已经推送过消息,不需要再次推送!","mediaId":needPublishChannelInfo.channelId};
}else {
loger.warn(needPublishChannelInfo.channelId,"频道已经被占用");
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data":"频道已经被占用!","mediaChannels":this.mediaModule.mediaChannels};
}
}
let result = this.mediaModule.getMediaPublishPath(_param);
this._emit(MessageTypes.VIDEO_GET_PUBLISH_PATH, result);
return result;
}
//获取当前所有频道信息
getAllChannelInfo(_param) {
loger.log('获取当前所有频道信息->');
return this.mediaModule.getAllMediaChannelInfo();
}
//推流
publishVideo(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接!", "mediaId": 0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
let channelInfo=this.mediaModule.getDefaultChannelInfo();
channelInfo.owner=GlobalConfig.nodeId;
channelInfo.status=ApeConsts.CHANNEL_STATUS_OPENING;
channelInfo.channelId=needPublishChannelInfo.channelId;
channelInfo.streamId=needPublishChannelInfo.streamId;//按规则拼接的流名称
channelInfo.timestamp=needPublishChannelInfo.timestamp;//时间戳
channelInfo.mediaType=ApeConsts.MEDIA_TYPE_VIDEO;
this.sendTableUpdateHandler(channelInfo);
if (_param == null || _param.publishUrl == null) {
loger.warn('推流->参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {"code": ApeConsts.RETURN_FAILED, "data": "参数错误!", "mediaId": 0});
return {"code": ApeConsts.RETURN_FAILED, "data": "参数错误"};
}
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId});
return {"code": ApeConsts.RETURN_SUCCESS, "data":"推流成功!","mediaId":needPublishChannelInfo.channelId};
//获取可选参数,转换为JSON字符串
try {
GlobalConfig.optionJsonData = JSON.stringify(_param.optionJsonData)||""
} catch (err) {
GlobalConfig.optionJsonData = "";
}
//停止推流,
stopPublishVideo(_param) {
loger.log('停止推流->',_param);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//根据推流的地址获取对应的频道信息
let needPublishChannelInfo = this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
if (needPublishChannelInfo == null) {
loger.warn('推流->推流数据已经无效', _param);
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "推流数据已经无效!",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "推流数据已经无效"};
}
//默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId=GlobalConfig.nodeId;
if(_param&&parseInt(_param.nodeId)>0){
nodeId=parseInt(_param.nodeId);
}
//判断当前是否还有空闲的channle
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn("推流->不能再打开更多的设备 ");
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "不能再打开更多的设备!",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels};
}
//默认为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);
}
//判断当前的频道是否已经占用
if (this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)) {
if (needPublishChannelInfo.nodeId == GlobalConfig.nodeId) {
loger.warn(needPublishChannelInfo.channelId, "已经推送过消息,不需要再次推送");
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_SUCCESS,
"data": "已经推送过消息,不需要再次推送!",
"mediaId": needPublishChannelInfo.channelId
});
return {
"code": ApeConsts.RETURN_SUCCESS,
"data": "已经推送过消息,不需要再次推送!",
"mediaId": needPublishChannelInfo.channelId
};
} else {
loger.warn(needPublishChannelInfo.channelId, "频道已经被占用");
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_FAILED,
"data": "频道已经被占用!",
"mediaId": 0
});
return {"code": ApeConsts.RETURN_FAILED, "data": "频道已经被占用!", "mediaChannels": this.mediaModule.mediaChannels};
}
}
//==========================屏幕共享=========================================================================
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.owner = GlobalConfig.nodeId;
channelInfo.status = ApeConsts.CHANNEL_STATUS_OPENING;
channelInfo.channelId = needPublishChannelInfo.channelId;
channelInfo.streamId = needPublishChannelInfo.streamId;//按规则拼接的流名称
channelInfo.timestamp = needPublishChannelInfo.timestamp;//时间戳
channelInfo.mediaType = ApeConsts.MEDIA_TYPE_VIDEO;
this.sendTableUpdateHandler(channelInfo);
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {
"code": ApeConsts.RETURN_SUCCESS,
"data": "推流成功!",
"mediaId": needPublishChannelInfo.channelId
});
return {"code": ApeConsts.RETURN_SUCCESS, "data": "推流成功!", "mediaId": needPublishChannelInfo.channelId};
}
//停止推流,
stopPublishVideo(_param) {
loger.log('停止推流->', _param);
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//屏幕共享连接打开
onPublishScreenShareFaile(){
loger.log('屏幕共享推流失败->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_FAILE);
//默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let nodeId = GlobalConfig.nodeId;
if (_param && parseInt(_param.nodeId) > 0) {
nodeId = parseInt(_param.nodeId);
}
//屏幕共享连接关闭
onPublishScreenShareClose(){
loger.log('屏幕共享推流关闭->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_CLOSE);
//默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
let releaseChannelId = 0;
if (_param && parseInt(_param.mediaId) > 0) {
releaseChannelId = parseInt(_param.mediaId);
}
//屏幕共享连接失败
onPublishScreenShareDisconnect(){
loger.log('屏幕共享服务器连接失败->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_DISCONNECT);
//释放channelId 的占用
if (releaseChannelId > 0) {
//第一种情况,释放nodeId占用的指定mediaId (channelId)
this._releaseChannelForNodeId(nodeId, releaseChannelId);
} else {
//第二种情况,释放nodeId占用的所有channelId
this._releaseNodeIdAllChannel(nodeId);
}
//屏幕共享连接失败
onPublishScreenShareConnected(){
loger.log('屏幕共享服务器连接成功->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_CONNECTED);
}
//==========================屏幕共享=========================================================================
//屏幕共享连接打开
onPublishScreenShareFaile() {
loger.log('屏幕共享推流失败->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_FAILE);
}
//屏幕共享连接关闭
onPublishScreenShareClose() {
loger.log('屏幕共享推流关闭->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_CLOSE);
}
//屏幕共享连接失败
onPublishScreenShareDisconnect() {
loger.log('屏幕共享服务器连接失败->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_DISCONNECT);
}
//屏幕共享连接失败
onPublishScreenShareConnected() {
loger.log('屏幕共享服务器连接成功->');
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_CONNECTED);
}
onPublishScreenMovieInfoChange(data) {
loger.log('屏幕共享MOVIE信息发生改变->');
this._emit(MessageTypes.PUBLISH_SCREEN_MOVIE_INFO_CHANGE, data);
}
onPublishScreenVideoInfoChange(data) {
loger.log('屏幕共享视频信息发生改变->');
this._emit(MessageTypes.PUBLISH_SCREEN_VIDEO_INFO_CHANGE, data);
}
//监听屏幕共享发布成功
onPublishScreenShareSuccess() {
loger.log('屏幕共享推流成功之后才能更新同步消息->');
//屏幕共享推流成功之后才能更新同步消息
let channelInfo = this.shareApe.getPublishChannelInfo();
this.sendTableUpdateHandler(channelInfo);
this._emit(MessageTypes.PUBLISH_SCREEN_SHARE_SUCCESS, {
"code": ApeConsts.RETURN_SUCCESS,
"data": "桌面共享推流!",
"mediaId": channelInfo.channelId
});
return {"code": ApeConsts.RETURN_SUCCESS, "data": "桌面共享推流!", "mediaId": channelInfo.channelId};
}
//桌面共享推流
publishScreenShare(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
this._emit(MessageTypes.VIDEO_PUBLISH_RESULT, {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接!", "mediaId": 0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
onPublishScreenMovieInfoChange(data){
loger.log('屏幕共享MOVIE信息发生改变->');
this._emit(MessageTypes.PUBLISH_SCREEN_MOVIE_INFO_CHANGE,data);
let publishType = 'flash';
if (_param && _param.type == 'live') {
publishType = 'live';
}
onPublishScreenVideoInfoChange(data){
loger.log('屏幕共享视频信息发生改变->');
this._emit(MessageTypes.PUBLISH_SCREEN_VIDEO_INFO_CHANGE,data);
//老师能开启屏幕共享
if (GlobalConfig.isHost) {
//获取屏幕共享推流的地址
let shareResult = this.mediaModule.getMediaPublishPathForScreenShare(this.shareApe.channelId, publishType);
shareResult.ip = _param.ip || "";//外部可以设置屏幕共享的IP
shareResult.port = _param.port || "";//外部可以设置屏幕共享的端口
this.shareApe.publish(shareResult);
}
//监听屏幕共享发布成功
onPublishScreenShareSuccess(){
loger.log('屏幕共享推流成功之后才能更新同步消息->');
//屏幕共享推流成功之后才能更新同步消息
let channelInfo=this.shareApe.getPublishChannelInfo();
this.sendTableUpdateHandler(channelInfo);
this._emit( MessageTypes.PUBLISH_SCREEN_SHARE_SUCCESS,{"code": ApeConsts.RETURN_SUCCESS, "data":"桌面共享推流!","mediaId":channelInfo.channelId});
return {"code": ApeConsts.RETURN_SUCCESS, "data":"桌面共享推流!","mediaId":channelInfo.channelId};
}
//桌面共享推流
publishScreenShare(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
this._emit( MessageTypes.VIDEO_PUBLISH_RESULT,{"code": ApeConsts.RETURN_FAILED, "data":"已经断开连接!","mediaId":0});
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
let publishType='flash';
if(_param&&_param.type=='live'){
publishType='live';
}
//老师能开启屏幕共享
if(GlobalConfig.isHost) {
//获取屏幕共享推流的地址
let shareResult = this.mediaModule.getMediaPublishPathForScreenShare(this.shareApe.channelId, publishType);
shareResult.ip=_param.ip||"";//外部可以设置屏幕共享的IP
shareResult.port=_param.port||"";//外部可以设置屏幕共享的端口
this.shareApe.publish(shareResult);
}
}
//停止桌面共享推流
stopPublishScreenShare(_param) {
loger.log('停止桌面共享推流->', _param);
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//只有老师能停止屏幕共享
if (GlobalConfig.isHost) {
let channelInfo = this.shareApe.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
this.sendTableUpdateHandler(channelInfo);
//停止桌面共享推流
stopPublishScreenShare(_param) {
loger.log('停止桌面共享推流->',_param);
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
//只有老师能停止屏幕共享
if(GlobalConfig.isHost){
let channelInfo=this.shareApe.getDefaultChannelInfo();
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
this.sendTableUpdateHandler(channelInfo);
this.shareApe.stopPublish();
}
this.shareApe.stopPublish();
}
//=============================屏幕共享 end=================================================
//释放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=this.mediaModule.getDefaultChannelInfo();
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId=channelId;
//=============================屏幕共享 end=================================================
this.sendTableUpdateHandler(channelInfo);
}else {
loger.warn(channelId,"不属于nodeId",nodeId,"不能释放",channelInfo);
}
}else {
loger.warn(nodeId,"要释放的channel不存在或者已经释放-->channelId",channelInfo);
}
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId){
if(!this.mcu.connected){
clearTimeout(this.releaseTimeId);
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
loger.log("释放nodeId占用的所有频道->",nodeId);
let openingChannelInfo = this.mediaModule.getOpeningMediaChannelForNodeId(nodeId);
if (openingChannelInfo.channelId== 0) {
loger.warn(nodeId,"没有占用channel不需要处理");
return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
}
//释放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=this.mediaModule.getDefaultChannelInfo();
channelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId=openingChannelInfo.channelId;
channelInfo.nodeId=openingChannelInfo.fromNodeId;//发送消息的人员nodeId
channelInfo.userRole=openingChannelInfo.userRole;
channelInfo.userName=openingChannelInfo.userName;
channelInfo.userId=openingChannelInfo.userId;
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId = channelId;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
this.releaseTimeId=setTimeout(function(){
loger.warn(nodeId,"检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this),800);
} else {
loger.warn(channelId, "不属于nodeId", nodeId, "不能释放", channelInfo);
}
} else {
loger.warn(nodeId, "要释放的channel不存在或者已经释放-->channelId", channelInfo);
}
}
//释放nodeId占用的所有频道
_releaseNodeIdAllChannel(nodeId) {
if (!this.mcu.connected) {
clearTimeout(this.releaseTimeId);
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
loger.log("释放nodeId占用的所有频道->", nodeId);
let openingChannelInfo = this.mediaModule.getOpeningMediaChannelForNodeId(nodeId);
if (openingChannelInfo.channelId == 0) {
loger.warn(nodeId, "没有占用channel不需要处理");
return {"code": ApeConsts.RETURN_FAILED, "data": "没有占用channel不需要处理"};
}
sendVideoBroadcastMsg(_param) {
if(!this.mcu.connected){
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('不能发送Video消息.McuClient还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"};
}
return {"code": ApeConsts.RETURN_FAILED, "data": "不能发送Video消息.McuClient还未初始化数据"};
}
if (_param == null) {
loger.warn('sendVideoCommandMsg失败,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendVideoCommandMsg失败,参数错误"};
}
// to, message
loger.log('视频模块广播消息.', _param);
if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn('视频模块广播消息->不能再打开更多的设备', _param);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备","mediaChannels":this.mediaModule.mediaChannels};
}
}
let channelInfo = this.mediaModule.getDefaultChannelInfo();
channelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
channelInfo.channelId = openingChannelInfo.channelId;
channelInfo.nodeId = openingChannelInfo.fromNodeId;//发送消息的人员nodeId
channelInfo.userRole = openingChannelInfo.userRole;
channelInfo.userName = openingChannelInfo.userName;
channelInfo.userId = openingChannelInfo.userId;
this.sendTableUpdateHandler(channelInfo);
//递归检查,800毫秒之后执行
this.releaseTimeId = setTimeout(function () {
loger.warn(nodeId, "检查频道是否占用");
this._releaseNodeIdAllChannel(nodeId);
}.bind(this), 800);
}
sendVideoBroadcastMsg(_param) {
if (!this.mcu.connected) {
loger.warn(GlobalConfig.getCurrentStatus());
return {"code": ApeConsts.RETURN_FAILED, "data": "已经断开连接"};
}
let videoSendPdu = new pdu['RCVideoSendDataRequestPdu'];
videoSendPdu.type = pdu.RCPDU_SEND_VIDEO_DATA_REQUEST;
videoSendPdu.isPublic = true;
if (this._classInfo === null || EngineUtils.isEmptyObject(this._classInfo)) {
loger.log('不能发送Video消息.McuClient还未初始化数据!');
if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN);
return {"code": 1, "data": "不能发送Video消息.McuClient还未初始化数据"};
}
return {"code": ApeConsts.RETURN_FAILED, "data": "不能发送Video消息.McuClient还未初始化数据"};
}
if (_param == null) {
loger.warn('sendVideoCommandMsg失败,参数错误', _param);
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return {"code": ApeConsts.RETURN_FAILED, "data": "sendVideoCommandMsg失败,参数错误"};
}
// to, message
loger.log('视频模块广播消息.', _param);
if (_param.actionType != null && _param.actionType == ApeConsts.MEDIA_ACTION_OPEN_CAMERA) {
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let freeChannel = this.mediaModule.getFreeMediaChannel();
if (freeChannel == 0) {
loger.warn('视频模块广播消息->不能再打开更多的设备', _param);
return {"code": ApeConsts.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels};
}
}
videoSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
videoSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人
videoSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
let videoSendPdu = new pdu['RCVideoSendDataRequestPdu'];
videoSendPdu.type = pdu.RCPDU_SEND_VIDEO_DATA_REQUEST;
videoSendPdu.isPublic = true;
let dataStr='';
try{
dataStr=JSON.stringify(_param.data);
}catch (err){
loger.warn('控制消息->JSON转换失败');
dataStr=_param.data;
}
videoSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + dataStr);//开头两个字会乱码
videoSendPdu.fromNodeId = GlobalConfig.nodeId;//发起人
videoSendPdu.toNodeId = parseInt(_param.toNodeId) || 0;//接收者,0就是所有人
videoSendPdu.actionType = parseInt(_param.actionType) || ApeConsts.MEDIA_ACTION_DEFAULT;
if (!videoSendPdu.isPublic && 0 != videoSendPdu.toNodeId) {
//发送给制定的人
this.send(videoSendPdu);
} else {
//发送给所有人
this.sendChatUniform(videoSendPdu);
}
return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
let dataStr = '';
try {
dataStr = JSON.stringify(_param.data);
} catch (err) {
loger.warn('控制消息->JSON转换失败');
dataStr = _param.data;
}
//发送到mcu同步(更新数据)
sendTableUpdateHandler(_channelInfo) {
//loger.log("video===sendTableUpdateHandler ");
let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);//let updateModelPdu=this.packPdu({},ApeConsts.VIDEO_OBJ_TABLE_ID+2);
if(updateModelPdu==null){
loger.warn("sendTableUpdateHandler error,updateModelPdu=null");
return;
}
videoSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + dataStr);//开头两个字会乱码
if (!videoSendPdu.isPublic && 0 != videoSendPdu.toNodeId) {
//发送给制定的人
this.send(videoSendPdu);
} else {
//发送给所有人
this.sendChatUniform(videoSendPdu);
}
return {"code": ApeConsts.RETURN_SUCCESS, "data": ""};
}
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = _channelInfo.channelId;//tableItemPdu.itemIdx=ApeConsts.VIDEO_OBJ_TABLE_ID+2;
tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
//发送到mcu同步(更新数据)
sendTableUpdateHandler(_channelInfo) {
//loger.log("video===sendTableUpdateHandler ");
let updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);//let updateModelPdu=this.packPdu({},ApeConsts.VIDEO_OBJ_TABLE_ID+2);
//insert
let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableInsertItemPdu.items.push(tableItemPdu);
if (updateModelPdu == null) {
loger.warn("sendTableUpdateHandler error,updateModelPdu=null");
return;
}
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.VIDEO_OBJ_TABLE_ID;//
updateObjPdu.subType = tableInsertItemPdu.type;
updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
let tableItemPdu = new pdu['RCRegistryTableItemPdu'];
tableItemPdu.itemIdx = _channelInfo.channelId;//tableItemPdu.itemIdx=ApeConsts.VIDEO_OBJ_TABLE_ID+2;
tableItemPdu.owner = _channelInfo.owner;//0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
//insert
let tableInsertItemPdu = new pdu['RCRegistryTableUpdateItemPdu'];
tableInsertItemPdu.type = pdu.RCPDU_REG_TABLE_UPDATE_PDU;//
tableInsertItemPdu.items.push(tableItemPdu);
let updateObjPdu = new pdu['RCRegistryUpdateObjPdu'];
updateObjPdu.objId = ApeConsts.VIDEO_OBJ_TABLE_ID;//
updateObjPdu.subType = tableInsertItemPdu.type;
updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
loger.log("发送更新VIDEO.itemIdx=" + tableItemPdu.itemIdx);
this.sendUniform(adapterPdu, true);
}
/////收到消息处理//////////////////////////////////////////////////
// 视频消息处理,内部处理,不需要告诉应用层
receiveVideoCommandHandler(_data) {
let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(_data);
if (videoReceivePdu == null) {
loger.warn("视频控制消息处理,收到的消息为null,不做处理");
return;
}
videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
let dataObj = {};
try {
dataObj = JSON.parse(videoReceivePdu.data);
} catch (err) {
loger.warn('控制消息->JSON转换失败');
dataObj = videoReceivePdu.data;
}
videoReceivePdu.data = dataObj;
//判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != GlobalConfig.nodeId) {
loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
} else {
loger.log('视频控制消息处理 .', videoReceivePdu);
this._emit(MessageTypes.VIDEO_BROADCAST, videoReceivePdu);
}
}
//同步
let adapterItemPdu = new pdu['RCAdapterItemPdu'];
adapterItemPdu.type = pdu.RCPDU_REG_UPDATE_OBJ;
adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
let adapterPdu = new pdu['RCAdapterPdu'];
adapterPdu.type = pdu.RCPDU_REG_ADAPTER;
adapterPdu.item.push(adapterItemPdu);
tableUpdateHandler(owner, itemIdx, itemData, seek) {
let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
loger.log("tableUpdateHandler->channel", itemIdx, 'mediaType', unpackChannelInfo.mediaType, 'status->', unpackChannelInfo.status, "seek->", seek);
loger.log("发送更新VIDEO.itemIdx=" + tableItemPdu.itemIdx);
this.sendUniform(adapterPdu, true);
//****很重要********
//如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
if (owner == 0) {
loger.log("释放占用的频道,channel", itemIdx);
unpackChannelInfo.status = ApeConsts.CHANNEL_STATUS_RELEASED;
unpackChannelInfo.streamId = "";
}
//屏幕共享的流不保存
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE && unpackChannelInfo.channelId > 0) {
this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
}
/////收到消息处理//////////////////////////////////////////////////
if (unpackChannelInfo && unpackChannelInfo.fromNodeId != GlobalConfig.nodeId) {
let receiveChannelInfo = {};
receiveChannelInfo.mediaId = unpackChannelInfo.channelId;
receiveChannelInfo.fromNodeId = unpackChannelInfo.fromNodeId;
receiveChannelInfo.userName = unpackChannelInfo.userName || "";
receiveChannelInfo.userRole = unpackChannelInfo.userRole || ApeConsts.normal;
receiveChannelInfo.mediaType = unpackChannelInfo.mediaType || ApeConsts.MEDIA_TYPE_DEFAULT;
receiveChannelInfo.screenWidth = unpackChannelInfo.screenWidth || GlobalConfig.screenWidth;
receiveChannelInfo.screenHeight = unpackChannelInfo.screenHeight || GlobalConfig.screenHeight;
receiveChannelInfo.deviceType = unpackChannelInfo.deviceType || 0;
receiveChannelInfo.optionJsonData = unpackChannelInfo.optionJsonData || "";
//消息不是自己同步的,需要处理
if (unpackChannelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
//正在推流
receiveChannelInfo.m3u8Url = "";
receiveChannelInfo.rtmpUrl = "";
receiveChannelInfo.replay = "";
receiveChannelInfo.seek = seek || 0;//这个是录制回放时使用的seek
let m3u8Stream = this.mediaModule.getMediaPlayPath({"type": "m3u8", "streamId": unpackChannelInfo.streamId});
let rtmpStream = this.mediaModule.getMediaPlayPath({"type": "rtmp", "streamId": unpackChannelInfo.streamId});
let replay = this.mediaModule.getMediaRecordPlaybackPath({
"type": "m3u8",
"streamId": unpackChannelInfo.streamId
});
if (m3u8Stream.code == 0) {
receiveChannelInfo.m3u8Url = m3u8Stream.playUrl;
}
if (rtmpStream.code == 0) {
receiveChannelInfo.rtmpUrl = rtmpStream.playUrl;
}
if (replay.code == 0) {
receiveChannelInfo.replay = replay.playUrl;
}
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
//广播播放视频的消息
loger.log("VIDEO_PLAY", receiveChannelInfo);
this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo);
} else {
//播放屏幕共享
loger.log("SCREEN_SHARE_PLAY", receiveChannelInfo);
this._emit(MessageTypes.SCREEN_SHARE_PLAY, receiveChannelInfo);
// 视频消息处理,内部处理,不需要告诉应用层
receiveVideoCommandHandler(_data) {
let videoReceivePdu = pdu['RCVideoSendDataRequestPdu'].decode(_data);
if (videoReceivePdu == null) {
loger.warn("视频控制消息处理,收到的消息为null,不做处理");
return;
}
videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2);//开头两个字会乱码
let dataObj= {};
try{
dataObj=JSON.parse(videoReceivePdu.data);
}catch (err){
loger.warn('控制消息->JSON转换失败');
dataObj= videoReceivePdu.data;
}
videoReceivePdu.data=dataObj;
//判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != GlobalConfig.nodeId) {
loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", GlobalConfig.nodeId);
} else {
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
//停止播放视频
loger.log("VIDEO_STOP", receiveChannelInfo);
this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo);
} else {
loger.log('视频控制消息处理 .',videoReceivePdu);
this._emit(MessageTypes.VIDEO_BROADCAST, videoReceivePdu);
}
//停止播放屏幕共享
if (unpackChannelInfo.channelId != 0) {
loger.log("SCREEN_SHARE_STOP", receiveChannelInfo);
this._emit(MessageTypes.SCREEN_SHARE_STOP, receiveChannelInfo);
} else {
loger.log("停止播放视频->channelId=0->不合法的id", receiveChannelInfo);
}
}
}
} else {
loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:");
loger.log(unpackChannelInfo);
if (unpackChannelInfo.status == ApeConsts.CHANNEL_STATUS_OPENING) {
GlobalConfig.openCamera = EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones = GlobalConfig.openCamera;
} else {
GlobalConfig.openCamera = 0;
GlobalConfig.openMicrophones = 0;
}
//更新用户的摄像头和麦克风状态
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
//非屏幕共享的情况下才更新状态
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
userName: GlobalConfig.userName,
userId: GlobalConfig.userId,
openCamera: GlobalConfig.openCamera,
openMicrophones: GlobalConfig.openMicrophones
});
}
}
if (unpackChannelInfo.mediaType != ApeConsts.MEDIA_TYPE_SHARE) {
//非屏幕共享情况的处理
MediaModule.allMediaChannelsList[itemIdx] = unpackChannelInfo;
console.log('MediaModule.allMediaChannelsList', MediaModule.allMediaChannelsList);
this._emit(MessageTypes.VIDEO_UPDATE, unpackChannelInfo);
}
tableUpdateHandler(owner, itemIdx, itemData,seek) {
let unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
loger.log("tableUpdateHandler->channel",itemIdx,'mediaType',unpackChannelInfo.mediaType,'status->',unpackChannelInfo.status,"seek->",seek);
//****很重要********
//如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
if(owner==0){
loger.log("释放占用的频道,channel",itemIdx);
unpackChannelInfo.status=ApeConsts.CHANNEL_STATUS_RELEASED;
unpackChannelInfo.streamId="";
}
//屏幕共享的流不保存
if(unpackChannelInfo.mediaType!=ApeConsts.MEDIA_TYPE_SHARE&&unpackChannelInfo.channelId>0){
this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
}
if(unpackChannelInfo&&unpackChannelInfo.fromNodeId!=GlobalConfig.nodeId){
let receiveChannelInfo={};
receiveChannelInfo.mediaId=unpackChannelInfo.channelId;
receiveChannelInfo.fromNodeId=unpackChannelInfo.fromNodeId;
receiveChannelInfo.userName=unpackChannelInfo.userName||"";
receiveChannelInfo.userRole=unpackChannelInfo.userRole||ApeConsts.normal;
receiveChannelInfo.mediaType=unpackChannelInfo.mediaType||ApeConsts.MEDIA_TYPE_DEFAULT;
receiveChannelInfo.screenWidth=unpackChannelInfo.screenWidth||GlobalConfig.screenWidth;
receiveChannelInfo.screenHeight=unpackChannelInfo.screenHeight||GlobalConfig.screenHeight;
receiveChannelInfo.deviceType=unpackChannelInfo.deviceType||0;
receiveChannelInfo.optionJsonData=unpackChannelInfo.optionJsonData||"";
//消息不是自己同步的,需要处理
if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
//正在推流
receiveChannelInfo.m3u8Url="";
receiveChannelInfo.rtmpUrl="";
receiveChannelInfo.replay="";
receiveChannelInfo.seek=seek||0;//这个是录制回放时使用的seek
let m3u8Stream=this.mediaModule.getMediaPlayPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
let rtmpStream=this.mediaModule.getMediaPlayPath({"type":"rtmp","streamId": unpackChannelInfo.streamId});
let replay=this.mediaModule.getMediaRecordPlaybackPath({"type":"m3u8","streamId": unpackChannelInfo.streamId});
if(m3u8Stream.code==0){
receiveChannelInfo.m3u8Url=m3u8Stream.playUrl;
}
if(rtmpStream.code==0){
receiveChannelInfo.rtmpUrl=rtmpStream.playUrl;
}
if(replay.code==0){
receiveChannelInfo.replay=replay.playUrl;
}
if(unpackChannelInfo.mediaType!=ApeConsts.MEDIA_TYPE_SHARE){
//广播播放视频的消息
loger.log("VIDEO_PLAY",receiveChannelInfo);
this._emit(MessageTypes.VIDEO_PLAY, receiveChannelInfo);
}else{
//播放屏幕共享
loger.log("SCREEN_SHARE_PLAY",receiveChannelInfo);
this._emit(MessageTypes.SCREEN_SHARE_PLAY, receiveChannelInfo);
}
}else {
if(unpackChannelInfo.mediaType!=ApeConsts.MEDIA_TYPE_SHARE){
//停止播放视频
loger.log("VIDEO_STOP",receiveChannelInfo);
this._emit(MessageTypes.VIDEO_STOP, receiveChannelInfo);
}else{
//停止播放屏幕共享
if(unpackChannelInfo.channelId!=0){
loger.log("SCREEN_SHARE_STOP", receiveChannelInfo);
this._emit(MessageTypes.SCREEN_SHARE_STOP, receiveChannelInfo);
}else {
loger.log("停止播放视频->channelId=0->不合法的id", receiveChannelInfo);
}
}
}
}else {
loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:");
loger.log(unpackChannelInfo);
if(unpackChannelInfo.status==ApeConsts.CHANNEL_STATUS_OPENING){
GlobalConfig.openCamera=EngineUtils.creatTimestamp();
GlobalConfig.openMicrophones=GlobalConfig.openCamera;
}else {
GlobalConfig.openCamera=0;
GlobalConfig.openMicrophones=0;
}
//更新用户的摄像头和麦克风状态
if(unpackChannelInfo.mediaType!=ApeConsts.MEDIA_TYPE_SHARE) {
//非屏幕共享的情况下才更新状态
this._emit(MessageTypes.USER_DEVICE_STATUS_CHAANGE, {
nodeId: GlobalConfig.nodeId,
userRole: GlobalConfig.userRole,
userName: GlobalConfig.userName,
userId: GlobalConfig.userId,
openCamera: GlobalConfig.openCamera,
openMicrophones: GlobalConfig.openMicrophones
});
}
}
}
if(unpackChannelInfo.mediaType!=ApeConsts.MEDIA_TYPE_SHARE){
//非屏幕共享情况的处理
MediaModule.allMediaChannelsList[itemIdx]=unpackChannelInfo;
console.log('MediaModule.allMediaChannelsList',MediaModule.allMediaChannelsList);
this._emit(MessageTypes.VIDEO_UPDATE, unpackChannelInfo);
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param) {
console.warn("录制状态发送改变->更新当前的状态->", this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels) {
let channelInfo = this.mediaModule.mediaChannels[i];
if (channelInfo) {
if (channelInfo.status == ApeConsts.CHANNEL_STATUS_RELEASED) {
channelInfo.owner = 0;
} else {
channelInfo.owner = channelInfo.fromNodeId;
}
this.sendTableUpdateHandler(channelInfo);
}
}
//更新媒体文件模块的录制信息,每次开启录制的时候需要把当前媒体文件的信息更新一次
updaterRecordApeStatus(_param){
console.warn("录制状态发送改变->更新当前的状态->",this.mediaModule.mediaChannels);
for (let i in this.mediaModule.mediaChannels){
let channelInfo=this.mediaModule.mediaChannels[i];
if(channelInfo){
if(channelInfo.status==ApeConsts.CHANNEL_STATUS_RELEASED){
channelInfo.owner=0;
}else {
channelInfo.owner=channelInfo.fromNodeId;
}
this.sendTableUpdateHandler(channelInfo);
}
}
}
//清除当前模块的数据
clearData() {
loger.log("clearData->");
MediaModule.allMediaChannelsList = {};
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
//清除当前模块的数据
clearData(){
loger.log("clearData->");
MediaModule.allMediaChannelsList={};
//判断type类型,根据type设置不同的参数
let packPduModel = new pdu['RCVideoChannelInfoPdu'];
packPduModel.status = _param.status || ApeConsts.CHANNEL_STATUS_RELEASED;
packPduModel.channelId = _itemIdx;
packPduModel.streamId = _param.streamId || "";
packPduModel.siteId = _param.siteId || GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId = parseInt(_param.classId) || parseInt(GlobalConfig.classId);
packPduModel.userId = _param.userId || "0";
packPduModel.mediaType = _param.mediaType || ApeConsts.MEDIA_TYPE_VIDEO;
packPduModel.timestamp = _param.timestamp || 0;
packPduModel.fromNodeId = _param.nodeId || GlobalConfig.nodeId;
packPduModel.userName = _param.userName || GlobalConfig.userName;
packPduModel.toNodeId = 0;
packPduModel.userRole = _param.userRole || GlobalConfig.userRole;
packPduModel.screenWidth = _param.screenWidth || GlobalConfig.screenWidth;
packPduModel.screenHeight = _param.screenHeight || GlobalConfig.screenHeight;
packPduModel.deviceType = _param.deviceType || GlobalConfig.deviceType;
packPduModel.optionJsonData = GlobalConfig.optionJsonData;
loger.log('packPdu->', packPduModel);
return packPduModel;
}
unPackPdu(owner, itemIdx, itemData) {
loger.log("unPackPdu->owner:", owner, "itemIdx->", itemIdx);
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
///////数据的封包和解包/////////////////////////////////////////
packPdu(_param, _itemIdx) {
//验证坐标点集合数组是否合法
if (_param == null || _itemIdx == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
//判断type类型,根据type设置不同的参数
let packPduModel = new pdu['RCVideoChannelInfoPdu'];
packPduModel.status = _param.status||ApeConsts.CHANNEL_STATUS_RELEASED;
packPduModel.channelId = _itemIdx;
packPduModel.streamId = _param.streamId||"";
packPduModel.siteId=_param.siteId||GlobalConfig.siteId;//GlobalConfig.siteId;
packPduModel.classId =parseInt(_param.classId)||parseInt(GlobalConfig.classId);
packPduModel.userId =_param.userId||"0";
packPduModel.mediaType =_param.mediaType|| ApeConsts.MEDIA_TYPE_VIDEO;
packPduModel.timestamp =_param.timestamp||0;
packPduModel.fromNodeId = _param.nodeId||GlobalConfig.nodeId;
packPduModel.userName=_param.userName||GlobalConfig.userName;
packPduModel.toNodeId = 0;
packPduModel.userRole=_param.userRole||GlobalConfig.userRole;
packPduModel.screenWidth=_param.screenWidth||GlobalConfig.screenWidth;
packPduModel.screenHeight=_param.screenHeight||GlobalConfig.screenHeight;
packPduModel.deviceType=_param.deviceType||GlobalConfig.deviceType;
packPduModel.optionJsonData=_param.optionJsonData||GlobalConfig.optionJsonData;
loger.log('packPdu->',packPduModel);
return packPduModel;
}
unPackPdu(owner, itemIdx, itemData) {
loger.log("unPackPdu->owner:",owner,"itemIdx->",itemIdx);
if (owner == null || itemIdx == null || itemData == null) {
this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
return null;
}
try {
let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData);
loger.log(videoChannelInfo);
return videoChannelInfo;
} catch (err) {
loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
try {
let videoChannelInfo = pdu['RCVideoChannelInfoPdu'].decode(itemData);
loger.log(videoChannelInfo);
return videoChannelInfo;
} catch (err) {
loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
}
return null;
}
}
export default VideoApe;
... ...