Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
李勇
/
McuClient
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
李勇
2017-02-23 10:45:49 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
66a7623819550bef4ac8a443c88e3a405b7055c4
66a76238
2 parents
4973ecf3
14b20f50
Merge branch 'mcuClientBranch'
隐藏空白字符变更
内嵌
并排对比
正在显示
11 个修改的文件
包含
723 行增加
和
401 行删除
src/EngineEntrance.js
src/GlobalConfig.js
src/McuClientEngine.js
src/MessageTypes.js
src/apes/ApeConsts.js
src/apes/AudioApe.js
src/apes/ConferApe.js
src/apes/DocApe.js
src/apes/MediaModule.js
src/apes/VideoApe.js
src/pdus/pro.js
src/EngineEntrance.js
查看文件 @
66a7623
...
...
@@ -11,6 +11,7 @@ import Loger from 'Loger';
import
ConferApe
from
'apes/ConferApe'
;
import
ChatApe
from
'apes/ChatApe'
;
import
VideoApe
from
'apes/VideoApe'
;
import
AudioApe
from
'apes/AudioApe'
;
import
DocApe
from
'apes/DocApe'
;
import
WhiteBoardApe
from
'apes/WhiteBoardApe'
;
import
EngineUtils
from
"EngineUtils"
;
...
...
@@ -29,6 +30,7 @@ let _mcu ;
let
_confer_ape
;
let
_chat_ape
;
let
_video_ape
;
let
_audio_ape
;
let
_doc_ape
;
let
_whiteboard_ape
;
...
...
@@ -68,7 +70,7 @@ export default class MessageEntrance extends Emiter {
// 底层MCU消息层
_mcu
=
Mcu
;
_mcu
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
_mcu
.
on
(
MessageTypes
.
CLASS_JOIN_SUCCESS
,
this
.
_
j
oinClassSuccessHandler
.
bind
(
this
));
//加入MCU会议完成
_mcu
.
on
(
MessageTypes
.
CLASS_JOIN_SUCCESS
,
this
.
_
mcuJ
oinClassSuccessHandler
.
bind
(
this
));
//加入MCU会议完成
// 注册所有应用Ape
...
...
@@ -87,11 +89,14 @@ export default class MessageEntrance extends Emiter {
_video_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
_video_ape
.
on
(
MessageTypes
.
VIDEO_UPDATE
,
this
.
videoUpdate
.
bind
(
this
));
_audio_ape
=
new
AudioApe
();
_audio_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
_audio_ape
.
on
(
MessageTypes
.
AUDIO_UPDATE
,
this
.
audioUpdate
.
bind
(
this
));
_whiteboard_ape
=
new
WhiteBoardApe
();
_whiteboard_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
//_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
_doc_ape
=
new
DocApe
();
_doc_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
_doc_ape
.
on
(
MessageTypes
.
DOC_UPDATE
,
this
.
docUpdateHandler
.
bind
(
this
));
...
...
@@ -115,13 +120,20 @@ export default class MessageEntrance extends Emiter {
this
.
sendChatMsg
=
this
.
_sendChatMsg
;
//videoApe
this
.
getPlayVideoPath
=
this
.
_getPlayVideoPath
;
this
.
getPublishVideoPath
=
this
.
_getPublishVideoPath
;
this
.
getVideoPlayPath
=
this
.
_getPlayVideoPath
;
this
.
getVideoPublishPath
=
this
.
_getPublishVideoPath
;
this
.
publishVideo
=
this
.
_publishVideo
;
this
.
stopPublishVideo
=
this
.
_stopPublishVideo
;
this
.
sendVideo
Command
Msg
=
this
.
sendVideoCommandMsg
;
this
.
sendVideo
Broadcast
Msg
=
this
.
sendVideoCommandMsg
;
//audioApe
this
.
getAudioPlayPath
=
this
.
_getPlayAudioPath
;
this
.
getAudioPublishPath
=
this
.
_getPublishAudioPath
;
this
.
publishAudio
=
this
.
_publishAudio
;
this
.
stopPublishAudio
=
this
.
_stopPublishAudio
;
this
.
sendAudioBroadcastMsg
=
this
.
sendAudioCommandMsg
;
//whiteBoradApe
this
.
sendInsertAnnotaion
=
this
.
_sendInsertAnnotaion
;
//this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
...
...
@@ -174,6 +186,7 @@ export default class MessageEntrance extends Emiter {
_onClassStatusInfoChange
(
_param
)
{
this
.
_sassSaveClassStatusInfo
();
}
//有人员离开
_onClassDeleteRoster
(
_data
){
//{"nodeId":nodeId}
...
...
@@ -184,18 +197,25 @@ export default class MessageEntrance extends Emiter {
if
(
_video_ape
){
_video_ape
.
stopPublishVideo
(
_data
);
}
if
(
_audio_ape
){
_audio_ape
.
stopPublishAudio
(
_data
);
}
}
}
//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
//的占用状态导致,对于这种情况,需要释放掉
_onClassNonentityRoster
(
_param
){
if
(
_param
==
null
||
_param
.
fromN
odeId
==
null
){
if
(
_param
==
null
||
_param
.
n
odeId
==
null
){
loger
.
warn
(
"onClassNonentityRoster.参数错误"
)
return
;
}
let
data
=
{
"nodeId"
:
_param
.
nodeId
};
if
(
_video_ape
){
_video_ape
.
stopPublishVideo
({
"nodeId"
:
_param
.
fromNodeId
});
_video_ape
.
stopPublishVideo
(
data
);
}
if
(
_audio_ape
){
_audio_ape
.
stopPublishAudio
(
data
);
}
}
...
...
@@ -219,12 +239,14 @@ export default class MessageEntrance extends Emiter {
return
;
}
loger
.
log
(
'init'
,
_param
);
//保存参数
GlobalConfig
.
classId
=
parseInt
(
_param
.
classId
);
GlobalConfig
.
portal
=
_param
.
portal
;
GlobalConfig
.
userRole
=
_param
.
userRole
||
ApeConsts
.
normal
;
GlobalConfig
.
userId
=
_param
.
userId
||
"0"
;
GlobalConfig
.
userName
=
_param
.
userName
||
""
;
//获取课堂校验信息
if
(
_sass
)
{
_sass
.
getJoinParams
(
GlobalConfig
.
getClassInfo
());
...
...
@@ -253,7 +275,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig
.
password
=
_param
.
password
||
""
;
GlobalConfig
.
hasCamera
=
(
typeof
_param
.
hasCamera
==
"boolean"
)?
_param
.
hasCamera
:
false
;
GlobalConfig
.
hasMicrophone
=
(
typeof
_param
.
hasMicrophone
==
"boolean"
)?
_param
.
hasMicrophone
:
false
;
debugger
;
//
debugger;
//开始校验
if
(
_sass
)
{
_sass
.
passwordAndMd5Checking
(
GlobalConfig
.
getClassInfo
());
...
...
@@ -269,13 +291,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig
.
siteId
=
_data
.
siteId
||
""
;
GlobalConfig
.
classType
=
_data
.
meetingType
||
0
;
/*//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
if (GlobalConfig.userRole == "host") {
GlobalConfig.passwordRequired = true;
} else {
GlobalConfig.passwordRequired = _data.passwordRequired || false;
}
*/
//host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
GlobalConfig
.
passwordRequired
=
_data
.
passwordRequired
||
false
;
//md5验证的时候需要Sass返回的值,不能更改
loger
.
log
(
'SASS平台获取入会验证信息成功.'
);
...
...
@@ -303,7 +319,7 @@ export default class MessageEntrance extends Emiter {
}
}
// 通过SASS平台验证
// 通过SASS平台验证
(密码和MD5)
_sassJoinSuccessHandler
(
_data
)
{
//返回值
/* flag 数值型 无 True:成功
...
...
@@ -330,42 +346,55 @@ export default class MessageEntrance extends Emiter {
"maxAudioChannels": 1,
"h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"
}*/
if
(
_data
.
h5_mcu_list
)
{
//MCU地址默认使用第一个
let
server
=
_data
.
h5_mcu_list
.
split
(
";"
)[
0
];
GlobalConfig
.
MCUServerIP
=
server
.
split
(
":"
)[
0
];
GlobalConfig
.
MCUServerPort
=
server
.
split
(
":"
)[
1
];
}
//视频推流播流地址
if
(
_data
.
ms
)
{
//MS地址默认使用第一个
let
server
=
_data
.
ms
.
split
(
";"
)[
0
];
GlobalConfig
.
MSServerIP
=
server
.
split
(
":"
)[
0
];
GlobalConfig
.
MSServerPort
=
server
.
split
(
":"
)[
1
];
}
//m3u8播流地址
if
(
_data
.
rs
){
//RS地址默认使用第一个
let
server
=
_data
.
rs
.
split
(
";"
)[
0
];
GlobalConfig
.
RSServerIP
=
server
.
split
(
":"
)[
0
];
GlobalConfig
.
RSServerPort
=
server
.
split
(
":"
)[
1
];
}
GlobalConfig
.
docServer
=
_data
.
doc
;
GlobalConfig
.
h5_mcu_list
=
_data
.
h5_mcu_list
;
GlobalConfig
.
h5Module
=
_data
.
h5Module
;
GlobalConfig
.
mcu
=
_data
.
mcu
;
GlobalConfig
.
ms
=
_data
.
ms
;
GlobalConfig
.
record
=
_data
.
record
;
GlobalConfig
.
rs
=
_data
.
rs
;
GlobalConfig
.
maxVideoChannels
=
_data
.
maxVideoChannels
;
GlobalConfig
.
maxAudioChannels
=
_data
.
maxAudioChannels
;
GlobalConfig
.
maxMediaChannels
=
_data
.
maxVideoChannels
+
_data
.
maxAudioChannels
;
/*
if (_data.h5_mcu_list) {
//MCU地址默认使用第一个
let server = _data.h5_mcu_list.split(";")[0];
GlobalConfig.MCUServerIP = server.split(":")[0];
GlobalConfig.MCUServerPort = server.split(":")[1];
}
//视频推流播流地址
if (_data.ms) {
//MS地址默认使用第一个
let server = _data.ms.split(";")[0];
GlobalConfig.MSServerIP = server.split(":")[0];
GlobalConfig.MSServerPort = server.split(":")[1];
}
//m3u8播流地址
if(_data.rs){
//RS地址默认使用第一个
let server = _data.rs.split(";")[0];
GlobalConfig.RSServerIP = server.split(":")[0];
GlobalConfig.RSServerPort = server.split(":")[1];
}
GlobalConfig.docServer = _data.doc;
GlobalConfig.h5_mcu_list = _data.h5_mcu_list;
GlobalConfig.h5Module = _data.h5Module;
GlobalConfig.mcu = _data.mcu;
GlobalConfig.ms = _data.ms;
GlobalConfig.record = _data.record;
GlobalConfig.rs = _data.rs;
GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
*/
/*
//这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃
//获取会议基本信息
if (_sass) {
_sass.getClassDetail();
}
*/
//获取会议最完整的数据
if
(
_sass
)
{
_sass
.
getClass
Detail
();
//会议基本信息
_sass
.
getClass
Param
();
}
}
...
...
@@ -398,7 +427,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig
.
classBeginTime
=
_data
.
beginTime
||
""
;
GlobalConfig
.
classEndTime
=
_data
.
endTime
||
""
;
//获取会议所有信息和以前保存的会议状态信息
//获取会议所有信息和以前保存的会议状态信息
(最全的信息)
if
(
_sass
)
{
_sass
.
getClassParam
();
}
...
...
@@ -411,8 +440,15 @@ export default class MessageEntrance extends Emiter {
// console.log(_data);
//包含整个会议最全的信息,储存数据
if
(
_data
)
{
GlobalConfig
.
className
=
_data
.
meetingName
||
""
;
GlobalConfig
.
classBeginTime
=
_data
.
beginTime
||
""
;
GlobalConfig
.
classEndTime
=
_data
.
endTime
||
""
;
GlobalConfig
.
maxVideoChannels
=
_data
.
maxVideoChannels
;
GlobalConfig
.
maxAudioChannels
=
_data
.
maxAudioChannels
;
GlobalConfig
.
setDocListPrepare
(
_data
.
docListPrepare
);
//提前上传的文档列表
GlobalConfig
.
set
DocRecordList
(
_data
.
docRecordList
);
//录制回放地址??
GlobalConfig
.
set
RecordList
(
_data
.
recordList
);
//录制回放地址
GlobalConfig
.
setDocList
(
_data
.
docList
);
//文档地址
GlobalConfig
.
setMsList
(
_data
.
msList
);
//推流播流服务器地址
GlobalConfig
.
setRsList
(
_data
.
rsList
);
//播放m3u8格式的地址
...
...
@@ -421,22 +457,45 @@ export default class MessageEntrance extends Emiter {
GlobalConfig
.
setMusicListPrepare
(
_data
.
musicListPrepare
);
//提前上传的声音文件列表
if
(
_data
.
mcuList
)
{
//MCU地址默认使用第一个
GlobalConfig
.
MCUServerIP
=
_data
.
mcuList
[
0
].
ip
||
""
;
GlobalConfig
.
MCUServerPort
=
_data
.
mcuList
[
0
].
port
||
""
;
}
//视频推流播流地址
if
(
_data
.
msList
)
{
//MS地址默认使用第一个
GlobalConfig
.
MSServerIP
=
_data
.
msList
[
0
].
ip
||
""
;
GlobalConfig
.
MSServerPort
=
_data
.
msList
[
0
].
port
||
""
;
}
//m3u8播流地址
if
(
_data
.
rsList
){
//RS地址默认使用第一个
GlobalConfig
.
RSServerIP
=
_data
.
rsList
[
0
].
ip
||
""
;
GlobalConfig
.
RSServerPort
=
_data
.
rsList
[
0
].
port
||
""
;
}
//文档地址
if
(
_data
.
docList
){
//doc地址默认使用第一个
GlobalConfig
.
DOCServerIP
=
_data
.
docList
[
0
].
ip
||
""
;
GlobalConfig
.
DOCServerPort
=
_data
.
docList
[
0
].
port
||
""
;
}
//record
if
(
_data
.
recordList
){
//地址默认使用第一个
GlobalConfig
.
RecordServerIP
=
_data
.
recordList
[
0
].
ip
||
""
;
GlobalConfig
.
RecordServerPort
=
_data
.
recordList
[
0
].
port
||
""
;
}
}
if
(
_data
.
currentInfo
)
{
//根据从Sass获取的数据信息,同步最后一次保存的会议状态信息
loger
.
log
(
"同步最后一次保存过的会议状态信息"
);
/*//解析BASE64的数据
loger.log("11111111111111111111111111111111");
console.log(GlobalConfig.classStatusInfo);
//已经保存过会议状态信息,读取之前的数据
let _classStatusInfo=EngineUtils.objectFromBase64(_data.currentInfo);
loger.log("classStatusInfo",_classStatusInfo);
GlobalConfig.classStatusInfo=_classStatusInfo;
loger.log("2222222222222222222222222");
console.log(GlobalConfig.classStatusInfo);*/
//console.log(_data.currentInfo);
GlobalConfig
.
setClassStatusInfo
(
_data
.
currentInfo
);
console
.
log
(
GlobalConfig
.
classStatusInfo
)
}
else
{
...
...
@@ -450,11 +509,6 @@ export default class MessageEntrance extends Emiter {
//保存会议状态信息
_sassSaveClassStatusInfo
()
{
if
(
GlobalConfig
.
isHost
)
{
//用get保存数据,数据内容需要转为BASE64
//let _classStatusInfo=EngineUtils.objectToBase64(GlobalConfig.classStatusInfo);
//loger.log("保存会议状态信息",_classStatusInfo);
//_sass.saveClassStatusInfo({"classStatusInfo":_classStatusInfo});//保存会议状态信息
//只有加入会议之后才能保存数据
if
(
GlobalConfig
.
getCurrentStatus
().
code
==
GlobalConfig
.
statusCode_2
.
code
)
{
//POST 保存数据
...
...
@@ -481,7 +535,7 @@ export default class MessageEntrance extends Emiter {
}
// MCU 会议成功
_
j
oinClassSuccessHandler
(
_data
)
{
_
mcuJ
oinClassSuccessHandler
(
_data
)
{
loger
.
log
(
'MCU 会议成功.'
);
GlobalConfig
.
setCurrentStatus
(
GlobalConfig
.
statusCode_2
);
...
...
@@ -490,17 +544,15 @@ export default class MessageEntrance extends Emiter {
//返回给客户端初始化成功的数据
let
initSuccessCallBackData
=
{};
//GlobalConfig.MCUServerIP=_data.MCUServerIP;
// GlobalConfig.MCUServerPort=_data.MCUServerPort;
initSuccessCallBackData
.
DOCServerIP
=
GlobalConfig
.
DOCServerIP
;
initSuccessCallBackData
.
DOCServerPort
=
GlobalConfig
.
DOCServerPort
;
initSuccessCallBackData
.
docServer
=
GlobalConfig
.
docServer
;
//文档服务器地址
initSuccessCallBackData
.
classId
=
GlobalConfig
.
classId
;
initSuccessCallBackData
.
className
=
GlobalConfig
.
className
;
initSuccessCallBackData
.
h5Module
=
GlobalConfig
.
h5Module
;
initSuccessCallBackData
.
isHost
=
GlobalConfig
.
isHost
;
initSuccessCallBackData
.
maxAudioChannels
=
GlobalConfig
.
maxAudioChannels
;
initSuccessCallBackData
.
maxVideoChannels
=
GlobalConfig
.
maxVideoChannels
;
initSuccessCallBackData
.
maxMediaChannels
=
GlobalConfig
.
maxMediaChannels
;
initSuccessCallBackData
.
mcuDelay
=
GlobalConfig
.
mcuDelay
;
initSuccessCallBackData
.
msType
=
GlobalConfig
.
msType
;
...
...
@@ -526,79 +578,6 @@ export default class MessageEntrance extends Emiter {
loger
.
log
(
'加入会议成功'
,
initSuccessCallBackData
);
_joinClassSuccessCallBackFun
(
initSuccessCallBackData
);
}
//loger.log('MCU 会议成功.');
//GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//if(_sass){
// _sass.getClassDetail();//会议信息
// _sass.getClassParam();//会议参数大全
//}
//
////储存数据
//GlobalConfig.MCUServerIP=_data.MCUServerIP;
//GlobalConfig.MCUServerPort=_data.MCUServerPort;
//GlobalConfig.classId=_data.classId;
//GlobalConfig.h5Module=_data.h5Module;
//GlobalConfig.maxAudioChannels=_data.maxAudioChannels;
//GlobalConfig.maxVideoChannels=_data.maxVideoChannels;
//GlobalConfig.maxMediaChannels=_data.maxMediaChannels;
//GlobalConfig.mcuClassInfo=_data.mcuClassInfo;
//GlobalConfig.mcuDelay=_data.mcuDelay;
//GlobalConfig.md5=_data.md5;
//GlobalConfig.msType=_data.msType;
//GlobalConfig.nodeId=_data.nodeId;
//GlobalConfig.password=_data.password;
//GlobalConfig.portal=_data.portal;
//GlobalConfig.role=_data.role;
//GlobalConfig.siteId=_data.siteId;
//GlobalConfig.topNodeID=_data.topNodeID;
//GlobalConfig.userId=_data.userId;
//GlobalConfig.userName=_data.userName;
//GlobalConfig.userRole=_data.userRole;
//GlobalConfig.userType=_data.userType;
//
////返回给客户数据
//if(_joinClassSuccessCallBackFun){
// //返回给客户端初始化成功的数据
// let initSuccessCallBackData={};
//
// //GlobalConfig.MCUServerIP=_data.MCUServerIP;
// // GlobalConfig.MCUServerPort=_data.MCUServerPort;
//
// initSuccessCallBackData.docServer=GlobalConfig.docServer;//文档服务器地址
// initSuccessCallBackData.classId=GlobalConfig.classId;
// initSuccessCallBackData.className=GlobalConfig.className;
// initSuccessCallBackData.h5Module=GlobalConfig.h5Module;
// initSuccessCallBackData.isHost=GlobalConfig.isHost;
// initSuccessCallBackData.maxAudioChannels=GlobalConfig.maxAudioChannels;
// initSuccessCallBackData.maxVideoChannels=GlobalConfig.maxVideoChannels;
// initSuccessCallBackData.maxMediaChannels=GlobalConfig.maxMediaChannels;
// initSuccessCallBackData.mcuDelay=GlobalConfig.mcuDelay;
//
// initSuccessCallBackData.msType=GlobalConfig.msType;
// initSuccessCallBackData.nodeId=GlobalConfig.nodeId;
// initSuccessCallBackData.password=GlobalConfig.password;
// initSuccessCallBackData.passwordRequired=GlobalConfig.passwordRequired;// 老师的默认是true
// //GlobalConfig.passwordRequired 老师的默认是true
// //GlobalConfig.portal=_data.portal;
// initSuccessCallBackData.role=GlobalConfig.role;
// initSuccessCallBackData.siteId=GlobalConfig.siteId;
// initSuccessCallBackData.topNodeID=GlobalConfig.topNodeID;
// initSuccessCallBackData.userId=GlobalConfig.userId;
// initSuccessCallBackData.userName=GlobalConfig.userName;
// initSuccessCallBackData.userRole=GlobalConfig.userRole;
// initSuccessCallBackData.userType=GlobalConfig.userType;
//
// initSuccessCallBackData.siteId=GlobalConfig.siteId;
// initSuccessCallBackData.classId=GlobalConfig.classId;
// initSuccessCallBackData.userRole=GlobalConfig.userRole;
// initSuccessCallBackData.userId=GlobalConfig.userId;
// initSuccessCallBackData.passwordRequired=GlobalConfig.passwordRequired;
// initSuccessCallBackData.classType=GlobalConfig.classType||ApeConsts.CLASS_TYPE_INTERACT;
// loger.log('加入会议成功',initSuccessCallBackData);
// _joinClassSuccessCallBackFun(initSuccessCallBackData);
//}
}
//Sass删除文档数据
...
...
@@ -653,6 +632,9 @@ export default class MessageEntrance extends Emiter {
if
(
_video_ape
){
_video_ape
.
stopPublishVideo
();
}
if
(
_audio_ape
){
_audio_ape
.
stopPublishAudio
();
}
//离开会议
if
(
_confer_ape
){
_confer_ape
.
leaveClass
();
...
...
@@ -714,6 +696,45 @@ export default class MessageEntrance extends Emiter {
}
}
//AudioApe
audioUpdate
(
_data
){
//音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if
(
_confer_ape
){
_confer_ape
.
updaterRosterStatus
(
_data
);
}
}
sendAudioCommandMsg
(
_param
){
if
(
_audio_ape
){
return
_audio_ape
.
sendAudioBroadcastMsg
(
_param
);
}
}
_getPlayAudioPath
(
_param
){
if
(
_audio_ape
){
return
_audio_ape
.
getAudioPlayPath
(
_param
);
}
}
_getPublishAudioPath
(
_param
){
if
(
_audio_ape
){
return
_audio_ape
.
getAudioPublishPath
(
_param
);
}
}
_publishAudio
(
_param
){
if
(
_audio_ape
){
return
_audio_ape
.
publishAudio
(
_param
);
}
}
_stopPublishAudio
(
_param
){
if
(
_audio_ape
){
return
_audio_ape
.
stopPublishAudio
(
_param
);
}
}
//WhiteBoardApe
// 添加标注,发送信息
_sendInsertAnnotaion
(
_param
){
...
...
@@ -820,30 +841,32 @@ export default class MessageEntrance extends Emiter {
if
(
GlobalConfig
.
isHost
){
for
(
let
value
of
GlobalConfig
.
docListPrepare
){
if
(
value
){
//{
// "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
// "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
// "createUserID": "972",
// "createUserIP": "114.241.81.175",
// "createUserName": "base",
// "dynamicPPT": 0,
// "dynamicTransferStatic": "",
// "id": "8ab3b0ed5a00f2fa015a0219a3df016c",
// "meetingNumber": "",
// "name": "McuClient_v.1.0.1_API.pdf",
// "orderStr": "",
// "pdfSize": 5,
// "processEndTime": "2017-02-03 11:54:31",
// "processRate": 0,
// "processStartTime": "2017-02-03 11:54:27",
// "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
// "siteID": "h5test",
// "size": 360920,
// "status": 3,
// "type": "pdf",
// "uploadEndTime": "2017-02-03 11:54:27",
// "uploadStartTime": "2017-02-03 11:54:27"
//}
/* //提前上传的文档文档信息的结构
{
"MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
"absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"createUserID": "972",
"createUserIP": "114.241.81.175",
"createUserName": "base",
"dynamicPPT": 0,
"dynamicTransferStatic": "",
"id": "8ab3b0ed5a00f2fa015a0219a3df016c",
"meetingNumber": "",
"name": "McuClient_v.1.0.1_API.pdf",
"orderStr": "",
"pdfSize": 5,
"processEndTime": "2017-02-03 11:54:31",
"processRate": 0,
"processStartTime": "2017-02-03 11:54:27",
"relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
"siteID": "h5test",
"size": 360920,
"status": 3,
"type": "pdf",
"uploadEndTime": "2017-02-03 11:54:27",
"uploadStartTime": "2017-02-03 11:54:27"
}*/
loger
.
log
(
"判断是否需要把提前上传的文档上传到mcu"
,
value
);
let
paramInfo
=
{
"pageNum"
:
value
.
pdfSize
,
...
...
src/GlobalConfig.js
查看文件 @
66a7623
...
...
@@ -30,7 +30,9 @@ class GlobalConfig {
static
getClassDetail
(){
return
this
.
classDetail
;
}
static
setClassDetail
(
_data
){
this
.
classDetail
=
_data
;
}
static
getClassInfo
(){
let
classInfo
=
{};
classInfo
.
siteId
=
this
.
siteId
;
...
...
@@ -55,7 +57,6 @@ class GlobalConfig {
classInfo
.
MCUServerPort
=
this
.
MCUServerPort
;
classInfo
.
maxVideoChannels
=
this
.
maxVideoChannels
;
classInfo
.
maxAudioChannels
=
this
.
maxAudioChannels
;
classInfo
.
maxMediaChannels
=
this
.
maxMediaChannels
;
return
classInfo
;
...
...
@@ -175,13 +176,13 @@ class GlobalConfig {
static
getDocListPrepare
(){
return
this
.
docListPrepare
;
}
//储存文档录制列表
static
setDocRecordList
(
_data
){
//储存录制列表
static
setRecordList
(
_data
){
if
(
_data
==
null
)
return
;
this
.
docR
ecordList
=
_data
;
this
.
r
ecordList
=
_data
;
}
static
getDocRecordList
(){
return
this
.
docRecordList
;
static
getRecordList
(){
return
this
.
recordList
;
}
//文档服务器列表
...
...
@@ -247,11 +248,12 @@ GlobalConfig.md5="";
GlobalConfig
.
msType
=
1
;
//目前固定用这个
GlobalConfig
.
mcuDelay
=
3000
;
//默认的延迟时间
GlobalConfig
.
docDelay
=
1600
;
//文档模块加入成功之后延迟发送送成功的消息给主模块
GlobalConfig
.
portal
=
"112.126.80.182:80"
;
GlobalConfig
.
ip
=
"112.126.80.182"
;
GlobalConfig
.
port
=
"80"
;
GlobalConfig
.
portal
=
"112.126.80.182:80"
;
//Sass IP
//GlobalConfig.ip="112.126.80.182";
//GlobalConfig.port="80";
GlobalConfig
.
MCUServerIP
=
"114.215.195.70"
;
GlobalConfig
.
docServer
=
""
;
//当前的文档地址加载的服务器地址
GlobalConfig
.
MCUServerPort
=
9003
;
GlobalConfig
.
MSServerIP
=
""
;
//推流 播流的地址
...
...
@@ -261,9 +263,16 @@ GlobalConfig.MSServerPort ="";
GlobalConfig
.
RSServerIP
=
""
;
GlobalConfig
.
RSServerPort
=
""
;
//DOC
GlobalConfig
.
DOCServerIP
=
""
;
GlobalConfig
.
DOCServerPort
=
""
;
GlobalConfig
.
RecordServerIP
=
""
;
GlobalConfig
.
RecordServerPort
=
""
;
GlobalConfig
.
maxVideoChannels
=
0
;
GlobalConfig
.
maxAudioChannels
=
0
;
GlobalConfig
.
maxMediaChannels
=
0
;
GlobalConfig
.
isDebug
=
false
;
GlobalConfig
.
deBugData
=
{};
...
...
@@ -315,7 +324,7 @@ GlobalConfig.classAllParam={};//Sass直接返回的所有会议信息(最全)
GlobalConfig
.
classDetail
=
{};
//Sass直接返回的当前课堂基本信息
GlobalConfig
.
docListPrepare
=
[];
// 已经提前上传的文档,进入课堂后需要自动加载
GlobalConfig
.
docR
ecordList
=
[];
//录制服务器地址集合
GlobalConfig
.
r
ecordList
=
[];
//录制服务器地址集合
GlobalConfig
.
docList
=
[];
//文档服务器地址集合
GlobalConfig
.
mcuList
=
[];
//录制服务器地址集合
GlobalConfig
.
msList
=
[];
//ms服务器地址集合
...
...
@@ -323,21 +332,5 @@ GlobalConfig.musicList=[];//music服务器地址集合
GlobalConfig
.
musicListPrepare
=
[];
//提提前上传的music集合
GlobalConfig
.
rsList
=
[];
// client type
//点对点会议版本
GlobalConfig
.
CT_P2PMEETING
=
0
;
/**
* 直播教育版本和大型直播版本
*/
GlobalConfig
.
CT_LIVEEDUCATION
=
1
;
/**
* 录制播放器
*/
GlobalConfig
.
CT_RECORDPLAYER
=
2
;
/**
* 实时流版本
*/
GlobalConfig
.
CT_LIVESTREAMING
=
3
;
GlobalConfig
.
clientType
=
0
;
export
default
GlobalConfig
;
...
...
src/McuClientEngine.js
查看文件 @
66a7623
//对外暴露的对象
import
EngineEntrance
from
'EngineEntrance'
;
import
MessageTypes
from
'MessageTypes'
;
const
MCU_CLIENT
=
new
EngineEntrance
();
const
MCU_CLIENT
=
new
EngineEntrance
();
//入口文件
export
function
createMcuClient
()
{
return
MCU_CLIENT
;
}
//监听是事件名和异常定义
export
{
MessageTypes
};
...
...
src/MessageTypes.js
查看文件 @
66a7623
...
...
@@ -29,7 +29,12 @@ MessageTypes.CHAT_RECEIVE = 'chat.receive';
//视频模块事件定义
MessageTypes
.
VIDEO_UPDATE
=
'video.update'
;
MessageTypes
.
VIDEO_COMMAND
=
'video.command'
;
MessageTypes
.
VIDEO_BROADCAST
=
'video.broadcast'
;
//音频模块事件定义
MessageTypes
.
AUDIO_UPDATE
=
'audio.update'
;
MessageTypes
.
AUDIO_BROADCAST
=
'audio.broadcast'
;
//文档模块事件定义
MessageTypes
.
DOC_DELETE
=
'document.delete'
;
//删除文档
...
...
src/apes/ApeConsts.js
查看文件 @
66a7623
...
...
@@ -82,10 +82,13 @@ ApeConsts.USER_MIC_OPEN = 0x0040; // 麦克风开启
ApeConsts
.
USER_CAMERA_OPEN
=
0x0080
;
// 视频开启
//VIDEO MIC 流媒体消息操作控制类型
ApeConsts
.
MEDIA_ACTION_DEFAULT
=
0
;
ApeConsts
.
MEDIA_ACTION_OPEN_CAMERA
=
1
;
// "open.camera";
ApeConsts
.
MEDIA_ACTION_CLOSE_CAMERA
=
2
;
// "close.camera";
ApeConsts
.
MEDIA_ACTION_OPEN_MIC
=
3
;
//"open.mic";
ApeConsts
.
MEDIA_ACTION_CLOSE_MIC
=
4
;
//"close.mic";
...
...
@@ -99,12 +102,16 @@ ApeConsts.MEDIA_TYPE_DEFAULT=0;//没有类型
ApeConsts
.
MEDIA_TYPE_VIDEO
=
1
;
//视频流(包含音频)
ApeConsts
.
MEDIA_TYPE_AUDIO
=
2
;
//音频流
//FLASH中使用下面4个
ApeConsts
.
CGS_RELEASED
=
0
;
///< 无人占用状态
ApeConsts
.
CGS_PENDING
=
1
;
///< 占用成功,等待打开
ApeConsts
.
CGS_OPENNED
=
2
;
///< 打开成功
ApeConsts
.
CGS_GRABBING
=
3
;
///< 准备占用中, 属于本地状态机需要用的状态,在多点数据库中不存在。
//return返回值状态
ApeConsts
.
RETURN_SUCCESS
=
0
;
//成功
ApeConsts
.
RETURN_FAILED
=
1
;
//失败
////FLASH中使用下面4个
//ApeConsts.CGS_RELEASED = 0;///< 无人占用状态
//ApeConsts.CGS_PENDING = 1;///< 占用成功,等待打开
//ApeConsts.CGS_OPENNED = 2;///< 打开成功
//ApeConsts.CGS_GRABBING = 3; ///< 准备占用中, 属于本地状态机需要用的状态,在多点数据库中不存在。
//
ApeConsts
.
INVALIDATE_CHANNEL_ID
=
-
1
;
...
...
src/apes/AudioApe.js
0 → 100644
查看文件 @
66a7623
// //////////////////////////////////////////////////////////////////////////////
//音频模块
// //////////////////////////////////////////////////////////////////////////////
import
Ape
from
'./Ape'
;
import
ApeConsts
from
'./ApeConsts'
;
import
pdu
from
'pdus'
;
import
Loger
from
'Loger'
;
import
MessageTypes
from
'MessageTypes'
;
import
GlobalConfig
from
'GlobalConfig'
;
import
EngineUtils
from
'EngineUtils'
;
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
.
mediaModule
=
new
MediaModule
();
this
.
mediaModule
.
MEDIA_OBJ_TABLE_ID
=
ApeConsts
.
AUDIO_OBJ_TABLE_ID
;
this
.
mediaModule
.
mediaChannels
=
{};
// 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_AUDIO_SEND_DATA_REQUEST
,
this
.
receiveAudiooCommandHandler
.
bind
(
this
));
}
//ape加入成功
onJoinChannelHandlerSuccess
(){
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this
.
mediaModule
.
maxMediaChannel
=
GlobalConfig
.
maxAudioChannels
;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getAudioPlayPath
(
_param
)
{
loger
.
log
(
'getAudioPlayPath'
);
return
this
.
mediaModule
.
getMediaPlayPath
(
_param
);
}
//获取推流地址
getAudioPublishPath
(
_param
)
{
loger
.
log
(
'getAudioPublishPath'
);
return
this
.
mediaModule
.
getMediaPublishPath
(
_param
);
}
//推流
publishAudio
(
_param
)
{
if
(
_param
==
null
||
_param
.
channelId
==
null
||
_param
.
classId
==
null
||
_param
.
userId
==
null
||
_param
.
siteId
==
null
||
_param
.
timestamp
==
null
)
{
loger
.
warn
(
'publishAudio,参数错误'
,
_param
);
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_INTERFACE_PARAM_WRONG
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"参数错误"
};
}
//同一个nodeId只允许推一个流,如果已经推了就不能再推
if
(
this
.
mediaModule
.
getOpeningMediaChannel
(
GlobalConfig
.
nodeId
)
!=
0
){
loger
.
warn
(
"publishAudio,已经存在一个流,不能再推"
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"已经存在一个流,不能再推"
};
}
//判断当前是否还有空闲的channle
let
freeChannel
=
this
.
mediaModule
.
getFreeMediaChannel
();
if
(
freeChannel
==
0
)
{
loger
.
warn
(
"publishAudio,没有空闲的channel "
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"不能再打开更多的设备"
};
}
//判断当前的频道是否已经占用
if
(
this
.
mediaModule
.
checkChannelIsOpening
(
_param
.
channelId
)){
loger
.
warn
(
_param
.
channelId
,
"频道已经被占用"
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"频道已经被占用!"
};
}
let
channelInfo
=
{};
channelInfo
.
status
=
ApeConsts
.
CHANNEL_STATUS_OPENING
;
channelInfo
.
fromNodeId
=
GlobalConfig
.
nodeId
;
channelInfo
.
channelId
=
_param
.
channelId
;
//freeChannel
channelInfo
.
timestamp
=
_param
.
timestamp
;
//EngineUtils.creatTimestamp();
channelInfo
.
classId
=
_param
.
classId
;
//GlobalConfig.classId;
channelInfo
.
siteId
=
_param
.
siteId
;
//GlobalConfig.siteId;
channelInfo
.
toNodeId
=
0
;
channelInfo
.
mediaType
=
ApeConsts
.
MEDIA_TYPE_AUDIO
;
this
.
sendTableUpdateHandler
(
channelInfo
);
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
"推流成功!"
}
}
//停止推流,
stopPublishAudio
(
_param
)
{
loger
.
log
(
'stopPublishAudio'
);
//_param如果为空,那么默认就是当前自己的nodeId,否则用_param
let
nodeId
;
if
(
_param
&&
parseInt
(
_param
.
nodeId
)
>=
0
){
nodeId
=
parseInt
(
_param
.
nodeId
);
}
else
{
nodeId
=
GlobalConfig
.
nodeId
;
}
let
openingChannel
=
this
.
mediaModule
.
getOpeningMediaChannel
(
nodeId
);
if
(
openingChannel
==
0
)
{
loger
.
warn
(
nodeId
,
"stopPublishAudio,没有占用channel,不需要关闭"
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"没有占用channel,不需要关闭"
};
}
let
channelInfo
=
{};
channelInfo
.
status
=
ApeConsts
.
CHANNEL_STATUS_RELEASED
;
channelInfo
.
fromNodeId
=
0
;
channelInfo
.
channelId
=
openingChannel
;
channelInfo
.
timestamp
=
0
;
channelInfo
.
classId
=
GlobalConfig
.
classId
;
channelInfo
.
toNodeId
=
0
;
channelInfo
.
mediaType
=
ApeConsts
.
MEDIA_TYPE_DEFAULT
;
this
.
sendTableUpdateHandler
(
channelInfo
);
}
sendAudioBroadcastMsg
(
_param
)
{
if
(
this
.
_classInfo
===
null
||
EngineUtils
.
isEmptyObject
(
this
.
_classInfo
))
{
loger
.
log
(
'sendAudioBroadcastMsg.McuClient还未初始化数据!'
);
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
(
'sendAudioBroadcastMsg,参数错误'
,
_param
);
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_INTERFACE_PARAM_WRONG
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"sendAudioBroadcastMsg,参数错误"
};
}
// to, message
loger
.
log
(
'发送Audio消息.'
,
_param
);
if
(
_param
.
actionType
!=
null
&&
_param
.
actionType
==
ApeConsts
.
MEDIA_ACTION_OPEN_CAMERA
)
{
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let
freeChannel
=
this
.
mediaModule
.
getFreeMediaChannel
();
if
(
freeChannel
==
0
)
{
loger
.
warn
(
'sendAudioBroadcastMsg,不能再打开更多的设备'
,
_param
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"不能再打开更多的设备"
};
}
}
let
audioSendPdu
=
new
pdu
[
'RCAudioSendDataRequestPdu'
];
audioSendPdu
.
type
=
pdu
.
RCPDU_AUDIO_SEND_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
;
audioSendPdu
.
data
=
this
.
_rCArrayBufferUtil
.
strToUint8Array
(
"h5"
+
_param
.
data
);
//开头两个字会乱码
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
(
"sendTableUpdateHandler error,updateModelPdu=null"
);
return
;
}
let
tableItemPdu
=
new
pdu
[
'RCRegistryTableItemPdu'
];
tableItemPdu
.
itemIdx
=
_channelInfo
.
channelId
;
tableItemPdu
.
owner
=
0
;
//收到flash的是这个值,不清楚先写固定
tableItemPdu
.
itemData
=
updateModelPdu
.
toArrayBuffer
();
//insert
let
tableInsertItemPdu
=
new
pdu
[
'RCRegistryTableUpdateItemPdu'
];
//optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
//repeated RCRegistryTableItemPdu items = 2;
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
(
"发送更新AUDIO.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
);
//开头两个字会乱码
loger
.
log
(
'音频消息处理 receiveAudiooCommandHandler.'
,
audioReceivePdu
);
//判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
if
(
audioReceivePdu
.
toNodeId
!=
0
&&
audioReceivePdu
.
toNodeId
!=
GlobalConfig
.
nodeId
)
{
loger
.
log
(
'音频消息不处理 toNodeId='
,
audioReceivePdu
.
toNodeId
,
"my nodeId="
,
GlobalConfig
.
nodeId
);
}
else
{
this
.
_emit
(
MessageTypes
.
AUDIO_BROADCAST
,
audioReceivePdu
);
}
}
tableUpdateHandler
(
owner
,
itemIdx
,
itemData
)
{
// debugger;
let
updateChannelInfo
=
this
.
unPackPdu
(
owner
,
itemIdx
,
itemData
);
this
.
mediaModule
.
mediaChannels
[
itemIdx
]
=
updateChannelInfo
;
this
.
_emit
(
MessageTypes
.
AUDIO_UPDATE
,
updateChannelInfo
);
}
///////数据的封包和解包/////////////////////////////////////////
packPdu
(
_param
,
_itemIdx
)
{
loger
.
log
(
"packPdu "
);
//验证坐标点集合数组是否合法
if
(
_param
==
null
||
_itemIdx
==
null
)
{
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
.
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
=
GlobalConfig
.
nodeId
;
packPduModel
.
toNodeId
=
0
;
console
.
log
(
"packPdu"
,
packPduModel
);
return
packPduModel
;
}
unPackPdu
(
owner
,
itemIdx
,
itemData
)
{
loger
.
log
(
"unPackPdu "
);
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
;
}
}
export
default
AudioApe
;
...
...
src/apes/ConferApe.js
查看文件 @
66a7623
...
...
@@ -454,8 +454,8 @@ class ConferApe extends Ape {
//视频模块发生更新,人员状态需要更新
updaterRosterStatus
(
_param
){
if
(
_param
){
loger
.
log
(
"视频模块发生更新,人员状态需要更新,fromNodeId->"
,
_param
.
fromNodeId
);
loger
.
log
(
_param
.
status
,
_param
.
fromNodeId
,
this
.
rosters
[
_param
.
fromNodeId
]);
loger
.
log
(
"媒体模块发生更新,人员状态需要更新,fromNodeId->"
,
_param
.
fromNodeId
);
loger
.
log
(
_param
.
status
,
_param
.
fromNodeId
);
//console.log(_param.fromNodeId);
//如果是自己。改变自己的状态同步到MCU
//if(_param.fromNodeId==GlobalConfig.nodeId){
...
...
@@ -465,8 +465,8 @@ class ConferApe extends Ape {
//如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
if
(
_param
.
status
==
ApeConsts
.
CHANNEL_STATUS_OPENING
&&
this
.
rosters
[
_param
.
fromNodeId
]
==
null
){
loger
.
log
(
"视频模块被占用,占有人已经不存在课堂中,释放Channel,_param->"
,
_param
);
this
.
_emit
(
MessageTypes
.
CLASS_NONENTITY_ROSTER
,
_param
.
fromNodeId
);
loger
.
log
(
"媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->"
,
_param
);
this
.
_emit
(
MessageTypes
.
CLASS_NONENTITY_ROSTER
,{
"nodeId"
:
_param
.
fromNodeId
});
}
}
}
...
...
src/apes/DocApe.js
查看文件 @
66a7623
...
...
@@ -145,7 +145,8 @@ class DocApe extends Ape {
return
""
;
}
let
fullPath
=
GlobalConfig
.
docServer
+
_param
.
relativeUrl
;
let
port
=
(
GlobalConfig
.
DOCServerPort
==
""
||
GlobalConfig
.
DOCServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
DOCServerPort
;
let
fullPath
=
GlobalConfig
.
DOCServerIP
+
port
+
_param
.
relativeUrl
;
var
index
;
switch
(
_param
.
type
){
case
"jpg"
:
...
...
src/apes/MediaModule.js
0 → 100644
查看文件 @
66a7623
// //////////////////////////////////////////////////////////////////////////////
// VideoApe、AudioApe 共用的方法单独提取处理
// //////////////////////////////////////////////////////////////////////////////
import
ApeConsts
from
'./ApeConsts'
;
import
Loger
from
'Loger'
;
import
MessageTypes
from
'MessageTypes'
;
import
GlobalConfig
from
'GlobalConfig'
;
import
EngineUtils
from
'EngineUtils'
;
let
loger
=
Loger
.
getLoger
(
'MediaModule'
);
class
MediaModule
{
constructor
()
{
this
.
mediaChannels
=
{};
this
.
maxMediaChannel
=
0
;
this
.
MEDIA_OBJ_TABLE_ID
=
0
;
}
//获取播流地址
getMediaPlayPath
(
_param
)
{
loger
.
log
(
'getMediaPlayPath'
);
if
(
_param
==
null
||
_param
.
siteId
==
null
||
_param
.
classId
==
null
||
_param
.
userId
==
null
||
_param
.
channelId
==
null
||
_param
.
timestamp
==
null
)
{
loger
.
warn
(
'getMediaPlayPath,参数错误'
,
_param
);
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_INTERFACE_PARAM_WRONG
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
""
};
}
let
path
=
""
;
let
port
=
""
;
if
(
_param
.
type
==
"m3u8"
)
{
//M3U8
//http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8
port
=
(
GlobalConfig
.
RSServerPort
==
""
||
GlobalConfig
.
RSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
RSServerPort
;
path
=
"http://"
+
GlobalConfig
.
RSServerIP
+
port
+
"/live/"
+
_param
.
siteId
+
"_"
+
_param
.
classId
+
"_"
+
_param
.
userId
+
"_"
+
_param
.
channelId
+
"_"
+
_param
.
timestamp
+
"/index.m3u8"
;
}
else
{
port
=
(
GlobalConfig
.
MSServerPort
==
""
||
GlobalConfig
.
MSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
MSServerPort
;
path
=
"rtmp://"
+
GlobalConfig
.
MSServerIP
+
port
+
"/live/"
+
_param
.
siteId
+
"_"
+
_param
.
classId
+
"_"
+
_param
.
userId
+
"_"
+
_param
.
channelId
+
"_"
+
_param
.
timestamp
;
}
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
""
,
"playUrl"
:
path
};
}
//获取推流地址
getMediaPublishPath
(
_param
)
{
loger
.
log
(
'getMediaPublishPath'
);
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let
freeChannel
=
this
.
getFreeMediaChannel
();
if
(
freeChannel
==
0
)
{
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"不能再打开更多的设备"
};
}
//默认方式推流
let
pubType
=
"live"
;
//flash推流
if
(
_param
&&
_param
.
type
==
"flash"
){
pubType
=
"flash"
;
}
//端口,有端口就显示 ":xxx",没有端口就是""
let
port
=
(
GlobalConfig
.
MSServerPort
==
""
||
GlobalConfig
.
MSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
MSServerPort
;
//时间戳
let
timestamp
=
EngineUtils
.
creatTimestamp
();
//生成推流地址和推流数据(同步数据的时候用)
let
publishUrl
=
"rtmp://"
+
GlobalConfig
.
MSServerIP
+
port
+
"/"
+
pubType
+
"/"
+
GlobalConfig
.
siteId
+
"_"
+
GlobalConfig
.
classId
+
"_"
+
GlobalConfig
.
userId
+
"_"
+
freeChannel
+
"_"
+
timestamp
;
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
""
,
"siteId"
:
GlobalConfig
.
siteId
,
"classId"
:
GlobalConfig
.
classId
,
"userId"
:
GlobalConfig
.
userId
,
"channelId"
:
freeChannel
,
"timestamp"
:
timestamp
,
"publishUrl"
:
publishUrl
};
}
//获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId
getFreeMediaChannel
()
{
let
counter
=
0
;
for
(
let
key
in
this
.
mediaChannels
)
{
let
item
=
this
.
mediaChannels
[
key
];
if
(
item
&&
item
.
status
==
ApeConsts
.
CHANNEL_STATUS_RELEASED
)
{
return
item
.
channelId
;
}
counter
++
;
}
loger
.
log
(
"getFreeMediaChannel"
,
"maxMediaChannel"
,
this
.
maxMediaChannel
,
"counter:"
,
counter
);
console
.
log
(
this
.
mediaChannels
);
if
(
counter
<
this
.
maxMediaChannel
)
{
return
this
.
MEDIA_OBJ_TABLE_ID
+
(
counter
);
}
return
0
;
//没有空闲的
}
//获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
getOpeningMediaChannel
(
_nodeId
){
if
(
_nodeId
==
null
||
_nodeId
==
0
){
return
0
;
}
for
(
let
key
in
this
.
mediaChannels
)
{
let
item
=
this
.
mediaChannels
[
key
];
if
(
item
&&
item
.
status
==
ApeConsts
.
CHANNEL_STATUS_OPENING
&&
item
.
fromNodeId
==
_nodeId
)
{
return
item
.
channelId
;
}
}
return
0
;
}
//检查频道是否已经被占用
checkChannelIsOpening
(
_channelId
){
if
(
_channelId
==
null
){
loger
.
warn
(
"checkChannelIsOpening error,channel="
,
_channelId
);
return
true
;
}
let
channelInfo
=
this
.
mediaChannels
[
_channelId
];
if
(
channelInfo
==
null
||
channelInfo
.
status
==
ApeConsts
.
CHANNEL_STATUS_RELEASED
){
return
false
;
}
return
true
;
}
}
export
default
MediaModule
;
...
...
src/apes/VideoApe.js
查看文件 @
66a7623
// //////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016-present All Rights Reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// http://www.apache.org/licenses/LICENSE-2.0
//
// Github Home: https://github.com/AlexWang1987
// Author: AlexWang
// Date: 2016-08-23 18:07:28
// QQ Email: 1669499355@qq.com
// Last Modified time: 2016-09-06 11:13:59
// Description: LiveClass-VideoApe
//
//视频模块
// //////////////////////////////////////////////////////////////////////////////
import
Ape
from
'./Ape'
;
...
...
@@ -20,10 +9,11 @@ import Loger from 'Loger';
import
MessageTypes
from
'MessageTypes'
;
import
GlobalConfig
from
'GlobalConfig'
;
import
EngineUtils
from
'EngineUtils'
;
import
MediaModule
from
"./MediaModule"
;
let
loger
=
Loger
.
getLoger
(
'Video
Chat
'
);
let
loger
=
Loger
.
getLoger
(
'Video
Ape
'
);
class
Video
Chat
extends
Ape
{
class
Video
Ape
extends
Ape
{
constructor
()
{
super
(
ApeConsts
.
VIDEO_SESSION_ID
,
...
...
@@ -31,8 +21,9 @@ class VideoChat extends Ape {
ApeConsts
.
VIDEO_SESSION_TAG
);
//Attributes
this
.
videoChannels
=
{};
this
.
mediaModule
=
new
MediaModule
();
this
.
mediaModule
.
MEDIA_OBJ_TABLE_ID
=
ApeConsts
.
VIDEO_OBJ_TABLE_ID
;
this
.
mediaModule
.
mediaChannels
=
{};
// Ape Models
this
.
registerKey
(
this
.
_session_id
,
this
.
_session_name
,
this
.
_session_tag
,
new
ArrayBuffer
);
...
...
@@ -41,84 +32,23 @@ class VideoChat extends Ape {
// videoApe 监听视频控制消息,用户之间的消息传递
this
.
on
(
pdu
.
RCPDU_VIDEO_SEND_DATA_REQUEST
,
this
.
receiveVideoCommandHandler
.
bind
(
this
));
}
//ape加入成功
onJoinChannelHandlerSuccess
(){
//这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
this
.
mediaModule
.
maxMediaChannel
=
GlobalConfig
.
maxVideoChannels
;
}
/////////////发送数据操作////////////////////////////////////////////
//获取播流地址
getPlayVideoPath
(
_param
)
{
loger
.
log
(
'getPlayVideoPath'
);
if
(
_param
==
null
||
_param
.
siteId
==
null
||
_param
.
classId
==
null
||
_param
.
userId
==
null
||
_param
.
channelId
==
null
||
_param
.
timestamp
==
null
)
{
loger
.
warn
(
'getPlayVideoPath,参数错误'
,
_param
);
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_INTERFACE_PARAM_WRONG
);
return
{
"code"
:
1
,
"data"
:
""
};
}
let
path
=
""
;
let
port
=
""
;
if
(
_param
.
type
==
"m3u8"
)
{
//M3U8
//http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8
port
=
(
GlobalConfig
.
RSServerPort
==
""
||
GlobalConfig
.
RSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
RSServerPort
;
path
=
"http://"
+
GlobalConfig
.
RSServerIP
+
port
+
"/live/"
+
_param
.
siteId
+
"_"
+
_param
.
classId
+
"_"
+
_param
.
userId
+
"_"
+
_param
.
channelId
+
"_"
+
_param
.
timestamp
+
"/index.m3u8"
;
}
else
{
port
=
(
GlobalConfig
.
MSServerPort
==
""
||
GlobalConfig
.
MSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
MSServerPort
;
path
=
"rtmp://"
+
GlobalConfig
.
MSServerIP
+
port
+
"/live/"
+
_param
.
siteId
+
"_"
+
_param
.
classId
+
"_"
+
_param
.
userId
+
"_"
+
_param
.
channelId
+
"_"
+
_param
.
timestamp
;
}
return
{
"code"
:
0
,
"data"
:
path
};
return
this
.
mediaModule
.
getMediaPlayPath
(
_param
);
}
//获取推流地址
getPublishVideoPath
(
_param
)
{
loger
.
log
(
'getPublishVideoPath'
);
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let
freeChannel
=
this
.
getFreeVideoChannel
();
if
(
freeChannel
==
0
)
{
return
{
"code"
:
1
,
"data"
:
"不能再打开更多的设备"
};
}
//默认方式推流
let
pubType
=
"live"
;
//flash推流
if
(
_param
&&
_param
.
type
==
"flash"
){
pubType
=
"flash"
;
}
//端口,有端口就显示 ":xxx",没有端口就是""
let
port
=
(
GlobalConfig
.
MSServerPort
==
""
||
GlobalConfig
.
MSServerPort
==
null
)
?
""
:
":"
+
GlobalConfig
.
MSServerPort
;
//时间戳
let
timestamp
=
EngineUtils
.
creatTimestamp
();
//生成推流地址和推流数据(同步数据的时候用)
let
publishUrl
=
"rtmp://"
+
GlobalConfig
.
MSServerIP
+
port
+
"/"
+
pubType
+
"/"
+
GlobalConfig
.
siteId
+
"_"
+
GlobalConfig
.
classId
+
"_"
+
GlobalConfig
.
userId
+
"_"
+
freeChannel
+
"_"
+
timestamp
;
return
{
"code"
:
0
,
"data"
:
{
"siteId"
:
GlobalConfig
.
siteId
,
"classId"
:
GlobalConfig
.
classId
,
"userId"
:
GlobalConfig
.
userId
,
"channelId"
:
freeChannel
,
"timestamp"
:
timestamp
,
"publishUrl"
:
publishUrl
}
};
return
this
.
mediaModule
.
getMediaPublishPath
(
_param
);
}
//推流
...
...
@@ -129,28 +59,28 @@ class VideoChat extends Ape {
{
loger
.
warn
(
'publishVideo,参数错误'
,
_param
);
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_INTERFACE_PARAM_WRONG
);
return
{
"code"
:
1
,
"data"
:
"
"
};
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"参数错误
"
};
}
loger
.
log
(
'publishVideo -> maxVideoChannels'
,
GlobalConfig
.
maxVideoChannels
);
//同一个nodeId只允许推一个流,如果已经推了就不能再推
if
(
this
.
getOpeningVideo
Channel
(
GlobalConfig
.
nodeId
)
!=
0
){
if
(
this
.
mediaModule
.
getOpeningMedia
Channel
(
GlobalConfig
.
nodeId
)
!=
0
){
loger
.
warn
(
"publishVideo,已经存在一个流,不能再推"
);
return
;
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"已经存在一个流,不能再推"
}
;
}
//判断当前是否还有空闲的channle
let
freeChannel
=
this
.
getFreeVideo
Channel
();
let
freeChannel
=
this
.
mediaModule
.
getFreeMedia
Channel
();
if
(
freeChannel
==
0
)
{
loger
.
warn
(
"publishVideo,没有空闲的channel "
);
return
{
"code"
:
1
,
"data"
:
"不能再打开更多的设备"
};
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"不能再打开更多的设备"
};
}
//判断当前的频道是否已经占用
if
(
this
.
checkChannelIsOpening
(
_param
.
channelId
)){
if
(
this
.
mediaModule
.
checkChannelIsOpening
(
_param
.
channelId
)){
loger
.
warn
(
_param
.
channelId
,
"频道已经被占用"
);
return
{
"code"
:
1
,
"data"
:
"频道已经被占用!"
};
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"频道已经被占用!"
};
}
let
channelInfo
=
{};
...
...
@@ -163,7 +93,7 @@ class VideoChat extends Ape {
channelInfo
.
toNodeId
=
0
;
channelInfo
.
mediaType
=
ApeConsts
.
MEDIA_TYPE_VIDEO
;
this
.
sendTableUpdateHandler
(
channelInfo
);
return
{
"code"
:
0
,
"data"
:
"推流成功!"
}
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
"推流成功!"
}
}
//停止推流,
...
...
@@ -177,10 +107,10 @@ class VideoChat extends Ape {
nodeId
=
GlobalConfig
.
nodeId
;
}
let
openingChannel
=
this
.
getOpeningVideo
Channel
(
nodeId
);
let
openingChannel
=
this
.
mediaModule
.
getOpeningMedia
Channel
(
nodeId
);
if
(
openingChannel
==
0
)
{
loger
.
warn
(
nodeId
,
"stopPublishVideo,没有打开的channel,不需要关闭"
);
return
{
"code"
:
1
,
"data"
:
"没有打开的channel,不需要关闭"
};
loger
.
warn
(
nodeId
,
"stopPublishVideo,没有占用channel,不需要关闭"
);
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"没有占用channel,不需要关闭"
};
}
let
channelInfo
=
{};
...
...
@@ -201,23 +131,22 @@ class VideoChat extends Ape {
this
.
_emit
(
MessageTypes
.
MCU_ERROR
,
MessageTypes
.
ERR_APE_SEND_FAILED_NO_JOIN
);
return
{
"code"
:
1
,
"data"
:
"不能发送Video消息.McuClient还未初始化数据"
};
}
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"
:
1
,
"data"
:
"sendVideoCommandMsg失败,参数错误"
};
;
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"sendVideoCommandMsg失败,参数错误"
};
}
// to, message
loger
.
log
(
'发送Video消息.'
,
_param
);
if
(
_param
.
actionType
!=
null
&&
_param
.
actionType
==
ApeConsts
.
MEDIA_ACTION_OPEN_CAMERA
)
{
//判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
let
freeChannel
=
this
.
getFreeVideo
Channel
();
let
freeChannel
=
this
.
mediaModule
.
getFreeMedia
Channel
();
if
(
freeChannel
==
0
)
{
loger
.
warn
(
'sendVideoCommandMsg,不能再打开更多的设备'
,
_param
);
return
{
"code"
:
1
,
"data"
:
"不能再打开更多的设备"
};
return
{
"code"
:
ApeConsts
.
RETURN_FAILED
,
"data"
:
"不能再打开更多的设备"
};
}
}
/* message RCVideoSendDataRequestPdu {
...
...
@@ -246,7 +175,7 @@ class VideoChat extends Ape {
loger
.
log
(
'发送公聊Video消息.'
);
this
.
sendChatUniform
(
videoSendPdu
);
}
return
{
"code"
:
0
,
"data"
:
""
};
return
{
"code"
:
ApeConsts
.
RETURN_SUCCESS
,
"data"
:
""
};
}
sendTableUpdateHandler
(
_channelInfo
)
{
...
...
@@ -314,45 +243,15 @@ class VideoChat extends Ape {
if
(
videoReceivePdu
.
toNodeId
!=
0
&&
videoReceivePdu
.
toNodeId
!=
GlobalConfig
.
nodeId
)
{
loger
.
log
(
'视频消息不处理 toNodeId='
,
videoReceivePdu
.
toNodeId
,
"my nodeId="
,
GlobalConfig
.
nodeId
);
}
else
{
this
.
_emit
(
MessageTypes
.
VIDEO_
COMMAND
,
videoReceivePdu
);
this
.
_emit
(
MessageTypes
.
VIDEO_
BROADCAST
,
videoReceivePdu
);
}
}
tableUpdateHandler
(
owner
,
itemIdx
,
itemData
)
{
// debugger;
let
videoChannelInfo
=
this
.
unPackPdu
(
owner
,
itemIdx
,
itemData
);
//videoChannelInfo.owner = owner;
//videoChannelInfo.channelId = itemIdx;
//videoChannelInfo.status = owner === 0 ? ApeConsts.CHANNEL_STATUS_RELEASED : videoChannelInfo.status;
//loger.log('视频消息处理 tableUpdateHandler.',videoChannelInfo);
this
.
videoChannels
[
itemIdx
]
=
videoChannelInfo
;
this
.
mediaModule
.
mediaChannels
[
itemIdx
]
=
videoChannelInfo
;
this
.
_emit
(
MessageTypes
.
VIDEO_UPDATE
,
videoChannelInfo
);
/* switch (videoChannelInfo.status) {
case ApeConsts.CHANNEL_STATUS_RELEASED:
// 只能关闭自己的流
if (this.activeChannelId === videoChannelInfo.channelId) {
this.activeChannelId = 0;
this.activeURL = '';
this.emitVideoChange();
}
break;
case ApeConsts.CHANNEL_STATUS_OPENING:
//_playUrl = "rtmfp://" + Config.mediaServerAddr + ":" + Config.mediaServerPort + "/message/" + _streamName;
//_cdnUrl = "rtmp://" + Config.mediaCDNServerAddr + ":" + Config.mediaCDNServerPort + "/message/" + _streamName;
//this.activeChannelId = videoChannelInfo.channelId;
//// AMS/FMS
//if (this._classInfo.msType ==ApeConsts.MS_TYPE_FMS) {
// this.activeURL = `http://dazhi.3mang.com/live/${this._classInfo.classId}/${this._classInfo.classId}_${videoChannelInfo.channelId}_flash_cam_mic_aac/playlist.m3u8`;
//}else {
// this.activeURL = `http://hls.3mang.com/live/${this._classInfo.classId}_${videoChannelInfo.channelId}_flash_cam_mic_aac/playlist.m3u8`;
//}
// 任何人都可以打开流
this.emitVideoChange();
break;
default:
break;
}*/
}
///////数据的封包和解包/////////////////////////////////////////
...
...
@@ -364,14 +263,6 @@ class VideoChat extends Ape {
return
null
;
}
/* message RCVideoChannelInfoPdu {
optional uint32 status = 1;//开启的状态
optional uint32 channel_id = 2;//唯一的频道id
optional uint32 timestamp = 3;//更新的时间戳
optional uint32 from_node_id = 4;//发起者的id
optional uint32 to_node_id = 5;//接收者的id,(如果是0,所有人都接收)
}*/
//判断type类型,根据type设置不同的参数
let
packPduModel
=
new
pdu
[
'RCVideoChannelInfoPdu'
];
packPduModel
.
status
=
_param
.
status
||
ApeConsts
.
CHANNEL_STATUS_RELEASED
;
...
...
@@ -403,53 +294,7 @@ class VideoChat extends Ape {
}
return
null
;
}
//获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId
getFreeVideoChannel
()
{
loger
.
log
(
"getFreeVideoChannel"
);
console
.
log
(
this
.
videoChannels
);
let
counter
=
0
;
for
(
let
key
in
this
.
videoChannels
)
{
let
item
=
this
.
videoChannels
[
key
];
if
(
item
&&
item
.
status
==
ApeConsts
.
CHANNEL_STATUS_RELEASED
)
{
return
item
.
channelId
;
}
counter
++
;
}
if
(
counter
<
GlobalConfig
.
maxVideoChannels
)
{
return
ApeConsts
.
VIDEO_OBJ_TABLE_ID
+
(
counter
);
}
return
0
;
//没有空闲的
}
//获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
getOpeningVideoChannel
(
_nodeId
){
if
(
_nodeId
==
null
||
_nodeId
==
0
){
return
0
;
}
for
(
let
key
in
this
.
videoChannels
)
{
let
item
=
this
.
videoChannels
[
key
];
if
(
item
&&
item
.
status
==
ApeConsts
.
CHANNEL_STATUS_OPENING
&&
item
.
fromNodeId
==
_nodeId
)
{
return
item
.
channelId
;
}
}
return
0
;
}
//检查频道是否已经被占用
checkChannelIsOpening
(
_channelId
){
if
(
_channelId
==
null
){
loger
.
warn
(
"checkChannelIsOpening error,channel="
,
_channelId
);
return
true
;
}
let
channelInfo
=
this
.
videoChannels
[
_channelId
];
if
(
channelInfo
==
null
||
channelInfo
.
status
==
ApeConsts
.
CHANNEL_STATUS_RELEASED
){
return
false
;
}
return
true
;
}
}
export
default
Video
Chat
;
export
default
Video
Ape
;
...
...
src/pdus/pro.js
查看文件 @
66a7623
...
...
@@ -740,10 +740,16 @@ message RCGiftSendDataRequestPdu {
optional
bytes
user_data
=
5
;
}
message
RCAudioSendDataRequestPdu
{
message
RCAudioSendDataRequestPdu
1
{
optional
uint32
initiator
=
1
;
required
bytes
user_data
=
2
;
}
message
RCAudioSendDataRequestPdu
{
required
uint32
from_node_id
=
1
;
//发起人
optional
uint32
to_node_id
=
2
;
//接收人,如果是0就是所有人都接收
optional
uint32
actionType
=
3
;
//消息指令类型;
optional
bytes
data
=
4
;
//其他数据,这个根据actionType来确定数据的结构
}
message
RCVideoSendDataRequestPdu
{
required
uint32
from_node_id
=
1
;
//发起人
...
...
@@ -759,6 +765,17 @@ message RCAudioChannelInfoRecordPdu {
required
uint32
bitrate
=
4
;
required
uint32
codec
=
5
;
}
message
RCAudioChannelInfoPdu
{
optional
uint32
status
=
1
;
//开启的状态
optional
uint32
channel_id
=
2
;
//唯一的频道id
optional
uint32
timestamp
=
3
;
//更新的时间戳
optional
uint32
from_node_id
=
4
;
//发起者的id
optional
uint32
to_node_id
=
5
;
//接收者的id,(如果是0,所有人都接收)
optional
uint32
media_type
=
6
;
//媒体类型:视频(包含音频)或音频
optional
uint32
class_id
=
7
;
//课堂号
optional
string
site_id
=
8
;
//站点号
optional
string
user_id
=
9
;
//用户的userId
}
message
RCVideoChannelInfoPdu
{
optional
uint32
status
=
1
;
//开启的状态
...
...
@@ -907,6 +924,7 @@ message RCClassStatusInfoPdu {
optional
uint32
active_doc_cur_page
=
21
;
//当前激活的文档的当前页
}
//end
`
;
...
...
请
注册
或
登录
后发表评论