diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index 417632f7e5..565242d45d 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -193,10 +193,8 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data, if (AV_RB32(input) == DCA_SYNCWORD_CORE_BE) { int frame_size; - if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) { - s->core_residual_valid = 0; + if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) return ret; - } s->packet |= DCA_PACKET_CORE; @@ -265,19 +263,20 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data, if (s->xll.chset[0].freq == 96000 && s->core.sample_rate == 48000) x96_synth = 1; - if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) { - s->core_residual_valid = 0; + if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) return ret; - } // Force lossy downmixed output on the first core frame filtered. // This prevents audible clicks when seeking and is consistent with // what reference decoder does when there are multiple channel sets. - if (!s->core_residual_valid) { - if (s->xll.nreschsets > 0 && s->xll.nchsets > 1) - s->packet |= DCA_PACKET_RECOVERY; - s->core_residual_valid = 1; + if (!(prev_packet & DCA_PACKET_RESIDUAL) && s->xll.nreschsets > 0 + && s->xll.nchsets > 1) { + av_log(avctx, AV_LOG_VERBOSE, "Forcing XLL recovery mode\n"); + s->packet |= DCA_PACKET_RECOVERY; } + + // Set 'residual ok' flag for the next frame + s->packet |= DCA_PACKET_RESIDUAL; } if ((ret = ff_dca_xll_filter_frame(&s->xll, frame)) < 0) { @@ -286,17 +285,14 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data, return ret; if (ret != AVERROR_INVALIDDATA || (avctx->err_recognition & AV_EF_EXPLODE)) return ret; - if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) { - s->core_residual_valid = 0; + if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) return ret; - } } } else if (s->packet & DCA_PACKET_CORE) { - if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) { - s->core_residual_valid = 0; + if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) return ret; - } - s->core_residual_valid = !!(s->core.filter_mode & DCA_FILTER_MODE_FIXED); + if (s->core.filter_mode & DCA_FILTER_MODE_FIXED) + s->packet |= DCA_PACKET_RESIDUAL; } else { av_log(avctx, AV_LOG_ERROR, "No valid DCA sub-stream found\n"); if (s->core_only) @@ -317,7 +313,7 @@ static av_cold void dcadec_flush(AVCodecContext *avctx) ff_dca_xll_flush(&s->xll); ff_dca_lbr_flush(&s->lbr); - s->core_residual_valid = 0; + s->packet &= DCA_PACKET_MASK; } static av_cold int dcadec_close(AVCodecContext *avctx) diff --git a/libavcodec/dcadec.h b/libavcodec/dcadec.h index 5e4707758b..85283326e7 100644 --- a/libavcodec/dcadec.h +++ b/libavcodec/dcadec.h @@ -40,7 +40,10 @@ #define DCA_PACKET_EXSS 0x02 #define DCA_PACKET_XLL 0x04 #define DCA_PACKET_LBR 0x08 -#define DCA_PACKET_RECOVERY 0x10 +#define DCA_PACKET_MASK 0x0f + +#define DCA_PACKET_RECOVERY 0x10 ///< Sync error recovery flag +#define DCA_PACKET_RESIDUAL 0x20 ///< Core valid for residual decoding typedef struct DCAContext { const AVClass *class; ///< class for AVOptions @@ -60,8 +63,6 @@ typedef struct DCAContext { int packet; ///< Packet flags - int core_residual_valid; ///< Core valid for residual decoding - int request_channel_layout; ///< Converted from avctx.request_channel_layout int core_only; ///< Core only decoding flag } DCAContext;