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
李勇
8 years ago
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
d333c3126cfdc0a63a24fa7c2f17f6c4ba12e6b9
d333c312
1 parent
ee8cdea7
1.音视频模块推流接口增加optionJsonData:{"bufferTime":0}} 用于设置播放流的时候的bufferTime
隐藏空白字符变更
内嵌
并排对比
正在显示
3 个修改的文件
包含
1066 行增加
和
984 行删除
src/EngineEntrance.js
src/apes/AudioApe.js
src/apes/VideoApe.js
src/EngineEntrance.js
查看文件 @
d333c31
...
...
@@ -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
);
}
}
...
...
src/apes/AudioApe.js
查看文件 @
d333c31
...
...
@@ -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
;
}
}
...
...
src/apes/VideoApe.js
查看文件 @
d333c31
...
...
@@ -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
;
...
...
请
注册
或
登录
后发表评论