diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 2f201a5fda..d4512d2df5 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1601,7 +1601,8 @@ typedef enum { SWITCH_CODEC_FLAG_FREE_POOL = (1 << 5), SWITCH_CODEC_FLAG_AAL2 = (1 << 6), SWITCH_CODEC_FLAG_PASSTHROUGH = (1 << 7), - SWITCH_CODEC_FLAG_READY = (1 << 8) + SWITCH_CODEC_FLAG_READY = (1 << 8), + SWITCH_CODEC_FLAG_HAS_PLC = (1 << 15) } switch_codec_flag_enum_t; typedef uint32_t switch_codec_flag_t; diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 38f6981665..84753983bd 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -328,6 +328,7 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels, &err); + switch_set_flag(codec, SWITCH_CODEC_FLAG_HAS_PLC); if (err != OPUS_OK) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create decoder: %s\n", opus_strerror(err)); @@ -417,20 +418,23 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, frame_samples = *decoded_data_len / 2 / codec->implementation->number_of_channels; frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400)); - /*FEC: shameless rip-off from mod_silk.c . OPUS only supports n+1 FEC , SILK is supposed to work with n+1, n+2*/ if (*flag & SFF_PLC) { - context->counter_plc_fec++; if (session) { jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO); } + if (jb && codec->cur_frame) { + found_frame = stfu_n_copy_next_frame(jb, (uint32_t)codec->cur_frame->timestamp, codec->cur_frame->seq, 1, &next_frame); + if (found_frame) { - samples = opus_decode(context->decoder_object, next_frame.data, next_frame.dlen, decoded_data, frame_size, 1); /* opus_decode() does PLC if there's no FEC in the packet*/ + samples = opus_decode(context->decoder_object, next_frame.data, next_frame.dlen, decoded_data, frame_size, 1); + if (samples < 0 ) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error (FEC): %s!\n", opus_strerror(samples)); - return SWITCH_STATUS_FALSE; } else { + context->counter_plc_fec++; + *flag &= ~SFF_PLC; *decoded_data_len = samples * 2 * codec->implementation->number_of_channels; return SWITCH_STATUS_SUCCESS; } @@ -438,13 +442,19 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, } } + /* opus_decode() does PLC if there's no FEC in the packet*/ samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, frame_size, 0); + if (*flag & SFF_PLC) { + context->counter_plc_fec++; + *flag &= ~SFF_PLC; + } + if (samples < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error: %s fs:%u plc:%d!\n", opus_strerror(samples), frame_size, !!(*flag & SFF_PLC)); return SWITCH_STATUS_GENERR; } - + *decoded_data_len = samples * 2 * codec->implementation->number_of_channels; return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/codecs/mod_silk/mod_silk.c b/src/mod/codecs/mod_silk/mod_silk.c index c3dba44a85..fc9163d4e6 100644 --- a/src/mod/codecs/mod_silk/mod_silk.c +++ b/src/mod/codecs/mod_silk/mod_silk.c @@ -204,6 +204,9 @@ static switch_status_t switch_silk_init(switch_codec_t *codec, } if (decoding) { + + switch_set_flag(codec, SWITCH_CODEC_FLAG_HAS_PLC); + if (SKP_Silk_SDK_Get_Decoder_Size(&decSizeBytes)) { return SWITCH_STATUS_FALSE; } @@ -335,14 +338,19 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec, *decoded_data_len = 0; if (lost_flag) { + *flag &= ~SFF_PLC; + if (session) { jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO); } + if (jb && codec->cur_frame) { for (i = 1; i <= MAX_LBRR_DELAY; i++) { found_frame = stfu_n_copy_next_frame(jb, (uint32_t)codec->cur_frame->timestamp, codec->cur_frame->seq, (uint16_t)i, &next_frame); + if (found_frame) { SKP_Silk_SDK_search_for_LBRR(next_frame.data, (const int)next_frame.dlen, i, (SKP_uint8*) &recbuff, &reclen); + if (reclen) { encoded_data = &recbuff; encoded_data_len = reclen; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index a4fd15f539..6eb6af3046 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -467,7 +467,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (!do_bugs) goto done; } - if (switch_test_flag(read_frame, SFF_PLC)) { + if (!switch_test_flag(read_frame->codec, SWITCH_CODEC_FLAG_HAS_PLC) && + (switch_channel_test_flag(session->channel, CF_JITTERBUFFER_PLC) || + switch_channel_test_flag(session->channel, CF_CNG_PLC)) && !session->plc) { + session->plc = plc_init(NULL); + } + + if (!switch_test_flag(read_frame->codec, SWITCH_CODEC_FLAG_HAS_PLC) && session->plc && switch_test_flag(read_frame, SFF_PLC)) { session->raw_read_frame.datalen = read_frame->codec->implementation->decoded_bytes_per_packet; session->raw_read_frame.samples = session->raw_read_frame.datalen / sizeof(int16_t) / session->read_impl.number_of_channels; session->raw_read_frame.channels = session->read_impl.number_of_channels; @@ -479,7 +485,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (!switch_core_codec_ready(codec)) { codec = read_frame->codec; } - + switch_thread_rwlock_rdlock(session->bug_rwlock); codec->cur_frame = read_frame; session->read_codec->cur_frame = read_frame; @@ -497,11 +503,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi } if (status == SWITCH_STATUS_SUCCESS && session->read_impl.number_of_channels == 1) { - if ((switch_channel_test_flag(session->channel, CF_JITTERBUFFER_PLC) || switch_channel_test_flag(session->channel, CF_CNG_PLC)) - && !session->plc) { - session->plc = plc_init(NULL); - } - if (session->plc) { if (switch_test_flag(read_frame, SFF_PLC)) { plc_fillin(session->plc, session->raw_read_frame.data, session->raw_read_frame.datalen / 2);