[FFmpeg-devel] [PATCH] opusdec: do not fail when LBRR frames are present
Lynne
dev at lynne.ee
Fri Sep 11 21:53:16 EEST 2020
On 11/09/2020 19:37, Anton Khirnov wrote:
> Decode and discard them.
>
> Fixes ticket 4641.
> ---
> libavcodec/opus_silk.c | 28 ++++++++++++++++++++--------
> libavcodec/opustab.c | 3 +++
> libavcodec/opustab.h | 3 +++
> 3 files changed, 26 insertions(+), 8 deletions(-)
>
> diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c
> index 2fcbf3b9d3..c683b25a20 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,8 @@ 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 */
> + if (s->output_channels == channel || redundant)
> return;
Maybe add a small TODO in the comment to actually implement error recovery?
>
> /* generate the output signal */
> @@ -814,15 +815,26 @@ 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);
> + }
nit: add brackets to the nb_frames loop
Apart from that LGTM.
Shouldn't be too difficult to implement proper error recovery in the
future, though it would have to be a setting, because 1-frame delay is
still a 1-frame delay.
More information about the ffmpeg-devel
mailing list