Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
BC
public
mediastreamer2
Commits
124f6c61
Commit
124f6c61
authored
Jun 02, 2014
by
Gautier Pelloux-Prayer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix network loss rate overestimation when there is congestion only
parent
95dbd944
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
58 additions
and
39 deletions
+58
-39
src/voip/qosanalyzer.c
src/voip/qosanalyzer.c
+43
-23
tester/mediastreamer2_adaptive_tester.c
tester/mediastreamer2_adaptive_tester.c
+15
-16
No files found.
src/voip/qosanalyzer.c
View file @
124f6c61
...
...
@@ -295,22 +295,26 @@ static bool_t stateful_analyser_process_rtcp(MSQosAnalyser *objbase, mblk_t *rtc
if
(
obj
->
previous_ext_high_seq_num_rec
>
0
){
loss_rate
=
(
1
.
-
(
uniq_emitted
-
cum_loss_curr
)
*
1
.
f
/
total_emitted
);
printf
(
"RECEIVE estimated loss rate=%f vs 'real'=%f
\n
"
,
loss_rate
,
report_block_get_fraction_lost
(
rb
)
/
256
.);
P
(
"RECEIVE estimated loss rate=%f vs 'real'=%f
\n
"
,
loss_rate
,
report_block_get_fraction_lost
(
rb
)
/
256
.);
}
if
(
obj
->
curindex
%
10
==
6
){
P
(
YELLOW
"SKIPPED first MIN burst %d: %f %f
\n
"
,
obj
->
curindex
-
1
,
up_bw
,
loss_rate
);
}
else
{
obj
->
latest
=
ms_new0
(
rtcpstatspoint_t
,
1
);
obj
->
latest
->
timestamp
=
ms_time
(
0
);
obj
->
latest
->
bandwidth
=
up_bw
;
obj
->
latest
->
loss_percent
=
MAX
(
0
,
loss_rate
);
obj
->
latest
->
rtt
=
cur
->
rt_prop
;
obj
->
rtcpstatspoint
=
ms_list_insert_sorted
(
obj
->
rtcpstatspoint
,
obj
->
latest
,
(
MSCompareFunc
)
sort_points
);
P
(
YELLOW
"one more %d: %f %f
\n
"
,
obj
->
curindex
-
1
,
obj
->
latest
->
bandwidth
,
obj
->
latest
->
loss_percent
);
obj
->
latest
=
ms_new0
(
rtcpstatspoint_t
,
1
);
obj
->
latest
->
timestamp
=
ms_time
(
0
);
obj
->
latest
->
bandwidth
=
up_bw
;
obj
->
latest
->
loss_percent
=
MAX
(
0
,
loss_rate
);
obj
->
latest
->
rtt
=
cur
->
rt_prop
;
obj
->
rtcpstatspoint
=
ms_list_insert_sorted
(
obj
->
rtcpstatspoint
,
obj
->
latest
,
(
MSCompareFunc
)
sort_points
);
if
(
obj
->
latest
->
loss_percent
<
1e-5
){
MSList
*
it
=
obj
->
rtcpstatspoint
;
MSList
*
latest_pos
=
ms_list_find
(
obj
->
rtcpstatspoint
,
obj
->
latest
);
while
(
it
!=
latest_pos
->
next
){
((
rtcpstatspoint_t
*
)
it
->
data
)
->
loss_percent
=
0
.
f
;
it
=
it
->
next
;
}
}
P
(
YELLOW
"one more %d: %f %f
\n
"
,
obj
->
curindex
-
2
,
obj
->
latest
->
bandwidth
,
obj
->
latest
->
loss_percent
);
if
(
ms_list_size
(
obj
->
rtcpstatspoint
)
>
ESTIM_HISTORY
){
P
(
RED
"Reached list maximum capacity (count=%d)"
,
ms_list_size
(
obj
->
rtcpstatspoint
));
...
...
@@ -330,16 +334,31 @@ static float lerp(float inf, float sup, float v){
return
inf
+
(
sup
-
inf
)
*
v
;
}
static
MSList
*
find_first_with_loss
(
MSList
*
list
){
for
(;
list
!=
NULL
;
list
=
list
->
next
){
if
(((
rtcpstatspoint_t
*
)
list
->
data
)
->
loss_percent
>
1e-5
){
return
list
;
}
}
return
NULL
;
}
static
void
smooth_values
(
MSStatefulQosAnalyser
*
obj
){
MSList
*
first_loss
=
find_first_with_loss
(
obj
->
rtcpstatspoint
);
MSList
*
it
=
obj
->
rtcpstatspoint
;
rtcpstatspoint_t
*
curr
=
(
rtcpstatspoint_t
*
)
it
->
data
;
double
prev_loss
=
curr
->
loss_percent
;
it
=
it
->
next
;
double
prev_loss
=
0
.;
if
(
first_loss
==
obj
->
rtcpstatspoint
){
prev_loss
=
curr
->
loss_percent
;
curr
->
loss_percent
=
lerp
(
curr
->
loss_percent
,
((
rtcpstatspoint_t
*
)
it
->
next
->
data
)
->
loss_percent
,
.
25
);
it
=
it
->
next
;
}
else
{
it
=
first_loss
;
}
curr
=
(
rtcpstatspoint_t
*
)
it
->
data
;
((
rtcpstatspoint_t
*
)
it
->
prev
->
data
)
->
loss_percent
=
lerp
(
prev_loss
,
curr
->
loss_percent
,
.
25
);
while
(
it
->
next
!=
NULL
){
curr
=
(
rtcpstatspoint_t
*
)
it
->
data
;
rtcpstatspoint_t
*
prev
=
((
rtcpstatspoint_t
*
)
it
->
prev
->
data
);
rtcpstatspoint_t
*
next
=
((
rtcpstatspoint_t
*
)
it
->
next
->
data
);
...
...
@@ -348,8 +367,8 @@ static void smooth_values(MSStatefulQosAnalyser *obj){
prev_loss
=
curr
->
loss_percent
;
curr
->
loss_percent
=
(
curr
->
loss_percent
+
new_loss
)
/
2
.;
it
=
it
->
next
;
curr
=
(
rtcpstatspoint_t
*
)
it
->
data
;
}
curr
=
(
rtcpstatspoint_t
*
)
it
->
data
;
curr
->
loss_percent
=
lerp
(
prev_loss
,
curr
->
loss_percent
,
.
75
);
}
...
...
@@ -376,10 +395,10 @@ static float compute_available_bw(MSStatefulQosAnalyser *obj){
/*suppose that first point is a reliable estimation of the constant network loss rate*/
if
(
size
>
3
){
smooth_values
(
obj
);
constant_network_loss
=
((
rtcpstatspoint_t
*
)
obj
->
rtcpstatspoint
->
next
->
data
)
->
loss_percent
;
/*
constant_network_loss = ((rtcpstatspoint_t *)obj->rtcpstatspoint->next->data)->loss_percent;
}else{
constant_network_loss
=
((
rtcpstatspoint_t
*
)
obj
->
rtcpstatspoint
->
data
)
->
loss_percent
;
}
*/
}
constant_network_loss
=
((
rtcpstatspoint_t
*
)
obj
->
rtcpstatspoint
->
data
)
->
loss_percent
;
P
(
"
\t
constant_network_loss=%f
\n
"
,
constant_network_loss
);
...
...
@@ -450,12 +469,13 @@ static void stateful_analyser_suggest_action(MSQosAnalyser *objbase, MSRateContr
obj
->
burst_state
=
MSStatefulQosAnalyserBurstEnable
;
}
/*test a min burst to avoid overestimation of available bandwidth*/
else
if
(
obj
->
curindex
%
10
==
5
||
obj
->
curindex
%
10
==
6
){
else
if
(
obj
->
curindex
%
10
==
2
||
obj
->
curindex
%
10
==
3
){
P
(
YELLOW
"try minimal burst!
\n
"
);
bw
*=
.
33
;
}
/*no bandwidth estimation computed*/
if
(
bw
<=
0
){
if
(
bw
<=
0
||
curbw
<=
0
){
action
->
type
=
MSRateControlActionDoNothing
;
action
->
value
=
0
;
}
else
if
(
bw
>
curbw
){
...
...
tester/mediastreamer2_adaptive_tester.c
View file @
124f6c61
...
...
@@ -133,6 +133,7 @@ static void audio_manager_start(stream_manager_t * mgr
,
int
target_bitrate
,
const
char
*
player_file
,
const
char
*
recorder_file
){
media_stream_set_target_network_bitrate
(
&
mgr
->
audio_stream
->
ms
,
target_bitrate
);
CU_ASSERT_EQUAL
(
audio_stream_start_full
(
mgr
->
audio_stream
...
...
@@ -155,7 +156,6 @@ static void video_manager_start( stream_manager_t * mgr
,
int
remote_port
,
int
target_bitrate
,
MSWebCam
*
cam
)
{
media_stream_set_target_network_bitrate
(
&
mgr
->
video_stream
->
ms
,
target_bitrate
);
int
result
=
video_stream_start
(
mgr
->
video_stream
...
...
@@ -191,8 +191,8 @@ static void basic_audio_stream() {
/*recorder should be initialized before sender to avoid missing the first
emitted packets*/
audio_manager_start
(
margaux
,
0
,
marielle
->
local_rtp
,
0
,
0
,
RECORDED_8K_1S_FILE
);
audio_manager_start
(
marielle
,
0
,
margaux
->
local_rtp
,
0
,
HELLO_8K_1S_FILE
,
0
);
audio_manager_start
(
margaux
,
0
,
marielle
->
local_rtp
,
0
,
NULL
,
RECORDED_8K_1S_FILE
);
audio_manager_start
(
marielle
,
0
,
margaux
->
local_rtp
,
0
,
HELLO_8K_1S_FILE
,
NULL
);
ms_filter_add_notify_callback
(
marielle
->
audio_stream
->
soundread
,
notify_cb
,
&
marielle
->
audio_stats
,
TRUE
);
...
...
@@ -277,16 +277,17 @@ static OrtpEvQueue * start_adaptive_stream(StreamType type, stream_manager_t **
rtp_session_set_duplication_ratio
(
marielle_ms
->
sessions
.
rtp_session
,
dup_ratio
);
if
(
marielle
->
type
==
AudioStreamType
){
audio_manager_start
(
marielle
,
payload
,
margaux
->
local_rtp
,
initial_bitrate
,
HELLO_16K_1S_FILE
,
NULL
);
audio_manager_start
(
marielle
,
payload
,
margaux
->
local_rtp
,
initial_bitrate
,
HELLO_16K_1S_FILE
,
NULL
);
ms_filter_call_method
(
marielle
->
audio_stream
->
soundread
,
MS_FILE_PLAYER_LOOP
,
&
pause_time
);
audio_manager_start
(
margaux
,
payload
,
marielle
->
local_rtp
,
-
1
,
NULL
,
RECORDED_16K_1S_FILE
);
audio_manager_start
(
margaux
,
payload
,
marielle
->
local_rtp
,
0
,
NULL
,
RECORDED_16K_1S_FILE
);
}
else
{
video_manager_start
(
marielle
,
payload
,
margaux
->
local_rtp
,
initial_bitrate
,
marielle_webcam
);
video_manager_start
(
marielle
,
payload
,
margaux
->
local_rtp
,
0
,
marielle_webcam
);
video_stream_set_direction
(
margaux
->
video_stream
,
VideoStreamRecvOnly
);
video_manager_start
(
margaux
,
payload
,
marielle
->
local_rtp
,
-
1
,
NULL
);
video_manager_start
(
margaux
,
payload
,
marielle
->
local_rtp
,
0
,
NULL
);
}
rtp_session_enable_network_simulation
(
margaux_ms
->
sessions
.
rtp_session
,
&
params
);
evq
=
ortp_ev_queue_new
();
...
...
@@ -318,9 +319,9 @@ static void iterate_adaptive_stream(stream_manager_t * marielle, stream_manager_
handle_queue_events
(
marielle
,
evq
);
if
(
retry
%
10
==
0
)
{
ms_message
(
"stream [%p] bandwidth usage: [d=%.1f,u=%.1f] kbit/sec"
,
marielle_ms
,
media_stream_get_down_bw
(
marielle_ms
)
/
1000
,
media_stream_get_up_bw
(
marielle_ms
)
/
1000
);
marielle_ms
,
media_stream_get_down_bw
(
marielle_ms
)
/
1000
,
media_stream_get_up_bw
(
marielle_ms
)
/
1000
);
ms_message
(
"stream [%p] bandwidth usage: [d=%.1f,u=%.1f] kbit/sec"
,
margaux_ms
,
media_stream_get_down_bw
(
margaux_ms
)
/
1000
,
media_stream_get_up_bw
(
margaux_ms
)
/
1000
);
margaux_ms
,
media_stream_get_down_bw
(
margaux_ms
)
/
1000
,
media_stream_get_up_bw
(
margaux_ms
)
/
1000
);
}
ms_usleep
(
100000
);
}
...
...
@@ -464,17 +465,15 @@ static void adaptive_vp8() {
CU_ASSERT_TRUE
(
marielle
->
video_stats
.
congestion_bw_estim
>
200
);
DEINIT
();
/*very low bandwidth causes a lot of packets to be dropped since congestion is
always present even if we are below the limit due to encoder bit-rate variation*/
evq
=
start_adaptive_stream
(
VideoStreamType
,
&
marielle
,
&
margaux
,
VP8_PAYLOAD_TYPE
,
300000
,
40000
,
0
,
50
,
0
);
evq
=
start_adaptive_stream
(
VideoStreamType
,
&
marielle
,
&
margaux
,
VP8_PAYLOAD_TYPE
,
300000
,
45000
,
0
,
50
,
0
);
iterate_adaptive_stream
(
marielle
,
margaux
,
evq
,
timeout_receive_rtcp
(
17
),
NULL
,
0
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
loss_estim
,
0
,
15
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
congestion_bw_estim
,
2
0
,
6
5
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
loss_estim
,
0
,
2
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
congestion_bw_estim
,
3
0
,
6
0
);
DEINIT
();
evq
=
start_adaptive_stream
(
VideoStreamType
,
&
marielle
,
&
margaux
,
VP8_PAYLOAD_TYPE
,
300000
,
70000
,
0
,
50
,
0
);
iterate_adaptive_stream
(
marielle
,
margaux
,
evq
,
timeout_receive_rtcp
(
17
),
NULL
,
0
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
loss_estim
,
0
,
10
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
loss_estim
,
0
,
2
);
CU_ASSERT_IN_RANGE
(
marielle
->
video_stats
.
congestion_bw_estim
,
50
,
95
);
DEINIT
();
...
...
@@ -498,7 +497,7 @@ static void packet_duplication() {
CU_ASSERT_EQUAL
(
stats
->
duplicated
,
dup_ratio
?
stats
->
packet_recv
/
(
dup_ratio
+
1
)
:
0
);
/*in theory, cumulative loss should be the invert of duplicated count, but
since cumulative loss is computed only on received RTCP report and duplicated
count is updated on each RTP packet received, we cannot accurately
verify
the values*/
count is updated on each RTP packet received, we cannot accurately
compare
the
se
values*/
CU_ASSERT_TRUE
(
stats
->
cum_packet_loss
<=
-
.
5
*
stats
->
duplicated
);
DEINIT
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment