mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 09:36:46 +00:00
FS-8130
Port video buffer to also support audio and remove original STFU jitter buffer Add some more resilience to video packet loss Add codec control mechanism for both call-specific debug and codec/call specfic params Make opus function better in packet loss and latent situations Use new codec control prams to make JB lookahead FEC optionally enabled or disabled mid-call Add Param to allow JB lookahead to be enabled.
This commit is contained in:
@@ -733,6 +733,8 @@ static switch_status_t switch_h264_control(switch_codec_t *codec,
|
||||
switch_codec_control_command_t cmd,
|
||||
switch_codec_control_type_t ctype,
|
||||
void *cmd_data,
|
||||
switch_codec_control_type_t atype,
|
||||
void *cmd_arg,
|
||||
switch_codec_control_type_t *rtype,
|
||||
void **ret_data) {
|
||||
|
||||
|
@@ -75,6 +75,8 @@ struct opus_context {
|
||||
uint32_t enc_frame_size;
|
||||
uint32_t dec_frame_size;
|
||||
uint32_t old_plpct;
|
||||
uint32_t debug;
|
||||
uint32_t use_jb_lookahead;
|
||||
opus_codec_settings_t codec_settings;
|
||||
};
|
||||
|
||||
@@ -89,6 +91,7 @@ struct {
|
||||
int asymmetric_samplerates;
|
||||
int keep_fec;
|
||||
int debuginfo;
|
||||
uint32_t use_jb_lookahead;
|
||||
switch_mutex_t *mutex;
|
||||
} opus_prefs;
|
||||
|
||||
@@ -534,7 +537,7 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec,
|
||||
|
||||
bytes = opus_encode(context->encoder_object, (void *) decoded_data, context->enc_frame_size, (unsigned char *) encoded_data, len);
|
||||
|
||||
if (globals.debug) {
|
||||
if (globals.debug || context->debug > 1) {
|
||||
int samplerate = context->enc_frame_size * 1000 / (codec->implementation->microseconds_per_packet / 1000);
|
||||
switch_opus_info(encoded_data, bytes, samplerate, "encode");
|
||||
}
|
||||
@@ -552,6 +555,7 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec,
|
||||
return SWITCH_STATUS_GENERR;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t switch_opus_decode(switch_codec_t *codec,
|
||||
switch_codec_t *other_codec,
|
||||
void *encoded_data,
|
||||
@@ -573,24 +577,57 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
|
||||
frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400));
|
||||
|
||||
if (*flag & SFF_PLC) {
|
||||
switch_core_session_t *session = codec->session;
|
||||
switch_jb_t *jb = NULL;
|
||||
int got_frame = 0;
|
||||
|
||||
plc = 1;
|
||||
|
||||
encoded_data = NULL;
|
||||
|
||||
opus_decoder_ctl(context->decoder_object, OPUS_GET_LAST_PACKET_DURATION(&frame_size));
|
||||
if (!frame_size) {
|
||||
frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400));
|
||||
|
||||
if (opus_prefs.use_jb_lookahead || context->use_jb_lookahead) {
|
||||
fec = 1;
|
||||
}
|
||||
|
||||
if (context->codec_settings.useinbandfec) {
|
||||
fec = 1;
|
||||
if (!fec && context->codec_settings.useinbandfec && session) {
|
||||
if (opus_packet_get_bandwidth(codec->cur_frame->data) != OPUS_BANDWIDTH_FULLBAND &&
|
||||
codec->cur_frame && (jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO))) {
|
||||
switch_frame_t frame = { 0 };
|
||||
uint8_t buf[SWITCH_RTP_MAX_BUF_LEN];
|
||||
frame.data = buf;
|
||||
frame.buflen = sizeof(buf);
|
||||
|
||||
if (switch_jb_peek_frame(jb, codec->cur_frame->seq, 1, &frame)) {
|
||||
got_frame = 1;
|
||||
fec = 1;
|
||||
encoded_data = frame.data;
|
||||
encoded_data_len = frame.datalen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_frame) {
|
||||
opus_decoder_ctl(context->decoder_object, OPUS_GET_LAST_PACKET_DURATION(&frame_size));
|
||||
|
||||
if (!frame_size) {
|
||||
frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400));
|
||||
}
|
||||
}
|
||||
|
||||
if (globals.debug || context->debug) {
|
||||
if (opus_prefs.use_jb_lookahead || context->use_jb_lookahead) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MISSING FRAME: %s\n", fec ? "Look-ahead FEC" : "PLC");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "MISSING FRAME: OPUS_PLC\n");
|
||||
}
|
||||
}
|
||||
|
||||
*flag &= ~SFF_PLC;
|
||||
}
|
||||
|
||||
if (globals.debug) {
|
||||
if (globals.debug || context->debug > 1) {
|
||||
int samplerate = context->dec_frame_size * 1000 / (codec->implementation->microseconds_per_packet / 1000);
|
||||
switch_opus_info((*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len,
|
||||
switch_opus_info(encoded_data, encoded_data_len,
|
||||
samplerate ? samplerate : codec->implementation->actual_samples_per_second, "decode");
|
||||
}
|
||||
|
||||
@@ -660,7 +697,7 @@ static switch_status_t switch_opus_encode_repacketize(switch_codec_t *codec,
|
||||
|
||||
ret = opus_repacketizer_out(rp, encoded_data, total_len+opus_repacketizer_get_nb_frames(rp));
|
||||
|
||||
if (globals.debug) {
|
||||
if (globals.debug || context->debug) {
|
||||
int samplerate = context->enc_frame_size * 1000 / (codec->implementation->microseconds_per_packet / 1000);
|
||||
switch_opus_info(encoded_data, ret, samplerate, "encode_repacketize");
|
||||
}
|
||||
@@ -706,6 +743,8 @@ static switch_status_t opus_load_config(switch_bool_t reload)
|
||||
opus_prefs.plpct = atoi(val);
|
||||
} else if (!strcasecmp(key, "asymmetric-sample-rates")) {
|
||||
opus_prefs.asymmetric_samplerates = atoi(val);
|
||||
} else if (!strcasecmp(key, "use-jb-lookahead")) {
|
||||
opus_prefs.use_jb_lookahead = switch_true(val);
|
||||
} else if (!strcasecmp(key, "keep-fec-enabled")) {
|
||||
opus_prefs.keep_fec = atoi(val);
|
||||
} else if (!strcasecmp(key, "maxaveragebitrate")) {
|
||||
@@ -777,7 +816,7 @@ static switch_status_t switch_opus_keep_fec_enabled(switch_codec_t *codec)
|
||||
* 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) {
|
||||
if (globals.debug || context->debug) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder: FEC is enabled\n");
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -789,7 +828,7 @@ static switch_status_t switch_opus_keep_fec_enabled(switch_codec_t *codec)
|
||||
|
||||
opus_encoder_ctl(context->encoder_object,OPUS_SET_BITRATE(current_bitrate));
|
||||
|
||||
if (globals.debug) {
|
||||
if (globals.debug || context->debug) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus encoder: increased bitrate to [%d] to keep FEC enabled\n", current_bitrate);
|
||||
}
|
||||
|
||||
@@ -801,12 +840,46 @@ static switch_status_t switch_opus_control(switch_codec_t *codec,
|
||||
switch_codec_control_command_t cmd,
|
||||
switch_codec_control_type_t ctype,
|
||||
void *cmd_data,
|
||||
switch_codec_control_type_t atype,
|
||||
void *cmd_arg,
|
||||
switch_codec_control_type_t *rtype,
|
||||
void **ret_data)
|
||||
{
|
||||
struct opus_context *context = codec->private_info;
|
||||
|
||||
switch(cmd) {
|
||||
case SCC_CODEC_SPECIFIC:
|
||||
{
|
||||
const char *cmd = (const char *)cmd_data;
|
||||
const char *arg = (const char *)cmd_arg;
|
||||
switch_codec_control_type_t reply_type = SCCT_STRING;
|
||||
const char *reply = "ERROR INVALID COMMAND";
|
||||
|
||||
if (!zstr(cmd)) {
|
||||
if (!strcasecmp(cmd, "jb_lookahead")) {
|
||||
if (!zstr(arg)) {
|
||||
context->use_jb_lookahead = switch_true(arg);
|
||||
}
|
||||
reply = context->use_jb_lookahead ? "LOOKAHEAD ON" : "LOOKAHEAD OFF";
|
||||
}
|
||||
}
|
||||
|
||||
if (rtype) {
|
||||
*rtype = reply_type;
|
||||
|
||||
if (reply) {
|
||||
*ret_data = (void *)reply;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case SCC_DEBUG:
|
||||
{
|
||||
int32_t level = *((uint32_t *) cmd_data);
|
||||
context->debug = level;
|
||||
}
|
||||
break;
|
||||
case SCC_AUDIO_PACKET_LOSS:
|
||||
{
|
||||
uint32_t plpct = *((uint32_t *) cmd_data);
|
||||
@@ -830,7 +903,7 @@ static switch_status_t switch_opus_control(switch_codec_t *codec,
|
||||
switch_opus_keep_fec_enabled(codec);
|
||||
}
|
||||
|
||||
if (globals.debug) {
|
||||
if (globals.debug || context->debug) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opus Adjusting packet loss percent from %d%% to %d%%!\n",
|
||||
context->old_plpct, plpct);
|
||||
}
|
||||
|
@@ -62,7 +62,7 @@ struct silk_context {
|
||||
SKP_SILK_SDK_DecControlStruct decoder_object;
|
||||
void *enc_state;
|
||||
void *dec_state;
|
||||
SKP_uint8 recbuff[STFU_DATALEN];
|
||||
SKP_uint8 recbuff[SWITCH_RTP_MAX_BUF_LEN];
|
||||
SKP_int16 reclen;
|
||||
};
|
||||
|
||||
@@ -326,12 +326,8 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
|
||||
SKP_int16 ret, len;
|
||||
int16_t *target = decoded_data;
|
||||
switch_core_session_t *session = codec->session;
|
||||
stfu_instance_t *jb = NULL;
|
||||
|
||||
switch_jb_t *jb = NULL;
|
||||
SKP_int lost_flag = (*flag & SFF_PLC);
|
||||
stfu_frame_t *next_frame = NULL;
|
||||
|
||||
int32_t found_frame;
|
||||
switch_bool_t did_lbrr = SWITCH_FALSE;
|
||||
int i;
|
||||
|
||||
@@ -345,11 +341,14 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
|
||||
}
|
||||
|
||||
if (jb && codec->cur_frame) {
|
||||
for (i = 1; i <= MAX_LBRR_DELAY; i++) {
|
||||
found_frame = stfu_n_peek_frame(jb, (uint32_t)codec->cur_frame->timestamp, codec->cur_frame->seq, (uint16_t)i, &next_frame);
|
||||
switch_frame_t frame = { 0 };
|
||||
uint8_t buf[SWITCH_RTP_MAX_BUF_LEN];
|
||||
frame.data = buf;
|
||||
frame.buflen = sizeof(buf);
|
||||
|
||||
if (found_frame) {
|
||||
SKP_Silk_SDK_search_for_LBRR(next_frame->data, (const int)next_frame->dlen, i, (SKP_uint8*) &context->recbuff, &context->reclen);
|
||||
for (i = 1; i <= MAX_LBRR_DELAY; i++) {
|
||||
if (switch_jb_peek_frame(jb, codec->cur_frame->seq, (uint16_t)i, &frame)) {
|
||||
SKP_Silk_SDK_search_for_LBRR(frame.data, (const int)frame.datalen, i, (SKP_uint8*) &context->recbuff, &context->reclen);
|
||||
|
||||
if (context->reclen) {
|
||||
encoded_data = &context->recbuff;
|
||||
|
@@ -940,6 +940,8 @@ static switch_status_t switch_vpx_control(switch_codec_t *codec,
|
||||
switch_codec_control_command_t cmd,
|
||||
switch_codec_control_type_t ctype,
|
||||
void *cmd_data,
|
||||
switch_codec_control_type_t atype,
|
||||
void *cmd_arg,
|
||||
switch_codec_control_type_t *rtype,
|
||||
void **ret_data)
|
||||
{
|
||||
|
Reference in New Issue
Block a user