Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
62130f77
Commit
62130f77
authored
Nov 27, 2020
by
kingyuanyuan
Committed by
Gitee
Nov 27, 2020
Browse files
Options
Browse Files
Download
Plain Diff
!1 多路RTP 流输出
Merge pull request !1 from kingyuanyuan/branch
parents
f7433b0f
50927548
显示空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
61 行增加
和
43 行删除
+61
-43
server/WebApi.cpp
+4
-4
src/Common/MediaSink.cpp
+1
-1
src/Common/MediaSource.cpp
+9
-9
src/Common/MediaSource.h
+6
-6
src/Common/MultiMediaSourceMuxer.cpp
+18
-10
src/Common/MultiMediaSourceMuxer.h
+3
-3
src/Rtp/RtpSender.cpp
+5
-4
src/Rtp/RtpSender.h
+2
-1
src/Rtp/RtpServer.cpp
+13
-5
没有找到文件。
server/WebApi.cpp
查看文件 @
62130f77
...
...
@@ -825,14 +825,14 @@ void installWebApi() {
api_regist2
(
"/index/api/startSendRtp"
,[](
API_ARGS2
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"ssrc"
,
"dst_url"
,
"dst_port"
,
"is_udp"
);
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"ssrc"
,
"dst_url"
,
"dst_port"
,
"is_udp"
,
"src_port"
);
auto
src
=
MediaSource
::
find
(
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
if
(
!
src
)
{
throw
ApiRetException
(
"该媒体流不存在"
,
API
::
OtherFailed
);
}
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
[
val
,
headerOut
,
invoker
](
const
SockException
&
ex
){
src
->
startSendRtp
(
allArgs
[
"dst_url"
],
allArgs
[
"dst_port"
],
allArgs
[
"ssrc"
],
allArgs
[
"is_udp"
],
allArgs
[
"src_port"
],
[
val
,
headerOut
,
invoker
](
const
SockException
&
ex
){
if
(
ex
)
{
const_cast
<
Value
&>
(
val
)[
"code"
]
=
API
::
OtherFailed
;
const_cast
<
Value
&>
(
val
)[
"msg"
]
=
ex
.
what
();
...
...
@@ -843,14 +843,14 @@ void installWebApi() {
api_regist1
(
"/index/api/stopSendRtp"
,[](
API_ARGS1
){
CHECK_SECRET
();
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
);
CHECK_ARGS
(
"vhost"
,
"app"
,
"stream"
,
"ssrc"
);
auto
src
=
MediaSource
::
find
(
allArgs
[
"vhost"
],
allArgs
[
"app"
],
allArgs
[
"stream"
]);
if
(
!
src
)
{
throw
ApiRetException
(
"该媒体流不存在"
,
API
::
OtherFailed
);
}
if
(
!
src
->
stopSendRtp
(
))
{
if
(
!
src
->
stopSendRtp
(
allArgs
[
"ssrc"
]))
{
throw
ApiRetException
(
"尚未开始推流,停止失败"
,
API
::
OtherFailed
);
}
});
...
...
src/Common/MediaSink.cpp
查看文件 @
62130f77
...
...
@@ -14,7 +14,7 @@
#define MAX_WAIT_MS_READY 10000
//如果添加Track,最多等待5秒
#define MAX_WAIT_MS_ADD_TRACK
5000
#define MAX_WAIT_MS_ADD_TRACK
1000
namespace
mediakit
{
...
...
src/Common/MediaSource.cpp
查看文件 @
62130f77
...
...
@@ -179,21 +179,21 @@ bool MediaSource::isRecording(Recorder::type type){
return
listener
->
isRecording
(
*
this
,
type
);
}
void
MediaSource
::
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
void
MediaSource
::
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
cb
(
SockException
(
Err_other
,
"尚未设置事件监听器"
));
return
;
}
return
listener
->
startSendRtp
(
*
this
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
cb
);
return
listener
->
startSendRtp
(
*
this
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
}
bool
MediaSource
::
stopSendRtp
(
)
{
bool
MediaSource
::
stopSendRtp
(
const
string
&
ssrc
)
{
auto
listener
=
_listener
.
lock
();
if
(
!
listener
)
{
return
false
;
}
return
listener
->
stopSendRtp
(
*
this
);
return
listener
->
stopSendRtp
(
*
this
,
ssrc
);
}
void
MediaSource
::
for_each_media
(
const
function
<
void
(
const
MediaSource
::
Ptr
&
src
)
>
&
cb
)
{
...
...
@@ -638,19 +638,19 @@ vector<Track::Ptr> MediaSourceEventInterceptor::getTracks(MediaSource &sender, b
return
listener
->
getTracks
(
sender
,
trackReady
);
}
void
MediaSourceEventInterceptor
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
void
MediaSourceEventInterceptor
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
auto
listener
=
_listener
.
lock
();
if
(
listener
)
{
listener
->
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
cb
);
listener
->
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
}
else
{
MediaSourceEvent
::
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
cb
);
MediaSourceEvent
::
startSendRtp
(
sender
,
dst_url
,
dst_port
,
ssrc
,
is_udp
,
src_port
,
cb
);
}
}
bool
MediaSourceEventInterceptor
::
stopSendRtp
(
MediaSource
&
sender
){
bool
MediaSourceEventInterceptor
::
stopSendRtp
(
MediaSource
&
sender
,
const
string
&
ssrc
){
auto
listener
=
_listener
.
lock
();
if
(
listener
)
{
return
listener
->
stopSendRtp
(
sender
);
return
listener
->
stopSendRtp
(
sender
,
ssrc
);
}
return
false
;
}
...
...
src/Common/MediaSource.h
查看文件 @
62130f77
...
...
@@ -83,9 +83,9 @@ public:
// 获取所有track相关信息
virtual
vector
<
Track
::
Ptr
>
getTracks
(
MediaSource
&
sender
,
bool
trackReady
=
true
)
const
{
return
vector
<
Track
::
Ptr
>
();
};
// 开始发送ps-rtp
virtual
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
{
cb
(
SockException
(
Err_other
,
"not implemented"
));};
virtual
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
{
cb
(
SockException
(
Err_other
,
"not implemented"
));};
// 停止发送ps-rtp
virtual
bool
stopSendRtp
(
MediaSource
&
sender
)
{
return
false
;
}
virtual
bool
stopSendRtp
(
MediaSource
&
sender
,
const
string
&
ssrc
)
{
return
false
;
}
private
:
Timer
::
Ptr
_async_close_timer
;
...
...
@@ -112,8 +112,8 @@ public:
bool
setupRecord
(
MediaSource
&
sender
,
Recorder
::
type
type
,
bool
start
,
const
string
&
custom_path
)
override
;
bool
isRecording
(
MediaSource
&
sender
,
Recorder
::
type
type
)
override
;
vector
<
Track
::
Ptr
>
getTracks
(
MediaSource
&
sender
,
bool
trackReady
=
true
)
const
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
override
;
bool
stopSendRtp
(
MediaSource
&
sender
)
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
override
;
bool
stopSendRtp
(
MediaSource
&
sender
,
const
string
&
ssrc
)
override
;
private
:
std
::
weak_ptr
<
MediaSourceEvent
>
_listener
;
...
...
@@ -256,9 +256,9 @@ public:
// 获取录制状态
bool
isRecording
(
Recorder
::
type
type
);
// 开始发送ps-rtp
void
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
);
void
startSendRtp
(
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
);
// 停止发送ps-rtp
bool
stopSendRtp
(
);
bool
stopSendRtp
(
const
string
&
ssrc
);
////////////////static方法,查找或生成MediaSource////////////////
...
...
src/Common/MultiMediaSourceMuxer.cpp
查看文件 @
62130f77
...
...
@@ -329,11 +329,11 @@ bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type
return
_muxer
->
isRecording
(
sender
,
type
);
}
void
MultiMediaSourceMuxer
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
void
MultiMediaSourceMuxer
::
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
#if defined(ENABLE_RTPPROXY)
RtpSender
::
Ptr
rtp_sender
=
std
::
make_shared
<
RtpSender
>
(
atoi
(
ssrc
.
data
()));
weak_ptr
<
MultiMediaSourceMuxer
>
weak_self
=
shared_from_this
();
rtp_sender
->
startSend
(
dst_url
,
dst_port
,
is_udp
,
[
weak_self
,
rtp_sender
,
cb
](
const
SockException
&
ex
)
{
rtp_sender
->
startSend
(
dst_url
,
dst_port
,
is_udp
,
src_port
,
[
weak_self
,
rtp_sender
,
cb
,
ssrc
](
const
SockException
&
ex
)
{
cb
(
ex
);
auto
strong_self
=
weak_self
.
lock
();
if
(
!
strong_self
||
ex
)
{
...
...
@@ -343,17 +343,20 @@ void MultiMediaSourceMuxer::startSendRtp(MediaSource &sender, const string &dst_
rtp_sender
->
addTrack
(
track
);
}
rtp_sender
->
addTrackCompleted
();
strong_self
->
_rtp_sender
=
rtp_sender
;
strong_self
->
_rtp_sender
[
ssrc
]
=
rtp_sender
;
});
#else
cb
(
SockException
(
Err_other
,
"该功能未启用,编译时请打开ENABLE_RTPPROXY宏"
));
#endif//ENABLE_RTPPROXY
}
bool
MultiMediaSourceMuxer
::
stopSendRtp
(
MediaSource
&
sender
){
bool
MultiMediaSourceMuxer
::
stopSendRtp
(
MediaSource
&
sender
,
const
string
&
ssrc
){
#if defined(ENABLE_RTPPROXY)
if
(
_rtp_sender
)
{
_rtp_sender
=
nullptr
;
map
<
string
,
RtpSender
::
Ptr
>::
iterator
ite
=
_rtp_sender
.
find
(
ssrc
);
if
(
ite
!=
_rtp_sender
.
end
())
{
ite
->
second
=
nullptr
;
_rtp_sender
.
erase
(
ite
);
return
true
;
}
#endif//ENABLE_RTPPROXY
...
...
@@ -442,9 +445,14 @@ void MultiMediaSourceMuxer::inputFrame(const Frame::Ptr &frame_in) {
_muxer
->
inputFrame
(
frame
);
#if defined(ENABLE_RTPPROXY)
auto
rtp_sender
=
_rtp_sender
;
if
(
rtp_sender
)
{
rtp_sender
->
inputFrame
(
frame
);
map
<
string
,
RtpSender
::
Ptr
>::
iterator
ite
=
_rtp_sender
.
begin
();
while
(
ite
!=
_rtp_sender
.
end
())
{
if
(
ite
->
second
)
{
ite
->
second
->
inputFrame
(
frame
);
}
ite
++
;
}
#endif //ENABLE_RTPPROXY
...
...
@@ -456,7 +464,7 @@ bool MultiMediaSourceMuxer::isEnabled(){
//无人观看时,每次检查是否真的无人观看
//有人观看时,则延迟一定时间检查一遍是否无人观看了(节省性能)
#if defined(ENABLE_RTPPROXY)
_is_enable
=
(
_muxer
->
isEnabled
()
||
_rtp_sender
);
_is_enable
=
(
_muxer
->
isEnabled
()
||
_rtp_sender
.
size
());
#else
_is_enable
=
_muxer
->
isEnabled
();
#endif //ENABLE_RTPPROXY
...
...
src/Common/MultiMediaSourceMuxer.h
查看文件 @
62130f77
...
...
@@ -142,13 +142,13 @@ public:
* @param is_udp 是否为udp
* @param cb 启动成功或失败回调
*/
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
override
;
void
startSendRtp
(
MediaSource
&
sender
,
const
string
&
dst_url
,
uint16_t
dst_port
,
const
string
&
ssrc
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
override
;
/**
* 停止ps-rtp发送
* @return 是否成功
*/
bool
stopSendRtp
(
MediaSource
&
sender
)
override
;
bool
stopSendRtp
(
MediaSource
&
sender
,
const
string
&
ssrc
)
override
;
/////////////////////////////////MediaSinkInterface override/////////////////////////////////
...
...
@@ -189,7 +189,7 @@ private:
MultiMuxerPrivate
::
Ptr
_muxer
;
std
::
weak_ptr
<
MultiMuxerPrivate
::
Listener
>
_track_listener
;
#if defined(ENABLE_RTPPROXY)
RtpSender
::
Ptr
_rtp_sender
;
map
<
string
,
RtpSender
::
Ptr
>
_rtp_sender
;
#endif //ENABLE_RTPPROXY
};
...
...
src/Rtp/RtpSender.cpp
查看文件 @
62130f77
...
...
@@ -26,14 +26,15 @@ RtpSender::RtpSender(uint32_t ssrc, uint8_t payload_type) {
RtpSender
::~
RtpSender
()
{
}
void
RtpSender
::
startSend
(
const
string
&
dst_url
,
uint16_t
dst_port
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
void
RtpSender
::
startSend
(
const
string
&
dst_url
,
uint16_t
dst_port
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
){
_is_udp
=
is_udp
;
_socket
=
Socket
::
createSocket
(
_poller
,
false
);
_dst_url
=
dst_url
;
_dst_port
=
dst_port
;
_src_port
=
src_port
;
weak_ptr
<
RtpSender
>
weak_self
=
shared_from_this
();
if
(
is_udp
)
{
_socket
->
bindUdpSock
(
0
);
_socket
->
bindUdpSock
(
src_port
);
auto
poller
=
_poller
;
WorkThreadPool
::
Instance
().
getPoller
()
->
async
([
cb
,
dst_url
,
dst_port
,
weak_self
,
poller
]()
{
struct
sockaddr
addr
;
...
...
@@ -65,7 +66,7 @@ void RtpSender::startSend(const string &dst_url, uint16_t dst_port, bool is_udp,
//tcp连接成功
strong_self
->
onConnect
();
}
}
);
}
,
5.0
F
,
"0.0.0.0"
,
src_port
);
}
}
...
...
@@ -149,7 +150,7 @@ void RtpSender::onErr(const SockException &ex, bool is_connect) {
if
(
!
strong_self
)
{
return
false
;
}
strong_self
->
startSend
(
strong_self
->
_dst_url
,
strong_self
->
_dst_port
,
strong_self
->
_is_udp
,
[
weak_self
](
const
SockException
&
ex
){
strong_self
->
startSend
(
strong_self
->
_dst_url
,
strong_self
->
_dst_port
,
strong_self
->
_is_udp
,
strong_self
->
_src_port
,
[
weak_self
](
const
SockException
&
ex
){
auto
strong_self
=
weak_self
.
lock
();
if
(
strong_self
&&
ex
)
{
//连接失败且本对象未销毁,那么重试连接
...
...
src/Rtp/RtpSender.h
查看文件 @
62130f77
...
...
@@ -37,7 +37,7 @@ public:
* @param is_udp 是否采用udp方式发送rtp
* @param cb 连接目标端口是否成功的回调
*/
void
startSend
(
const
string
&
dst_url
,
uint16_t
dst_port
,
bool
is_udp
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
);
void
startSend
(
const
string
&
dst_url
,
uint16_t
dst_port
,
bool
is_udp
,
uint16_t
src_port
,
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
);
/**
* 输入帧数据
...
...
@@ -74,6 +74,7 @@ private:
bool
_is_connect
=
false
;
string
_dst_url
;
uint16_t
_dst_port
;
uint16_t
_src_port
;
Socket
::
Ptr
_socket
;
EventPoller
::
Ptr
_poller
;
Timer
::
Ptr
_connect_timer
;
...
...
src/Rtp/RtpServer.cpp
查看文件 @
62130f77
...
...
@@ -51,20 +51,28 @@ void RtpServer::start(uint16_t local_port, const string &stream_id, bool enable
if
(
!
stream_id
.
empty
())
{
//指定了流id,那么一个端口一个流(不管是否包含多个ssrc的多个流,绑定rtp源后,会筛选掉ip端口不匹配的流)
process
=
RtpSelector
::
Instance
().
getProcess
(
stream_id
,
true
);
udp_server
->
setOnRead
([
udp_server
,
process
](
const
Buffer
::
Ptr
&
buf
,
struct
sockaddr
*
addr
,
int
)
{
process
->
inputRtp
(
true
,
udp_server
,
buf
->
data
(),
buf
->
size
(),
addr
);
//udp_server->setOnRead([udp_server, process](const Buffer::Ptr &buf, struct sockaddr *addr, int) {
// process->inputRtp(true, udp_server, buf->data(), buf->size(), addr);
//});
weak_ptr
<
Socket
>
weak_sock
=
udp_server
;
udp_server
->
setOnRead
([
weak_sock
,
process
](
const
Buffer
::
Ptr
&
buf
,
struct
sockaddr
*
addr
,
int
)
{
process
->
inputRtp
(
true
,
weak_sock
.
lock
(),
buf
->
data
(),
buf
->
size
(),
addr
);
});
}
else
{
//未指定流id,一个端口多个流,通过ssrc来分流
auto
&
ref
=
RtpSelector
::
Instance
();
udp_server
->
setOnRead
([
&
ref
,
udp_server
](
const
Buffer
::
Ptr
&
buf
,
struct
sockaddr
*
addr
,
int
)
{
ref
.
inputRtp
(
udp_server
,
buf
->
data
(),
buf
->
size
(),
addr
);
//udp_server->setOnRead([&ref, udp_server](const Buffer::Ptr &buf, struct sockaddr *addr, int) {
// ref.inputRtp(udp_server, buf->data(), buf->size(), addr);
//});
weak_ptr
<
Socket
>
weak_sock
=
udp_server
;
udp_server
->
setOnRead
([
&
ref
,
weak_sock
](
const
Buffer
::
Ptr
&
buf
,
struct
sockaddr
*
addr
,
int
)
{
ref
.
inputRtp
(
weak_sock
.
lock
(),
buf
->
data
(),
buf
->
size
(),
addr
);
});
}
_on_clearup
=
[
udp_server
,
process
,
stream_id
]()
{
//去除循环引用
udp_server
->
setOnRead
(
nullptr
);
//udp_server->setOnRead(nullptr);
if
(
process
)
{
//删除rtp处理器
RtpSelector
::
Instance
().
delProcess
(
stream_id
,
process
.
get
());
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论