PR #25304 opened by Marti2203
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25304
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25304.patch

`mov_update_iamf_streams()` looks up the stream group of each IAMF audio 
element by comparing only the group id, and keeps the last match. Mix 
presentation groups are created after the audio element groups and get the 
`mix_presentation_id` as their id, so when a mix presentation id equals an 
audio element id, the mix presentation group is picked instead. Its entries are 
the streams of all audio elements, so the same stream gets its index entries 
copied twice and `av_assert0(!out_sti->index_entries)` aborts ffprobe and 
ffmpeg.

The file can be written by FFmpeg's own mp4 muxer: two audio elements with ids 
1 and 2 and a mix presentation with id 1.

```
ffmpeg -f lavfi -i sine=d=1 -f lavfi -i sine=f=880:d=1 \
  -stream_group "type=iamf_audio_element:id=1:st=0,layer=ch_layout=mono" \
  -stream_group "type=iamf_audio_element:id=2:st=1,layer=ch_layout=mono" \
  -stream_group 
"type=iamf_mix_presentation:id=1:stg=0:stg=1,submix=parameter_id=100:parameter_rate=48000:default_mix_gain=0.0|element=stg=0:parameter_id=101:parameter_rate=48000:headphones_rendering_mode=stereo|element=stg=1:parameter_id=102:parameter_rate=48000:headphones_rendering_mode=stereo|layout=sound_system=stereo"
 \
  -map 0 -map 1 -streamid 0:0 -streamid 1:1 -c:a flac -t 1 mix1.mp4
ffprobe mix1.mp4
Assertion !out_sti->index_entries failed at libavformat/mov.c:5543
Aborted (core dumped)
```

With mix presentation id 3 the same file probes fine. The lookup of the audio 
elements of a submix in `mov_read_iacb()` already checks for 
`AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT` and breaks on the first match; the 
patch does the same here. With it, the file above probes and decodes with `-map 
0 -f null -`, and the groups and stream durations are the same as for the id 3 
file.

The second commit adds `fate-mov-mp4-iamf-stereo-id-collision`, which muxes two 
audio elements and a mix presentation with colliding ids from 
`asynth-44100-2.wav` and demuxes/probes the result, so no samples are needed. 
It aborts with exit code 134 on master and passes with the fix. `fate-iamf` 
(including its sample tests) and `fate-mov` pass, apart from 33 mov tests whose 
samples (heif, avif, cenc, ...) I did not have locally.

Open PR #24256 changes the ids of other mov stream groups to sequential values, 
but leaves the IAMF ones alone, so it does not cover this case.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified 
manually.

