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
May 15, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
修复rtsp播放器时间戳紊乱的bug
parent
cded823b
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
152 行增加
和
165 行删除
+152
-165
src/Rtsp/RtspPlayer.cpp
+127
-140
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"
,
sendRtspRequest
(
"SETUP"
,
baseUrl
,
{
"Transport"
,
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
_apRtpS
ock
[
trackIndex
]
->
get_local_port
()
<<
"-"
<<
_apRtcpS
ock
[
trackIndex
]
->
get_local_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
;
...
...
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
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论