From 6385fb863a7e800dbb2668fd0ed4e1203b1ba18e Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Thu, 17 Sep 2015 12:52:55 -0400 Subject: [PATCH] FS-8161: mod_opus: Keep FEC enabled only if loss > 10 ( otherwise PLC is supposed to be better) --- src/mod/codecs/mod_opus/mod_opus.c | 63 +++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 6f56727667..74f797512a 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -309,6 +309,33 @@ static switch_bool_t switch_opus_has_fec(const uint8_t* payload,int payload_leng return SWITCH_FALSE; } +/* this is only useful for fs = 8000 hz, the map is only used + * at the beginning of the call. */ +static int switch_opus_get_fec_bitrate(int fs, int loss) +{ + int threshold_bitrates[25] = { + 15600,15200,15200,15200,14800, + 14800,14800,14800,14400,14400, + 14400,14000,14000,14000,13600, + 13600,13600,13600,13200,13200, + 13200,12800,12800,12800,12400 + }; + + if (loss <= 0){ + return SWITCH_STATUS_FALSE; + } + + if (fs == 8000) { + if (loss >=25) { + return threshold_bitrates[24]; + } else { + return threshold_bitrates[loss-1]; + } + } + + return SWITCH_STATUS_FALSE ; +} + static switch_status_t switch_opus_info(void * encoded_data, uint32_t len, uint32_t samples_per_second, char *print_text) { int nb_samples; @@ -493,7 +520,20 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag } if (opus_codec_settings.useinbandfec) { + /* FEC on the encoder: start the call with a preconfigured packet loss percentage */ + int fec_bitrate = opus_codec_settings.maxaveragebitrate; + int loss_percent = opus_prefs.plpct ; opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(opus_codec_settings.useinbandfec)); + opus_encoder_ctl(context->encoder_object, OPUS_SET_PACKET_LOSS_PERC(loss_percent)); + if (opus_prefs.keep_fec){ + fec_bitrate = switch_opus_get_fec_bitrate(enc_samplerate,loss_percent); + /* keep a bitrate for which the encoder will always add FEC */ + if (fec_bitrate != SWITCH_STATUS_FALSE) { + opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(fec_bitrate)); + /* will override the maxaveragebitrate set in opus.conf.xml */ + opus_codec_settings.maxaveragebitrate = fec_bitrate; + } + } } if (opus_codec_settings.usedtx) { @@ -954,18 +994,21 @@ static switch_status_t switch_opus_control(switch_codec_t *codec, plpct = 100; } - calc = plpct % 10; - plpct = plpct - calc + ( calc ? 10 : 0); - - if (opus_prefs.plpct > 0 && plpct < opus_prefs.plpct) { - plpct = opus_prefs.plpct; - } - - if (plpct != context->old_plpct) { + if (opus_prefs.keep_fec) { opus_encoder_ctl(context->encoder_object, OPUS_SET_PACKET_LOSS_PERC(plpct)); - + } else { + calc = plpct % 10; + plpct = plpct - calc + ( calc ? 10 : 0); + } + if (plpct != context->old_plpct) { if (opus_prefs.keep_fec) { - switch_opus_keep_fec_enabled(codec); + if (plpct > 10) { + /* this will increase bitrate a little bit, just to keep FEC enabled */ + switch_opus_keep_fec_enabled(codec); + } + } else { + /* this can have no effect because FEC is F(bitrate,packetloss), let the codec decide if FEC is to be used or not */ + opus_encoder_ctl(context->encoder_object, OPUS_SET_PACKET_LOSS_PERC(plpct)); } if (globals.debug || context->debug) {