🤖 Generated with [Claude Code](https://claude.com/claude-code)



From 4acb7b826f1120527020c41d6cabd2acf1a69cde Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Wed, 21 Oct 2026 19:01:04 +0800
Subject: [PATCH 1/2] avformat/mov: check the stream group type when updating
 IAMF streams

The lookup of the stream group for each IAMF audio element compared only
the group id and kept the last match. Mix presentation groups are created
after the audio element groups and use the mix_presentation_id as their
id, so if a mix_presentation_id equals an audio_element_id the mix
presentation group was picked instead. Its entries are the streams of
every audio element, so the same output stream got its index entries
filled twice and the av_assert0(!out_sti->index_entries) aborted.

Such files are written by FFmpeg's own mp4 muxer, e.g. with two audio
elements with ids 1 and 2 and a mix presentation with id 1.

Check the group type and stop at the first match, as is already done
when looking up the audio elements of a mix presentation submix.

Signed-off-by: Martin Mirchev <[email protected]>
---
 libavformat/mov.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 910df844dce..aef265b5315 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5520,8 +5520,11 @@ static int mov_update_iamf_streams(MOVContext *c, const 
AVStream *st)
         const AVStreamGroup *stg = NULL;
 
         for (int j = 0; j < c->fc->nb_stream_groups; j++)
-            if (c->fc->stream_groups[j]->id == 
iamf->audio_elements[i]->audio_element_id)
+            if (c->fc->stream_groups[j]->type == 
AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT &&
+                c->fc->stream_groups[j]->id   == 
iamf->audio_elements[i]->audio_element_id) {
                 stg = c->fc->stream_groups[j];
+                break;
+            }
         av_assert0(stg);
 
         for (int j = 0; j < stg->nb_entries; j++) {
-- 
2.54.0


From 61a04e802d4ab938006899e9a6c9d3086968198c Mon Sep 17 00:00:00 2001
From: Martin Mirchev <[email protected]>
Date: Wed, 21 Oct 2026 19:01:48 +0800
Subject: [PATCH 2/2] tests/fate/mov: add a test for IAMF stream group id
 collisions

Mux two IAMF audio elements with ids 1 and 2 and a mix presentation with
id 1 into mp4, then demux and probe the result. Without the previous
commit the mov demuxer aborts on an assertion when reading this file.

Signed-off-by: Martin Mirchev <[email protected]>
---
 tests/fate/mov.mak                            | 11 +++
 .../ref/fate/mov-mp4-iamf-stereo-id-collision | 84 +++++++++++++++++++
 tests/streamgroups/audio_element-stereo-2     |  2 +
 .../streamgroups/mix_presentation-stereo-id-1 |  2 +
 4 files changed, 99 insertions(+)
 create mode 100644 tests/ref/fate/mov-mp4-iamf-stereo-id-collision
 create mode 100644 tests/streamgroups/audio_element-stereo-2
 create mode 100644 tests/streamgroups/mix_presentation-stereo-id-1

diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak
index 3550e1d7b81..0ef4c2c4d5e 100644
--- a/tests/fate/mov.mak
+++ b/tests/fate/mov.mak
@@ -483,6 +483,17 @@ fate-mov-mp4-iamf-stereo: CMD = transcode wav $(SRC) mp4 " 
\
   -streamid 0:0 -c:a flac -t 1" "-c:a copy -map 0" \
   "-show_entries 
stream_group=index,id,nb_streams,type:stream_group_components:stream_group_disposition:stream_group_tags:stream_group_stream=index,id:stream_group_stream_disposition"
 
+# Two audio elements and a mix presentation whose id equals the id of the 
first audio element.
+FATE_MOV_FFMPEG_FFPROBE-$(call TRANSCODE, FLAC, MP4 MOV, WAV_DEMUXER 
PCM_S16LE_DECODER) += fate-mov-mp4-iamf-stereo-id-collision
+fate-mov-mp4-iamf-stereo-id-collision: tests/data/asynth-44100-2.wav 
tests/data/streamgroups/audio_element-stereo 
tests/data/streamgroups/audio_element-stereo-2 
tests/data/streamgroups/mix_presentation-stereo-id-1
+fate-mov-mp4-iamf-stereo-id-collision: SRC = 
$(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-mov-mp4-iamf-stereo-id-collision: CMD = transcode wav $(SRC) mp4 " \
+  -/stream_group $(TARGET_PATH)/tests/data/streamgroups/audio_element-stereo \
+  -/stream_group $(TARGET_PATH)/tests/data/streamgroups/audio_element-stereo-2 
\
+  -/stream_group 
$(TARGET_PATH)/tests/data/streamgroups/mix_presentation-stereo-id-1 \
+  -map 0:a -map 0:a -streamid 0:0 -streamid 1:1 -c:a flac -t 1" "-c:a copy 
-map 0" \
+  "-show_entries 
stream_group=index,id,nb_streams,type:stream_group_stream=index,id:stream=index,id,duration_ts"
+
 FATE_MOV_FFMPEG_FFPROBE-$(call TRANSCODE, FLAC, MP4 MOV, WAV_DEMUXER 
PCM_S16LE_DECODER ARESAMPLE_FILTER) += fate-mov-mp4-iamf-5_1_4
 fate-mov-mp4-iamf-5_1_4: tests/data/asynth-44100-10.wav 
tests/data/filtergraphs/iamf_5_1_4 tests/data/streamgroups/audio_element-5_1_4 
tests/data/streamgroups/mix_presentation-5_1_4
 fate-mov-mp4-iamf-5_1_4: SRC = $(TARGET_PATH)/tests/data/asynth-44100-10.wav
diff --git a/tests/ref/fate/mov-mp4-iamf-stereo-id-collision 
b/tests/ref/fate/mov-mp4-iamf-stereo-id-collision
new file mode 100644
index 00000000000..c3a6d51cc5c
--- /dev/null
+++ b/tests/ref/fate/mov-mp4-iamf-stereo-id-collision
@@ -0,0 +1,84 @@
+0587a41960832c1797fe25162b953a4c 
*tests/data/fate/mov-mp4-iamf-stereo-id-collision.mp4
+29293 tests/data/fate/mov-mp4-iamf-stereo-id-collision.mp4
+#extradata 0:       34, 0xa77c0cd6
+#extradata 1:       34, 0xa77c0cd6
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: flac
+#sample_rate 0: 44100
+#channel_layout_name 0: stereo
+#tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: flac
+#sample_rate 1: 44100
+#channel_layout_name 1: stereo
+0,          0,          0,     4096,     1323, 0xb9bc0f9a
+1,          0,          0,     4096,     1323, 0xb9bc0f9a
+0,       4096,       4096,     4096,     1254, 0xf7e910bc
+1,       4096,       4096,     4096,     1254, 0xf7e910bc
+0,       8192,       8192,     4096,     1320, 0xe4fe09c9
+1,       8192,       8192,     4096,     1320, 0xe4fe09c9
+0,      12288,      12288,     4096,     1280, 0x22e9127e
+1,      12288,      12288,     4096,     1280, 0x22e9127e
+0,      16384,      16384,     4096,     1331, 0x8bc61bbf
+1,      16384,      16384,     4096,     1331, 0x8bc61bbf
+0,      20480,      20480,     4096,     1267, 0x2c4708fa
+1,      20480,      20480,     4096,     1267, 0x2c4708fa
+0,      24576,      24576,     4096,     1282, 0x0438152d
+1,      24576,      24576,     4096,     1282, 0x0438152d
+0,      28672,      28672,     4096,     1313, 0x2e79ffa2
+1,      28672,      28672,     4096,     1313, 0x2e79ffa2
+0,      32768,      32768,     4096,     1323, 0xb9f70fce
+1,      32768,      32768,     4096,     1323, 0xb9f70fce
+0,      36864,      36864,     4096,     1254, 0xf6f01051
+1,      36864,      36864,     4096,     1254, 0xf6f01051
+0,      40960,      40960,     4096,     1235, 0xcf181f77, S=1, Skip Samples,  
     10, 0x047700bf
+1,      40960,      40960,     4096,     1235, 0xcf181f77, S=1, Skip Samples,  
     10, 0x047700bf
+[STREAM_GROUP]
+index=0
+id=0x1
+nb_streams=1
+type=IAMF Audio Element
+[STREAM]
+index=0
+id=0x0
+duration_ts=44100
+[/STREAM]
+[/STREAM_GROUP]
+[STREAM_GROUP]
+index=1
+id=0x2
+nb_streams=1
+type=IAMF Audio Element
+[STREAM]
+index=1
+id=0x1
+duration_ts=44100
+[/STREAM]
+[/STREAM_GROUP]
+[STREAM_GROUP]
+index=2
+id=0x1
+nb_streams=2
+type=IAMF Mix Presentation
+[STREAM]
+index=0
+id=0x0
+duration_ts=44100
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+duration_ts=44100
+[/STREAM]
+[/STREAM_GROUP]
+[STREAM]
+index=0
+id=0x0
+duration_ts=44100
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+duration_ts=44100
+[/STREAM]
diff --git a/tests/streamgroups/audio_element-stereo-2 
b/tests/streamgroups/audio_element-stereo-2
new file mode 100644
index 00000000000..c935ebf99c5
--- /dev/null
+++ b/tests/streamgroups/audio_element-stereo-2
@@ -0,0 +1,2 @@
+type=iamf_audio_element:id=2:st=1,
+layer=ch_layout=stereo,
diff --git a/tests/streamgroups/mix_presentation-stereo-id-1 
b/tests/streamgroups/mix_presentation-stereo-id-1
new file mode 100644
index 00000000000..93333a87169
--- /dev/null
+++ b/tests/streamgroups/mix_presentation-stereo-id-1
@@ -0,0 +1,2 @@
+type=iamf_mix_presentation:id=1:stg=0:stg=1,
+submix=parameter_id=100:parameter_rate=48000:default_mix_gain=1.0|element=stg=0:parameter_id=101:parameter_rate=48000:headphones_rendering_mode=stereo|element=stg=1:parameter_id=102:parameter_rate=48000:headphones_rendering_mode=stereo|layout=sound_system=stereo,
-- 
2.54.0

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

Reply via email to