]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7601 #resolve
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 4 Jun 2015 20:01:36 +0000 (15:01 -0500)
committerBrian <brian@freeswitch.org>
Thu, 4 Jun 2015 20:01:36 +0000 (15:01 -0500)
src/include/switch_types.h
src/mod/codecs/mod_opus/mod_opus.c
src/mod/codecs/mod_silk/mod_silk.c
src/switch_core_io.c

index 2f201a5fdaf9e0ce7cf9b4e428f15290ee991638..d4512d2df56fc0336061142f8087698b59619c5c 100644 (file)
@@ -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;
 
index 38f69816652dec260a5ca2d3aea6c7c4521e3e62..84753983bd03a05090733b7e5b4343ac5d5dd4f9 100644 (file)
@@ -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;
index c3dba44a8574bd90fafbd96fc3911a8e6d24f7e8..fc9163d4e65d7c4b0414577a95ed9a94ba27209e 100644 (file)
@@ -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;
index a4fd15f53935727882bc7aea3dc0ae1b9ff1713f..6eb6af3046098a3e3bedc34406f180c54fd5cba0 100644 (file)
@@ -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);