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
4cc2982a
Commit
4cc2982a
authored
Mar 11, 2023
by
xia-chu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
重写jitter buffer算法,修复seq回环时可能丢包的bug
parent
c301ecd2
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
102 行增加
和
73 行删除
+102
-73
src/Rtsp/RtpReceiver.h
+99
-67
tests/test_sortor.cpp
+0
-2
webrtc/WebRtcTransport.cpp
+3
-4
没有找到文件。
src/Rtsp/RtpReceiver.h
查看文件 @
4cc2982a
...
...
@@ -26,6 +26,8 @@ template<typename T, typename SEQ = uint16_t>
class
PacketSortor
{
public
:
static
constexpr
SEQ
SEQ_MAX
=
(
std
::
numeric_limits
<
SEQ
>::
max
)();
using
iterator
=
typename
std
::
map
<
SEQ
,
T
>::
iterator
;
PacketSortor
()
=
default
;
~
PacketSortor
()
=
default
;
...
...
@@ -36,7 +38,7 @@ public:
*/
void
clear
()
{
_started
=
false
;
_
seq_cycle_count
=
0
;
_
ticker
.
resetTime
()
;
_pkt_sort_cache_map
.
clear
();
}
...
...
@@ -46,95 +48,128 @@ public:
size_t
getJitterSize
()
const
{
return
_pkt_sort_cache_map
.
size
();
}
/**
* 获取seq回环次数
*/
size_t
getCycleCount
()
const
{
return
_seq_cycle_count
;
}
/**
* 输入并排序
* @param seq 序列号
* @param packet 包负载
*/
void
sortPacket
(
SEQ
seq
,
T
packet
)
{
_latest_seq
=
seq
;
if
(
!
_started
)
{
// 记录第一个seq
_started
=
true
;
_last_seq_out
=
seq
-
1
;
}
if
(
seq
==
static_cast
<
SEQ
>
(
_last_seq_out
+
1
))
{
auto
next_seq
=
static_cast
<
SEQ
>
(
_last_seq_out
+
1
);
if
(
seq
==
next_seq
)
{
// 收到下一个seq
output
(
seq
,
std
::
move
(
packet
));
// 清空连续包列表
flushPacket
();
return
;
}
if
(
seq
<
_last_seq_out
&&
_last_seq_out
!=
SEQ_MAX
&&
seq
<
1024
&&
_last_seq_out
>
SEQ_MAX
-
1024
)
{
// seq回环,清空回环前缓存
flush
();
_last_seq_out
=
SEQ_MAX
;
++
_seq_cycle_count
;
sortPacket
(
seq
,
std
::
move
(
packet
));
if
(
seq
<
next_seq
&&
!
mayLooped
(
next_seq
,
seq
))
{
// 无回环风险, 过滤seq回退包
return
;
}
_pkt_sort_cache_map
.
emplace
(
seq
,
std
::
move
(
packet
));
if
(
seq
<=
_last_seq_out
&&
_last_seq_out
!=
SEQ_MAX
)
{
// 这个回退包已经不再等待
return
;
if
(
needForceFlush
(
seq
))
{
forceFlush
(
next_seq
);
}
}
_pkt_sort_cache_map
.
emplace
(
seq
,
std
::
move
(
packet
));
auto
it_min
=
_pkt_sort_cache_map
.
begin
();
auto
it_max
=
_pkt_sort_cache_map
.
rbegin
();
if
(
it_max
->
first
-
it_min
->
first
>
(
SEQ_MAX
>>
1
))
{
// 回环后,收到回环前的大值seq, 忽略掉
_pkt_sort_cache_map
.
erase
((
++
it_max
).
base
());
return
;
void
flush
()
{
if
(
!
_pkt_sort_cache_map
.
empty
())
{
forceFlush
(
static_cast
<
SEQ
>
(
_last_seq_out
+
1
));
_pkt_sort_cache_map
.
clear
();
}
}
tryFlushFrontPacket
();
void
setParams
(
size_t
max_buffer_size
,
size_t
max_buffer_ms
,
size_t
max_distance
)
{
_max_buffer_size
=
max_buffer_size
;
_max_buffer_ms
=
max_buffer_ms
;
_max_distance
=
max_distance
;
}
if
(
_pkt_sort_cache_map
.
size
()
>
_max_buffer_size
||
(
_ticker
.
elapsedTime
()
>
_max_buffer_ms
&&
!
_pkt_sort_cache_map
.
empty
()))
{
// buffer太长,强行减小
WarnL
<<
"packet dropped: "
<<
static_cast
<
SEQ
>
(
_last_seq_out
+
1
)
<<
" -> "
<<
static_cast
<
SEQ
>
(
_pkt_sort_cache_map
.
begin
()
->
first
-
1
)
<<
", jitter buffer size: "
<<
_pkt_sort_cache_map
.
size
()
<<
", jitter buffer ms: "
<<
_ticker
.
elapsedTime
();
popIterator
(
_pkt_sort_cache_map
.
begin
());
private
:
SEQ
distance
(
SEQ
seq
)
{
SEQ
ret
;
auto
next_seq
=
static_cast
<
SEQ
>
(
_last_seq_out
+
1
);
if
(
seq
>
next_seq
)
{
ret
=
seq
-
next_seq
;
}
else
{
ret
=
next_seq
-
seq
;
}
if
(
ret
>
SEQ_MAX
>>
1
)
{
return
SEQ_MAX
-
ret
;
}
return
ret
;
}
void
flush
()
{
// 清空缓存
while
(
!
_pkt_sort_cache_map
.
empty
())
{
popIterator
(
_pkt_sort_cache_map
.
begin
());
}
bool
needForceFlush
(
SEQ
seq
)
{
return
!
_pkt_sort_cache_map
.
empty
()
&&
(
_pkt_sort_cache_map
.
size
()
>
_max_buffer_size
||
distance
(
seq
)
>
_max_distance
||
_ticker
.
elapsedTime
()
>
_max_buffer_ms
);
}
private
:
void
tryFlushFrontPacket
()
{
while
(
!
_pkt_sort_cache_map
.
empty
())
{
auto
it
=
_pkt_sort_cache_map
.
begin
();
auto
next_seq
=
static_cast
<
SEQ
>
(
_last_seq_out
+
1
);
if
(
it
->
first
<
next_seq
)
{
_pkt_sort_cache_map
.
erase
(
it
);
continue
;
//外部调用代码确保_pkt_sort_cache_map不为空
void
forceFlush
(
SEQ
next_seq
)
{
// 寻找距离比next_seq大的最近的seq
auto
it
=
_pkt_sort_cache_map
.
lower_bound
(
next_seq
);
if
(
it
==
_pkt_sort_cache_map
.
end
())
{
// 没有比next_seq更大的seq,应该是回环时丢包导致
it
=
_pkt_sort_cache_map
.
begin
();
}
// 丢包无法恢复,把这个包当做next_seq
popIterator
(
it
);
// 清空连续包列表
flushPacket
();
// 删除距离next_seq太大的包
for
(
auto
it
=
_pkt_sort_cache_map
.
begin
();
it
!=
_pkt_sort_cache_map
.
end
();)
{
if
(
distance
(
it
->
first
)
>
_max_distance
)
{
it
=
_pkt_sort_cache_map
.
erase
(
it
);
}
else
{
++
it
;
}
if
(
it
->
first
==
next_seq
)
{
// 连续的seq
popIterator
(
it
);
}
}
bool
mayLooped
(
SEQ
last_seq
,
SEQ
now_seq
)
{
return
last_seq
>
SEQ_MAX
-
_max_distance
||
now_seq
<
_max_distance
;
}
void
flushPacket
()
{
if
(
_pkt_sort_cache_map
.
empty
())
{
return
;
}
auto
next_seq
=
static_cast
<
SEQ
>
(
_last_seq_out
+
1
);
auto
it
=
_pkt_sort_cache_map
.
lower_bound
(
next_seq
);
if
(
!
mayLooped
(
next_seq
,
next_seq
))
{
// 无回环风险, 清空 < next_seq的值
it
=
_pkt_sort_cache_map
.
erase
(
_pkt_sort_cache_map
.
begin
(),
it
);
}
while
(
it
!=
_pkt_sort_cache_map
.
end
())
{
// 找到下一个包
if
(
it
->
first
==
static_cast
<
SEQ
>
(
_last_seq_out
+
1
))
{
it
=
popIterator
(
it
);
continue
;
}
break
;
}
}
void
popIterator
(
typename
std
::
map
<
SEQ
,
T
>::
iterator
it
)
{
auto
seq
=
it
->
first
;
auto
data
=
std
::
move
(
it
->
second
);
_pkt_sort_cache_map
.
erase
(
it
);
output
(
seq
,
std
::
move
(
data
));
iterator
popIterator
(
iterator
it
)
{
output
(
it
->
first
,
std
::
move
(
it
->
second
));
return
_pkt_sort_cache_map
.
erase
(
it
);
}
void
output
(
SEQ
seq
,
T
packet
)
{
auto
next_seq
=
static_cast
<
SEQ
>
(
_last_seq_out
+
1
);
if
(
seq
!=
next_seq
)
{
WarnL
<<
"packet dropped: "
<<
next_seq
<<
" -> "
<<
static_cast
<
SEQ
>
(
seq
-
1
)
<<
", latest seq: "
<<
_latest_seq
<<
", jitter buffer size: "
<<
_pkt_sort_cache_map
.
size
()
<<
", jitter buffer ms: "
<<
_ticker
.
elapsedTime
();
}
_last_seq_out
=
seq
;
_cb
(
seq
,
std
::
move
(
packet
));
_ticker
.
resetTime
();
...
...
@@ -142,23 +177,25 @@ private:
private
:
bool
_started
=
false
;
//排序缓存最大保存数据长度,单位毫秒
size_t
_max_buffer_ms
=
3
000
;
//排序缓存最大保存数据个数
//
排序缓存最大保存数据长度,单位毫秒
size_t
_max_buffer_ms
=
1
000
;
//
排序缓存最大保存数据个数
size_t
_max_buffer_size
=
1024
;
//记录上次output至今的时间
// seq最大跳跃距离
size_t
_max_distance
=
256
;
// 记录上次output至今的时间
toolkit
::
Ticker
_ticker
;
//下次应该输出的SEQ
// 最近输入的seq
SEQ
_latest_seq
=
0
;
// 下次应该输出的SEQ
SEQ
_last_seq_out
=
0
;
//seq回环次数计数
size_t
_seq_cycle_count
=
0
;
//pkt排序缓存,根据seq排序
// pkt排序缓存,根据seq排序
std
::
map
<
SEQ
,
T
>
_pkt_sort_cache_map
;
//回调
//
回调
std
::
function
<
void
(
SEQ
seq
,
T
packet
)
>
_cb
;
};
class
RtpTrack
:
p
rivate
PacketSortor
<
RtpPacket
::
Ptr
>
{
class
RtpTrack
:
p
ublic
PacketSortor
<
RtpPacket
::
Ptr
>
{
public
:
class
BadRtpException
:
public
std
::
invalid_argument
{
public
:
...
...
@@ -268,11 +305,6 @@ public:
return
_track
[
index
].
getJitterSize
();
}
size_t
getCycleCount
(
int
index
)
const
{
assert
(
index
<
kCount
&&
index
>=
0
);
return
_track
[
index
].
getCycleCount
();
}
uint32_t
getSSRC
(
int
index
)
const
{
assert
(
index
<
kCount
&&
index
>=
0
);
return
_track
[
index
].
getSSRC
();
...
...
tests/test_sortor.cpp
查看文件 @
4cc2982a
...
...
@@ -111,7 +111,6 @@ void test_real() {
}
cout
<<
"输入数据个数:"
<<
input_list
.
size
()
<<
" 回环次数:"
<<
sortor
.
getCycleCount
()
<<
" 抖动缓冲区大小:"
<<
sortor
.
getJitterSize
();
//清空缓存
...
...
@@ -206,7 +205,6 @@ void test_rand(){
i
+=
(
count
+
1
);
}
cout
<<
"输入数据个数:"
<<
input_list
.
size
()
<<
" 回环次数:"
<<
sortor
.
getCycleCount
()
<<
" 抖动缓冲区大小:"
<<
sortor
.
getJitterSize
()
<<
" 丢包个数:"
<<
drop_list
.
size
()
<<
" 重复包个数:"
<<
repeat_list
.
size
();
...
...
webrtc/WebRtcTransport.cpp
查看文件 @
4cc2982a
...
...
@@ -652,15 +652,14 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const {
///////////////////////////////////////////////////////////////////
class
RtpChannel
:
public
RtpTrackImp
,
public
std
::
enable_shared_from_this
<
RtpChannel
>
{
class
RtpChannel
:
public
RtpTrackImp
,
public
std
::
enable_shared_from_this
<
RtpChannel
>
{
public
:
RtpChannel
(
EventPoller
::
Ptr
poller
,
RtpTrackImp
::
OnSorted
cb
,
function
<
void
(
const
FCI_NACK
&
nack
)
>
on_nack
)
{
_poller
=
std
::
move
(
poller
);
_on_nack
=
std
::
move
(
on_nack
);
setOnSorted
(
std
::
move
(
cb
));
//设置jitter buffer参数
RtpTrackImp
::
setParams
(
1024
,
NackContext
::
kNackMaxMS
,
512
);
_nack_ctx
.
setOnNack
([
this
](
const
FCI_NACK
&
nack
)
{
onNack
(
nack
);
});
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论