aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/opus_silk.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-09-11 19:32:43 +0200
committerAnton Khirnov <anton@khirnov.net>2020-10-01 11:16:17 +0200
commit33b4b788aac91dfd522415baaedcbda160482816 (patch)
treed98faf6fb9bbd1d66ea4a1ae53833490d79cd6b1 /libavcodec/opus_silk.c
parent3bf5cc9c588b41d4ba49821e57650dbbf187f932 (diff)
downloadffmpeg-33b4b788aac91dfd522415baaedcbda160482816.tar.gz
opusdec: do not fail when LBRR frames are present
Decode and discard them. Fixes ticket 4641.
Diffstat (limited to 'libavcodec/opus_silk.c')
-rw-r--r--libavcodec/opus_silk.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c
index 2fcbf3b9d3..913053c5e2 100644
--- a/libavcodec/opus_silk.c
+++ b/libavcodec/opus_silk.c
@@ -506,7 +506,8 @@ static inline void silk_decode_excitation(SilkContext *s, OpusRangeCoder *rc,
#define LTP_ORDER 5
static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
- int frame_num, int channel, int coded_channels, int active, int active1)
+ int frame_num, int channel, int coded_channels,
+ int active, int active1, int redundant)
{
/* per frame */
int voiced; // combines with active to indicate inactive, active, or active+voiced
@@ -665,8 +666,9 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
silk_decode_excitation(s, rc, residual + SILK_MAX_LAG, qoffset_high,
active, voiced);
- /* skip synthesising the side channel if we want mono-only */
- if (s->output_channels == channel)
+ /* skip synthesising the output if we do not need it */
+ // TODO: implement error recovery
+ if (s->output_channels == channel || redundant)
return;
/* generate the output signal */
@@ -814,15 +816,27 @@ int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc,
active[i][j] = ff_opus_rc_dec_log(rc, 1);
redundancy[i] = ff_opus_rc_dec_log(rc, 1);
- if (redundancy[i]) {
- avpriv_report_missing_feature(s->avctx, "LBRR frames");
- return AVERROR_PATCHWELCOME;
+ }
+
+ /* read the per-frame LBRR flags */
+ for (i = 0; i < coded_channels; i++)
+ if (redundancy[i] && duration_ms > 20) {
+ redundancy[i] = ff_opus_rc_dec_cdf(rc, duration_ms == 40 ?
+ ff_silk_model_lbrr_flags_40 : ff_silk_model_lbrr_flags_60);
}
+
+ /* decode the LBRR frames */
+ for (i = 0; i < nb_frames; i++) {
+ for (j = 0; j < coded_channels; j++)
+ if (redundancy[j] & (1 << i)) {
+ int active1 = (j == 0 && !(redundancy[1] & (1 << i))) ? 0 : 1;
+ silk_decode_frame(s, rc, i, j, coded_channels, 1, active1, 1);
+ }
}
for (i = 0; i < nb_frames; i++) {
for (j = 0; j < coded_channels && !s->midonly; j++)
- silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active[1][i]);
+ silk_decode_frame(s, rc, i, j, coded_channels, active[j][i], active[1][i], 0);
/* reset the side channel if it is not coded */
if (s->midonly && s->frame[1].coded)