This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 564f92cce2 avcodec/ac3dec_fixed: preserve overlap across dependent
substreams
564f92cce2 is described below
commit 564f92cce23ae95399476617b8a1dc357f002a47
Author: Ayoub Nabil Boubagrat
<[email protected]>
AuthorDate: Tue Aug 18 14:40:56 2026 +0200
Commit: James Almer <[email protected]>
CommitDate: Wed Aug 19 01:54:15 2026 +0000
avcodec/ac3dec_fixed: preserve overlap across dependent substreams
ac-3 cores and dependent e-ac-3 substreams may use different
coefficient scales while owning separate delay slots.
the global reset added in 5ba2a2c841 cleared both sets of slots on
every substream switch, corrupting the mdct overlap of valid 7.1
streams.
track the scale per substream and clear only its own delay slots when
it changes. add a fate test using the existing the_great_wall sample.
Signed-off-by: Ayoub Nabil Boubagrat
<[email protected]>
---
libavcodec/ac3dec.c | 30 +++++++++++++++++-------------
libavcodec/ac3dec.h | 3 +++
tests/fate/ac3.mak | 9 ++++++++-
3 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index e3a711ebbf..9f85446bf4 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -1398,9 +1398,6 @@ static int ac3_decode_frame(AVCodecContext *avctx,
AVFrame *frame,
AC3DecodeContext *s = avctx->priv_data;
int blk, ch, err, offset, ret;
int i;
-#if USE_FIXED
- int previous_coeff_bits;
-#endif
int skip = 0, got_independent_frame = 0;
const uint8_t *channel_map;
uint8_t extended_channel_map[EAC3_MAX_CHANNELS];
@@ -1435,9 +1432,6 @@ static int ac3_decode_frame(AVCodecContext *avctx,
AVFrame *frame,
buf = s->input_buffer;
dependent_frame:
-#if USE_FIXED
- previous_coeff_bits = fixed_coeff_bits(s);
-#endif
/* initialize the GetBitContext with the start of valid AC-3 Frame */
if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
return ret;
@@ -1445,13 +1439,6 @@ dependent_frame:
/* parse the syncinfo */
err = parse_frame_header(s);
-#if USE_FIXED
- /* Do not mix Q0 and Q2 overlap samples if a malformed or explicitly
- * forced stream switches between E-AC-3 and AC-3. */
- if (!err && previous_coeff_bits != fixed_coeff_bits(s))
- memset(s->delay, 0, sizeof(s->delay));
-#endif
-
if (err) {
switch (err) {
case AC3_PARSE_ERROR_SYNC:
@@ -1573,6 +1560,23 @@ dependent_frame:
/* decode the audio blocks */
channel_map = ff_ac3_dec_channel_map[s->output_mode &
~AC3_OUTPUT_LFEON][s->lfe_on];
offset = s->frame_type == EAC3_FRAME_TYPE_DEPENDENT ? AC3_MAX_CHANNELS : 0;
+#if USE_FIXED
+ /* delay[] holds overlap samples scaled by the coefficient format that was
+ * in use when they were produced. The independent and the dependent
+ * substream own disjoint delay slots and may legitimately use different
+ * formats, so only drop the overlap of the substream whose format really
+ * changed, as happens when a malformed or explicitly forced stream
+ * switches between E-AC-3 and AC-3. */
+ if (!err) {
+ const int coeff_bits = fixed_coeff_bits(s);
+ const int slot = offset ? 1 : 0;
+
+ if (s->delay_coeff_bits[slot] != coeff_bits) {
+ memset(s->delay[offset], 0, AC3_MAX_CHANNELS *
sizeof(s->delay[0]));
+ s->delay_coeff_bits[slot] = coeff_bits;
+ }
+ }
+#endif
for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
output[ch] = s->output[ch + offset];
s->outptr[ch] = s->output[ch + offset];
diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index 1a4da07fa3..c0e6f683ef 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -252,6 +252,9 @@ typedef struct AC3DecodeContext {
DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS];
///< fixed-point transform coefficients
DECLARE_ALIGNED(32, INTFLOAT,
transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform
coefficients
DECLARE_ALIGNED(32, INTFLOAT, delay)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE];
///< delay - added to the next block
+#if USE_FIXED
+ int delay_coeff_bits[2]; ///< coefficient format of delay[],
per substream
+#endif
DECLARE_ALIGNED(32, INTFLOAT, window)[AC3_BLOCK_SIZE];
///< window coefficients
DECLARE_ALIGNED(32, INTFLOAT, tmp_output)[AC3_BLOCK_SIZE];
///< temporary storage for output before windowing
DECLARE_ALIGNED(32, SHORTFLOAT,
output)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct
transform and windowing
diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak
index 90977a80c0..70aa4f4568 100644
--- a/tests/fate/ac3.mak
+++ b/tests/fate/ac3.mak
@@ -63,10 +63,17 @@ FATE_EAC3 += fate-eac3-5
fate-eac3-5: CMD = pcm -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3
fate-eac3-5: REF = $(SAMPLES)/eac3/the_great_wall_7.1.pcm
-$(FATE_AC3) $(FATE_EAC3): CMP = oneoff
+# the fixed decoder has to keep the overlap of the independent substream when
+# the dependent substream uses a different coefficient format
+FATE_EAC3_FIXED += fate-eac3-fixed-dependent-substream
+fate-eac3-fixed-dependent-substream: CMD = pcm -c ac3_fixed -i
$(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3
+fate-eac3-fixed-dependent-substream: REF =
$(SAMPLES)/eac3/the_great_wall_7.1.pcm
+
+$(FATE_AC3) $(FATE_EAC3) $(FATE_EAC3_FIXED): CMP = oneoff
FATE_AC3-$(call PCM, AC3, AC3 AC3_FIXED, PCM_S16LE_MUXER ARESAMPLE_FILTER)
+= $(FATE_AC3)
FATE_EAC3-$(call PCM, EAC3, EAC3, PCM_S16LE_MUXER ARESAMPLE_FILTER)
+= $(FATE_EAC3)
+FATE_EAC3-$(call PCM, EAC3, EAC3 AC3_FIXED, PCM_S16LE_MUXER ARESAMPLE_FILTER)
+= $(FATE_EAC3_FIXED)
FATE_AC3-$(call ENCDEC, AC3, MP4 MOV, WAV_MUXER WAV_DEMUXER ARESAMPLE_FILTER
PCM_S16LE_ENCODER PIPE_PROTOCOL) += fate-ac3-encode
fate-ac3-encode: CMD = enc_dec_pcm mp4 wav s16le $(subst
$(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a ac3 -b:a 128k
--
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]