PR #23264 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23264
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23264.patch

Fixes ticket #11183


>From 56a5e670ea53b7e8cf5cdd51fe6341cfd6675165 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 28 May 2026 12:03:01 -0300
Subject: [PATCH 1/2] avformat/mov: add support for version 1 of chnl box

Fixes ticket #11183.

Signed-off-by: James Almer <[email protected]>
---
 libavformat/mov.c      |  4 ++--
 libavformat/mov_chan.c | 40 ++++++++++++++++++++++++++++++++++------
 libavformat/mov_chan.h |  3 ++-
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index d0d4910676..d8e4d1399f 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1236,14 +1236,14 @@ static int mov_read_chnl(MOVContext *c, AVIOContext 
*pb, MOVAtom atom)
 
     version = avio_r8(pb);
     flags   = avio_rb24(pb);
-    if (version != 0 || flags != 0) {
+    if (version > 1 || flags != 0) {
         av_log(c->fc, AV_LOG_ERROR,
                "Unsupported 'chnl' box with version %d, flags: %#x",
                version, flags);
         return AVERROR_INVALIDDATA;
     }
 
-    ret = ff_mov_read_chnl(c->fc, pb, st);
+    ret = ff_mov_read_chnl(c->fc, pb, st, version);
     if (ret < 0)
         return ret;
 
diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c
index befe6ebc86..bba185742f 100644
--- a/libavformat/mov_chan.c
+++ b/libavformat/mov_chan.c
@@ -733,11 +733,18 @@ int ff_mov_get_channel_positions_from_layout(const 
AVChannelLayout *layout,
     return 0;
 }
 
-int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st)
+int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st, int 
version)
 {
     int stream_structure = avio_r8(pb);
+    int base_channel_count;
+    int obj_count = 0;
     int ret;
 
+    if (version == 1) {
+        stream_structure >>= 4;
+        base_channel_count = avio_r8(pb);
+    }
+
     // stream carries channels
     if (stream_structure & 1) {
         int layout = avio_r8(pb);
@@ -747,6 +754,13 @@ int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, 
AVStream *st)
             AVChannelLayout *ch_layout = &st->codecpar->ch_layout;
             int nb_channels = ch_layout->nb_channels;
 
+            if (version == 1) {
+                nb_channels = avio_r8(pb);
+                obj_count = base_channel_count - nb_channels;
+                if (obj_count < 0)
+                    return AVERROR_INVALIDDATA;
+            }
+
             av_channel_layout_uninit(ch_layout);
             ret = av_channel_layout_custom_init(ch_layout, nb_channels);
             if (ret < 0)
@@ -776,16 +790,30 @@ int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, 
AVStream *st)
             if (ret < 0)
                 return ret;
         } else {
-            uint64_t omitted_channel_map = avio_rb64(pb);
-            ret = mov_get_channel_layout_from_config(layout, 
&st->codecpar->ch_layout, omitted_channel_map);
-            if (ret < 0)
-                return ret;
+            uint64_t omitted_channel_map = 0;
+            int omitted_channel_present = 1, channel_order_definition = 0;
+
+            if (version == 1) {
+                int byte = avio_r8(pb);
+                omitted_channel_present  =  byte       & 1;
+                channel_order_definition = (byte >> 1) & 0x7;
+            }
+
+            if (omitted_channel_present)
+                omitted_channel_map = avio_rb64(pb);
+            if (!channel_order_definition) {
+                ret = mov_get_channel_layout_from_config(layout, 
&st->codecpar->ch_layout, omitted_channel_map);
+                if (ret < 0)
+                    return ret;
+            } else
+                av_log(s, AV_LOG_TRACE, "'chnl' with channel_order_definition 
%d\n", channel_order_definition);
         }
     }
 
     // stream carries objects
     if (stream_structure & 2) {
-        int obj_count = avio_r8(pb);
+        if (version == 0)
+            obj_count = avio_r8(pb);
         av_log(s, AV_LOG_TRACE, "'chnl' with object_count %d\n", obj_count);
     }
 
diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h
index b901538279..51f24176f6 100644
--- a/libavformat/mov_chan.h
+++ b/libavformat/mov_chan.h
@@ -181,8 +181,9 @@ int ff_mov_get_channel_positions_from_layout(const 
AVChannelLayout *layout,
  * @param s     AVFormatContext
  * @param pb    AVIOContext
  * @param st    The stream to set codec values for
+ * @param version Version of the tag
  * @return      0 if ok, or negative AVERROR code on failure
  */
-int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st);
+int ff_mov_read_chnl(AVFormatContext *s, AVIOContext *pb, AVStream *st, int 
version);
 
 #endif /* AVFORMAT_MOV_CHAN_H */
-- 
2.52.0


>From 5b07d26be26053bc9c0e964cfffb938cb4f631f6 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 28 May 2026 12:05:29 -0300
Subject: [PATCH 2/2] avformat/mov: don't abort on unsupported or invalid chnl
 boxes

They are optional and just define a channel layout, which may also be defined
by the underlying codec.

Signed-off-by: James Almer <[email protected]>
---
 libavformat/mov.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index d8e4d1399f..581850373f 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1236,16 +1236,14 @@ static int mov_read_chnl(MOVContext *c, AVIOContext 
*pb, MOVAtom atom)
 
     version = avio_r8(pb);
     flags   = avio_rb24(pb);
-    if (version > 1 || flags != 0) {
-        av_log(c->fc, AV_LOG_ERROR,
-               "Unsupported 'chnl' box with version %d, flags: %#x",
+    if (version != 1 || flags != 0) {
+        av_log(c->fc, AV_LOG_WARNING,
+               "Unsupported 'chnl' box with version %d, flags: %#x\n",
                version, flags);
-        return AVERROR_INVALIDDATA;
+        return 0;
     }
 
-    ret = ff_mov_read_chnl(c->fc, pb, st, version);
-    if (ret < 0)
-        return ret;
+    ff_mov_read_chnl(c->fc, pb, st, version);
 
     if (avio_tell(pb) != end) {
         av_log(c->fc, AV_LOG_WARNING, "skip %" PRId64 " bytes of unknown data 
inside chnl\n",
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to