ref: 8101b33e6c59b51b22aeeeaf39045e34a402b01f
parent: ccaaffa9a3ee427e9401c4dcf6462e378d9a4694
author: Mark Harris <mark.hsj@gmail.com>
date: Mon Jun 20 18:23:26 EDT 2022
Correct redundancy handling with lost/DTX frames In https://github.com/xiph/opus/issues/253, the encoder generates a Hybrid frame with redundancy, to switch to CELT-only mode, and then activates DTX immediately afterwards. The decoder ran Hybrid PLC, which isn't right. Use CELT PLC instead if there was already a transition to CELT via redundancy at the end of the previous frame. Also do not use a stale CELT decoder to decode a second redundancy frame when the first redundancy frame for a transition from SILK-only mode was lost. Instead of mixing in old audio from the last time that CELT was used, ignore the second redundancy frame in this case. Alternatively the CELT decoder could be reset before decoding, but it would not be ready until after the 2.5 ms of audio that is needed. Reviewed by Jean-Marc Valin.
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -278,7 +278,8 @@
ec_dec_init(&dec,(unsigned char*)data,len);
} else {
audiosize = frame_size;
- mode = st->prev_mode;
+ /* Run PLC using last used mode (CELT if we ended with CELT redundancy) */
+ mode = st->prev_redundancy ? MODE_CELT_ONLY : st->prev_mode;
bandwidth = 0;
if (mode == 0)
@@ -419,7 +420,7 @@
start_band = 0;
if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
- && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
+ && ec_tell(&dec)+17+20*(mode == MODE_HYBRID) <= 8*len)
{
/* Check if we have a redundant 0-8 kHz band */
if (mode == MODE_HYBRID)
@@ -454,6 +455,10 @@
{
transition = 0;
pcm_transition_silk_size=ALLOC_NONE;
+ /* don't use stale CELT decoder to decode second redundancy frame if
+ the first redundancy frame for a transition from SILK was lost */
+ if (celt_to_silk && st->prev_mode == MODE_SILK_ONLY && !st->prev_redundancy)
+ redundancy = 0;
}
ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);