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
f71a9bfa
Commit
f71a9bfa
authored
4 years ago
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复rtsp播放器时间戳紊乱的bug
parent
cded823b
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
153 行增加
和
166 行删除
+153
-166
src/Rtsp/RtspPlayer.cpp
+128
-141
src/Rtsp/RtspPlayer.h
+25
-25
没有找到文件。
src/Rtsp/RtspPlayer.cpp
查看文件 @
f71a9bfa
...
...
@@ -10,14 +10,11 @@
#include <set>
#include <cmath>
#include <stdarg.h>
#include <algorithm>
#include <iomanip>
#include "Common/config.h"
#include "RtspPlayer.h"
#include "Util/MD5.h"
#include "Util/mini.h"
#include "Util/util.h"
#include "Util/base64.h"
#include "Network/sockutil.h"
...
...
@@ -40,28 +37,28 @@ RtspPlayer::~RtspPlayer(void) {
}
void
RtspPlayer
::
teardown
(){
if
(
alive
())
{
sendRtspRequest
(
"TEARDOWN"
,
_
strContentB
ase
);
sendRtspRequest
(
"TEARDOWN"
,
_
content_b
ase
);
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
}
_
rtspMd5N
once
.
clear
();
_r
tspR
ealm
.
clear
();
_
aTrackInfo
.
clear
();
_s
trSession
.
clear
();
_
strContentB
ase
.
clear
();
_
md5_n
once
.
clear
();
_realm
.
clear
();
_
sdp_track
.
clear
();
_s
ession_id
.
clear
();
_
content_b
ase
.
clear
();
RtpReceiver
::
clear
();
CLEAR_ARR
(
_
apRtpS
ock
);
CLEAR_ARR
(
_
apRtcpS
ock
);
CLEAR_ARR
(
_
aui16FirstSeq
)
CLEAR_ARR
(
_
aui64RtpRecv
)
CLEAR_ARR
(
_
aui64RtpRecv
)
CLEAR_ARR
(
_
aui16NowSeq
)
_p
PlayT
imer
.
reset
();
_
pRtpT
imer
.
reset
();
_
uiCseq
=
1
;
_on
Handshak
e
=
nullptr
;
CLEAR_ARR
(
_
rtp_s
ock
);
CLEAR_ARR
(
_
rtcp_s
ock
);
CLEAR_ARR
(
_
rtp_seq_start
)
CLEAR_ARR
(
_
rtp_recv_count
)
CLEAR_ARR
(
_
rtp_recv_count
)
CLEAR_ARR
(
_
rtp_seq_now
)
_p
lay_check_t
imer
.
reset
();
_
rtp_check_t
imer
.
reset
();
_
cseq_send
=
1
;
_on
_respons
e
=
nullptr
;
}
void
RtspPlayer
::
play
(
const
string
&
strUrl
){
...
...
@@ -81,20 +78,20 @@ void RtspPlayer::play(const string &strUrl){
(
*
this
)[
kRtspPwdIsMD5
]
=
false
;
}
_
strU
rl
=
url
.
_url
;
_
eT
ype
=
(
Rtsp
::
eRtpType
)(
int
)(
*
this
)[
kRtpType
];
DebugL
<<
url
.
_url
<<
" "
<<
(
url
.
_user
.
size
()
?
url
.
_user
:
"null"
)
<<
" "
<<
(
url
.
_passwd
.
size
()
?
url
.
_passwd
:
"null"
)
<<
" "
<<
_
eT
ype
;
_
play_u
rl
=
url
.
_url
;
_
rtp_t
ype
=
(
Rtsp
::
eRtpType
)(
int
)(
*
this
)[
kRtpType
];
DebugL
<<
url
.
_url
<<
" "
<<
(
url
.
_user
.
size
()
?
url
.
_user
:
"null"
)
<<
" "
<<
(
url
.
_passwd
.
size
()
?
url
.
_passwd
:
"null"
)
<<
" "
<<
_
rtp_t
ype
;
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
float
playTimeOutSec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
_p
PlayTimer
.
reset
(
new
Timer
(
playTimeOutSec
,
[
weakSelf
]()
{
_p
lay_check_timer
.
reset
(
new
Timer
(
playTimeOutSec
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
strongSelf
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"play rtsp timeout"
),
false
);
return
false
;
},
getPoller
()));
},
getPoller
()));
if
(
!
(
*
this
)[
kNetAdapter
].
empty
()){
setNetAdapter
((
*
this
)[
kNetAdapter
]);
...
...
@@ -111,9 +108,9 @@ void RtspPlayer::onConnect(const SockException &err){
}
void
RtspPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
{
if
(
_benchmark_mode
&&
!
_p
PlayT
imer
){
if
(
_benchmark_mode
&&
!
_p
lay_check_t
imer
){
//在性能测试模式下,如果rtsp握手完毕后,不再解析rtp包
_rtp
T
icker
.
resetTime
();
_rtp
_recv_t
icker
.
resetTime
();
return
;
}
input
(
pBuf
->
data
(),
pBuf
->
size
());
...
...
@@ -121,12 +118,12 @@ void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
void
RtspPlayer
::
onErr
(
const
SockException
&
ex
)
{
//定时器_pPlayTimer为空后表明握手结束了
onPlayResult_l
(
ex
,
!
_p
PlayT
imer
);
onPlayResult_l
(
ex
,
!
_p
lay_check_t
imer
);
}
// from live555
bool
RtspPlayer
::
handleAuthenticationFailure
(
const
string
&
paramsStr
)
{
if
(
!
_r
tspR
ealm
.
empty
()){
if
(
!
_realm
.
empty
()){
//已经认证过了
return
false
;
}
...
...
@@ -141,17 +138,17 @@ bool RtspPlayer::handleAuthenticationFailure(const string ¶msStr) {
});
if
(
sscanf
(
paramsStr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
, stale=%[a-zA-Z]"
,
realm
,
nonce
,
stale
)
==
3
)
{
_r
tspR
ealm
=
(
const
char
*
)
realm
;
_
rtspMd5N
once
=
(
const
char
*
)
nonce
;
_realm
=
(
const
char
*
)
realm
;
_
md5_n
once
=
(
const
char
*
)
nonce
;
return
true
;
}
if
(
sscanf
(
paramsStr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
"
,
realm
,
nonce
)
==
2
)
{
_r
tspR
ealm
=
(
const
char
*
)
realm
;
_
rtspMd5N
once
=
(
const
char
*
)
nonce
;
_realm
=
(
const
char
*
)
realm
;
_
md5_n
once
=
(
const
char
*
)
nonce
;
return
true
;
}
if
(
sscanf
(
paramsStr
.
data
(),
"Basic realm=
\"
%[^
\"
]
\"
"
,
realm
)
==
1
)
{
_r
tspR
ealm
=
(
const
char
*
)
realm
;
_realm
=
(
const
char
*
)
realm
;
return
true
;
}
return
false
;
...
...
@@ -176,30 +173,25 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
throw
std
::
runtime_error
(
StrPrinter
<<
"DESCRIBE:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
_
strContentB
ase
=
parser
[
"Content-Base"
];
_
content_b
ase
=
parser
[
"Content-Base"
];
if
(
_
strContentB
ase
.
empty
()){
_
strContentBase
=
_strU
rl
;
if
(
_
content_b
ase
.
empty
()){
_
content_base
=
_play_u
rl
;
}
if
(
_
strContentB
ase
.
back
()
==
'/'
)
{
_
strContentB
ase
.
pop_back
();
if
(
_
content_b
ase
.
back
()
==
'/'
)
{
_
content_b
ase
.
pop_back
();
}
SdpParser
sdpParser
(
parser
.
Content
());
//解析sdp
_
aTrackInfo
=
sdpParser
.
getAvailableTrack
();
_
sdp_track
=
sdpParser
.
getAvailableTrack
();
auto
title
=
sdpParser
.
getTrack
(
TrackTitle
);
_
is_play_back
=
false
;
bool
is_play_back
=
false
;
if
(
title
&&
title
->
_duration
){
_is_play_back
=
true
;
}
for
(
auto
&
stamp
:
_stamp
){
stamp
.
setPlayBack
(
_is_play_back
);
stamp
.
setRelativeStamp
(
0
);
is_play_back
=
true
;
}
if
(
_
aTrackInfo
.
empty
())
{
if
(
_
sdp_track
.
empty
())
{
throw
std
::
runtime_error
(
"无有效的Sdp Track"
);
}
if
(
!
onCheckSDP
(
sdpParser
.
toString
()))
{
...
...
@@ -211,8 +203,8 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
//有必要的情况下创建udp端口
void
RtspPlayer
::
createUdpSockIfNecessary
(
int
track_idx
){
auto
&
rtpSockRef
=
_
apRtpS
ock
[
track_idx
];
auto
&
rtcpSockRef
=
_
apRtcpS
ock
[
track_idx
];
auto
&
rtpSockRef
=
_
rtp_s
ock
[
track_idx
];
auto
&
rtcpSockRef
=
_
rtcp_s
ock
[
track_idx
];
if
(
!
rtpSockRef
||
!
rtcpSockRef
)
{
auto
pr
=
makeSockPair
(
getPoller
(),
get_local_ip
());
rtpSockRef
=
pr
.
first
;
...
...
@@ -222,10 +214,10 @@ void RtspPlayer::createUdpSockIfNecessary(int track_idx){
//发送SETUP命令
void
RtspPlayer
::
sendSetup
(
unsigned
int
trackIndex
)
{
_on
Handshake
=
std
::
bind
(
&
RtspPlayer
::
handleResSETUP
,
this
,
placeholders
::
_1
,
trackIndex
);
auto
&
track
=
_
aTrackInfo
[
trackIndex
];
auto
baseUrl
=
_
strContentB
ase
+
"/"
+
track
->
_control_surffix
;
switch
(
_
eT
ype
)
{
_on
_response
=
std
::
bind
(
&
RtspPlayer
::
handleResSETUP
,
this
,
placeholders
::
_1
,
trackIndex
);
auto
&
track
=
_
sdp_track
[
trackIndex
];
auto
baseUrl
=
_
content_b
ase
+
"/"
+
track
->
_control_surffix
;
switch
(
_
rtp_t
ype
)
{
case
Rtsp
:
:
RTP_TCP
:
{
sendRtspRequest
(
"SETUP"
,
baseUrl
,{
"Transport"
,
StrPrinter
<<
"RTP/AVP/TCP;unicast;interleaved="
<<
track
->
_type
*
2
<<
"-"
<<
track
->
_type
*
2
+
1
});
}
...
...
@@ -236,10 +228,10 @@ void RtspPlayer::sendSetup(unsigned int trackIndex) {
break
;
case
Rtsp
:
:
RTP_UDP
:
{
createUdpSockIfNecessary
(
trackIndex
);
sendRtspRequest
(
"SETUP"
,
baseUrl
,
{
"Transport"
,
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
_apRtpS
ock
[
trackIndex
]
->
get_local_port
()
<<
"-"
<<
_apRtcpS
ock
[
trackIndex
]
->
get_local_port
()});
sendRtspRequest
(
"SETUP"
,
baseUrl
,
{
"Transport"
,
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
_rtp_s
ock
[
trackIndex
]
->
get_local_port
()
<<
"-"
<<
_rtcp_s
ock
[
trackIndex
]
->
get_local_port
()});
}
break
;
default
:
...
...
@@ -253,34 +245,34 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
StrPrinter
<<
"SETUP:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
if
(
uiTrackIndex
==
0
)
{
_s
trSession
=
parser
[
"Session"
];
_s
trSession
.
append
(
";"
);
_s
trSession
=
FindField
(
_strSession
.
data
(),
nullptr
,
";"
);
_s
ession_id
=
parser
[
"Session"
];
_s
ession_id
.
append
(
";"
);
_s
ession_id
=
FindField
(
_session_id
.
data
(),
nullptr
,
";"
);
}
auto
strTransport
=
parser
[
"Transport"
];
if
(
strTransport
.
find
(
"TCP"
)
!=
string
::
npos
||
strTransport
.
find
(
"interleaved"
)
!=
string
::
npos
){
_
eT
ype
=
Rtsp
::
RTP_TCP
;
_
rtp_t
ype
=
Rtsp
::
RTP_TCP
;
}
else
if
(
strTransport
.
find
(
"multicast"
)
!=
string
::
npos
){
_
eT
ype
=
Rtsp
::
RTP_MULTICAST
;
_
rtp_t
ype
=
Rtsp
::
RTP_MULTICAST
;
}
else
{
_
eT
ype
=
Rtsp
::
RTP_UDP
;
_
rtp_t
ype
=
Rtsp
::
RTP_UDP
;
}
RtspSplitter
::
enableRecvRtp
(
_
eT
ype
==
Rtsp
::
RTP_TCP
);
RtspSplitter
::
enableRecvRtp
(
_
rtp_t
ype
==
Rtsp
::
RTP_TCP
);
if
(
_
eT
ype
==
Rtsp
::
RTP_TCP
)
{
if
(
_
rtp_t
ype
==
Rtsp
::
RTP_TCP
)
{
string
interleaved
=
FindField
(
FindField
((
strTransport
+
";"
).
data
(),
"interleaved="
,
";"
).
data
(),
NULL
,
"-"
);
_
aTrackInfo
[
uiTrackIndex
]
->
_interleaved
=
atoi
(
interleaved
.
data
());
_
sdp_track
[
uiTrackIndex
]
->
_interleaved
=
atoi
(
interleaved
.
data
());
}
else
{
const
char
*
strPos
=
(
_
eT
ype
==
Rtsp
::
RTP_MULTICAST
?
"port="
:
"server_port="
)
;
const
char
*
strPos
=
(
_
rtp_t
ype
==
Rtsp
::
RTP_MULTICAST
?
"port="
:
"server_port="
)
;
auto
port_str
=
FindField
((
strTransport
+
";"
).
data
(),
strPos
,
";"
);
uint16_t
rtp_port
=
atoi
(
FindField
(
port_str
.
data
(),
NULL
,
"-"
).
data
());
uint16_t
rtcp_port
=
atoi
(
FindField
(
port_str
.
data
(),
"-"
,
NULL
).
data
());
auto
&
pRtpSockRef
=
_
apRtpS
ock
[
uiTrackIndex
];
auto
&
pRtcpSockRef
=
_
apRtcpS
ock
[
uiTrackIndex
];
auto
&
pRtpSockRef
=
_
rtp_s
ock
[
uiTrackIndex
];
auto
&
pRtcpSockRef
=
_
rtcp_s
ock
[
uiTrackIndex
];
if
(
_
eT
ype
==
Rtsp
::
RTP_MULTICAST
)
{
if
(
_
rtp_t
ype
==
Rtsp
::
RTP_MULTICAST
)
{
//udp组播
auto
multiAddr
=
FindField
((
strTransport
+
";"
).
data
(),
"destination="
,
";"
);
pRtpSockRef
.
reset
(
new
Socket
(
getPoller
()));
...
...
@@ -322,7 +314,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
WarnL
<<
"收到其他地址的rtp数据:"
<<
SockUtil
::
inet_ntoa
(((
struct
sockaddr_in
*
)
addr
)
->
sin_addr
);
return
;
}
strongSelf
->
handleOneRtp
(
uiTrackIndex
,
strongSelf
->
_
aTrackInfo
[
uiTrackIndex
],
(
unsigned
char
*
)
buf
->
data
(),
buf
->
size
());
strongSelf
->
handleOneRtp
(
uiTrackIndex
,
strongSelf
->
_
sdp_track
[
uiTrackIndex
],
(
unsigned
char
*
)
buf
->
data
(),
buf
->
size
());
});
if
(
pRtcpSockRef
)
{
...
...
@@ -336,12 +328,12 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
WarnL
<<
"收到其他地址的rtcp数据:"
<<
SockUtil
::
inet_ntoa
(((
struct
sockaddr_in
*
)
addr
)
->
sin_addr
);
return
;
}
strongSelf
->
onRtcpPacket
(
uiTrackIndex
,
strongSelf
->
_
aTrackInfo
[
uiTrackIndex
],
(
unsigned
char
*
)
buf
->
data
(),
buf
->
size
());
strongSelf
->
onRtcpPacket
(
uiTrackIndex
,
strongSelf
->
_
sdp_track
[
uiTrackIndex
],
(
unsigned
char
*
)
buf
->
data
(),
buf
->
size
());
});
}
}
if
(
uiTrackIndex
<
_
aTrackInfo
.
size
()
-
1
)
{
if
(
uiTrackIndex
<
_
sdp_track
.
size
()
-
1
)
{
//需要继续发送SETUP命令
sendSetup
(
uiTrackIndex
+
1
);
return
;
...
...
@@ -353,12 +345,12 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
void
RtspPlayer
::
sendDescribe
()
{
//发送DESCRIBE命令后处理函数:handleResDESCRIBE
_on
Handshake
=
std
::
bind
(
&
RtspPlayer
::
handleResDESCRIBE
,
this
,
placeholders
::
_1
);
sendRtspRequest
(
"DESCRIBE"
,
_strUrl
,{
"Accept"
,
"application/sdp"
});
_on
_response
=
std
::
bind
(
&
RtspPlayer
::
handleResDESCRIBE
,
this
,
placeholders
::
_1
);
sendRtspRequest
(
"DESCRIBE"
,
_play_url
,
{
"Accept"
,
"application/sdp"
});
}
void
RtspPlayer
::
sendOptions
(){
_on
Handshak
e
=
[
this
](
const
Parser
&
parser
){
_on
_respons
e
=
[
this
](
const
Parser
&
parser
){
if
(
parser
.
Url
()
!=
"200"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"OPTIONS:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
...
...
@@ -372,36 +364,36 @@ void RtspPlayer::sendOptions(){
//发送Describe请求,获取sdp
sendDescribe
();
};
sendRtspRequest
(
"OPTIONS"
,
_strU
rl
);
sendRtspRequest
(
"OPTIONS"
,
_play_u
rl
);
}
void
RtspPlayer
::
sendKeepAlive
(){
_on
Handshak
e
=
[
this
](
const
Parser
&
parser
){};
_on
_respons
e
=
[
this
](
const
Parser
&
parser
){};
if
(
_supported_cmd
.
find
(
"GET_PARAMETER"
)
!=
_supported_cmd
.
end
()){
//支持GET_PARAMETER,用此命令保活
sendRtspRequest
(
"GET_PARAMETER"
,
_strU
rl
);
sendRtspRequest
(
"GET_PARAMETER"
,
_play_u
rl
);
}
else
{
//不支持GET_PARAMETER,用OPTIONS命令保活
sendRtspRequest
(
"OPTIONS"
,
_strU
rl
);
sendRtspRequest
(
"OPTIONS"
,
_play_u
rl
);
}
}
void
RtspPlayer
::
sendPause
(
int
type
,
uint32_t
seekMS
){
_on
Handshake
=
std
::
bind
(
&
RtspPlayer
::
handleResPAUSE
,
this
,
placeholders
::
_1
,
type
);
_on
_response
=
std
::
bind
(
&
RtspPlayer
::
handleResPAUSE
,
this
,
placeholders
::
_1
,
type
);
//开启或暂停rtsp
switch
(
type
){
case
type_pause
:
sendRtspRequest
(
"PAUSE"
,
_
strContentB
ase
);
sendRtspRequest
(
"PAUSE"
,
_
content_b
ase
);
break
;
case
type_play
:
sendRtspRequest
(
"PLAY"
,
_
strContentB
ase
);
sendRtspRequest
(
"PLAY"
,
_
content_b
ase
);
break
;
case
type_seek
:
sendRtspRequest
(
"PLAY"
,
_
strContentB
ase
,
{
"Range"
,
StrPrinter
<<
"npt="
<<
setiosflags
(
ios
::
fixed
)
<<
setprecision
(
2
)
<<
seekMS
/
1000.0
<<
"-"
});
sendRtspRequest
(
"PLAY"
,
_
content_b
ase
,
{
"Range"
,
StrPrinter
<<
"npt="
<<
setiosflags
(
ios
::
fixed
)
<<
setprecision
(
2
)
<<
seekMS
/
1000.0
<<
"-"
});
break
;
default
:
WarnL
<<
"unknown type : "
<<
type
;
_on
Handshak
e
=
nullptr
;
_on
_respons
e
=
nullptr
;
break
;
}
}
...
...
@@ -428,7 +420,7 @@ void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
if
(
type
==
type_pause
)
{
//暂停成功!
_
pRtpT
imer
.
reset
();
_
rtp_check_t
imer
.
reset
();
return
;
}
...
...
@@ -445,22 +437,20 @@ void RtspPlayer::handleResPAUSE(const Parser& parser,int type) {
DebugL
<<
"seekTo(ms):"
<<
iSeekTo
;
}
//设置相对时间戳
_stamp
[
0
].
setRelativeStamp
(
iSeekTo
);
_stamp
[
1
].
setRelativeStamp
(
iSeekTo
);
onPlayResult_l
(
SockException
(
Err_success
,
type
==
type_seek
?
"resum rtsp success"
:
"rtsp play success"
),
type
==
type_seek
);
}
void
RtspPlayer
::
onWholeRtspPacket
(
Parser
&
parser
)
{
try
{
decltype
(
_on
Handshake
)
fun
;
_on
Handshake
.
swap
(
fun
);
if
(
fun
){
fun
(
parser
);
decltype
(
_on
_response
)
func
;
_on
_response
.
swap
(
func
);
if
(
fun
c
){
fun
c
(
parser
);
}
parser
.
Clear
();
}
catch
(
std
::
exception
&
err
)
{
//定时器_pPlayTimer为空后表明握手结束了
onPlayResult_l
(
SockException
(
Err_other
,
err
.
what
()),
!
_p
PlayT
imer
);
onPlayResult_l
(
SockException
(
Err_other
,
err
.
what
()),
!
_p
lay_check_t
imer
);
}
}
...
...
@@ -470,12 +460,12 @@ void RtspPlayer::onRtpPacket(const char *data, uint64_t len) {
if
(
interleaved
%
2
==
0
){
trackIdx
=
getTrackIndexByInterleaved
(
interleaved
);
if
(
trackIdx
!=
-
1
)
{
handleOneRtp
(
trackIdx
,
_aTrackInfo
[
trackIdx
],
(
unsigned
char
*
)
data
+
4
,
len
-
4
);
handleOneRtp
(
trackIdx
,
_sdp_track
[
trackIdx
],
(
unsigned
char
*
)
data
+
4
,
len
-
4
);
}
}
else
{
trackIdx
=
getTrackIndexByInterleaved
(
interleaved
-
1
);
if
(
trackIdx
!=
-
1
)
{
onRtcpPacket
(
trackIdx
,
_
aTrackInfo
[
trackIdx
],
(
unsigned
char
*
)
data
+
4
,
len
-
4
);
onRtcpPacket
(
trackIdx
,
_
sdp_track
[
trackIdx
],
(
unsigned
char
*
)
data
+
4
,
len
-
4
);
}
}
}
...
...
@@ -545,8 +535,8 @@ void RtspPlayer::sendReceiverReport(bool overTcp,int iTrackIndex){
static
const
char
s_cname
[]
=
"ZLMediaKitRtsp"
;
uint8_t
aui8Rtcp
[
4
+
32
+
10
+
sizeof
(
s_cname
)
+
1
]
=
{
0
};
uint8_t
*
pui8Rtcp_RR
=
aui8Rtcp
+
4
,
*
pui8Rtcp_SDES
=
pui8Rtcp_RR
+
32
;
auto
&
track
=
_
aTrackInfo
[
iTrackIndex
];
auto
&
counter
=
_
aRtcpCnt
[
iTrackIndex
];
auto
&
track
=
_
sdp_track
[
iTrackIndex
];
auto
&
counter
=
_
rtcp_counter
[
iTrackIndex
];
aui8Rtcp
[
0
]
=
'$'
;
aui8Rtcp
[
1
]
=
track
->
_interleaved
+
1
;
...
...
@@ -602,25 +592,22 @@ void RtspPlayer::sendReceiverReport(bool overTcp,int iTrackIndex){
if
(
overTcp
){
send
(
obtainBuffer
((
char
*
)
aui8Rtcp
,
sizeof
(
aui8Rtcp
)));
}
else
if
(
_
apRtcpS
ock
[
iTrackIndex
])
{
_
apRtcpS
ock
[
iTrackIndex
]
->
send
((
char
*
)
aui8Rtcp
+
4
,
sizeof
(
aui8Rtcp
)
-
4
);
}
else
if
(
_
rtcp_s
ock
[
iTrackIndex
])
{
_
rtcp_s
ock
[
iTrackIndex
]
->
send
((
char
*
)
aui8Rtcp
+
4
,
sizeof
(
aui8Rtcp
)
-
4
);
}
}
void
RtspPlayer
::
onRtpSorted
(
const
RtpPacket
::
Ptr
&
rtppt
,
int
trackidx
){
//统计丢包率
if
(
_
aui16FirstSeq
[
trackidx
]
==
0
||
rtppt
->
sequence
<
_aui16FirstSeq
[
trackidx
])
{
_
aui16FirstSeq
[
trackidx
]
=
rtppt
->
sequence
;
_
aui64RtpRecv
[
trackidx
]
=
0
;
if
(
_
rtp_seq_start
[
trackidx
]
==
0
||
rtppt
->
sequence
<
_rtp_seq_start
[
trackidx
])
{
_
rtp_seq_start
[
trackidx
]
=
rtppt
->
sequence
;
_
rtp_recv_count
[
trackidx
]
=
0
;
}
_
aui64RtpRecv
[
trackidx
]
++
;
_
aui16NowSeq
[
trackidx
]
=
rtppt
->
sequence
;
_
rtp_recv_count
[
trackidx
]
++
;
_
rtp_seq_now
[
trackidx
]
=
rtppt
->
sequence
;
_stamp
[
trackidx
]
=
rtppt
->
timeStamp
;
//计算相对时间戳
int64_t
dts_out
;
_stamp
[
trackidx
].
revise
(
rtppt
->
timeStamp
,
rtppt
->
timeStamp
,
dts_out
,
dts_out
);
rtppt
->
timeStamp
=
dts_out
;
onRecvRTP_l
(
rtppt
,
_aTrackInfo
[
trackidx
]);
onRecvRTP_l
(
rtppt
,
_sdp_track
[
trackidx
]);
}
float
RtspPlayer
::
getPacketLossRate
(
TrackType
type
)
const
{
...
...
@@ -628,9 +615,9 @@ float RtspPlayer::getPacketLossRate(TrackType type) const{
if
(
iTrackIdx
==
-
1
){
uint64_t
totalRecv
=
0
;
uint64_t
totalSend
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
_
aTrackInfo
.
size
();
i
++
)
{
totalRecv
+=
_
aui64RtpRecv
[
i
];
totalSend
+=
(
_
aui16NowSeq
[
i
]
-
_aui16FirstSeq
[
i
]
+
1
);
for
(
unsigned
int
i
=
0
;
i
<
_
sdp_track
.
size
();
i
++
)
{
totalRecv
+=
_
rtp_recv_count
[
i
];
totalSend
+=
(
_
rtp_seq_now
[
i
]
-
_rtp_seq_start
[
i
]
+
1
);
}
if
(
totalSend
==
0
){
return
0
;
...
...
@@ -638,14 +625,14 @@ float RtspPlayer::getPacketLossRate(TrackType type) const{
return
1.0
-
(
double
)
totalRecv
/
totalSend
;
}
if
(
_
aui16NowSeq
[
iTrackIdx
]
-
_aui16FirstSeq
[
iTrackIdx
]
+
1
==
0
){
if
(
_
rtp_seq_now
[
iTrackIdx
]
-
_rtp_seq_start
[
iTrackIdx
]
+
1
==
0
){
return
0
;
}
return
1.0
-
(
double
)
_
aui64RtpRecv
[
iTrackIdx
]
/
(
_aui16NowSeq
[
iTrackIdx
]
-
_aui16FirstSeq
[
iTrackIdx
]
+
1
);
return
1.0
-
(
double
)
_
rtp_recv_count
[
iTrackIdx
]
/
(
_rtp_seq_now
[
iTrackIdx
]
-
_rtp_seq_start
[
iTrackIdx
]
+
1
);
}
uint32_t
RtspPlayer
::
getProgressMilliSecond
()
const
{
return
MAX
(
_stamp
[
0
]
.
getRelativeStamp
(),
_stamp
[
1
].
getRelativeStamp
()
);
return
MAX
(
_stamp
[
0
]
,
_stamp
[
1
]
);
}
void
RtspPlayer
::
seekToMilliSecond
(
uint32_t
ms
)
{
...
...
@@ -668,15 +655,15 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url, const std
void
RtspPlayer
::
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
StrCaseMap
&
header_const
)
{
auto
header
=
header_const
;
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
_
uiCseq
++
);
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
_
cseq_send
++
);
header
.
emplace
(
"User-Agent"
,
SERVER_NAME
);
if
(
!
_s
trSession
.
empty
()){
header
.
emplace
(
"Session"
,
_strSession
);
if
(
!
_s
ession_id
.
empty
()){
header
.
emplace
(
"Session"
,
_session_id
);
}
if
(
!
_r
tspR
ealm
.
empty
()
&&
!
(
*
this
)[
kRtspUser
].
empty
()){
if
(
!
_
rtspMd5N
once
.
empty
()){
if
(
!
_realm
.
empty
()
&&
!
(
*
this
)[
kRtspUser
].
empty
()){
if
(
!
_
md5_n
once
.
empty
()){
//MD5认证
/*
response计算方法如下:
...
...
@@ -688,14 +675,14 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
*/
string
encrypted_pwd
=
(
*
this
)[
kRtspPwd
];
if
(
!
(
*
this
)[
kRtspPwdIsMD5
].
as
<
bool
>
()){
encrypted_pwd
=
MD5
((
*
this
)[
kRtspUser
]
+
":"
+
_rtspR
ealm
+
":"
+
encrypted_pwd
).
hexdigest
();
encrypted_pwd
=
MD5
((
*
this
)[
kRtspUser
]
+
":"
+
_r
ealm
+
":"
+
encrypted_pwd
).
hexdigest
();
}
auto
response
=
MD5
(
encrypted_pwd
+
":"
+
_rtspMd5Nonce
+
":"
+
MD5
(
cmd
+
":"
+
url
).
hexdigest
()).
hexdigest
();
auto
response
=
MD5
(
encrypted_pwd
+
":"
+
_md5_nonce
+
":"
+
MD5
(
cmd
+
":"
+
url
).
hexdigest
()).
hexdigest
();
_StrPrinter
printer
;
printer
<<
"Digest "
;
printer
<<
"username=
\"
"
<<
(
*
this
)[
kRtspUser
]
<<
"
\"
, "
;
printer
<<
"realm=
\"
"
<<
_r
tspR
ealm
<<
"
\"
, "
;
printer
<<
"nonce=
\"
"
<<
_
rtspMd5N
once
<<
"
\"
, "
;
printer
<<
"realm=
\"
"
<<
_realm
<<
"
\"
, "
;
printer
<<
"nonce=
\"
"
<<
_
md5_n
once
<<
"
\"
, "
;
printer
<<
"uri=
\"
"
<<
url
<<
"
\"
, "
;
printer
<<
"response=
\"
"
<<
response
<<
"
\"
"
;
header
.
emplace
(
"Authorization"
,
printer
);
...
...
@@ -717,23 +704,23 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
}
void
RtspPlayer
::
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
pkt
,
const
SdpTrack
::
Ptr
&
track
)
{
_rtp
T
icker
.
resetTime
();
_rtp
_recv_t
icker
.
resetTime
();
onRecvRTP
(
pkt
,
track
);
int
iTrackIndex
=
getTrackIndexByInterleaved
(
pkt
->
interleaved
);
if
(
iTrackIndex
==
-
1
)
{
return
;
}
RtcpCounter
&
counter
=
_
aRtcpCnt
[
iTrackIndex
];
RtcpCounter
&
counter
=
_
rtcp_counter
[
iTrackIndex
];
counter
.
pktCnt
=
pkt
->
sequence
;
auto
&
ticker
=
_
aRtcpT
icker
[
iTrackIndex
];
auto
&
ticker
=
_
rtcp_send_t
icker
[
iTrackIndex
];
if
(
ticker
.
elapsedTime
()
>
5
*
1000
)
{
//send rtcp every 5 second
counter
.
lastTimeStamp
=
counter
.
timeStamp
;
//直接保存网络字节序
memcpy
(
&
counter
.
timeStamp
,
pkt
->
data
()
+
8
,
4
);
if
(
counter
.
lastTimeStamp
!=
0
)
{
sendReceiverReport
(
_
eT
ype
==
Rtsp
::
RTP_TCP
,
iTrackIndex
);
sendReceiverReport
(
_
rtp_t
ype
==
Rtsp
::
RTP_TCP
,
iTrackIndex
);
ticker
.
resetTime
();
}
...
...
@@ -750,27 +737,27 @@ void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
if
(
!
ex
){
//播放成功,恢复rtp接收超时定时器
_rtp
T
icker
.
resetTime
();
_rtp
_recv_t
icker
.
resetTime
();
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
int
timeoutMS
=
(
*
this
)[
kMediaTimeoutMS
].
as
<
int
>
();
//创建rtp数据接收超时检测定时器
_
pRtpTimer
.
reset
(
new
Timer
(
timeoutMS
/
2000.0
,
[
weakSelf
,
timeoutMS
]()
{
_
rtp_check_timer
.
reset
(
new
Timer
(
timeoutMS
/
2000.0
,
[
weakSelf
,
timeoutMS
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
_rtp
Ticker
.
elapsedTime
()
>
timeoutMS
)
{
if
(
strongSelf
->
_rtp
_recv_ticker
.
elapsedTime
()
>
timeoutMS
)
{
//接收rtp媒体数据包超时
strongSelf
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"receive rtp timeout"
),
true
);
return
false
;
}
return
true
;
},
getPoller
()));
},
getPoller
()));
}
if
(
!
handshakeCompleted
)
{
//开始播放阶段
_p
PlayT
imer
.
reset
();
_p
lay_check_t
imer
.
reset
();
onPlayResult
(
ex
);
//是否为性能测试模式
_benchmark_mode
=
(
*
this
)[
Client
::
kBenchmarkMode
].
as
<
int
>
();
...
...
@@ -787,25 +774,25 @@ void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
}
}
int
RtspPlayer
::
getTrackIndexByInterleaved
(
int
interleaved
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
_
aTrackInfo
.
size
();
i
++
)
{
if
(
_
aTrackInfo
[
i
]
->
_interleaved
==
interleaved
)
{
int
RtspPlayer
::
getTrackIndexByInterleaved
(
int
interleaved
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
_
sdp_track
.
size
();
i
++
)
{
if
(
_
sdp_track
[
i
]
->
_interleaved
==
interleaved
)
{
return
i
;
}
}
if
(
_aTrackInfo
.
size
()
==
1
)
{
if
(
_sdp_track
.
size
()
==
1
)
{
return
0
;
}
return
-
1
;
}
int
RtspPlayer
::
getTrackIndexByTrackType
(
TrackType
trackType
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
_
aTrackInfo
.
size
();
i
++
)
{
if
(
_
aTrackInfo
[
i
]
->
_type
==
trackType
)
{
for
(
unsigned
int
i
=
0
;
i
<
_
sdp_track
.
size
();
i
++
)
{
if
(
_
sdp_track
[
i
]
->
_type
==
trackType
)
{
return
i
;
}
}
if
(
_aTrackInfo
.
size
()
==
1
)
{
if
(
_sdp_track
.
size
()
==
1
)
{
return
0
;
}
return
-
1
;
...
...
This diff is collapsed.
Click to expand it.
src/Rtsp/RtspPlayer.h
查看文件 @
f71a9bfa
...
...
@@ -105,40 +105,40 @@ private:
void
sendReceiverReport
(
bool
overTcp
,
int
iTrackIndex
);
void
createUdpSockIfNecessary
(
int
track_idx
);
private
:
string
_strUrl
;
vector
<
SdpTrack
::
Ptr
>
_aTrackInfo
;
function
<
void
(
const
Parser
&
)
>
_onHandshake
;
Socket
::
Ptr
_apRtpSock
[
2
];
//RTP端口,trackid idx 为数组下标
Socket
::
Ptr
_apRtcpSock
[
2
];
//RTCP端口,trackid idx 为数组下标
string
_play_url
;
vector
<
SdpTrack
::
Ptr
>
_sdp_track
;
function
<
void
(
const
Parser
&
)
>
_on_response
;
//RTP端口,trackid idx 为数组下标
Socket
::
Ptr
_rtp_sock
[
2
];
//RTCP端口,trackid idx 为数组下标
Socket
::
Ptr
_rtcp_sock
[
2
];
//rtsp鉴权相关
string
_
rtspMd5N
once
;
string
_r
tspR
ealm
;
string
_
md5_n
once
;
string
_realm
;
//rtsp info
string
_s
trSession
;
u
nsigned
int
_uiCseq
=
1
;
string
_
strContentB
ase
;
Rtsp
::
eRtpType
_
eT
ype
=
Rtsp
::
RTP_TCP
;
string
_s
ession_id
;
u
int32_t
_cseq_send
=
1
;
string
_
content_b
ase
;
Rtsp
::
eRtpType
_
rtp_t
ype
=
Rtsp
::
RTP_TCP
;
/* 丢包率统计需要用到的参数 */
uint16_t
_aui16FirstSeq
[
2
]
=
{
0
,
0
};
uint16_t
_aui16NowSeq
[
2
]
=
{
0
,
0
};
uint64_t
_aui64RtpRecv
[
2
]
=
{
0
,
0
};
uint16_t
_rtp_seq_start
[
2
]
=
{
0
,
0
};
uint16_t
_rtp_seq_now
[
2
]
=
{
0
,
0
};
uint64_t
_rtp_recv_count
[
2
]
=
{
0
,
0
};
//当前rtp时间戳
uint32_t
_stamp
[
2
]
=
{
0
,
0
};
//超时功能实现
Ticker
_rtp
T
icker
;
std
::
shared_ptr
<
Timer
>
_p
PlayT
imer
;
std
::
shared_ptr
<
Timer
>
_
pRtpT
imer
;
Ticker
_rtp
_recv_t
icker
;
std
::
shared_ptr
<
Timer
>
_p
lay_check_t
imer
;
std
::
shared_ptr
<
Timer
>
_
rtp_check_t
imer
;
//时间戳
Stamp
_stamp
[
2
];
//rtcp统计,trackid idx 为数组下标
RtcpCounter
_rtcp_counter
[
2
];
//rtcp发送时间,trackid idx 为数组下标
Ticker
_rtcp_send_ticker
[
2
];
//rtcp相关
RtcpCounter
_aRtcpCnt
[
2
];
//rtcp统计,trackid idx 为数组下标
Ticker
_aRtcpTicker
[
2
];
//rtcp发送时间,trackid idx 为数组下标
//是否为rtsp点播
bool
_is_play_back
;
//是否为性能测试模式
bool
_benchmark_mode
=
false
;
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论