mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-04 17:51:03 +00:00
Merge pull request #327 in FS/freeswitch from ~DRAGOS_OANCEA/freeswitch-dragos:opus-keep-fec-on to master
* commit 'b3f453b02f62da450681c4b584bda838134c1317': FS-7772: mod_opus: add functionality to keep FEC enabled on the encoder by modifying the bitrate if packet loss changes (Opus codec specific behaviour).
This commit is contained in:
commit
5b76e4ade9
@ -25,6 +25,7 @@
|
|||||||
*
|
*
|
||||||
* Brian K. West <brian@freeswitch.org>
|
* Brian K. West <brian@freeswitch.org>
|
||||||
* Noel Morgan <noel@vwci.com>
|
* Noel Morgan <noel@vwci.com>
|
||||||
|
* Dragos Oancea <droancea@yahoo.com>
|
||||||
*
|
*
|
||||||
* mod_opus.c -- The OPUS ultra-low delay audio codec (http://www.opus-codec.org/)
|
* mod_opus.c -- The OPUS ultra-low delay audio codec (http://www.opus-codec.org/)
|
||||||
*
|
*
|
||||||
@ -86,6 +87,7 @@ struct {
|
|||||||
int sprop_maxcapturerate;
|
int sprop_maxcapturerate;
|
||||||
int plpct;
|
int plpct;
|
||||||
int asymmetric_samplerates;
|
int asymmetric_samplerates;
|
||||||
|
int keep_fec;
|
||||||
int debuginfo;
|
int debuginfo;
|
||||||
switch_mutex_t *mutex;
|
switch_mutex_t *mutex;
|
||||||
} opus_prefs;
|
} opus_prefs;
|
||||||
@ -594,6 +596,8 @@ static switch_status_t opus_load_config(switch_bool_t reload)
|
|||||||
opus_prefs.plpct = atoi(val);
|
opus_prefs.plpct = atoi(val);
|
||||||
} else if (!strcasecmp(key, "asymmetric-sample-rates")) {
|
} else if (!strcasecmp(key, "asymmetric-sample-rates")) {
|
||||||
opus_prefs.asymmetric_samplerates = atoi(val);
|
opus_prefs.asymmetric_samplerates = atoi(val);
|
||||||
|
} else if (!strcasecmp(key, "keep-fec-enabled")) {
|
||||||
|
opus_prefs.keep_fec = atoi(val);
|
||||||
} else if (!strcasecmp(key, "maxaveragebitrate")) {
|
} else if (!strcasecmp(key, "maxaveragebitrate")) {
|
||||||
opus_prefs.maxaveragebitrate = atoi(val);
|
opus_prefs.maxaveragebitrate = atoi(val);
|
||||||
if ( opus_prefs.maxaveragebitrate < 6000 || opus_prefs.maxaveragebitrate > 510000 ) {
|
if ( opus_prefs.maxaveragebitrate < 6000 || opus_prefs.maxaveragebitrate > 510000 ) {
|
||||||
@ -621,6 +625,55 @@ static switch_status_t opus_load_config(switch_bool_t reload)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static switch_status_t switch_opus_keep_fec_enabled(switch_codec_t *codec)
|
||||||
|
{
|
||||||
|
struct opus_context *context = codec->private_info;
|
||||||
|
opus_int32 current_bitrate;
|
||||||
|
opus_int32 current_loss;
|
||||||
|
uint32_t LBRR_threshold_bitrate,LBRR_rate_thres_bps,real_target_bitrate ;
|
||||||
|
opus_int32 a32,b32;
|
||||||
|
uint32_t fs = context->enc_frame_size * 1000 / (codec->implementation->microseconds_per_packet / 1000);
|
||||||
|
float frame_rate = 1000 / (codec->implementation->microseconds_per_packet / 1000);
|
||||||
|
uint32_t step = 8000 / (codec->implementation->microseconds_per_packet / 1000); /* this works for 10 ms, 20 ms and 40 ms frame sizes. not for 60 ms*/
|
||||||
|
|
||||||
|
opus_encoder_ctl(context->encoder_object, OPUS_GET_BITRATE(¤t_bitrate));
|
||||||
|
opus_encoder_ctl(context->encoder_object, OPUS_GET_PACKET_LOSS_PERC(¤t_loss));
|
||||||
|
if( fs == 8000 ) {
|
||||||
|
LBRR_rate_thres_bps = 12000; /*LBRR_NB_MIN_RATE_BPS*/
|
||||||
|
} else if( fs == 12000 ) {
|
||||||
|
LBRR_rate_thres_bps = 14000; /*LBRR_MB_MIN_RATE_BPS*/
|
||||||
|
} else {
|
||||||
|
LBRR_rate_thres_bps = 16000; /*LBRR_WB_MIN_RATE_BPS*/
|
||||||
|
}
|
||||||
|
/*see opus-1.1/src/opus_encoder.c , opus_encode_native() */
|
||||||
|
real_target_bitrate = 8 * (current_bitrate * context->enc_frame_size / ( fs * 8 ) - 1) * frame_rate ;
|
||||||
|
/*check if the internally used bitrate is above the threshold defined in opus-1.1/silk/control_codec.c */
|
||||||
|
a32 = LBRR_rate_thres_bps * (125 -(((current_loss) < (25)) ? (current_loss) : (25)));
|
||||||
|
b32 = ((opus_int32)((0.01) * ((opus_int64)1 << (16)) + 0.5));
|
||||||
|
LBRR_threshold_bitrate = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
|
||||||
|
if ((!real_target_bitrate || !LBRR_threshold_bitrate)){
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,"Opus encoder: error while controlling FEC params\n");
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
/* Is there any FEC at the current bitrate and requested packet loss ?
|
||||||
|
* If yes, then keep the current bitrate. If not, modify bitrate to keep FEC on. */
|
||||||
|
if (real_target_bitrate > LBRR_threshold_bitrate) {
|
||||||
|
/*FEC is already enabled, do nothing*/
|
||||||
|
if (globals.debug)
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"Opus encoder: FEC is enabled\n");
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
while (real_target_bitrate <= LBRR_threshold_bitrate) {
|
||||||
|
current_bitrate += step;
|
||||||
|
real_target_bitrate = 8 * (current_bitrate * context->enc_frame_size / ( fs * 8 ) - 1) * frame_rate ;
|
||||||
|
}
|
||||||
|
opus_encoder_ctl(context->encoder_object,OPUS_SET_BITRATE(current_bitrate));
|
||||||
|
if (globals.debug)
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"Opus encoder: increased bitrate to [%d] to keep FEC enabled\n",current_bitrate);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static switch_status_t switch_opus_control(switch_codec_t *codec,
|
static switch_status_t switch_opus_control(switch_codec_t *codec,
|
||||||
switch_codec_control_command_t cmd,
|
switch_codec_control_command_t cmd,
|
||||||
switch_codec_control_type_t ctype,
|
switch_codec_control_type_t ctype,
|
||||||
@ -645,6 +698,8 @@ static switch_status_t switch_opus_control(switch_codec_t *codec,
|
|||||||
|
|
||||||
if (plpct != context->old_plpct) {
|
if (plpct != context->old_plpct) {
|
||||||
opus_encoder_ctl(context->encoder_object, OPUS_SET_PACKET_LOSS_PERC(plpct));
|
opus_encoder_ctl(context->encoder_object, OPUS_SET_PACKET_LOSS_PERC(plpct));
|
||||||
|
if (opus_prefs.keep_fec)
|
||||||
|
switch_opus_keep_fec_enabled(codec);
|
||||||
}
|
}
|
||||||
context->old_plpct = plpct;
|
context->old_plpct = plpct;
|
||||||
}
|
}
|
||||||
@ -805,7 +860,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
|
|||||||
switch_opus_encode, /* function to encode raw data into encoded data */
|
switch_opus_encode, /* function to encode raw data into encoded data */
|
||||||
switch_opus_decode, /* function to decode encoded data into raw data */
|
switch_opus_decode, /* function to decode encoded data into raw data */
|
||||||
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
||||||
|
codec_interface->implementations->codec_control = switch_opus_control;
|
||||||
settings.stereo = 1;
|
settings.stereo = 1;
|
||||||
dft_fmtp = gen_fmtp(&settings, pool);
|
dft_fmtp = gen_fmtp(&settings, pool);
|
||||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||||
@ -825,6 +880,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
|
|||||||
switch_opus_encode, /* function to encode raw data into encoded data */
|
switch_opus_encode, /* function to encode raw data into encoded data */
|
||||||
switch_opus_decode, /* function to decode encoded data into raw data */
|
switch_opus_decode, /* function to decode encoded data into raw data */
|
||||||
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
switch_opus_destroy); /* deinitalize a codec handle using this implementation */
|
||||||
|
codec_interface->implementations->codec_control = switch_opus_control;
|
||||||
|
|
||||||
bytes *= 2;
|
bytes *= 2;
|
||||||
samples *= 2;
|
samples *= 2;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user