mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-22 13:48:09 +00:00
Quality reporting: do not send reports on low bandwidth connections
This commit is contained in:
parent
5df2086f6f
commit
03b2dade14
3 changed files with 42 additions and 44 deletions
|
|
@ -31,17 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
/***************************************************************************
|
||||
* TODO / REMINDER LIST
|
||||
***************************************************************************
|
||||
For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000).
|
||||
|
||||
rlq value: need algo to compute it
|
||||
|
||||
3.4 overload avoidance?
|
||||
a. Send only one report at the end of each call. (audio | video?)
|
||||
b. Use interval reports only on "problem" calls that are being closely monitored.
|
||||
|
||||
- The Session report when
|
||||
codec change
|
||||
session fork
|
||||
rtt SR recuperer
|
||||
***************************************************************************
|
||||
* END OF TODO / REMINDER LIST
|
||||
****************************************************************************/
|
||||
|
|
@ -108,8 +98,6 @@ static void reset_avg_metrics(reporting_session_report_t * report){
|
|||
metrics[i]->jitter_buffer.max = 0;
|
||||
|
||||
metrics[i]->delay.round_trip_delay = 0;
|
||||
|
||||
/*metrics[i]->delay.symm_one_way_delay = 0;*/
|
||||
}
|
||||
report->last_report_date = ms_time(NULL);
|
||||
}
|
||||
|
|
@ -164,8 +152,6 @@ static uint8_t are_metrics_filled(const reporting_content_metrics_t rm) {
|
|||
IF_NUM_IN_RANGE(rm.delay.round_trip_delay, 0, 65535, ret|=METRICS_DELAY);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moslq/rm.rtcp_xr_count, 1, 5, ret|=METRICS_QUALITY_ESTIMATES);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moscq/rm.rtcp_xr_count, 1, 5, ret|=METRICS_QUALITY_ESTIMATES);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.rlq/rm.rtcp_xr_count, 1, 120, ret|=METRICS_QUALITY_ESTIMATES);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.rcq/rm.rtcp_xr_count, 1, 120, ret|=METRICS_QUALITY_ESTIMATES);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -210,18 +196,13 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
|
|||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " PD=%s", rm.session_description.payload_desc);
|
||||
APPEND_IF(buffer, size, offset, " SR=%d", rm.session_description.sample_rate, rm.session_description.sample_rate != -1);
|
||||
APPEND_IF(buffer, size, offset, " FD=%d", rm.session_description.frame_duration, rm.session_description.frame_duration != -1);
|
||||
/*append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets);*/
|
||||
/*append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec);*/
|
||||
/*append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp);
|
||||
APPEND_IF(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment, rm.session_description.packet_loss_concealment != -1);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state);*/
|
||||
}
|
||||
|
||||
if ((available_metrics & METRICS_JITTER_BUFFER) != 0){
|
||||
append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:");
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive, 0, 3);
|
||||
/*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15);*/
|
||||
if (rm.rtcp_xr_count){
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal/rm.rtcp_xr_count, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max/rm.rtcp_xr_count, 0, 65535);
|
||||
|
|
@ -250,8 +231,6 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
|
|||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay/rm.rtcp_xr_count, 0, 65535);
|
||||
}
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay, 0, 65535);
|
||||
/*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay, 0, 65535);*/
|
||||
/*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay, 0, 65535);*/
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter, 0, 65535);
|
||||
}
|
||||
|
|
@ -260,7 +239,6 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
|
|||
append_to_buffer(buffer, size, offset, "\r\nSignal:");
|
||||
APPEND_IF(buffer, size, offset, " SL=%d", rm.signal.level, rm.signal.level != 127);
|
||||
APPEND_IF(buffer, size, offset, " NL=%d", rm.signal.noise_level, rm.signal.noise_level != 127);
|
||||
/*append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss);*/
|
||||
}
|
||||
|
||||
/*if quality estimates metrics are available, rtcp_xr_count should be always not null*/
|
||||
|
|
@ -269,19 +247,8 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
|
|||
IF_NUM_IN_RANGE(rm.quality_estimates.moscq/rm.rtcp_xr_count, 1, 5, moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq/rm.rtcp_xr_count));
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nQualityEst:");
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq/rm.rtcp_xr_count, 1, 120);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg);*/
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq/rm.rtcp_xr_count, 1, 120);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg);*/
|
||||
/*append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg);*/
|
||||
/*append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQ=%s", moslq_str);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQ=%s", moscq_str);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg);*/
|
||||
}
|
||||
|
||||
if ((available_metrics & METRICS_ADAPTIVE_ALGORITHM) != 0){
|
||||
|
|
@ -304,7 +271,7 @@ static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * off
|
|||
ms_free(moscq_str);
|
||||
}
|
||||
|
||||
static int send_report(const LinphoneCall* call, reporting_session_report_t * report, const char * report_event) {
|
||||
static int send_report(LinphoneCall* call, reporting_session_report_t * report, const char * report_event) {
|
||||
LinphoneContent content = {0};
|
||||
LinphoneAddress *addr;
|
||||
int expires = -1;
|
||||
|
|
@ -313,6 +280,12 @@ static int send_report(const LinphoneCall* call, reporting_session_report_t * re
|
|||
char * buffer;
|
||||
int ret = 0;
|
||||
|
||||
/*if we are on a low bandwidth network, do not send reports to not overload it*/
|
||||
if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){
|
||||
ms_warning("QualityReporting[%p]: Avoid sending reports on low bandwidth network", call);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*if the call was hung up too early, we might have invalid IPs information
|
||||
in that case, we abort the report since it's not useful data*/
|
||||
if (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0
|
||||
|
|
@ -323,14 +296,14 @@ static int send_report(const LinphoneCall* call, reporting_session_report_t * re
|
|||
, report_event
|
||||
, linphone_call_get_duration(call)
|
||||
, (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0) ? "local" : "remote");
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
addr = linphone_address_new(linphone_proxy_config_get_quality_reporting_collector(call->dest_proxy));
|
||||
if (addr == NULL) {
|
||||
ms_warning("QualityReporting[%p]: Asked to submit reporting statistics but no collector address found"
|
||||
, call);
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
buffer = (char *) ms_malloc(size);
|
||||
|
|
@ -364,7 +337,7 @@ static int send_report(const LinphoneCall* call, reporting_session_report_t * re
|
|||
|
||||
/*(WIP) Memory leak: PUBLISH message is never freed (issue 1283)*/
|
||||
if (! linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content)){
|
||||
ret=3;
|
||||
ret=4;
|
||||
}
|
||||
linphone_address_destroy(addr);
|
||||
|
||||
|
|
@ -502,6 +475,11 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) {
|
|||
}
|
||||
}
|
||||
|
||||
/* generate random float in interval ] 0.9 t ; 1.1 t [*/
|
||||
static float reporting_rand(float t){
|
||||
return t * (.2f * (rand() / (RAND_MAX * 1.0f)) + 0.9f);
|
||||
}
|
||||
|
||||
void linphone_reporting_on_rtcp_received(LinphoneCall *call, int stats_type) {
|
||||
reporting_session_report_t * report = call->log->reporting.reports[stats_type];
|
||||
reporting_content_metrics_t * metrics = NULL;
|
||||
|
|
@ -528,7 +506,6 @@ void linphone_reporting_on_rtcp_received(LinphoneCall *call, int stats_type) {
|
|||
|
||||
metrics->rtcp_xr_count++;
|
||||
|
||||
metrics->quality_estimates.rcq += rtcp_XR_voip_metrics_get_r_factor(block);
|
||||
metrics->quality_estimates.moslq += rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f;
|
||||
metrics->quality_estimates.moscq += rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f;
|
||||
|
||||
|
|
@ -545,8 +522,9 @@ void linphone_reporting_on_rtcp_received(LinphoneCall *call, int stats_type) {
|
|||
}
|
||||
}while(rtcp_next_packet(block));
|
||||
|
||||
/* check if we should send an interval report */
|
||||
if (report_interval>0 && ms_time(NULL)-report->last_report_date>report_interval){
|
||||
/* check if we should send an interval report - use a random sending time to
|
||||
dispatch reports and avoid sending them too close from each other */
|
||||
if (report_interval>0 && ms_time(NULL)-report->last_report_date>reporting_rand(report_interval)){
|
||||
linphone_reporting_publish_interval_report(call);
|
||||
}
|
||||
}
|
||||
|
|
@ -625,6 +603,7 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
reporting_session_report_t * linphone_reporting_new() {
|
||||
int i;
|
||||
reporting_session_report_t * rm = ms_new0(reporting_session_report_t,1);
|
||||
|
|
|
|||
|
|
@ -88,8 +88,6 @@ typedef struct reporting_content_metrics {
|
|||
|
||||
// quality estimates - optional
|
||||
struct {
|
||||
int rlq; // linked to moslq - in [0..120]
|
||||
int rcq; //voip metrics R factor - no - vary or avg in [0..120]
|
||||
float moslq; // no - vary or avg - voip metrics - in [0..4.9]
|
||||
float moscq; // no - vary or avg - voip metrics - in [0..4.9]
|
||||
} quality_estimates;
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static void quality_reporting_not_used_without_config() {
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void quality_reporting_not_sent_if_call_not_started() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -88,6 +89,26 @@ static void quality_reporting_not_sent_if_call_not_started() {
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void quality_reporting_not_sent_if_low_bandwidth() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCallParams* marie_params;
|
||||
|
||||
marie_params=linphone_core_create_default_call_parameters(marie->lc);
|
||||
linphone_call_params_enable_low_bandwidth(marie_params,TRUE);
|
||||
|
||||
CU_ASSERT_TRUE(call_with_params(marie,pauline,marie_params,NULL));
|
||||
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void quality_reporting_at_call_termination() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -178,10 +199,10 @@ static void quality_reporting_session_report_if_video_stopped() {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
test_t quality_reporting_tests[] = {
|
||||
{ "Not used if no config", quality_reporting_not_used_without_config},
|
||||
{ "Call term session report not sent if call did not start", quality_reporting_not_sent_if_call_not_started},
|
||||
{ "Call term session report not sent if low bandwidth", quality_reporting_not_sent_if_low_bandwidth},
|
||||
{ "Call term session report sent if call ended normally", quality_reporting_at_call_termination},
|
||||
{ "Interval report if interval is configured", quality_reporting_interval_report},
|
||||
{ "Session report sent if video stopped during call", quality_reporting_session_report_if_video_stopped},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue