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-22 16:20:09 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c47b2bcade432dedead944e4f9ce3d4f03c69ff6
c47b2bca
1 parent
9845310e
1.调整视频模块,把视频和音频模块共用的功能单独分离出来
隐藏空白字符变更
内嵌
并排对比
正在显示
4 个修改的文件
包含
32 行增加
和
144 行删除
src/EngineEntrance.js
src/McuClientEngine.js
src/apes/ConferApe.js
src/apes/VideoApe.js
src/EngineEntrance.js
查看文件 @
c47b2bc
...
...
@@ -91,7 +91,7 @@ export default class MessageEntrance extends Emiter {
_audio_ape
=
new
AudioApe
();
_audio_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
_audio_ape
.
on
(
MessageTypes
.
AUDIO_UPDATE
,
this
.
vide
oUpdate
.
bind
(
this
));
_audio_ape
.
on
(
MessageTypes
.
AUDIO_UPDATE
,
this
.
audi
oUpdate
.
bind
(
this
));
_whiteboard_ape
=
new
WhiteBoardApe
();
_whiteboard_ape
.
on
(
'*'
,
(
type
,
data
)
=>
this
.
_emit
(
type
,
data
));
...
...
@@ -198,7 +198,7 @@ export default class MessageEntrance extends Emiter {
_video_ape
.
stopPublishVideo
(
_data
);
}
if
(
_audio_ape
){
_
vide
o_ape
.
stopPublishAudio
(
_data
);
_
audi
o_ape
.
stopPublishAudio
(
_data
);
}
}
}
...
...
@@ -206,15 +206,15 @@ export default class MessageEntrance extends Emiter {
//当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
//的占用状态导致,对于这种情况,需要释放掉
_onClassNonentityRoster
(
_param
){
if
(
_param
==
null
||
_param
.
fromN
odeId
==
null
){
if
(
_param
==
null
||
_param
.
n
odeId
==
null
){
loger
.
warn
(
"onClassNonentityRoster.参数错误"
)
return
;
}
if
(
_video_ape
){
_video_ape
.
stopPublishVideo
({
"nodeId"
:
_param
.
fromN
odeId
});
_video_ape
.
stopPublishVideo
({
"nodeId"
:
_param
.
n
odeId
});
}
if
(
_audio_ape
){
_audio_ape
.
stopPublishAudio
({
"nodeId"
:
_param
.
fromN
odeId
});
_audio_ape
.
stopPublishAudio
({
"nodeId"
:
_param
.
n
odeId
});
}
}
...
...
@@ -738,7 +738,7 @@ export default class MessageEntrance extends Emiter {
//AudioApe
audioUpdate
(
_data
){
//
视
频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
//
音
频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
if
(
_confer_ape
){
_confer_ape
.
updaterRosterStatus
(
_data
);
}
...
...
src/McuClientEngine.js
查看文件 @
c47b2bc
//对外暴露的对象
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/apes/ConferApe.js
查看文件 @
c47b2bc
...
...
@@ -454,7 +454,7 @@ class ConferApe extends Ape {
//视频模块发生更新,人员状态需要更新
updaterRosterStatus
(
_param
){
if
(
_param
){
loger
.
log
(
"
视频
模块发生更新,人员状态需要更新,fromNodeId->"
,
_param
.
fromNodeId
);
loger
.
log
(
"
媒体
模块发生更新,人员状态需要更新,fromNodeId->"
,
_param
.
fromNodeId
);
loger
.
log
(
_param
.
status
,
_param
.
fromNodeId
,
this
.
rosters
[
_param
.
fromNodeId
]);
//console.log(_param.fromNodeId);
//如果是自己。改变自己的状态同步到MCU
...
...
@@ -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/VideoApe.js
查看文件 @
c47b2bc
// //////////////////////////////////////////////////////////////////////////////
//
// 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,6 +9,7 @@ import Loger from 'Loger';
import
MessageTypes
from
'MessageTypes'
;
import
GlobalConfig
from
'GlobalConfig'
;
import
EngineUtils
from
'EngineUtils'
;
import
MediaModule
from
"./MediaModule"
;
let
loger
=
Loger
.
getLoger
(
'VideoApe'
);
...
...
@@ -31,8 +21,9 @@ class VideoApe 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 VideoApe 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
);
}
//推流
...
...
@@ -135,20 +65,20 @@ class VideoApe extends Ape {
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
;
}
//判断当前是否还有空闲的channle
let
freeChannel
=
this
.
getFreeVideo
Channel
();
let
freeChannel
=
this
.
mediaModule
.
getFreeMedia
Channel
();
if
(
freeChannel
==
0
)
{
loger
.
warn
(
"publishVideo,没有空闲的channel "
);
return
{
"code"
:
1
,
"data"
:
"不能再打开更多的设备"
};
}
//判断当前的频道是否已经占用
if
(
this
.
checkChannelIsOpening
(
_param
.
channelId
)){
if
(
this
.
mediaModule
.
checkChannelIsOpening
(
_param
.
channelId
)){
loger
.
warn
(
_param
.
channelId
,
"频道已经被占用"
);
return
{
"code"
:
1
,
"data"
:
"频道已经被占用!"
};
}
...
...
@@ -177,7 +107,7 @@ class VideoApe 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,不需要关闭"
};
...
...
@@ -214,7 +144,7 @@ class VideoApe extends Ape {
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"
:
"不能再打开更多的设备"
};
...
...
@@ -325,7 +255,7 @@ class VideoApe extends Ape {
//videoChannelInfo.channelId = itemIdx;
//videoChannelInfo.status = owner === 0 ? ApeConsts.CHANNEL_STATUS_RELEASED : videoChannelInfo.status;
//loger.log('视频消息处理 tableUpdateHandler.',videoChannelInfo);
this
.
video
Channels
[
itemIdx
]
=
videoChannelInfo
;
this
.
mediaModule
.
media
Channels
[
itemIdx
]
=
videoChannelInfo
;
this
.
_emit
(
MessageTypes
.
VIDEO_UPDATE
,
videoChannelInfo
);
/* switch (videoChannelInfo.status) {
...
...
@@ -403,52 +333,6 @@ class VideoApe 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
VideoApe
;
...
...
请
注册
或
登录
后发表评论