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]

Reply via email to