fix network loss rate overestimation when there is congestion only

parent 95dbd944
......@@ -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("\tconstant_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){
......
......@@ -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, 20, 65);
CU_ASSERT_IN_RANGE(marielle->video_stats.loss_estim, 0, 2);
CU_ASSERT_IN_RANGE(marielle->video_stats.congestion_bw_estim, 30, 60);
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 these values*/
CU_ASSERT_TRUE(stats->cum_packet_loss <= -.5*stats->duplicated);
DEINIT();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment