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 f10fdd6310 avformat/movenc: fix dec3 chan_loc derivation for E-AC-3
dependent substreams
f10fdd6310 is described below
commit f10fdd631026056517edbad79ee0a136ef71c5df
Author: Brian Leake <[email protected]>
AuthorDate: Fri Aug 21 16:03:12 2026 -0700
Commit: James Almer <[email protected]>
CommitDate: Sat Aug 22 22:58:47 2026 +0000
avformat/movenc: fix dec3 chan_loc derivation for E-AC-3 dependent
substreams
chan_loc was derived from the bitstream's chanmap with a plain shift, but
the two fields use different bit orders, so every E-AC-3 stream carrying
a dependent substream (7.1 and above) was muxed with the wrong channel
layout signalled in the container.
chanmap is a 16-bit field read MSB-first, so flag index i sits at bit
(15 - i); this matches how ff_eac3_custom_channel_map_locations is
indexed in ac3_parser.c. Per ETSI TS 102 366 Annex F, chan_loc bits 0-7
carry flag indices 5-12, i.e. chanmap bit (10 - j). The mapping is not
contiguous at the top: index 13 (Lts/Rts) has no chan_loc bit and must be
skipped, and chan_loc bit 8 carries LFE2, which is index 14 and so
chanmap bit 1. The 0x1f mask was also 5 bits where 9 are needed, so some
flags were dropped rather than merely misplaced.
Effect on the layouts that use a dependent substream:
layout chanmap before after
7.1 0x1A00 0x010 0x002
5.1.2 0x0010 0x000 0x040
5.1.4 0x0210 0x010 0x042
LFE2 0x0002 0x000 0x100
For 7.1 the field claimed Lsd/Rsd (surround direct), a position no 7.1
speaker layout has, instead of Lrs/Rrs. This is invisible to FFmpeg,
whose decoder reads the layout from the bitstream, but demuxers that
trust the container act on it: Apple's AudioToolbox reported the affected
files as "7.1 (L C R Ls Rs LFE Lsd Rsd)" and collapsed them to a stereo
downmix, losing the centre channel, all four surrounds and the LFE.
Verified with samples.ffmpeg.org/A-codecs/AC3/eac3/7_pt_1.eac3, whose
dependent substream declares chanmap 0x1A00. After this change the muxed
dec3 carries 0x002, matching GPAC MP4Box for the same input, and
AudioToolbox reports "7.1 (L C R Ls Rs LFE Rls Rrs)" with all eight
channels intact.
Signed-off-by: Brian Leake <[email protected]>
---
libavformat/movenc.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 367caecee9..03599c1653 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -572,10 +572,24 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt,
MOVTrack *track)
ret /= 8;
/* get the dependent stream channel map, if exists */
- if (hdr->channel_map_present)
- info->substream[parent].chan_loc |= (hdr->channel_map >>
5) & 0x1f;
- else
+ if (hdr->channel_map_present) {
+ /* chanmap is a 16-bit field read MSB-first, so flag index
+ * i sits at bit (15 - i), matching the indexing of
+ * ff_eac3_custom_channel_map_locations. chan_loc bits 0-7
+ * carry flag indices 5-12, i.e. chanmap bit (10 - j).
+ * The mapping is not contiguous at the top: index 13
+ * (Lts/Rts) has no chan_loc bit and is skipped, and
+ * chan_loc bit 8 carries LFE2, which is index 14 and so
+ * chanmap bit 1. */
+ for (int j = 0; j < 8; j++) {
+ if ((hdr->channel_map >> (10 - j)) & 1)
+ info->substream[parent].chan_loc |= 1 << j;
+ }
+ if ((hdr->channel_map >> 1) & 1)
+ info->substream[parent].chan_loc |= 1 << 8;
+ } else {
info->substream[parent].chan_loc |= hdr->channel_mode;
+ }
cumul_size += hdr->frame_size;
}
}
--
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]