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
304275a0
Commit
304275a0
authored
May 09, 2019
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rtsp播放器支持rtcp
parent
9d92f613
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
174 行增加
和
40 行删除
+174
-40
src/Rtsp/RtpReceiver.cpp
+12
-1
src/Rtsp/RtpReceiver.h
+3
-0
src/Rtsp/Rtsp.h
+1
-0
src/Rtsp/RtspPlayer.cpp
+146
-17
src/Rtsp/RtspPlayer.h
+6
-8
src/Rtsp/RtspSession.cpp
+6
-10
src/Rtsp/RtspSession.h
+0
-4
没有找到文件。
src/Rtsp/RtpReceiver.cpp
查看文件 @
304275a0
...
...
@@ -116,11 +116,12 @@ bool RtpReceiver::handleOneRtp(int iTrackidx,SdpTrack::Ptr &track, unsigned char
_aui32SeqOkCnt
[
iTrackidx
]
=
0
;
_abSortStarted
[
iTrackidx
]
=
true
;
// WarnL << "包乱序或丢包:" << iTrackidx <<" " << rtppt.sequence << " " << _aui16LastSeq[iTrackidx];
if
(
_aui16LastSeq
[
iTrackidx
]
>
rtppt
.
sequence
&&
_aui16LastSeq
[
iTrackidx
]
-
rtppt
.
sequence
>
0x
7F
FF
){
if
(
_aui16LastSeq
[
iTrackidx
]
>
rtppt
.
sequence
&&
_aui16LastSeq
[
iTrackidx
]
-
rtppt
.
sequence
>
0xFF
){
//sequence回环,清空所有排序缓存
while
(
_amapRtpSort
[
iTrackidx
].
size
())
{
POP_HEAD
(
iTrackidx
)
}
++
_clcyeCount
[
iTrackidx
];
}
}
else
{
//正确序列的包
...
...
@@ -157,6 +158,7 @@ void RtpReceiver::clear() {
CLEAR_ARR
(
_aui32SsrcErrorCnt
)
CLEAR_ARR
(
_aui32SeqOkCnt
)
CLEAR_ARR
(
_abSortStarted
)
CLEAR_ARR
(
_clcyeCount
)
_amapRtpSort
[
0
].
clear
();
_amapRtpSort
[
1
].
clear
();
...
...
@@ -166,4 +168,13 @@ void RtpReceiver::setPoolSize(int size) {
_pktPool
.
setSize
(
size
);
}
int
RtpReceiver
::
getJitterSize
(
int
iTrackidx
){
return
_amapRtpSort
[
iTrackidx
].
size
();
}
int
RtpReceiver
::
getCycleCount
(
int
iTrackidx
){
return
_clcyeCount
[
iTrackidx
];
}
}
//namespace mediakit
src/Rtsp/RtpReceiver.h
查看文件 @
304275a0
...
...
@@ -64,11 +64,14 @@ protected:
virtual
void
onRtpSorted
(
const
RtpPacket
::
Ptr
&
rtppt
,
int
trackidx
){}
void
clear
();
void
setPoolSize
(
int
size
);
int
getJitterSize
(
int
iTrackidx
);
int
getCycleCount
(
int
iTrackidx
);
private
:
uint32_t
_aui32SsrcErrorCnt
[
2
]
=
{
0
,
0
};
/* RTP包排序所用参数 */
uint16_t
_aui16LastSeq
[
2
]
=
{
0
,
0
};
uint32_t
_aui32SeqOkCnt
[
2
]
=
{
0
,
0
};
uint32_t
_clcyeCount
[
2
]
=
{
0
,
0
};
bool
_abSortStarted
[
2
]
=
{
0
,
0
};
map
<
uint16_t
,
RtpPacket
::
Ptr
>
_amapRtpSort
[
2
];
RtspMediaSource
::
PoolType
_pktPool
;
...
...
src/Rtsp/Rtsp.h
查看文件 @
304275a0
...
...
@@ -113,6 +113,7 @@ public:
uint32_t
octCount
=
0
;
//网络字节序
uint32_t
timeStamp
=
0
;
uint32_t
lastTimeStamp
=
0
;
};
string
FindField
(
const
char
*
buf
,
const
char
*
start
,
const
char
*
end
,
int
bufSize
=
0
);
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
304275a0
...
...
@@ -71,7 +71,6 @@ void RtspPlayer::teardown(){
CLEAR_ARR
(
_aiFistStamp
);
CLEAR_ARR
(
_aiNowStamp
);
_pBeatTimer
.
reset
();
_pPlayTimer
.
reset
();
_pRtpTimer
.
reset
();
_iSeekTo
=
0
;
...
...
@@ -369,17 +368,6 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
return
;
}
//所有setup命令发送完毕
//设置心跳包发送定时器
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
_pBeatTimer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,
[
weakSelf
](){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
return
false
;
}
strongSelf
->
sendRtcpPacket
();
return
true
;
},
getPoller
()));
//发送play命令
pause
(
false
);
}
...
...
@@ -491,11 +479,132 @@ void RtspPlayer::onRtcpPacket(int iTrackidx, SdpTrack::Ptr &track, unsigned char
}
void
RtspPlayer
::
sendRtcpPacket
(){
//目前只实现了通过options命令实现心跳包
sendOptions
();
#if 0
//改代码提取自FFmpeg,参考之
// Receiver Report
avio_w8(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
avio_w8(pb, RTCP_RR);
avio_wb16(pb, 7); /* length in words - 1 */
// our own SSRC: we use the server's SSRC + 1 to avoid conflicts
avio_wb32(pb, s->ssrc + 1);
avio_wb32(pb, s->ssrc); // server SSRC
// some placeholders we should really fill...
// RFC 1889/p64
extended_max = stats->cycles + stats->max_seq;
expected = extended_max - stats->base_seq;
lost = expected - stats->received;
lost = FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
expected_interval = expected - stats->expected_prior;
stats->expected_prior = expected;
received_interval = stats->received - stats->received_prior;
stats->received_prior = stats->received;
lost_interval = expected_interval - received_interval;
if (expected_interval == 0 || lost_interval <= 0)
fraction = 0;
else
fraction = (lost_interval << 8) / expected_interval;
fraction = (fraction << 24) | lost;
avio_wb32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
avio_wb32(pb, extended_max); /* max sequence received */
avio_wb32(pb, stats->jitter >> 4); /* jitter */
if (s->last_rtcp_ntp_time == AV_NOPTS_VALUE) {
avio_wb32(pb, 0); /* last SR timestamp */
avio_wb32(pb, 0); /* delay since last SR */
} else {
uint32_t middle_32_bits = s->last_rtcp_ntp_time >> 16; // this is valid, right? do we need to handle 64 bit values special?
uint32_t delay_since_last = av_rescale(av_gettime_relative() - s->last_rtcp_reception_time,
65536, AV_TIME_BASE);
avio_wb32(pb, middle_32_bits); /* last SR timestamp */
avio_wb32(pb, delay_since_last); /* delay since last SR */
}
// CNAME
avio_w8(pb, (RTP_VERSION << 6) + 1); /* 1 report block */
avio_w8(pb, RTCP_SDES);
len = strlen(s->hostname);
avio_wb16(pb, (7 + len + 3) / 4); /* length in words - 1 */
avio_wb32(pb, s->ssrc + 1);
avio_w8(pb, 0x01);
avio_w8(pb, len);
avio_write(pb, s->hostname, len);
avio_w8(pb, 0); /* END */
// padding
for (len = (7 + len) % 4; len % 4; len++)
avio_w8(pb, 0);
#endif
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
];
aui8Rtcp
[
0
]
=
'$'
;
aui8Rtcp
[
1
]
=
track
->
_interleaved
+
1
;
aui8Rtcp
[
2
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
>>
8
;
aui8Rtcp
[
3
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
&
0xFF
;
pui8Rtcp_RR
[
0
]
=
0x81
;
/* 1 report block */
pui8Rtcp_RR
[
1
]
=
0xC9
;
//RTCP_RR
pui8Rtcp_RR
[
2
]
=
0x00
;
pui8Rtcp_RR
[
3
]
=
0x07
;
/* length in words - 1 */
uint32_t
ssrc
=
htonl
(
track
->
_ssrc
+
1
);
// our own SSRC: we use the server's SSRC + 1 to avoid conflicts
memcpy
(
&
pui8Rtcp_RR
[
4
],
&
ssrc
,
4
);
ssrc
=
htonl
(
track
->
_ssrc
);
// server SSRC
memcpy
(
&
pui8Rtcp_RR
[
8
],
&
ssrc
,
4
);
//FIXME: 8 bits of fraction, 24 bits of total packets lost
pui8Rtcp_RR
[
12
]
=
0x00
;
pui8Rtcp_RR
[
13
]
=
0x00
;
pui8Rtcp_RR
[
14
]
=
0x00
;
pui8Rtcp_RR
[
15
]
=
0x00
;
//FIXME: max sequence received
int
cycleCount
=
getCycleCount
(
iTrackIndex
);
pui8Rtcp_RR
[
16
]
=
cycleCount
>>
8
;
pui8Rtcp_RR
[
17
]
=
cycleCount
&
0xFF
;
pui8Rtcp_RR
[
18
]
=
counter
.
pktCnt
>>
8
;
pui8Rtcp_RR
[
19
]
=
counter
.
pktCnt
&
0xFF
;
uint32_t
jitter
=
htonl
(
getJitterSize
(
iTrackIndex
));
//FIXME: jitter
memcpy
(
pui8Rtcp_RR
+
20
,
&
jitter
,
4
);
/* last SR timestamp */
memcpy
(
pui8Rtcp_RR
+
24
,
&
counter
.
lastTimeStamp
,
4
);
uint32_t
msInc
=
htonl
(
ntohl
(
counter
.
timeStamp
)
-
ntohl
(
counter
.
lastTimeStamp
));
/* delay since last SR */
memcpy
(
pui8Rtcp_RR
+
28
,
&
msInc
,
4
);
// CNAME
pui8Rtcp_SDES
[
0
]
=
0x81
;
pui8Rtcp_SDES
[
1
]
=
0xCA
;
pui8Rtcp_SDES
[
2
]
=
0x00
;
pui8Rtcp_SDES
[
3
]
=
0x06
;
memcpy
(
&
pui8Rtcp_SDES
[
4
],
&
ssrc
,
4
);
pui8Rtcp_SDES
[
8
]
=
0x01
;
pui8Rtcp_SDES
[
9
]
=
0x0f
;
memcpy
(
&
pui8Rtcp_SDES
[
10
],
s_cname
,
sizeof
(
s_cname
));
pui8Rtcp_SDES
[
10
+
sizeof
(
s_cname
)]
=
0x00
;
if
(
overTcp
){
send
(
obtainBuffer
((
char
*
)
aui8Rtcp
,
sizeof
(
aui8Rtcp
)));
}
else
if
(
_apRtcpSock
[
iTrackIndex
])
{
_apRtcpSock
[
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
])
{
...
...
@@ -608,9 +717,29 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
send
(
printer
<<
"
\r\n
"
);
}
void
RtspPlayer
::
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
p
Rtpp
t
,
const
SdpTrack
::
Ptr
&
track
)
{
void
RtspPlayer
::
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
p
k
t
,
const
SdpTrack
::
Ptr
&
track
)
{
_rtpTicker
.
resetTime
();
onRecvRTP
(
pRtppt
,
track
);
onRecvRTP
(
pkt
,
track
);
int
iTrackIndex
=
getTrackIndexByInterleaved
(
pkt
->
interleaved
);
if
(
iTrackIndex
==
-
1
){
return
;
}
RtcpCounter
&
counter
=
_aRtcpCnt
[
iTrackIndex
];
counter
.
pktCnt
=
pkt
->
sequence
;
auto
&
ticker
=
_aRtcpTicker
[
iTrackIndex
];
if
(
ticker
.
elapsedTime
()
>
5
*
1000
)
{
//send rtcp every 5 second
counter
.
lastTimeStamp
=
counter
.
timeStamp
;
//直接保存网络字节序
memcpy
(
&
counter
.
timeStamp
,
pkt
->
payload
+
8
,
4
);
if
(
counter
.
lastTimeStamp
!=
0
){
sendReceiverReport
(
_eType
==
Rtsp
::
RTP_TCP
,
iTrackIndex
);
ticker
.
resetTime
();
}
}
}
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
...
...
src/Rtsp/RtspPlayer.h
查看文件 @
304275a0
...
...
@@ -94,11 +94,6 @@ protected:
* @param uiLen
*/
virtual
void
onRtcpPacket
(
int
iTrackidx
,
SdpTrack
::
Ptr
&
track
,
unsigned
char
*
pucData
,
unsigned
int
uiLen
);
/**
* 发送rtcp包维持心跳
*/
virtual
void
sendRtcpPacket
();
private
:
void
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
pRtppt
,
const
SdpTrack
::
Ptr
&
track
);
void
onPlayResult_l
(
const
SockException
&
ex
);
...
...
@@ -125,6 +120,7 @@ private:
void
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
StrCaseMap
&
header
=
StrCaseMap
());
void
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
std
::
initializer_list
<
string
>
&
header
);
void
sendReceiverReport
(
bool
overTcp
,
int
iTrackIndex
);
private
:
string
_strUrl
;
SdpAttr
_sdpAttr
;
...
...
@@ -151,15 +147,17 @@ private:
Ticker
_rtpTicker
;
std
::
shared_ptr
<
Timer
>
_pPlayTimer
;
std
::
shared_ptr
<
Timer
>
_pRtpTimer
;
//心跳定时器
std
::
shared_ptr
<
Timer
>
_pBeatTimer
;
//播放进度控制,单位毫秒
uint32_t
_iSeekTo
=
0
;
//单位毫秒
uint32_t
_aiFistStamp
[
2
]
=
{
0
,
0
};
uint32_t
_aiNowStamp
[
2
]
=
{
0
,
0
};
//rtcp相关
RtcpCounter
_aRtcpCnt
[
2
];
//rtcp统计,trackid idx 为数组下标
Ticker
_aRtcpTicker
[
2
];
//rtcp发送时间,trackid idx 为数组下标
};
}
/* namespace mediakit */
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
304275a0
...
...
@@ -1190,7 +1190,6 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
break
;
}
#ifdef RTSP_SEND_RTCP
int
iTrackIndex
=
getTrackIndexByInterleaved
(
pkt
->
interleaved
);
if
(
iTrackIndex
==
-
1
){
return
;
...
...
@@ -1206,21 +1205,19 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
memcpy
(
&
counter
.
timeStamp
,
pkt
->
payload
+
8
,
4
);
sendSenderReport
(
_rtpType
==
Rtsp
::
RTP_TCP
,
iTrackIndex
);
}
#endif
}
#ifdef RTSP_SEND_RTCP
inline
void
RtspSession
::
sendSenderReport
(
bool
overTcp
,
int
iTrackIndex
)
{
static
const
char
s
erver_
name
[]
=
"ZLMediaKitRtsp"
;
uint8_t
aui8Rtcp
[
4
+
28
+
10
+
sizeof
(
s
erver_
name
)
+
1
]
=
{
0
};
static
const
char
s
_c
name
[]
=
"ZLMediaKitRtsp"
;
uint8_t
aui8Rtcp
[
4
+
28
+
10
+
sizeof
(
s
_c
name
)
+
1
]
=
{
0
};
uint8_t
*
pui8Rtcp_SR
=
aui8Rtcp
+
4
,
*
pui8Rtcp_SDES
=
pui8Rtcp_SR
+
28
;
auto
&
track
=
_aTrackInfo
[
iTrackIndex
];
auto
&
counter
=
_aRtcpCnt
[
iTrackIndex
];
aui8Rtcp
[
0
]
=
'$'
;
aui8Rtcp
[
1
]
=
track
->
_interleaved
+
1
;
aui8Rtcp
[
2
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
/
256
;
aui8Rtcp
[
3
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
%
256
;
aui8Rtcp
[
2
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
>>
8
;
aui8Rtcp
[
3
]
=
(
sizeof
(
aui8Rtcp
)
-
4
)
&
0xFF
;
pui8Rtcp_SR
[
0
]
=
0x80
;
pui8Rtcp_SR
[
1
]
=
0xC8
;
...
...
@@ -1260,8 +1257,8 @@ inline void RtspSession::sendSenderReport(bool overTcp,int iTrackIndex) {
pui8Rtcp_SDES
[
8
]
=
0x01
;
pui8Rtcp_SDES
[
9
]
=
0x0f
;
memcpy
(
&
pui8Rtcp_SDES
[
10
],
s
erver_name
,
sizeof
(
server_
name
));
pui8Rtcp_SDES
[
10
+
sizeof
(
s
erver_
name
)]
=
0x00
;
memcpy
(
&
pui8Rtcp_SDES
[
10
],
s
_cname
,
sizeof
(
s_c
name
));
pui8Rtcp_SDES
[
10
+
sizeof
(
s
_c
name
)]
=
0x00
;
if
(
overTcp
){
send
(
obtainBuffer
((
char
*
)
aui8Rtcp
,
sizeof
(
aui8Rtcp
)));
...
...
@@ -1269,7 +1266,6 @@ inline void RtspSession::sendSenderReport(bool overTcp,int iTrackIndex) {
_apRtcpSock
[
iTrackIndex
]
->
send
((
char
*
)
aui8Rtcp
+
4
,
sizeof
(
aui8Rtcp
)
-
4
);
}
}
#endif
}
/* namespace mediakit */
...
...
src/Rtsp/RtspSession.h
查看文件 @
304275a0
...
...
@@ -46,8 +46,6 @@
using
namespace
std
;
using
namespace
toolkit
;
#define RTSP_SEND_RTCP
namespace
mediakit
{
class
RtspSession
;
...
...
@@ -200,11 +198,9 @@ private:
//rtsp推流相关
RtspToRtmpMediaSource
::
Ptr
_pushSrc
;
#ifdef RTSP_SEND_RTCP
RtcpCounter
_aRtcpCnt
[
2
];
//rtcp统计,trackid idx 为数组下标
Ticker
_aRtcpTicker
[
2
];
//rtcp发送时间,trackid idx 为数组下标
inline
void
sendSenderReport
(
bool
overTcp
,
int
iTrackIndex
);
#endif
};
/**
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论