summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Harris <mark.hsj@gmail.com>2022-06-20 22:23:26 -0700
committerMark Harris <mark.hsj@gmail.com>2022-06-25 14:10:35 -0700
commit8101b33e6c59b51b22aeeeaf39045e34a402b01f (patch)
treea5c0471ff666864caaae97beec621e9ead5ccb30
parentccaaffa9a3ee427e9401c4dcf6462e378d9a4694 (diff)
downloadopus-8101b33e6c59b51b22aeeeaf39045e34a402b01f.tar.gz
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.
-rw-r--r--src/opus_decoder.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 9113638a..0be87dc0 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -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);