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
08789454
Unverified
Commit
08789454
authored
Sep 13, 2022
by
custompal
Committed by
GitHub
Sep 13, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rtsp支持指定播放单一track (#1937)
parent
d04a6d43
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
64 行增加
和
26 行删除
+64
-26
3rdpart/ZLToolKit
+1
-1
player/test_player.cpp
+4
-1
src/Common/config.cpp
+1
-0
src/Common/config.h
+3
-0
src/Rtsp/RtspPlayer.cpp
+14
-3
src/Rtsp/RtspSession.cpp
+39
-21
src/Rtsp/RtspSession.h
+2
-0
没有找到文件。
ZLToolKit
@
9300828f
Subproject commit
82f82e723eda127777aaf91ad0e4615e8d56e8d5
Subproject commit
9300828fd9df9f581d1422171a5f13bdc2a4e6ab
player/test_player.cpp
查看文件 @
08789454
...
...
@@ -53,7 +53,7 @@ int main(int argc, char *argv[]) {
Logger
::
Instance
().
add
(
std
::
make_shared
<
ConsoleChannel
>
());
Logger
::
Instance
().
setWriter
(
std
::
make_shared
<
AsyncLogWriter
>
());
if
(
argc
!=
3
)
{
if
(
argc
<
3
)
{
ErrorL
<<
"
\r\n
测试方法:./test_player rtxp_url rtp_type
\r\n
"
<<
"例如:./test_player rtsp://admin:123456@127.0.0.1/live/0 0
\r\n
"
<<
endl
;
...
...
@@ -119,6 +119,9 @@ int main(int argc, char *argv[]) {
(
*
player
)[
Client
::
kRtpType
]
=
atoi
(
argv
[
2
]);
//不等待track ready再回调播放成功事件,这样可以加快秒开速度
(
*
player
)[
Client
::
kWaitTrackReady
]
=
false
;
if
(
argc
>
3
)
{
(
*
player
)[
Client
::
kPlayTrack
]
=
atoi
(
argv
[
3
]);
}
player
->
play
(
argv
[
1
]);
SDLDisplayerHelper
::
Instance
().
runLoop
();
return
0
;
...
...
src/Common/config.cpp
查看文件 @
08789454
...
...
@@ -317,6 +317,7 @@ const string kMediaTimeoutMS = "media_timeout_ms";
const
string
kBeatIntervalMS
=
"beat_interval_ms"
;
const
string
kBenchmarkMode
=
"benchmark_mode"
;
const
string
kWaitTrackReady
=
"wait_track_ready"
;
const
string
kPlayTrack
=
"play_track"
;
}
// namespace Client
}
// namespace mediakit
...
...
src/Common/config.h
查看文件 @
08789454
...
...
@@ -375,6 +375,9 @@ extern const std::string kBeatIntervalMS;
extern
const
std
::
string
kBenchmarkMode
;
// 播放器在触发播放成功事件时,是否等待所有track ready时再回调
extern
const
std
::
string
kWaitTrackReady
;
// rtsp播放指定track,可选项有0(不指定,默认)、1(视频)、2(音频)
// 设置方法:player[Client::kPlayTrack] = 0/1/2;
extern
const
std
::
string
kPlayTrack
;
}
// namespace Client
}
// namespace mediakit
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
08789454
...
...
@@ -197,13 +197,24 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
_content_base
.
pop_back
();
}
SdpParser
sdpParser
(
parser
.
Content
());
//解析sdp
_sdp_track
=
sdpParser
.
getAvailableTrack
();
SdpParser
sdpParser
(
parser
.
Content
());
string
sdp
;
auto
play_track
=
(
TrackType
)((
int
)(
*
this
)[
Client
::
kPlayTrack
]
-
1
);
if
(
play_track
!=
TrackInvalid
)
{
auto
track
=
sdpParser
.
getTrack
(
play_track
);
_sdp_track
.
emplace_back
(
track
);
sdp
=
track
->
toString
();
}
else
{
_sdp_track
=
sdpParser
.
getAvailableTrack
();
sdp
=
sdpParser
.
toString
();
}
if
(
_sdp_track
.
empty
())
{
throw
std
::
runtime_error
(
"无有效的Sdp Track"
);
}
if
(
!
onCheckSDP
(
sdp
Parser
.
toString
()
))
{
if
(
!
onCheckSDP
(
sdp
))
{
throw
std
::
runtime_error
(
"onCheckSDP faied"
);
}
_rtcp_context
.
clear
();
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
08789454
...
...
@@ -801,13 +801,14 @@ void RtspSession::handleReq_Play(const Parser &parser) {
InfoP
(
this
)
<<
"rtsp seekTo(ms):"
<<
iStartTime
;
}
vector
<
TrackType
>
inited_tracks
;
_StrPrinter
rtp_info
;
for
(
auto
&
track
:
_sdp_track
)
{
if
(
track
->
_inited
==
false
)
{
//还有track没有setup
shutdown
(
SockException
(
Err_shutdown
,
"track not setuped"
));
return
;
//为支持播放器播放单一track, 不校验没有发setup的track
continue
;
}
inited_tracks
.
emplace_back
(
track
->
_type
);
track
->
_ssrc
=
play_src
->
getSsrc
(
track
->
_type
);
track
->
_seq
=
play_src
->
getSeqence
(
track
->
_type
);
track
->
_time_stamp
=
play_src
->
getTimeStamp
(
track
->
_type
);
...
...
@@ -824,6 +825,12 @@ void RtspSession::handleReq_Play(const Parser &parser) {
res_header
.
emplace
(
"Range"
,
StrPrinter
<<
"npt="
<<
setiosflags
(
ios
::
fixed
)
<<
setprecision
(
2
)
<<
play_src
->
getTimeStamp
(
TrackInvalid
)
/
1000.0
);
sendRtspResponse
(
"200 OK"
,
res_header
);
//设置播放track
if
(
inited_tracks
.
size
()
==
1
)
{
_target_play_track
=
inited_tracks
[
0
];
InfoP
(
this
)
<<
"指定播放track:"
<<
_target_play_track
;
}
//在回复rtsp信令后再恢复播放
play_src
->
pause
(
false
);
...
...
@@ -956,13 +963,17 @@ void RtspSession::onRcvPeerUdpData(int interleaved, const Buffer::Ptr &buf, cons
}
else
if
(
!
_udp_connected_flags
.
count
(
interleaved
))
{
//这是rtsp播放器的rtp打洞包
_udp_connected_flags
.
emplace
(
interleaved
);
_rtp_socks
[
interleaved
/
2
]
->
bindPeerAddr
((
struct
sockaddr
*
)
&
addr
);
if
(
_rtp_socks
[
interleaved
/
2
])
{
_rtp_socks
[
interleaved
/
2
]
->
bindPeerAddr
((
struct
sockaddr
*
)
&
addr
);
}
}
}
else
{
//rtcp包
if
(
!
_udp_connected_flags
.
count
(
interleaved
))
{
_udp_connected_flags
.
emplace
(
interleaved
);
_rtcp_socks
[(
interleaved
-
1
)
/
2
]
->
bindPeerAddr
((
struct
sockaddr
*
)
&
addr
);
if
(
_rtcp_socks
[(
interleaved
-
1
)
/
2
])
{
_rtcp_socks
[(
interleaved
-
1
)
/
2
]
->
bindPeerAddr
((
struct
sockaddr
*
)
&
addr
);
}
}
onRtcpPacket
((
interleaved
-
1
)
/
2
,
_sdp_track
[(
interleaved
-
1
)
/
2
],
buf
->
data
(),
buf
->
size
());
}
...
...
@@ -1190,32 +1201,39 @@ void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
void
RtspSession
::
sendRtpPacket
(
const
RtspMediaSource
::
RingDataType
&
pkt
)
{
switch
(
_rtp_type
)
{
case
Rtsp
:
:
RTP_TCP
:
{
size_t
i
=
0
;
auto
size
=
pkt
->
size
();
setSendFlushFlag
(
false
);
pkt
->
for_each
([
&
](
const
RtpPacket
::
Ptr
&
rtp
)
{
updateRtcpContext
(
rtp
);
if
(
++
i
==
size
)
{
se
tSendFlushFlag
(
true
);
if
(
_target_play_track
==
TrackInvalid
||
_target_play_track
==
rtp
->
type
)
{
updateRtcpContext
(
rtp
);
se
nd
(
rtp
);
}
send
(
rtp
);
});
flushAll
();
setSendFlushFlag
(
true
);
}
break
;
case
Rtsp
:
:
RTP_UDP
:
{
size_t
i
=
0
;
auto
size
=
pkt
->
size
();
//下标0表示视频,1表示音频
Socket
::
Ptr
rtp_socks
[
2
];
rtp_socks
[
TrackVideo
]
=
_rtp_socks
[
getTrackIndexByTrackType
(
TrackVideo
)];
rtp_socks
[
TrackAudio
]
=
_rtp_socks
[
getTrackIndexByTrackType
(
TrackAudio
)];
pkt
->
for_each
([
&
](
const
RtpPacket
::
Ptr
&
rtp
)
{
updateRtcpContext
(
rtp
);
int
track_index
=
getTrackIndexByTrackType
(
rtp
->
type
);
auto
&
pSock
=
_rtp_socks
[
track_index
];
if
(
!
pSock
)
{
shutdown
(
SockException
(
Err_shutdown
,
"udp sock not opened yet"
));
return
;
if
(
_target_play_track
==
TrackInvalid
||
_target_play_track
==
rtp
->
type
)
{
updateRtcpContext
(
rtp
);
auto
&
sock
=
rtp_socks
[
rtp
->
type
];
if
(
!
sock
)
{
shutdown
(
SockException
(
Err_shutdown
,
"udp sock not opened yet"
));
return
;
}
_bytes_usage
+=
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
;
sock
->
send
(
std
::
make_shared
<
BufferRtp
>
(
rtp
,
RtpPacket
::
kRtpTcpHeaderSize
),
nullptr
,
0
,
false
);
}
_bytes_usage
+=
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
;
pSock
->
send
(
std
::
make_shared
<
BufferRtp
>
(
rtp
,
RtpPacket
::
kRtpTcpHeaderSize
),
nullptr
,
0
,
++
i
==
size
);
});
for
(
auto
&
sock
:
rtp_socks
)
{
if
(
sock
)
{
sock
->
flushAll
();
}
}
}
break
;
default
:
...
...
src/Rtsp/RtspSession.h
查看文件 @
08789454
...
...
@@ -195,6 +195,8 @@ private:
RtspMediaSource
::
RingType
::
RingReader
::
Ptr
_play_reader
;
//sdp里面有效的track,包含音频或视频
std
::
vector
<
SdpTrack
::
Ptr
>
_sdp_track
;
//播放器setup指定的播放track,默认为TrackInvalid表示不指定即音视频都推
TrackType
_target_play_track
=
TrackInvalid
;
////////RTP over udp////////
//RTP端口,trackid idx 为数组下标
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论