Skip to content
Snippets Groups Projects
Verified Commit 8101b33e authored by Mark Harris's avatar Mark Harris
Browse files

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.
parent ccaaffa9
No related branches found
No related tags found
No related merge requests found
......@@ -278,7 +278,8 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
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 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
{
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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment