ffmpeg-devel
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
September 2026
- 10 participants
- 105 discussions
[PR] [release/9.0] avformat/cbs: move AV1 feature definition to their own header (PR #24454)
by ffmpeg-devel 10 Sep '26
by ffmpeg-devel 10 Sep '26
10 Sep '26
PR #24454 opened by ffmpeg-devel
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24454
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24454.patch
**Backport:** https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24410
The lavf AV1 CBS implementation disables metadata, tile lists and padding,
but movenccenc.c sees the default AV1RawOBU definition. On 32-bit MinGW,
the metadata member raises the union alignment from four to eight bytes,
placing obu at offset 16 in the caller instead of offset 12 in CBS.
Consequently AV1 CENC reads the wrong fields and fails to write tiles.
Move the feature definitions into the common lavf CBS header so that the
parser and its callers use the same AV1RawOBU layout. Keep the reduced
set of parsed OBU types.
Add a FATE encryption/decryption test using the existing nonuniform-tile
AV1 sample. The test fails before this change with GCC -m32 -malign-double
(which reproduces the relevant MinGW layout) and passes afterwards with
the same reference on that configuration and AArch64.
Fixes #23069.
From a8e6953bd26dbc07668c7156c7beabc65c2cb19a Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Mon, 7 Sep 2026 17:05:38 -0300
Subject: [PATCH 1/2] avformat/cbs: move AV1 feature definition to their own
header
The lavf AV1 CBS implementation disables metadata, tile lists and padding,
but movenccenc.c sees the default AV1RawOBU definition. On 32-bit MinGW,
the metadata member raises the union alignment from four to eight bytes,
placing obu at offset 16 in the caller instead of offset 12 in CBS.
Consequently AV1 CENC reads the wrong fields and fails to write tiles.
Move the feature definitions into the common lavf CBS header so that the
parser and its callers use the same AV1RawOBU layout. Keep the reduced
set of parsed OBU types.
Add a FATE encryption/decryption test using the existing nonuniform-tile
AV1 sample. The test fails before this change with GCC -m32 -malign-double
(which reproduces the relevant MinGW layout) and passes afterwards with
the same reference on that configuration and AArch64.
Fixes #23069.
Assisted-by: Fairy
Signed-off-by: James Almer <jamrial(a)gmail.com>
(cherry picked from commit 05bd55ff6eaeb1a352ee40bed58c4ad5740d64e9)
---
libavformat/cbs_av1.c | 5 +----
libavformat/cbs_av1.h | 30 ++++++++++++++++++++++++++++++
libavformat/movenccenc.c | 2 +-
tests/fate/mov.mak | 5 +++++
tests/ref/fate/mov-av1-cenc | 32 ++++++++++++++++++++++++++++++++
5 files changed, 69 insertions(+), 5 deletions(-)
create mode 100644 libavformat/cbs_av1.h
create mode 100644 tests/ref/fate/mov-av1-cenc
diff --git a/libavformat/cbs_av1.c b/libavformat/cbs_av1.c
index efaed7dfd0..93bcbb878d 100644
--- a/libavformat/cbs_av1.c
+++ b/libavformat/cbs_av1.c
@@ -16,8 +16,5 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define CBS_AV1_OBU_TILE_LIST 0
-#define CBS_AV1_OBU_METADATA 0
-#define CBS_AV1_OBU_PADDING 0
-#include "cbs.h"
+#include "cbs_av1.h"
#include "libavcodec/cbs_av1.c"
diff --git a/libavformat/cbs_av1.h b/libavformat/cbs_av1.h
new file mode 100644
index 0000000000..0d5e28d388
--- /dev/null
+++ b/libavformat/cbs_av1.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_CBS_AV1_H
+#define AVFORMAT_CBS_AV1_H
+
+#include "cbs.h"
+
+#define CBS_AV1_OBU_TILE_LIST 0
+#define CBS_AV1_OBU_METADATA 0
+#define CBS_AV1_OBU_PADDING 0
+
+#include "libavcodec/cbs_av1.h"
+
+#endif /* AVFORMAT_CBS_AV1_H */
diff --git a/libavformat/movenccenc.c b/libavformat/movenccenc.c
index 4e1f31d2b5..4808b59773 100644
--- a/libavformat/movenccenc.c
+++ b/libavformat/movenccenc.c
@@ -21,7 +21,7 @@
#include "movenccenc.h"
#include "libavcodec/av1_parse.h"
#include "libavcodec/bytestream.h"
-#include "libavcodec/cbs_av1.h"
+#include "libavformat/cbs_av1.h"
#include "libavutil/attributes.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mem.h"
diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak
index 3bc075f608..56dc3763c0 100644
--- a/tests/fate/mov.mak
+++ b/tests/fate/mov.mak
@@ -198,6 +198,11 @@ fate-mov-mp4-fragmented-ttml-dfxp: CMD = transcode srt $(TARGET_SAMPLES)/sub/Sub
"-f lavfi -i smptehdbars=duration=24.5245:size=320x180:rate=24000/1001,format=yuv420p" \
"" "" "data"
+FATE_MOV_FFMPEG_SAMPLES-$(call REMUX, MP4 IVF, MOV_DEMUXER AV1_PARSER EXTRACT_EXTRADATA_BSF) += fate-mov-av1-cenc
+fate-mov-av1-cenc: CMD = transcode ivf $(TARGET_SAMPLES)/av1/non_uniform_tiling.ivf mp4 \
+ "-c:v copy -encryption_scheme cenc-aes-ctr -encryption_key 00112233445566778899aabbccddeeff -encryption_kid 00112233445566778899aabbccddeeff" \
+ "-c:v copy" "" "" "-decryption_key 00112233445566778899aabbccddeeff"
+
# avif demuxing - still image with 1 item.
FATE_MOV_FFMPEG_SAMPLES-$(call FRAMECRC, MOV, AV1, AV1_PARSER) \
+= fate-mov-avif-demux-still-image-1-item
diff --git a/tests/ref/fate/mov-av1-cenc b/tests/ref/fate/mov-av1-cenc
new file mode 100644
index 0000000000..785ea598e3
--- /dev/null
+++ b/tests/ref/fate/mov-av1-cenc
@@ -0,0 +1,32 @@
+4c0d58049d04303b98cd7c07013a1183 *tests/data/fate/mov-av1-cenc.mp4
+39366 tests/data/fate/mov-av1-cenc.mp4
+#extradata 0: 17, 0x197103ea
+#tb 0: 1/12288
+#media_type 0: video
+#codec_id 0: av1
+#dimensions 0: 720x300
+#sar 0: 1/1
+0, 0, 0, 512, 17049, 0x6d66f097
+0, 512, 512, 512, 8365, 0x9c48024d, F=0x0
+0, 1024, 1024, 512, 77, 0x88251d4e, F=0x0
+0, 1536, 1536, 512, 232, 0x3c31706f, F=0x0
+0, 2048, 2048, 512, 245, 0x8195753f, F=0x0
+0, 2560, 2560, 512, 271, 0x134f86cc, F=0x0
+0, 3072, 3072, 512, 246, 0x04b777cf, F=0x0
+0, 3584, 3584, 512, 143, 0x6cbd43a3, F=0x0
+0, 4096, 4096, 512, 215, 0x88d66733, F=0x0
+0, 4608, 4608, 512, 83, 0xb2d22362, F=0x0
+0, 5120, 5120, 512, 50, 0x75d211e2, F=0x0
+0, 5632, 5632, 512, 5087, 0x505ec5f3, F=0x0
+0, 6144, 6144, 512, 242, 0x70fe6f2c, F=0x0
+0, 6656, 6656, 512, 366, 0xcb0caedc, F=0x0
+0, 7168, 7168, 512, 644, 0xf72e3623, F=0x0
+0, 7680, 7680, 512, 668, 0x0cff4537, F=0x0
+0, 8192, 8192, 512, 239, 0x364c77a4, F=0x0
+0, 8704, 8704, 512, 400, 0x7e3bbaef, F=0x0
+0, 9216, 9216, 512, 404, 0x175cb5db, F=0x0
+0, 9728, 9728, 512, 277, 0x113185c5, F=0x0
+0, 10240, 10240, 512, 46, 0x0c860cfa, F=0x0
+0, 10752, 10752, 512, 659, 0x501b392a, F=0x0
+0, 11264, 11264, 512, 478, 0x0503e8ec, F=0x0
+0, 11776, 11776, 512, 1132, 0x952a1543, F=0x0
--
2.52.0
From 5d5b450d2c760e3e185fcd23283837e74ae7ba2e Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Tue, 8 Sep 2026 22:10:18 -0300
Subject: [PATCH 2/2] tests/fate/mov: add more CENC tests
This covers h264 and hevc for both Annex B and ISOBMFF input codepaths.
Signed-off-by: James Almer <jamrial(a)gmail.com>
(cherry picked from commit 5b614efc7e6134274fa5d05e240736be2dc203cc)
---
tests/fate/mov.mak | 12 ++++++++++--
tests/ref/fate/mov-h264-cenc | 25 +++++++++++++++++++++++++
tests/ref/fate/mov-h264_iso-cenc | 13 +++++++++++++
tests/ref/fate/mov-hevc-cenc | 9 +++++++++
tests/ref/fate/mov-hevc_iso-cenc | 10 ++++++++++
5 files changed, 67 insertions(+), 2 deletions(-)
create mode 100644 tests/ref/fate/mov-h264-cenc
create mode 100644 tests/ref/fate/mov-h264_iso-cenc
create mode 100644 tests/ref/fate/mov-hevc-cenc
create mode 100644 tests/ref/fate/mov-hevc_iso-cenc
diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak
index 56dc3763c0..87882756c1 100644
--- a/tests/fate/mov.mak
+++ b/tests/fate/mov.mak
@@ -198,10 +198,18 @@ fate-mov-mp4-fragmented-ttml-dfxp: CMD = transcode srt $(TARGET_SAMPLES)/sub/Sub
"-f lavfi -i smptehdbars=duration=24.5245:size=320x180:rate=24000/1001,format=yuv420p" \
"" "" "data"
-FATE_MOV_FFMPEG_SAMPLES-$(call REMUX, MP4 IVF, MOV_DEMUXER AV1_PARSER EXTRACT_EXTRADATA_BSF) += fate-mov-av1-cenc
-fate-mov-av1-cenc: CMD = transcode ivf $(TARGET_SAMPLES)/av1/non_uniform_tiling.ivf mp4 \
+define FATE_MOV_CENC_TEST
+FATE_MOV_FFMPEG_SAMPLES-$(call REMUX, MP4 $(4), MOV_DEMUXER $(2)_PARSER EXTRACT_EXTRADATA_BSF) += fate-mov-$(1)-cenc
+fate-mov-$(1)-cenc: CMD = transcode $(3) $(TARGET_SAMPLES)/$(5) mp4 \
"-c:v copy -encryption_scheme cenc-aes-ctr -encryption_key 00112233445566778899aabbccddeeff -encryption_kid 00112233445566778899aabbccddeeff" \
"-c:v copy" "" "" "-decryption_key 00112233445566778899aabbccddeeff"
+endef
+
+$(eval $(call FATE_MOV_CENC_TEST,av1,AV1,ivf,IVF,av1/non_uniform_tiling.ivf))
+$(eval $(call FATE_MOV_CENC_TEST,h264,H264,h264,H264,h264-conformance/CAMACI3_Sony_C.jsv))
+$(eval $(call FATE_MOV_CENC_TEST,h264_iso,H264,matroska,MATROSKA,h264/dts_5frames.mkv))
+$(eval $(call FATE_MOV_CENC_TEST,hevc,HEVC,hevc,HEVC,hevc-conformance/ipcm_A_NEC_3.bit))
+$(eval $(call FATE_MOV_CENC_TEST,hevc_iso,HEVC,mov,MOV,hevc/extradata-reload-multi-stsd.mov))
# avif demuxing - still image with 1 item.
FATE_MOV_FFMPEG_SAMPLES-$(call FRAMECRC, MOV, AV1, AV1_PARSER) \
diff --git a/tests/ref/fate/mov-h264-cenc b/tests/ref/fate/mov-h264-cenc
new file mode 100644
index 0000000000..75c15e7238
--- /dev/null
+++ b/tests/ref/fate/mov-h264-cenc
@@ -0,0 +1,25 @@
+59561bc01461cbcb947281c091cac9ee *tests/data/fate/mov-h264-cenc.mp4
+72996 tests/data/fate/mov-h264-cenc.mp4
+#extradata 0: 25, 0x5c9d073a
+#tb 0: 1/1200000
+#media_type 0: video
+#codec_id 0: h264
+#dimensions 0: 192x128
+#sar 0: 0/1
+0, -96000, -96000, 48000, 5183, 0x9bc6204f, F=0x5
+0, -48000, -48000, 48000, 4528, 0x9e28ce6e, F=0x4
+0, 0, 0, 48000, 4660, 0x1ff41c2a, F=0x0
+0, 48000, 48000, 48000, 3740, 0x8cec5062, F=0x0
+0, 96000, 96000, 48000, 3492, 0x8471c705, F=0x0
+0, 144000, 144000, 48000, 4793, 0xab1b7855, F=0x0
+0, 192000, 192000, 48000, 3351, 0xad2783f0, F=0x0
+0, 240000, 240000, 48000, 3396, 0xe0908da6, F=0x0
+0, 288000, 288000, 48000, 4846, 0x03a36085, F=0x0
+0, 336000, 336000, 48000, 3870, 0xdd6fa409, F=0x0
+0, 384000, 384000, 48000, 4022, 0x2a85ee8e, F=0x0
+0, 432000, 432000, 48000, 5641, 0x60cfe0ca, F=0x0
+0, 480000, 480000, 48000, 4221, 0x97733c38, F=0x0
+0, 528000, 528000, 48000, 4068, 0xfc65fe01, F=0x0
+0, 576000, 576000, 48000, 3971, 0x1b7aa573, F=0x0
+0, 624000, 624000, 48000, 3964, 0x4abab2ed, F=0x0
+0, 672000, 672000, 48000, 3867, 0xf12f9612, F=0x0
diff --git a/tests/ref/fate/mov-h264_iso-cenc b/tests/ref/fate/mov-h264_iso-cenc
new file mode 100644
index 0000000000..96a6e9a723
--- /dev/null
+++ b/tests/ref/fate/mov-h264_iso-cenc
@@ -0,0 +1,13 @@
+03e458edc426f90f52b560e175ad32d2 *tests/data/fate/mov-h264_iso-cenc.mp4
+15542 tests/data/fate/mov-h264_iso-cenc.mp4
+#extradata 0: 40, 0xcd870951
+#tb 0: 1/16000
+#media_type 0: video
+#codec_id 0: h264
+#dimensions 0: 512x256
+#sar 0: 1/1
+0, 0, 0, 2672, 14428, 0x1c626b86
+0, 2672, 2672, 2656, 11, 0x08f901f1, F=0x0
+0, 5328, 5328, 2672, 11, 0x09990211, F=0x0
+0, 8000, 8000, 2672, 11, 0x0a390231, F=0x0
+0, 10672, 10672, 2672, 11, 0x0ad90251, F=0x0
diff --git a/tests/ref/fate/mov-hevc-cenc b/tests/ref/fate/mov-hevc-cenc
new file mode 100644
index 0000000000..c823b24ed5
--- /dev/null
+++ b/tests/ref/fate/mov-hevc-cenc
@@ -0,0 +1,9 @@
+67d984d1166e68b085e85dabac1d69fb *tests/data/fate/mov-hevc-cenc.mp4
+6166 tests/data/fate/mov-hevc-cenc.mp4
+#extradata 0: 101, 0x8d351483
+#tb 0: 1/1200000
+#media_type 0: video
+#codec_id 0: hevc
+#dimensions 0: 416x240
+#sar 0: 0/1
+0, 0, 0, 48000, 5155, 0x18ffdb5c
diff --git a/tests/ref/fate/mov-hevc_iso-cenc b/tests/ref/fate/mov-hevc_iso-cenc
new file mode 100644
index 0000000000..2a1a3dcc19
--- /dev/null
+++ b/tests/ref/fate/mov-hevc_iso-cenc
@@ -0,0 +1,10 @@
+3b47c19a63210cf0bc2be5bf51fa36ad *tests/data/fate/mov-hevc_iso-cenc.mp4
+5548 tests/data/fate/mov-hevc_iso-cenc.mp4
+#extradata 0: 110, 0xb3a41478
+#tb 0: 1/12800
+#media_type 0: video
+#codec_id 0: hevc
+#dimensions 0: 128x128
+#sar 0: 1/1
+0, 0, 0, 512, 2108, 0x57c38f64
+0, 512, 512, 512, 31, 0xabe10d25, F=0x0
--
2.52.0
1
0
[PR] tests/fate/iamf: add tests with PCM audio and binaural loudness layout (PR #24453)
by James Almer 10 Sep '26
by James Almer 10 Sep '26
10 Sep '26
PR #24453 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24453
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24453.patch
Increases coverage a bit
From e51ad7533215a08a318cf68d2d63672cc81949bf Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Thu, 10 Sep 2026 21:17:01 -0300
Subject: [PATCH] tests/fate/iamf: add tests with PCM audio and binaural
loudness layout
Increases coverage a bit.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
tests/fate/iamf.mak | 12 +
tests/ref/fate/iamf-ambisonic_3-copy | 892 ++++++++++++++++++++++++++
tests/ref/fate/iamf-ambisonic_3-demux | 890 +++++++++++++++++++++++++
3 files changed, 1794 insertions(+)
create mode 100644 tests/ref/fate/iamf-ambisonic_3-copy
create mode 100644 tests/ref/fate/iamf-ambisonic_3-demux
diff --git a/tests/fate/iamf.mak b/tests/fate/iamf.mak
index a686be7952..a090d069dd 100644
--- a/tests/fate/iamf.mak
+++ b/tests/fate/iamf.mak
@@ -83,6 +83,18 @@ fate-iamf-ambisonic_1-projection-copy: CMD = stream_remux iamf $(TARGET_SAMPLES)
"-map 0 -stream_group map=0=0:st=0:st=1:st=2:st=3 -stream_group map=0=1:stg=0 -streamid 0:0 -streamid 1:1 -streamid 2:2 -streamid 3:3" "" "-c:a copy -frames:a 0 -map 0:g:i:300" \
"-show_entries stream_group=index,id,nb_streams,type:stream_group_components:stream_group_stream=index,id:stream_group_stream_disposition"
+FATE_IAMF_SAMPLES-$(call FRAMECRC, IAMF, PCM_S16LE) += fate-iamf-ambisonic_3-demux
+fate-iamf-ambisonic_3-demux: CMD = stream_demux iamf $(TARGET_SAMPLES)/iamf/test_000096.iamf "" \
+ "-c:a copy -frames:a 0 -map 0:g:\#300" \
+ "-show_entries stream_group=index,id,nb_streams,type:stream_group_components:stream_group_stream=index,id:stream_group_stream_disposition"
+
+FATE_IAMF_SAMPLES-$(call REMUX, IAMF, PCM_S16LE_DECODER) += fate-iamf-ambisonic_3-copy
+fate-iamf-ambisonic_3-copy: CMD = stream_remux iamf $(TARGET_SAMPLES)/iamf/test_000096.iamf "" iamf \
+ "-map 0 -stream_group map=0=0:st=0:st=1:st=2:st=3:st=4:st=5:st=6:st=7:st=8:st=9:st=10:st=11:st=12:st=13:st=14:st=15 \
+ -stream_group map=0=1:stg=0 -streamid 0:0 -streamid 1:1 -streamid 2:2 -streamid 3:3 -streamid 4:4 -streamid 5:5 -streamid 6:6 -streamid 7:7 -streamid 8:8 -streamid 9:9 -streamid 10:10 -streamid 11:11 -streamid 12:12 -streamid 13:13 -streamid 14:14 -streamid 15:15" \
+ "" "-c:a copy -frames:a 0 -map 0:g:i:300" \
+ "-show_entries stream_group=index,id,nb_streams,type:stream_group_components:stream_group_stream=index,id:stream_group_stream_disposition"
+
FATE_IAMF += $(FATE_IAMF-yes)
FATE_IAMF_SAMPLES += $(FATE_IAMF_SAMPLES-yes)
diff --git a/tests/ref/fate/iamf-ambisonic_3-copy b/tests/ref/fate/iamf-ambisonic_3-copy
new file mode 100644
index 0000000000..7e2a42338a
--- /dev/null
+++ b/tests/ref/fate/iamf-ambisonic_3-copy
@@ -0,0 +1,892 @@
+284e34260bc42c691cdbebd3327cad9c *tests/data/fate/iamf-ambisonic_3-copy.iamf
+7711966 tests/data/fate/iamf-ambisonic_3-copy.iamf
+#tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 48000
+#channel_layout_name 0: mono
+#tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout_name 1: mono
+#tb 2: 1/48000
+#media_type 2: audio
+#codec_id 2: pcm_s16le
+#sample_rate 2: 48000
+#channel_layout_name 2: mono
+#tb 3: 1/48000
+#media_type 3: audio
+#codec_id 3: pcm_s16le
+#sample_rate 3: 48000
+#channel_layout_name 3: mono
+#tb 4: 1/48000
+#media_type 4: audio
+#codec_id 4: pcm_s16le
+#sample_rate 4: 48000
+#channel_layout_name 4: mono
+#tb 5: 1/48000
+#media_type 5: audio
+#codec_id 5: pcm_s16le
+#sample_rate 5: 48000
+#channel_layout_name 5: mono
+#tb 6: 1/48000
+#media_type 6: audio
+#codec_id 6: pcm_s16le
+#sample_rate 6: 48000
+#channel_layout_name 6: mono
+#tb 7: 1/48000
+#media_type 7: audio
+#codec_id 7: pcm_s16le
+#sample_rate 7: 48000
+#channel_layout_name 7: mono
+#tb 8: 1/48000
+#media_type 8: audio
+#codec_id 8: pcm_s16le
+#sample_rate 8: 48000
+#channel_layout_name 8: mono
+#tb 9: 1/48000
+#media_type 9: audio
+#codec_id 9: pcm_s16le
+#sample_rate 9: 48000
+#channel_layout_name 9: mono
+#tb 10: 1/48000
+#media_type 10: audio
+#codec_id 10: pcm_s16le
+#sample_rate 10: 48000
+#channel_layout_name 10: mono
+#tb 11: 1/48000
+#media_type 11: audio
+#codec_id 11: pcm_s16le
+#sample_rate 11: 48000
+#channel_layout_name 11: mono
+#tb 12: 1/48000
+#media_type 12: audio
+#codec_id 12: pcm_s16le
+#sample_rate 12: 48000
+#channel_layout_name 12: mono
+#tb 13: 1/48000
+#media_type 13: audio
+#codec_id 13: pcm_s16le
+#sample_rate 13: 48000
+#channel_layout_name 13: mono
+#tb 14: 1/48000
+#media_type 14: audio
+#codec_id 14: pcm_s16le
+#sample_rate 14: 48000
+#channel_layout_name 14: mono
+#tb 15: 1/48000
+#media_type 15: audio
+#codec_id 15: pcm_s16le
+#sample_rate 15: 48000
+#channel_layout_name 15: mono
+[STREAM_GROUP]
+index=0
+id=0x12c
+nb_streams=16
+type=IAMF Audio Element
+[COMPONENT]
+nb_layers=1
+audio_element_type=1
+default_w=0
+[SUBCOMPONENT]
+channel_layout=ambisonic 3
+ambisonics_mode=0
+[/SUBCOMPONENT]
+[/COMPONENT]
+[STREAM]
+index=0
+id=0x0
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=2
+id=0x2
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=3
+id=0x3
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=4
+id=0x4
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=5
+id=0x5
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=6
+id=0x6
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=7
+id=0x7
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=8
+id=0x8
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=9
+id=0x9
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=10
+id=0xa
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=11
+id=0xb
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=12
+id=0xc
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=13
+id=0xd
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=14
+id=0xe
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=15
+id=0xf
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[/STREAM_GROUP]
+[STREAM_GROUP]
+index=1
+id=0x2a
+nb_streams=16
+type=IAMF Mix Presentation
+[COMPONENT]
+nb_submixes=1
+[SUBCOMPONENT]
+en-us=test_mix_pres
+[/SUBCOMPONENT]
+[SUBCOMPONENT]
+nb_elements=1
+nb_layouts=2
+default_mix_gain=0/256
+[PIECE]
+stream_id=300
+default_mix_gain=0/256
+headphones_rendering_mode=1
+[SUBPIECE]
+en-us=test_sub_mix_0_audio_element_0
+[/SUBPIECE]
+[SUBPIECE]
+name=element_mix_config
+nb_subblocks=0
+type=0
+parameter_id=999
+parameter_rate=48000
+duration=0
+constant_subblock_duration=0
+[/SUBPIECE]
+[/PIECE]
+[PIECE]
+name=output_mix_config
+nb_subblocks=0
+type=0
+parameter_id=998
+parameter_rate=48000
+duration=0
+constant_subblock_duration=0
+[/PIECE]
+[PIECE]
+sound_system=stereo
+integrated_loudness=-2834/256
+digital_peak=0/256
+true_peak=0/1
+dialogue_anchored_loudness=0/1
+album_anchored_loudness=0/1
+[/PIECE]
+[PIECE]
+sound_system=binaural
+integrated_loudness=-32768/256
+digital_peak=-32768/256
+true_peak=0/1
+dialogue_anchored_loudness=0/1
+album_anchored_loudness=0/1
+[/PIECE]
+[/SUBCOMPONENT]
+[/COMPONENT]
+[STREAM]
+index=0
+id=0x0
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=2
+id=0x2
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=3
+id=0x3
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=4
+id=0x4
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=5
+id=0x5
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=6
+id=0x6
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=7
+id=0x7
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=8
+id=0x8
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=9
+id=0x9
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=10
+id=0xa
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=11
+id=0xb
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=12
+id=0xc
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=13
+id=0xd
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=14
+id=0xe
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=15
+id=0xf
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[/STREAM_GROUP]
diff --git a/tests/ref/fate/iamf-ambisonic_3-demux b/tests/ref/fate/iamf-ambisonic_3-demux
new file mode 100644
index 0000000000..5b56e81d1b
--- /dev/null
+++ b/tests/ref/fate/iamf-ambisonic_3-demux
@@ -0,0 +1,890 @@
+#tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 48000
+#channel_layout_name 0: mono
+#tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout_name 1: mono
+#tb 2: 1/48000
+#media_type 2: audio
+#codec_id 2: pcm_s16le
+#sample_rate 2: 48000
+#channel_layout_name 2: mono
+#tb 3: 1/48000
+#media_type 3: audio
+#codec_id 3: pcm_s16le
+#sample_rate 3: 48000
+#channel_layout_name 3: mono
+#tb 4: 1/48000
+#media_type 4: audio
+#codec_id 4: pcm_s16le
+#sample_rate 4: 48000
+#channel_layout_name 4: mono
+#tb 5: 1/48000
+#media_type 5: audio
+#codec_id 5: pcm_s16le
+#sample_rate 5: 48000
+#channel_layout_name 5: mono
+#tb 6: 1/48000
+#media_type 6: audio
+#codec_id 6: pcm_s16le
+#sample_rate 6: 48000
+#channel_layout_name 6: mono
+#tb 7: 1/48000
+#media_type 7: audio
+#codec_id 7: pcm_s16le
+#sample_rate 7: 48000
+#channel_layout_name 7: mono
+#tb 8: 1/48000
+#media_type 8: audio
+#codec_id 8: pcm_s16le
+#sample_rate 8: 48000
+#channel_layout_name 8: mono
+#tb 9: 1/48000
+#media_type 9: audio
+#codec_id 9: pcm_s16le
+#sample_rate 9: 48000
+#channel_layout_name 9: mono
+#tb 10: 1/48000
+#media_type 10: audio
+#codec_id 10: pcm_s16le
+#sample_rate 10: 48000
+#channel_layout_name 10: mono
+#tb 11: 1/48000
+#media_type 11: audio
+#codec_id 11: pcm_s16le
+#sample_rate 11: 48000
+#channel_layout_name 11: mono
+#tb 12: 1/48000
+#media_type 12: audio
+#codec_id 12: pcm_s16le
+#sample_rate 12: 48000
+#channel_layout_name 12: mono
+#tb 13: 1/48000
+#media_type 13: audio
+#codec_id 13: pcm_s16le
+#sample_rate 13: 48000
+#channel_layout_name 13: mono
+#tb 14: 1/48000
+#media_type 14: audio
+#codec_id 14: pcm_s16le
+#sample_rate 14: 48000
+#channel_layout_name 14: mono
+#tb 15: 1/48000
+#media_type 15: audio
+#codec_id 15: pcm_s16le
+#sample_rate 15: 48000
+#channel_layout_name 15: mono
+[STREAM_GROUP]
+index=0
+id=0x12c
+nb_streams=16
+type=IAMF Audio Element
+[COMPONENT]
+nb_layers=1
+audio_element_type=1
+default_w=0
+[SUBCOMPONENT]
+channel_layout=ambisonic 3
+ambisonics_mode=0
+[/SUBCOMPONENT]
+[/COMPONENT]
+[STREAM]
+index=0
+id=0x0
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=2
+id=0x2
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=3
+id=0x3
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=4
+id=0x4
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=5
+id=0x5
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=6
+id=0x6
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=7
+id=0x7
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=8
+id=0x8
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=9
+id=0x9
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=10
+id=0xa
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=11
+id=0xb
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=12
+id=0xc
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=13
+id=0xd
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=14
+id=0xe
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=15
+id=0xf
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[/STREAM_GROUP]
+[STREAM_GROUP]
+index=1
+id=0x2a
+nb_streams=16
+type=IAMF Mix Presentation
+[COMPONENT]
+nb_submixes=1
+[SUBCOMPONENT]
+en-us=test_mix_pres
+[/SUBCOMPONENT]
+[SUBCOMPONENT]
+nb_elements=1
+nb_layouts=2
+default_mix_gain=0/256
+[PIECE]
+stream_id=300
+default_mix_gain=0/256
+headphones_rendering_mode=1
+[SUBPIECE]
+en-us=test_sub_mix_0_audio_element_0
+[/SUBPIECE]
+[SUBPIECE]
+name=element_mix_config
+nb_subblocks=0
+type=0
+parameter_id=999
+parameter_rate=48000
+duration=0
+constant_subblock_duration=0
+[/SUBPIECE]
+[/PIECE]
+[PIECE]
+name=output_mix_config
+nb_subblocks=0
+type=0
+parameter_id=998
+parameter_rate=48000
+duration=0
+constant_subblock_duration=0
+[/PIECE]
+[PIECE]
+sound_system=stereo
+integrated_loudness=-2834/256
+digital_peak=0/256
+true_peak=0/1
+dialogue_anchored_loudness=0/1
+album_anchored_loudness=0/1
+[/PIECE]
+[PIECE]
+sound_system=binaural
+integrated_loudness=-32768/256
+digital_peak=-32768/256
+true_peak=0/1
+dialogue_anchored_loudness=0/1
+album_anchored_loudness=0/1
+[/PIECE]
+[/SUBCOMPONENT]
+[/COMPONENT]
+[STREAM]
+index=0
+id=0x0
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=1
+id=0x1
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=2
+id=0x2
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=3
+id=0x3
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=4
+id=0x4
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=5
+id=0x5
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=6
+id=0x6
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=7
+id=0x7
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=8
+id=0x8
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=9
+id=0x9
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=10
+id=0xa
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=11
+id=0xb
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=12
+id=0xc
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=13
+id=0xd
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=14
+id=0xe
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[STREAM]
+index=15
+id=0xf
+DISPOSITION:default=0
+DISPOSITION:dub=0
+DISPOSITION:original=0
+DISPOSITION:comment=0
+DISPOSITION:lyrics=0
+DISPOSITION:karaoke=0
+DISPOSITION:forced=0
+DISPOSITION:hearing_impaired=0
+DISPOSITION:visual_impaired=0
+DISPOSITION:clean_effects=0
+DISPOSITION:attached_pic=0
+DISPOSITION:timed_thumbnails=0
+DISPOSITION:non_diegetic=0
+DISPOSITION:captions=0
+DISPOSITION:descriptions=0
+DISPOSITION:metadata=0
+DISPOSITION:dependent=1
+DISPOSITION:still_image=0
+DISPOSITION:multilayer=0
+[/STREAM]
+[/STREAM_GROUP]
--
2.52.0
1
0
[PR] avutil/hwcontext_vulkan: disable host image transfers for multi-plane images on NVIDIA (PR #24452)
by Kacper Michajłow 10 Sep '26
by Kacper Michajłow 10 Sep '26
10 Sep '26
PR #24452 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24452
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24452.patch
NVIDIA's host image copy resolves every plane's parameters as if it
were plane 0, so a plain hwupload,hwdownload round trip returns a
corrupted frame. Frames with one image per plane and single-plane
formats are not affected. Exclude HIC for multi-plane images instead of
restoring the full blocklist dropped in 4ec050211a.
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24451
From 05c312e11ea780394504ea4e1aec43073daf83dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <kasper93(a)gmail.com>
Date: Fri, 11 Sep 2026 00:31:48 +0200
Subject: [PATCH] avutil/hwcontext_vulkan: disable host image transfers for
multi-plane images on NVIDIA
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
NVIDIA's host image copy resolves every plane's parameters as if it
were plane 0, so a plain hwupload,hwdownload round trip returns a
corrupted frame. Frames with one image per plane and single-plane
formats are not affected. Exclude HIC for multi-plane images instead of
restoring the full blocklist dropped in 4ec050211a.
Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24451
Signed-off-by: Kacper Michajłow <kasper93(a)gmail.com>
---
libavutil/hwcontext_vulkan.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index aa0efdd755..2859ee17c3 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -3033,6 +3033,18 @@ static int vulkan_host_transfer_usable(AVHWFramesContext *hwfc)
FFVulkanFunctions *vk = &p->vkctx.vkfn;
VkResult ret;
+ /* NVIDIA's host image copy resolves every plane's parameters as if it were
+ * plane 0, so every plane but the first is corrupted on both upload and
+ * download. Frames with one image per plane are unaffected.
+ */
+ const struct FFVkFormatEntry *fmt = vk_find_format_entry(hwfc->sw_format);
+ if (p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
+ fmt && fmt->vk_planes > 1 && hwctx->format[0] == fmt->vkf) {
+ av_log(hwfc, AV_LOG_VERBOSE, "Disabling host image transfers: "
+ "NVIDIA drivers mishandle multi-plane images\n");
+ return 0;
+ }
+
const VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
ff_vk_find_struct(hwctx->create_pnext,
VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
--
2.52.0
1
0
[PR] Add missing D3D11 interop, array format and error code definitions (PR #6)
by flowreen 10 Sep '26
by flowreen 10 Sep '26
10 Sep '26
PR #6 opened by flowreen
URL: https://code.ffmpeg.org/FFmpeg/nv-codec-headers/pulls/6
Patch URL: https://code.ffmpeg.org/FFmpeg/nv-codec-headers/pulls/6.patch
Adds the CUDA driver API definitions that FFmpeg needs for D3D11 interop through the external memory and external semaphore API, plus three error codes and one array format:
* `CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE` (6) and `_KMT` (7)
* `CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE` (5), `D3D11_KEYED_MUTEX` (7) and `_KMT` (8)
* `CUDA_EXTERNAL_MEMORY_DEDICATED` (0x1)
* `CU_AD_FORMAT_UNORM_INT_101010_2` (0x50)
* `CUDA_ERROR_OUT_OF_MEMORY` (2), `CUDA_ERROR_INVALID_HANDLE` (400), `CUDA_ERROR_NOT_SUPPORTED` (801)
Values taken from the CUDA driver API reference (cuda.h, `group__CUDA__TYPES`). No version bump.
FFmpeg/FFmpeg#24316 (D3D11 to Vulkan and CUDA frame transfer) currently carries local `FF_` copies of these; once a release with them exists, FFmpeg can drop the copies and bump its ffnvcodec check.
From 466b82c4fc5185967fac8d1e4476179eaf42d059 Mon Sep 17 00:00:00 2001
From: flowreen <florinn91(a)yahoo.com>
Date: Thu, 10 Sep 2026 23:36:28 +0200
Subject: [PATCH] Add missing D3D11 interop, array format and error code
definitions
---
include/ffnvcodec/dynlink_cuda.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/ffnvcodec/dynlink_cuda.h b/include/ffnvcodec/dynlink_cuda.h
index 25077cd..c893a3b 100644
--- a/include/ffnvcodec/dynlink_cuda.h
+++ b/include/ffnvcodec/dynlink_cuda.h
@@ -66,8 +66,11 @@ typedef struct CUlinkState_st *CUlinkState;
typedef enum cudaError_enum {
CUDA_SUCCESS = 0,
CUDA_ERROR_INVALID_VALUE = 1,
+ CUDA_ERROR_OUT_OF_MEMORY = 2,
+ CUDA_ERROR_INVALID_HANDLE = 400,
CUDA_ERROR_NOT_READY = 600,
CUDA_ERROR_LAUNCH_TIMEOUT = 702,
+ CUDA_ERROR_NOT_SUPPORTED = 801,
CUDA_ERROR_UNKNOWN = 999
} CUresult;
@@ -107,6 +110,7 @@ typedef enum CUarray_format_enum {
CU_AD_FORMAT_SIGNED_INT32 = 0x0a,
CU_AD_FORMAT_HALF = 0x10,
CU_AD_FORMAT_FLOAT = 0x20,
+ CU_AD_FORMAT_UNORM_INT_101010_2 = 0x50,
CU_AD_FORMAT_NV12 = 0xb0,
CU_AD_FORMAT_P016 = 0xa1,
CU_AD_FORMAT_NV16 = 0xa2,
@@ -168,6 +172,8 @@ typedef enum CUexternalMemoryHandleType_enum {
CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT = 3,
CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP = 4,
CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE = 5,
+ CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE = 6,
+ CU_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_RESOURCE_KMT = 7,
} CUexternalMemoryHandleType;
typedef enum CUexternalSemaphoreHandleType_enum {
@@ -175,6 +181,9 @@ typedef enum CUexternalSemaphoreHandleType_enum {
CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32 = 2,
CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT = 3,
CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE = 4,
+ CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE = 5,
+ CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_KEYED_MUTEX = 7,
+ CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_KEYED_MUTEX_KMT = 8,
CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD = 9,
CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 = 10,
} CUexternalSemaphoreHandleType;
@@ -325,6 +334,8 @@ typedef enum CUGLDeviceList_enum {
CU_GL_DEVICE_LIST_NEXT_FRAME = 3,
} CUGLDeviceList;
+#define CUDA_EXTERNAL_MEMORY_DEDICATED 0x1
+
typedef struct CUDA_EXTERNAL_MEMORY_HANDLE_DESC_st {
CUexternalMemoryHandleType type;
union {
--
2.52.0
1
0
10 Sep '26
PR #24450 opened by Kyle Swanson (kylophone)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24450
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24450.patch
Speedup is around 73% on an AMD EPYC 9R14, single threaded 4K 12-bit
ProRes 4444.
From 67403121672adf57b978f4c8adb3eac56615424d Mon Sep 17 00:00:00 2001
From: Kyle Swanson <k(a)ylo.ph>
Date: Thu, 10 Sep 2026 21:19:13 +0000
Subject: [PATCH] avcodec/x86/proresdsp: add ff_prores_idct_put_12_avx2
Speedup is around 73% on an AMD EPYC 9R14, single threaded 4K 12-bit
ProRes 4444.
---
libavcodec/x86/proresdsp.asm | 257 ++++++++++++++++++++++++++++++++
libavcodec/x86/proresdsp_init.c | 7 +
2 files changed, 264 insertions(+)
diff --git a/libavcodec/x86/proresdsp.asm b/libavcodec/x86/proresdsp.asm
index 37aa103d07..8b7b137fc9 100644
--- a/libavcodec/x86/proresdsp.asm
+++ b/libavcodec/x86/proresdsp.asm
@@ -48,6 +48,27 @@ cextern w7_min_w5
%include "libavcodec/x86/simple_idct10_template.asm"
+%if HAVE_AVX2_EXTERNAL
+align 32
+pd_w1_12: times 8 dd 45451
+align 32
+pd_w2_12: times 8 dd 42813
+align 32
+pd_w3_12: times 8 dd 38531
+align 32
+pd_w4_12: times 8 dd 32767
+align 32
+pd_w5_12: times 8 dd 25746
+align 32
+pd_w6_12: times 8 dd 17734
+align 32
+pd_w7_12: times 8 dd 9041
+align 32
+pd_round_row12: times 8 dd 1<<(16-1)
+pw_col_bias_12: times 8 dw 8192+2
+pw_4091: times 8 dw 4091
+%endif
+
SECTION .text
define_constants _hi
@@ -65,4 +86,240 @@ INIT_XMM avx
idct_fn
%endif
+%if HAVE_AVX2_EXTERNAL
+%macro AB_TERMS_12_AVX2 1
+ pmulld m8, m0, [pd_w4_12]
+%if %1
+ paddd m8, [pd_round_row12]
+%endif
+ pmulld m9, m2, [pd_w2_12]
+ paddd m8, m9
+ pmulld m9, m4, [pd_w4_12]
+ paddd m8, m9
+ pmulld m9, m6, [pd_w6_12]
+ paddd m8, m9
+
+ pmulld m10, m0, [pd_w4_12]
+%if %1
+ paddd m10, [pd_round_row12]
+%endif
+ pmulld m9, m2, [pd_w6_12]
+ paddd m10, m9
+ pmulld m9, m4, [pd_w4_12]
+ psubd m10, m9
+ pmulld m9, m6, [pd_w2_12]
+ psubd m10, m9
+
+ pmulld m11, m0, [pd_w4_12]
+%if %1
+ paddd m11, [pd_round_row12]
+%endif
+ pmulld m9, m2, [pd_w6_12]
+ psubd m11, m9
+ pmulld m9, m4, [pd_w4_12]
+ psubd m11, m9
+ pmulld m9, m6, [pd_w2_12]
+ paddd m11, m9
+
+ pmulld m12, m0, [pd_w4_12]
+%if %1
+ paddd m12, [pd_round_row12]
+%endif
+ pmulld m9, m2, [pd_w2_12]
+ psubd m12, m9
+ pmulld m9, m4, [pd_w4_12]
+ paddd m12, m9
+ pmulld m9, m6, [pd_w6_12]
+ psubd m12, m9
+
+ pmulld m13, m1, [pd_w1_12]
+ pmulld m9, m3, [pd_w3_12]
+ paddd m13, m9
+ pmulld m9, m5, [pd_w5_12]
+ paddd m13, m9
+ pmulld m9, m7, [pd_w7_12]
+ paddd m13, m9
+
+ pmulld m14, m1, [pd_w3_12]
+ pmulld m9, m3, [pd_w7_12]
+ psubd m14, m9
+ pmulld m9, m5, [pd_w1_12]
+ psubd m14, m9
+ pmulld m9, m7, [pd_w5_12]
+ psubd m14, m9
+
+ pmulld m15, m1, [pd_w5_12]
+ pmulld m9, m3, [pd_w1_12]
+ psubd m15, m9
+ pmulld m9, m5, [pd_w7_12]
+ paddd m15, m9
+ pmulld m9, m7, [pd_w3_12]
+ paddd m15, m9
+
+ pmulld m0, m1, [pd_w7_12]
+ pmulld m9, m3, [pd_w5_12]
+ psubd m0, m9
+ pmulld m9, m5, [pd_w3_12]
+ paddd m0, m9
+ pmulld m9, m7, [pd_w1_12]
+ psubd m0, m9
+%endmacro
+
+%macro COMBINE_PACK_ROW_REG_12 6
+ paddd m%4, %1, %2
+ psrad m%4, %3
+ psubd m%5, %1, %2
+ psrad m%5, %3
+ vextracti128 xm%6, m%4, 1
+ packssdw xm%4, xm%6
+ vextracti128 xm%6, m%5, 1
+ packssdw xm%5, xm%6
+%endmacro
+
+%macro COMBINE_PACK_CLIP_PUT_12 5
+ paddd m1, %1, %2
+ psubd m2, %1, %2
+ psrad m1, %3
+ psrad m2, %3
+ vextracti128 xm3, m1, 0
+ vextracti128 xm4, m1, 1
+ packssdw xm3, xm4
+ pmaxsw xm3, [pw_4]
+ pminsw xm3, [pw_4091]
+ imul r4, lsizeq, %4
+ mova [pixelsq+r4], xm3
+ vextracti128 xm3, m2, 0
+ vextracti128 xm4, m2, 1
+ packssdw xm3, xm4
+ pmaxsw xm3, [pw_4]
+ pminsw xm3, [pw_4091]
+ imul r4, lsizeq, %5
+ mova [pixelsq+r4], xm3
+%endmacro
+
+INIT_YMM avx2
+cglobal prores_idct_put_12, 4, 5, 16, 32, pixels, lsize, block, qmat
+ movu xm0,[blockq+0*16]
+ pmullw xm0,[qmatq+0*16]
+ movu xm1,[blockq+1*16]
+ pmullw xm1,[qmatq+1*16]
+ movu xm2,[blockq+2*16]
+ pmullw xm2,[qmatq+2*16]
+ movu xm3,[blockq+3*16]
+ pmullw xm3,[qmatq+3*16]
+ movu xm4,[blockq+4*16]
+ pmullw xm4,[qmatq+4*16]
+ movu xm5,[blockq+5*16]
+ pmullw xm5,[qmatq+5*16]
+ movu xm6,[blockq+6*16]
+ pmullw xm6,[qmatq+6*16]
+ movu xm7,[blockq+7*16]
+ pmullw xm7,[qmatq+7*16]
+
+ por xm14, xm1, xm2
+ por xm14, xm14, xm3
+ por xm14, xm14, xm4
+ por xm14, xm14, xm5
+ por xm14, xm14, xm6
+ por xm14, xm14, xm7
+ pxor xm9, xm9
+ pcmpeqw xm14, xm9
+ paddw xm15, xm0, [pw_1]
+ psraw xm15, 1
+ mova [rsp+0], xm14
+ mova [rsp+16], xm15
+
+ vpmovsxwd m0, xm0
+ vpmovsxwd m1, xm1
+ vpmovsxwd m2, xm2
+ vpmovsxwd m3, xm3
+ vpmovsxwd m4, xm4
+ vpmovsxwd m5, xm5
+ vpmovsxwd m6, xm6
+ vpmovsxwd m7, xm7
+
+ AB_TERMS_12_AVX2 1
+
+ COMBINE_PACK_ROW_REG_12 m8, m13, 16, 9, 7, 3
+ COMBINE_PACK_ROW_REG_12 m10,m14, 16, 1, 6, 3
+ COMBINE_PACK_ROW_REG_12 m11,m15, 16, 2, 5, 3
+ COMBINE_PACK_ROW_REG_12 m12,m0, 16, 3, 4, 0
+
+ mova xm8, [rsp+0]
+ mova xm10,[rsp+16]
+ pand xm10, xm8
+ pandn xm9, xm8, xm9
+ por xm9, xm10
+ pandn xm1, xm8, xm1
+ por xm1, xm10
+ pandn xm2, xm8, xm2
+ por xm2, xm10
+ pandn xm3, xm8, xm3
+ por xm3, xm10
+ pandn xm4, xm8, xm4
+ por xm4, xm10
+ pandn xm5, xm8, xm5
+ por xm5, xm10
+ pandn xm6, xm8, xm6
+ por xm6, xm10
+ pandn xm7, xm8, xm7
+ por xm7, xm10
+ mova xm0, xm9
+
+ mova [blockq+0*16], xm0
+ mova [blockq+1*16], xm1
+ mova [blockq+2*16], xm2
+ mova [blockq+3*16], xm3
+ mova [blockq+4*16], xm4
+ mova [blockq+5*16], xm5
+ mova [blockq+6*16], xm6
+ mova [blockq+7*16], xm7
+
+ INIT_XMM avx
+ mova xm0,[blockq+0*16]
+ mova xm1,[blockq+1*16]
+ mova xm2,[blockq+2*16]
+ mova xm3,[blockq+3*16]
+ mova xm4,[blockq+4*16]
+ mova xm5,[blockq+5*16]
+ mova xm6,[blockq+6*16]
+ mova xm7,[blockq+7*16]
+ TRANSPOSE8x8W 0,1,2,3,4,5,6,7,8
+ mova [blockq+0*16],xm0
+ mova [blockq+1*16],xm1
+ mova [blockq+2*16],xm2
+ mova [blockq+3*16],xm3
+ mova [blockq+4*16],xm4
+ mova [blockq+5*16],xm5
+ mova [blockq+6*16],xm6
+ mova [blockq+7*16],xm7
+ INIT_YMM avx2
+
+ movu xm0,[blockq+0*16]
+ paddw xm0,[pw_col_bias_12]
+ vpmovsxwd m0, xm0
+ movu xm1,[blockq+1*16]
+ vpmovsxwd m1, xm1
+ movu xm2,[blockq+2*16]
+ vpmovsxwd m2, xm2
+ movu xm3,[blockq+3*16]
+ vpmovsxwd m3, xm3
+ movu xm4,[blockq+4*16]
+ vpmovsxwd m4, xm4
+ movu xm5,[blockq+5*16]
+ vpmovsxwd m5, xm5
+ movu xm6,[blockq+6*16]
+ vpmovsxwd m6, xm6
+ movu xm7,[blockq+7*16]
+ vpmovsxwd m7, xm7
+
+ AB_TERMS_12_AVX2 0
+
+ COMBINE_PACK_CLIP_PUT_12 m8, m13, 17, 0, 7
+ COMBINE_PACK_CLIP_PUT_12 m10,m14, 17, 1, 6
+ COMBINE_PACK_CLIP_PUT_12 m11,m15, 17, 2, 5
+ COMBINE_PACK_CLIP_PUT_12 m12,m0, 17, 3, 4
+ RET
+%endif
+
%endif
diff --git a/libavcodec/x86/proresdsp_init.c b/libavcodec/x86/proresdsp_init.c
index f7abbfa692..9f92adf518 100644
--- a/libavcodec/x86/proresdsp_init.c
+++ b/libavcodec/x86/proresdsp_init.c
@@ -29,6 +29,8 @@ void ff_prores_idct_put_10_sse2(uint16_t *dst, ptrdiff_t linesize,
int16_t *block, const int16_t *qmat);
void ff_prores_idct_put_10_avx (uint16_t *dst, ptrdiff_t linesize,
int16_t *block, const int16_t *qmat);
+void ff_prores_idct_put_12_avx2(uint16_t *dst, ptrdiff_t linesize,
+ int16_t *block, const int16_t *qmat);
av_cold void ff_proresdsp_init_x86(ProresDSPContext *dsp, int bits_per_raw_sample)
{
@@ -45,6 +47,11 @@ av_cold void ff_proresdsp_init_x86(ProresDSPContext *dsp, int bits_per_raw_sampl
dsp->idct_permutation_type = FF_IDCT_PERM_TRANSPOSE;
dsp->idct_put = ff_prores_idct_put_10_avx;
}
+ } else if (bits_per_raw_sample == 12) {
+ if (EXTERNAL_AVX2(cpu_flags)) {
+ dsp->idct_permutation_type = FF_IDCT_PERM_TRANSPOSE;
+ dsp->idct_put = ff_prores_idct_put_12_avx2;
+ }
}
#endif /* ARCH_X86_64 */
}
--
2.52.0
1
0
[PR] [release/6.0] avfilter/vf_colorcorrect: backport histogram cleanup (PR #24449)
by Forgejo_Fairy 10 Sep '26
by Forgejo_Fairy 10 Sep '26
10 Sep '26
PR #24449 opened by Forgejo_Fairy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24449
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24449.patch
The colorcorrect filter allocates two histogram buffers but does not release them in `uninit()` on release/6.0. Backport 5f87a68cf70da to free both buffers, preserving the original author.
Addresses the release/6.0 portion of #22776. This is equivalent to the reporter’s [submitted backport](https://patchwork.ffmpeg.org/project/ffmpeg/patch/tencent_A128044…; the upstream commit applies cleanly to base ba69be84a1ce. The release/5.0 backport is tracked separately.
Validation: the submitted patch and this cherry-pick have identical stable patch IDs. The patched filter object compiled successfully on AArch64 with GCC 13.3.0 using `./configure --disable-everything --disable-programs --disable-doc --disable-autodetect --enable-avfilter --enable-filter=colorcorrect` and `make -j8 libavfilter/vf_colorcorrect.o`. `git diff --check` passed. Runtime sanitizer validation is the reporter’s evidence in #22776; the security PoC was not independently executed in this investigation.
From 110e2cd229d5acfdd950f5d09381afc41c263523 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda(a)gmail.com>
Date: Mon, 27 Nov 2023 12:08:20 +0100
Subject: [PATCH] avfilter/vf_colorcorrect: fix memory leaks
(cherry picked from commit 5f87a68cf70dafeab2fb89b42e41a4c29053b89b)
Assisted-by: Fairy
---
libavfilter/vf_colorcorrect.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavfilter/vf_colorcorrect.c b/libavfilter/vf_colorcorrect.c
index ee97b62b0e..ac2de2a357 100644
--- a/libavfilter/vf_colorcorrect.c
+++ b/libavfilter/vf_colorcorrect.c
@@ -498,6 +498,8 @@ static av_cold void uninit(AVFilterContext *ctx)
ColorCorrectContext *s = ctx->priv;
av_freep(&s->analyzeret);
+ av_freep(&s->uhistogram);
+ av_freep(&s->vhistogram);
}
static const AVFilterPad colorcorrect_inputs[] = {
--
2.52.0
1
0
[PR] [release/5.0] avfilter/vf_colorcorrect: backport histogram cleanup (PR #24448)
by Forgejo_Fairy 10 Sep '26
by Forgejo_Fairy 10 Sep '26
10 Sep '26
PR #24448 opened by Forgejo_Fairy
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24448
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24448.patch
The colorcorrect filter allocates two histogram buffers but does not release them in `uninit()` on release/5.0. Backport 5f87a68cf70da to free both buffers, preserving the original author.
Addresses the release/5.0 portion of #22776. This is equivalent to the reporter’s [submitted backport](https://patchwork.ffmpeg.org/project/ffmpeg/patch/tencent_FE200A4…; the upstream commit applies cleanly to base 64626725c36c. The release/6.0 backport is tracked separately.
Validation: the submitted patch and this cherry-pick have identical stable patch IDs. The patched filter object compiled successfully on AArch64 with GCC 13.3.0 using `./configure --disable-everything --disable-programs --disable-doc --disable-autodetect --enable-avfilter --enable-filter=colorcorrect` and `make -j8 libavfilter/vf_colorcorrect.o`. `git diff --check` passed. Runtime sanitizer validation is the reporter’s evidence in #22776; the security PoC was not independently executed in this investigation.
From 1a60a7f85b3cae0b1ea62e62220ded7facbd8324 Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda(a)gmail.com>
Date: Mon, 27 Nov 2023 12:08:20 +0100
Subject: [PATCH] avfilter/vf_colorcorrect: fix memory leaks
(cherry picked from commit 5f87a68cf70dafeab2fb89b42e41a4c29053b89b)
Assisted-by: Fairy
---
libavfilter/vf_colorcorrect.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavfilter/vf_colorcorrect.c b/libavfilter/vf_colorcorrect.c
index ee97b62b0e..ac2de2a357 100644
--- a/libavfilter/vf_colorcorrect.c
+++ b/libavfilter/vf_colorcorrect.c
@@ -498,6 +498,8 @@ static av_cold void uninit(AVFilterContext *ctx)
ColorCorrectContext *s = ctx->priv;
av_freep(&s->analyzeret);
+ av_freep(&s->uhistogram);
+ av_freep(&s->vhistogram);
}
static const AVFilterPad colorcorrect_inputs[] = {
--
2.52.0
1
0
10 Sep '26
PR #24447 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24447
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24447.patch
Too many merge conflicts to attempt individual cherry-picks.
From 1a769dec777e07e4c41f21c810477f1f859100e9 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Thu, 10 Sep 2026 16:46:30 -0300
Subject: [PATCH] avformat/iamf: backport assorted fixes
Too many merge conflics to attempt individual cherry-picks.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavformat/iamf_parse.c | 5 +++++
libavformat/iamf_writer.c | 17 ++++++++++++-----
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c
index 12d348a705..892145cd87 100644
--- a/libavformat/iamf_parse.c
+++ b/libavformat/iamf_parse.c
@@ -1011,6 +1011,11 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
mix_presentation->cmix = mix;
mix_presentation->count_label = ffio_read_leb(pbc);
+ if (mix_presentation->count_label > len - avio_tell(pbc)) {
+ mix_presentation->count_label = 0;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
mix_presentation->language_label = av_calloc(mix_presentation->count_label,
sizeof(*mix_presentation->language_label));
if (!mix_presentation->language_label) {
diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
index ef7cecab27..0c43b64f83 100644
--- a/libavformat/iamf_writer.c
+++ b/libavformat/iamf_writer.c
@@ -100,12 +100,18 @@ static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)
}
static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
- IAMFCodecConfig *codec_config)
+ IAMFCodecConfig *codec_config, void *log_ctx)
{
const AVStream *st = stg->streams[0];
IAMFCodecConfig **tmp;
int j, ret = 0;
+ if (!st->codecpar->frame_size) {
+ av_log(log_ctx, AV_LOG_ERROR, "frame_size is unset for stream id %d\n",
+ st->id);
+ return AVERROR(EINVAL);
+ }
+
codec_config->codec_id = st->codecpar->codec_id;
codec_config->codec_tag = st->codecpar->codec_tag;
switch (codec_config->codec_id) {
@@ -308,7 +314,7 @@ int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void
if (!codec_config)
return AVERROR(ENOMEM);
- ret = fill_codec_config(iamf, stg, codec_config);
+ ret = fill_codec_config(iamf, stg, codec_config, log_ctx);
if (ret < 0) {
av_free(codec_config);
return ret;
@@ -1239,9 +1245,10 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
// IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
- skip_samples = pkt->dts < 0
- ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
- : 0;
+ if (!skip_samples)
+ skip_samples = pkt->dts < 0
+ ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
+ : 0;
discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
}
--
2.52.0
1
0
10 Sep '26
PR #24446 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24446
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24446.patch
Too many merge conflicts to attempt individual cherry-picks.
From 5df6c1e37b39842a2eaed168938fd7933b2202d1 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Thu, 10 Sep 2026 16:40:16 -0300
Subject: [PATCH] avformat/iamf: backport assorted fixes
Too many merge conflics to attempt individual cherry-picks.
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavformat/iamf_parse.c | 84 +++++++++++++++++++++++++++++++++++----
libavformat/iamf_reader.c | 32 +++++++++++++--
libavformat/iamf_writer.c | 27 ++++++++++---
3 files changed, 126 insertions(+), 17 deletions(-)
diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c
index 29b8acd351..87f13069e6 100644
--- a/libavformat/iamf_parse.c
+++ b/libavformat/iamf_parse.c
@@ -406,6 +406,7 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
int substream_count, coupled_substream_count;
int expanded_loudspeaker_layout = -1;
int ret, byte = avio_r8(pb);
+ int channels;
layer = av_iamf_audio_element_add_layer(audio_element->element);
if (!layer)
@@ -418,7 +419,8 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
substream_count = avio_r8(pb);
coupled_substream_count = avio_r8(pb);
- if (substream_count + k > audio_element->nb_substreams)
+ if (!substream_count || coupled_substream_count > substream_count ||
+ substream_count + k > audio_element->nb_substreams)
return AVERROR_INVALIDDATA;
audio_element->layers[i].substream_count = substream_count;
@@ -428,8 +430,14 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
layer->output_gain = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 8);
}
- if (!i && loudspeaker_layout == 15)
+ if (loudspeaker_layout == 15) {
+ if (i) {
+ av_log(s, AV_LOG_ERROR, "expanded_loudspeaker_layout set with more than one layer in Audio Element #%d\n",
+ audio_element->audio_element_id);
+ return AVERROR_INVALIDDATA;
+ }
expanded_loudspeaker_layout = avio_r8(pb);
+ }
if (expanded_loudspeaker_layout >= 0 && expanded_loudspeaker_layout < 13) {
av_channel_layout_copy(&ch_layout, &ff_iamf_expanded_scalable_ch_layouts[expanded_loudspeaker_layout]);
} else if (loudspeaker_layout < 10) {
@@ -451,7 +459,13 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
return AVERROR_PATCHWELCOME;
}
- if (i && ch_layout.nb_channels <= audio_element->element->layers[i-1]->ch_layout.nb_channels)
+ channels = ch_layout.nb_channels;
+ if (i) {
+ if (ch_layout.nb_channels <= audio_element->element->layers[i-1]->ch_layout.nb_channels)
+ return AVERROR_INVALIDDATA;
+ channels -= audio_element->element->layers[i-1]->ch_layout.nb_channels;
+ }
+ if (channels != substream_count + coupled_substream_count)
return AVERROR_INVALIDDATA;
for (int j = 0; j < substream_count; j++) {
@@ -489,6 +503,9 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
}
}
+ if (n != ch_layout.nb_channels)
+ return AVERROR_INVALIDDATA;
+
ret = av_channel_layout_retype(&layer->ch_layout, AV_CHANNEL_ORDER_NATIVE, 0);
if (ret < 0 && ret != AVERROR(ENOSYS))
return ret;
@@ -590,6 +607,7 @@ static int ambisonics_config(void *s, AVIOContext *pb,
static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
unsigned int type,
const IAMFAudioElement *audio_element,
+ const IAMFCodecConfig *codec_config,
AVIAMFParamDefinition **out_param_definition)
{
IAMFParamDefinition *param_definition = NULL;
@@ -612,17 +630,29 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
if (mode == 0) {
duration = ffio_read_leb(pb);
- if (!duration)
+ if (!duration || duration > av_rescale(codec_config->nb_samples,
+ codec_config->sample_rate, parameter_rate)) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
return AVERROR_INVALIDDATA;
+ }
constant_subblock_duration = ffio_read_leb(pb);
if (constant_subblock_duration == 0)
nb_subblocks = ffio_read_leb(pb);
else {
+ if (constant_subblock_duration > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ return AVERROR_INVALIDDATA;
+ }
nb_subblocks = duration / constant_subblock_duration;
total_duration = duration;
}
}
+ if (nb_subblocks > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id);
+ return AVERROR_INVALIDDATA;
+ }
+
param = av_iamf_param_definition_alloc(type, nb_subblocks, ¶m_size);
if (!param)
return AVERROR(ENOMEM);
@@ -633,6 +663,11 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
if (constant_subblock_duration == 0) {
subblock_duration = ffio_read_leb(pb);
+ if (subblock_duration > duration - total_duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
+ av_free(param);
+ return AVERROR_INVALIDDATA;
+ }
total_duration += subblock_duration;
} else if (i == nb_subblocks - 1)
subblock_duration = duration - i * constant_subblock_duration;
@@ -859,13 +894,17 @@ static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
ret = AVERROR_INVALIDDATA;
goto fail;
}
- ret = param_parse(s, c, pbc, type, audio_element, &element->demixing_info);
+ ret = param_parse(s, c, pbc, type,
+ audio_element, codec_config,
+ &element->demixing_info);
} else if (type == AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
if (element->recon_gain_info) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
- ret = param_parse(s, c, pbc, type, audio_element, &element->recon_gain_info);
+ ret = param_parse(s, c, pbc, type,
+ audio_element, codec_config,
+ &element->recon_gain_info);
} else {
unsigned param_definition_size = ffio_read_leb(pbc);
avio_skip(pbc, param_definition_size);
@@ -920,6 +959,7 @@ static int label_string(AVIOContext *pb, char **label)
static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
{
AVIAMFMixPresentation *mix;
+ const IAMFCodecConfig *codec_config = NULL;
IAMFMixPresentation **tmp, *mix_presentation = NULL;
FFIOContext b;
AVIOContext *pbc;
@@ -969,6 +1009,11 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
mix_presentation->cmix = mix;
mix_presentation->count_label = ffio_read_leb(pbc);
+ if (mix_presentation->count_label > len - avio_tell(pbc)) {
+ mix_presentation->count_label = 0;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
mix_presentation->language_label = av_calloc(mix_presentation->count_label,
sizeof(*mix_presentation->language_label));
if (!mix_presentation->language_label) {
@@ -995,6 +1040,12 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
}
nb_submixes = ffio_read_leb(pbc);
+ if (!nb_submixes) {
+ av_log(s, AV_LOG_ERROR, "Mix presentation %u has no submixes\n", mix_presentation_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
for (int i = 0; i < nb_submixes; i++) {
AVIAMFSubmix *sub_mix;
unsigned nb_elements, nb_layouts;
@@ -1006,9 +1057,17 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
}
nb_elements = ffio_read_leb(pbc);
+ if (!nb_elements) {
+ av_log(s, AV_LOG_ERROR, "Submix %d from Mix presentation %u has no audio elements\n",
+ i, mix_presentation_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
for (int j = 0; j < nb_elements; j++) {
AVIAMFSubmixElement *submix_element;
IAMFAudioElement *audio_element = NULL;
+ const IAMFCodecConfig *config = NULL;
unsigned int rendering_config_extension_size;
submix_element = av_iamf_submix_add_element(sub_mix);
@@ -1031,6 +1090,7 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
ret = AVERROR_INVALIDDATA;
goto fail;
}
+ config = ff_iamf_get_codec_config(c, audio_element->codec_config_id);
for (int k = 0; k < mix_presentation->count_label; k++) {
char *annotation = NULL;
@@ -1049,14 +1109,22 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
avio_skip(pbc, rendering_config_extension_size);
ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
- NULL,
+ audio_element, config,
&submix_element->element_mix_config);
if (ret < 0)
goto fail;
submix_element->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
+
+ if (!codec_config || (config->nb_samples >
+ av_rescale(codec_config->nb_samples,
+ codec_config->sample_rate,
+ config->sample_rate)))
+ codec_config = config;
}
- ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, NULL, &sub_mix->output_mix_config);
+ ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
+ NULL, codec_config,
+ &sub_mix->output_mix_config);
if (ret < 0)
goto fail;
sub_mix->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
diff --git a/libavformat/iamf_reader.c b/libavformat/iamf_reader.c
index 2098f264aa..eab49a8fc0 100644
--- a/libavformat/iamf_reader.c
+++ b/libavformat/iamf_reader.c
@@ -105,6 +105,7 @@ static int audio_frame_obu(AVFormatContext *s, const IAMFDemuxContext *c,
static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
AVIOContext *pbc, int len)
{
+ const IAMFAudioElement *audio_element;
const IAMFParamDefinition *param_definition;
const AVIAMFParamDefinition *param;
AVIAMFParamDefinition *out_param = NULL;
@@ -141,6 +142,7 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
goto fail;
}
+ audio_element = param_definition->audio_element;
param = param_definition->param;
if (!param_definition->mode) {
duration = ffio_read_leb(pb);
@@ -148,10 +150,23 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
ret = AVERROR_INVALIDDATA;
goto fail;
}
+ if (audio_element) {
+ const IAMFCodecConfig *codec_config = ff_iamf_get_codec_config(&c->iamf, audio_element->codec_config_id);
+ if (duration > av_rescale(codec_config->nb_samples, codec_config->sample_rate, param->parameter_rate)) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
constant_subblock_duration = ffio_read_leb(pb);
if (constant_subblock_duration == 0)
nb_subblocks = ffio_read_leb(pb);
else {
+ if (constant_subblock_duration > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
nb_subblocks = duration / constant_subblock_duration;
total_duration = duration;
}
@@ -161,6 +176,12 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
nb_subblocks = param->nb_subblocks;
}
+ if (nb_subblocks > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
out_param = av_iamf_param_definition_alloc(param->type, nb_subblocks, &out_param_size);
if (!out_param) {
ret = AVERROR(ENOMEM);
@@ -180,6 +201,11 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
if (!param_definition->mode && !constant_subblock_duration) {
subblock_duration = ffio_read_leb(pb);
+ if (duration - total_duration > subblock_duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
total_duration += subblock_duration;
} else if (i == nb_subblocks - 1)
subblock_duration = duration - i * constant_subblock_duration;
@@ -214,10 +240,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
AVIAMFReconGain *recon = subblock;
- const IAMFAudioElement *audio_element = param_definition->audio_element;
- const AVIAMFAudioElement *element = audio_element->celement;
+ const AVIAMFAudioElement *element;
- av_assert0(audio_element && element);
+ av_assert0(audio_element && audio_element->celement);
+ element = audio_element->celement;
for (int i = 0; i < element->nb_layers; i++) {
const AVIAMFLayer *layer = element->layers[i];
if (layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN) {
diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
index 4b2bd87004..dcd8dcfa19 100644
--- a/libavformat/iamf_writer.c
+++ b/libavformat/iamf_writer.c
@@ -100,12 +100,18 @@ static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)
}
static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
- IAMFCodecConfig *codec_config)
+ IAMFCodecConfig *codec_config, void *log_ctx)
{
const AVStream *st = stg->streams[0];
IAMFCodecConfig **tmp;
int j, ret = 0;
+ if (!st->codecpar->frame_size) {
+ av_log(log_ctx, AV_LOG_ERROR, "frame_size is unset for stream id %d\n",
+ st->id);
+ return AVERROR(EINVAL);
+ }
+
codec_config->codec_id = st->codecpar->codec_id;
codec_config->codec_tag = st->codecpar->codec_tag;
switch (codec_config->codec_id) {
@@ -308,7 +314,7 @@ int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void
if (!codec_config)
return AVERROR(ENOMEM);
- ret = fill_codec_config(iamf, stg, codec_config);
+ ret = fill_codec_config(iamf, stg, codec_config, log_ctx);
if (ret < 0) {
av_free(codec_config);
return ret;
@@ -733,8 +739,16 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
int layout = 0, expanded_layout = 0;
get_loudspeaker_layout(element->layers[0], &layout, &expanded_layout);
/* When the loudspeaker_layout = 15, the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
- if (layout == 15)
+ if (layout == 15) {
param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
+ /* expanded_loudspeaker_layout SHALL only be present when num_layers = 1 and loudspeaker_layout is set to 15 */
+ if (element->nb_layers > 1) {
+ av_log(log_ctx, AV_LOG_ERROR, "expanded_loudspeaker_layout present when using more than one layer in "
+ "Stream Group #%u\n",
+ audio_element->audio_element_id);
+ return AVERROR(EINVAL);
+ }
+ }
/* When the loudspeaker_layout of the (non-)scalable channel audio (i.e., num_layers = 1) is less than or equal to 3.1.2ch,
* (i.e., Mono, Stereo, or 3.1.2ch), the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
else if (element->nb_layers == 1 && (layout == 0 || layout == 1 || layout == 8))
@@ -1222,9 +1236,10 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
// IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
- skip_samples = pkt->dts < 0
- ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
- : 0;
+ if (!skip_samples)
+ skip_samples = pkt->dts < 0
+ ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
+ : 0;
discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
}
--
2.52.0
1
0
10 Sep '26
PR #24445 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24445
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24445.patch
Too many merge conflicts to attempt individual cherry-picks.
From 96f225f3474ca8012cf6d53a51455f98ccfac609 Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Sun, 14 Jun 2026 10:06:27 -0300
Subject: [PATCH 1/2] avformat/iamf_writer: reject muxing PCM streams
Supporting PCM streams requires API changes present in newer releases that
can't be backported, so don't create invalid files.
Signed-off-by: James Almer <jamrial(a)gmail.com>
(cherry picked from commit 1034b144ff73aeae201ecbf132b3ca89b321ec16)
---
libavformat/iamf_writer.c | 31 +------------------------------
1 file changed, 1 insertion(+), 30 deletions(-)
diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
index 163d7e1200..8617469aa7 100644
--- a/libavformat/iamf_writer.c
+++ b/libavformat/iamf_writer.c
@@ -89,12 +89,6 @@ static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)
codec_config->audio_roll_distance = -1;
break;
case AV_CODEC_ID_FLAC:
- case AV_CODEC_ID_PCM_S16BE:
- case AV_CODEC_ID_PCM_S24BE:
- case AV_CODEC_ID_PCM_S32BE:
- case AV_CODEC_ID_PCM_S16LE:
- case AV_CODEC_ID_PCM_S24LE:
- case AV_CODEC_ID_PCM_S32LE:
codec_config->audio_roll_distance = 0;
break;
default:
@@ -494,35 +488,12 @@ static int iamf_write_codec_config(const IAMFContext *iamf,
avio_write(dyn_bc, codec_config->extradata, codec_config->extradata_size);
break;
case AV_CODEC_ID_PCM_S16LE:
- avio_w8(dyn_bc, 1);
- avio_w8(dyn_bc, 16);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
case AV_CODEC_ID_PCM_S24LE:
- avio_w8(dyn_bc, 1);
- avio_w8(dyn_bc, 24);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
case AV_CODEC_ID_PCM_S32LE:
- avio_w8(dyn_bc, 1);
- avio_w8(dyn_bc, 32);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
case AV_CODEC_ID_PCM_S16BE:
- avio_w8(dyn_bc, 0);
- avio_w8(dyn_bc, 16);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
case AV_CODEC_ID_PCM_S24BE:
- avio_w8(dyn_bc, 0);
- avio_w8(dyn_bc, 24);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
case AV_CODEC_ID_PCM_S32BE:
- avio_w8(dyn_bc, 0);
- avio_w8(dyn_bc, 32);
- avio_wb32(dyn_bc, codec_config->sample_rate);
- break;
+ return AVERROR(ENOSYS);
default:
break;
}
--
2.52.0
From 17638a3a3cbd2e3f8098ee091669fa854453ef9e Mon Sep 17 00:00:00 2001
From: James Almer <jamrial(a)gmail.com>
Date: Thu, 10 Sep 2026 16:20:01 -0300
Subject: [PATCH 2/2] avformat/iamf: backport assorted fixes
Signed-off-by: James Almer <jamrial(a)gmail.com>
---
libavformat/iamf_parse.c | 166 +++++++++++++++--
libavformat/iamf_reader.c | 34 +++-
libavformat/iamf_writer.c | 167 ++++++++++++++----
libavformat/iamfdec.c | 2 +-
tests/ref/fate/iamf-5_1-copy | 2 +-
tests/ref/fate/iamf-5_1-demux | 2 +-
tests/ref/fate/iamf-5_1_4 | 6 +-
tests/ref/fate/iamf-7_1_4 | 6 +-
tests/ref/fate/mov-mp4-iamf-5_1_4 | 6 +-
tests/ref/fate/mov-mp4-iamf-7_1_4-video-first | 6 +-
tests/ref/fate/mov-mp4-iamf-7_1_4-video-last | 6 +-
11 files changed, 332 insertions(+), 71 deletions(-)
diff --git a/libavformat/iamf_parse.c b/libavformat/iamf_parse.c
index bab266e175..667124dd69 100644
--- a/libavformat/iamf_parse.c
+++ b/libavformat/iamf_parse.c
@@ -347,6 +347,37 @@ static int update_extradata(AVCodecParameters *codecpar)
return 0;
}
+static int parse_coupled_substream(AVChannelLayout *out, AVChannelLayout *in, int n)
+{
+ if (in->u.mask & AV_CH_LAYOUT_STEREO) {
+ out->u.map[n++].id = AV_CHAN_FRONT_LEFT;
+ out->u.map[n++].id = AV_CHAN_FRONT_RIGHT;
+ in->u.mask &= ~AV_CH_LAYOUT_STEREO;
+ } else if (in->u.mask & (AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)) {
+ out->u.map[n++].id = AV_CHAN_FRONT_LEFT_OF_CENTER;
+ out->u.map[n++].id = AV_CHAN_FRONT_RIGHT_OF_CENTER;
+ in->u.mask &= ~(AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER);
+ } else if (in->u.mask & (AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)) {
+ out->u.map[n++].id = AV_CHAN_SIDE_LEFT;
+ out->u.map[n++].id = AV_CHAN_SIDE_RIGHT;
+ in->u.mask &= ~(AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT);
+ } else if (in->u.mask & (AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)) {
+ out->u.map[n++].id = AV_CHAN_BACK_LEFT;
+ out->u.map[n++].id = AV_CHAN_BACK_RIGHT;
+ in->u.mask &= ~(AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT);
+ } else if (in->u.mask & (AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)) {
+ out->u.map[n++].id = AV_CHAN_TOP_FRONT_LEFT;
+ out->u.map[n++].id = AV_CHAN_TOP_FRONT_RIGHT;
+ in->u.mask &= ~(AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT);
+ } else if (in->u.mask & (AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT)) {
+ out->u.map[n++].id = AV_CHAN_TOP_BACK_LEFT;
+ out->u.map[n++].id = AV_CHAN_TOP_BACK_RIGHT;
+ in->u.mask &= ~(AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT);
+ }
+
+ return n;
+}
+
static int scalable_channel_layout_config(void *s, AVIOContext *pb,
IAMFAudioElement *audio_element,
const IAMFCodecConfig *codec_config)
@@ -364,11 +395,13 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
return AVERROR(ENOMEM);
audio_element->nb_layers = nb_layers;
- for (int i = 0; i < nb_layers; i++) {
+ for (int i = 0, n = 0; i < nb_layers; i++) {
+ AVChannelLayout ch_layout = { 0 };
AVIAMFLayer *layer;
int loudspeaker_layout, output_gain_is_present_flag;
int substream_count, coupled_substream_count;
int ret, byte = avio_r8(pb);
+ int channels;
layer = av_iamf_audio_element_add_layer(audio_element->element);
if (!layer)
@@ -381,7 +414,8 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
substream_count = avio_r8(pb);
coupled_substream_count = avio_r8(pb);
- if (substream_count + k > audio_element->nb_substreams)
+ if (!substream_count || coupled_substream_count > substream_count ||
+ substream_count + k > audio_element->nb_substreams)
return AVERROR_INVALIDDATA;
audio_element->layers[i].substream_count = substream_count;
@@ -391,14 +425,29 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
layer->output_gain = av_make_q(sign_extend(avio_rb16(pb), 16), 1 << 8);
}
- if (loudspeaker_layout < 10)
- av_channel_layout_copy(&layer->ch_layout, &ff_iamf_scalable_ch_layouts[loudspeaker_layout]);
- else
- layer->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_UNSPEC,
- .nb_channels = substream_count +
- coupled_substream_count };
+ if (loudspeaker_layout < 10) {
+ av_channel_layout_copy(&ch_layout, &ff_iamf_scalable_ch_layouts[loudspeaker_layout]);
+ if (i) {
+ uint64_t mask = av_channel_layout_subset(&audio_element->element->layers[i-1]->ch_layout, UINT64_MAX);
+ // When the first layer is Mono, the second layer may not have the C channel (e.g. Stereo)
+ if (audio_element->element->layers[i-1]->ch_layout.nb_channels == 1)
+ n--;
+ else if ((ch_layout.u.mask & mask) != mask)
+ return AVERROR_INVALIDDATA;
+ ch_layout.u.mask &= ~mask;
+ }
+ } else {
+ av_log(s, AV_LOG_ERROR, "Unsupported loudspeaker_layout %d\n", loudspeaker_layout);
+ return AVERROR(ENOSYS);
+ }
- if (i && layer->ch_layout.nb_channels <= audio_element->element->layers[i-1]->ch_layout.nb_channels)
+ channels = ch_layout.nb_channels;
+ if (i) {
+ if (ch_layout.nb_channels <= audio_element->element->layers[i-1]->ch_layout.nb_channels)
+ return AVERROR_INVALIDDATA;
+ channels -= audio_element->element->layers[i-1]->ch_layout.nb_channels;
+ }
+ if (channels != substream_count + coupled_substream_count)
return AVERROR_INVALIDDATA;
for (int j = 0; j < substream_count; j++) {
@@ -412,6 +461,36 @@ static int scalable_channel_layout_config(void *s, AVIOContext *pb,
return ret;
}
+ ret = av_channel_layout_custom_init(&layer->ch_layout, ch_layout.nb_channels);
+ if (ret < 0)
+ return ret;
+ for (int j = 0; j < n; j++)
+ layer->ch_layout.u.map[j].id = av_channel_layout_channel_from_index(&audio_element->element->layers[i-1]->ch_layout, j);
+
+ coupled_substream_count = audio_element->layers[i].coupled_substream_count;
+ while (coupled_substream_count--) {
+ n = parse_coupled_substream(&layer->ch_layout, &ch_layout, n);
+ }
+
+ substream_count -= audio_element->layers[i].coupled_substream_count;
+ n = parse_coupled_substream(&layer->ch_layout, &ch_layout, n); // In case the first layer is Mono
+ while (substream_count--) {
+ if (ch_layout.u.mask & AV_CH_FRONT_CENTER) {
+ layer->ch_layout.u.map[n++].id = AV_CHAN_FRONT_CENTER;
+ ch_layout.u.mask &= ~AV_CH_FRONT_CENTER;
+ }
+ if (ch_layout.u.mask & AV_CH_LOW_FREQUENCY) {
+ layer->ch_layout.u.map[n++].id = AV_CHAN_LOW_FREQUENCY;
+ ch_layout.u.mask &= ~AV_CH_LOW_FREQUENCY;
+ }
+ }
+
+ if (n != ch_layout.nb_channels)
+ return AVERROR_INVALIDDATA;
+
+ ret = av_channel_layout_retype(&layer->ch_layout, AV_CHANNEL_ORDER_NATIVE, 0);
+ if (ret < 0 && ret != AVERROR(ENOSYS))
+ return ret;
}
if (k != audio_element->nb_substreams)
@@ -474,6 +553,10 @@ static int ambisonics_config(void *s, AVIOContext *pb,
for (int i = 0; i < output_channel_count; i++)
layer->ch_layout.u.map[i].id = avio_r8(pb) + AV_CHAN_AMBISONIC_BASE;
+
+ ret = av_channel_layout_retype(&layer->ch_layout, AV_CHANNEL_ORDER_AMBISONIC, 0);
+ if (ret < 0 && ret != AVERROR(ENOSYS))
+ return ret;
} else {
int coupled_substream_count = avio_r8(pb); // M
int nb_demixing_matrix = substream_count + coupled_substream_count;
@@ -508,6 +591,7 @@ static int ambisonics_config(void *s, AVIOContext *pb,
static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
unsigned int type,
const IAMFAudioElement *audio_element,
+ const IAMFCodecConfig *codec_config,
AVIAMFParamDefinition **out_param_definition)
{
IAMFParamDefinition *param_definition = NULL;
@@ -530,17 +614,29 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
if (mode == 0) {
duration = ffio_read_leb(pb);
- if (!duration)
+ if (!duration || duration > av_rescale(codec_config->nb_samples,
+ codec_config->sample_rate, parameter_rate)) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
return AVERROR_INVALIDDATA;
+ }
constant_subblock_duration = ffio_read_leb(pb);
if (constant_subblock_duration == 0)
nb_subblocks = ffio_read_leb(pb);
else {
+ if (constant_subblock_duration > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ return AVERROR_INVALIDDATA;
+ }
nb_subblocks = duration / constant_subblock_duration;
total_duration = duration;
}
}
+ if (nb_subblocks > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id);
+ return AVERROR_INVALIDDATA;
+ }
+
param = av_iamf_param_definition_alloc(type, nb_subblocks, ¶m_size);
if (!param)
return AVERROR(ENOMEM);
@@ -551,6 +647,11 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
if (constant_subblock_duration == 0) {
subblock_duration = ffio_read_leb(pb);
+ if (subblock_duration > duration - total_duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
+ av_free(param);
+ return AVERROR_INVALIDDATA;
+ }
total_duration += subblock_duration;
} else if (i == nb_subblocks - 1)
subblock_duration = duration - i * constant_subblock_duration;
@@ -595,7 +696,7 @@ static int param_parse(void *s, IAMFContext *c, AVIOContext *pb,
if (param_definition) {
if (param_definition->param_size != param_size || memcmp(param_definition->param, param, param_size)) {
- av_log(s, AV_LOG_ERROR, "Incosistent parameters for parameter_id %u\n", parameter_id);
+ av_log(s, AV_LOG_ERROR, "Inconsistent parameters for parameter_id %u\n", parameter_id);
av_free(param);
return AVERROR_INVALIDDATA;
}
@@ -669,7 +770,7 @@ static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
codec_config = ff_iamf_get_codec_config(c, codec_config_id);
if (!codec_config) {
- av_log(s, AV_LOG_ERROR, "Non existant codec config id %d referenced in an audio element\n", codec_config_id);
+ av_log(s, AV_LOG_ERROR, "Non existent codec config id %d referenced in an audio element\n", codec_config_id);
ret = AVERROR_INVALIDDATA;
goto fail;
}
@@ -777,13 +878,17 @@ static int audio_element_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
ret = AVERROR_INVALIDDATA;
goto fail;
}
- ret = param_parse(s, c, pbc, type, audio_element, &element->demixing_info);
+ ret = param_parse(s, c, pbc, type,
+ audio_element, codec_config,
+ &element->demixing_info);
} else if (type == AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
if (element->recon_gain_info) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
- ret = param_parse(s, c, pbc, type, audio_element, &element->recon_gain_info);
+ ret = param_parse(s, c, pbc, type,
+ audio_element, codec_config,
+ &element->recon_gain_info);
} else {
unsigned param_definition_size = ffio_read_leb(pbc);
avio_skip(pbc, param_definition_size);
@@ -838,6 +943,7 @@ static int label_string(AVIOContext *pb, char **label)
static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int len)
{
AVIAMFMixPresentation *mix;
+ const IAMFCodecConfig *codec_config = NULL;
IAMFMixPresentation **tmp, *mix_presentation = NULL;
FFIOContext b;
AVIOContext *pbc;
@@ -887,6 +993,11 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
mix_presentation->cmix = mix;
mix_presentation->count_label = ffio_read_leb(pbc);
+ if (mix_presentation->count_label > len - avio_tell(pbc)) {
+ mix_presentation->count_label = 0;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
mix_presentation->language_label = av_calloc(mix_presentation->count_label,
sizeof(*mix_presentation->language_label));
if (!mix_presentation->language_label) {
@@ -913,6 +1024,12 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
}
nb_submixes = ffio_read_leb(pbc);
+ if (!nb_submixes) {
+ av_log(s, AV_LOG_ERROR, "Mix presentation %u has no submixes\n", mix_presentation_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
for (int i = 0; i < nb_submixes; i++) {
AVIAMFSubmix *sub_mix;
unsigned nb_elements, nb_layouts;
@@ -924,9 +1041,17 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
}
nb_elements = ffio_read_leb(pbc);
+ if (!nb_elements) {
+ av_log(s, AV_LOG_ERROR, "Submix %d from Mix presentation %u has no audio elements\n",
+ i, mix_presentation_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
for (int j = 0; j < nb_elements; j++) {
AVIAMFSubmixElement *submix_element;
IAMFAudioElement *audio_element = NULL;
+ const IAMFCodecConfig *config = NULL;
unsigned int rendering_config_extension_size;
submix_element = av_iamf_submix_add_element(sub_mix);
@@ -949,6 +1074,7 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
ret = AVERROR_INVALIDDATA;
goto fail;
}
+ config = ff_iamf_get_codec_config(c, audio_element->codec_config_id);
for (int k = 0; k < mix_presentation->count_label; k++) {
char *annotation = NULL;
@@ -967,14 +1093,22 @@ static int mix_presentation_obu(void *s, IAMFContext *c, AVIOContext *pb, int le
avio_skip(pbc, rendering_config_extension_size);
ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
- NULL,
+ audio_element, config,
&submix_element->element_mix_config);
if (ret < 0)
goto fail;
submix_element->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
+
+ if (!codec_config || (config->nb_samples >
+ av_rescale(codec_config->nb_samples,
+ codec_config->sample_rate,
+ config->sample_rate)))
+ codec_config = config;
}
- ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN, NULL, &sub_mix->output_mix_config);
+ ret = param_parse(s, c, pbc, AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN,
+ NULL, codec_config,
+ &sub_mix->output_mix_config);
if (ret < 0)
goto fail;
sub_mix->default_mix_gain = av_make_q(sign_extend(avio_rb16(pbc), 16), 1 << 8);
diff --git a/libavformat/iamf_reader.c b/libavformat/iamf_reader.c
index 9a8371d9e3..eab49a8fc0 100644
--- a/libavformat/iamf_reader.c
+++ b/libavformat/iamf_reader.c
@@ -105,6 +105,7 @@ static int audio_frame_obu(AVFormatContext *s, const IAMFDemuxContext *c,
static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
AVIOContext *pbc, int len)
{
+ const IAMFAudioElement *audio_element;
const IAMFParamDefinition *param_definition;
const AVIAMFParamDefinition *param;
AVIAMFParamDefinition *out_param = NULL;
@@ -135,12 +136,13 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
parameter_id = ffio_read_leb(pb);
param_definition = ff_iamf_get_param_definition(&c->iamf, parameter_id);
if (!param_definition) {
- av_log(s, AV_LOG_VERBOSE, "Non existant parameter_id %d referenced in a parameter block. Ignoring\n",
+ av_log(s, AV_LOG_VERBOSE, "Non existent parameter_id %d referenced in a parameter block. Ignoring\n",
parameter_id);
ret = 0;
goto fail;
}
+ audio_element = param_definition->audio_element;
param = param_definition->param;
if (!param_definition->mode) {
duration = ffio_read_leb(pb);
@@ -148,10 +150,23 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
ret = AVERROR_INVALIDDATA;
goto fail;
}
+ if (audio_element) {
+ const IAMFCodecConfig *codec_config = ff_iamf_get_codec_config(&c->iamf, audio_element->codec_config_id);
+ if (duration > av_rescale(codec_config->nb_samples, codec_config->sample_rate, param->parameter_rate)) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
constant_subblock_duration = ffio_read_leb(pb);
if (constant_subblock_duration == 0)
nb_subblocks = ffio_read_leb(pb);
else {
+ if (constant_subblock_duration > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid block duration in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
nb_subblocks = duration / constant_subblock_duration;
total_duration = duration;
}
@@ -161,6 +176,12 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
nb_subblocks = param->nb_subblocks;
}
+ if (nb_subblocks > duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid duration or subblock count in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
out_param = av_iamf_param_definition_alloc(param->type, nb_subblocks, &out_param_size);
if (!out_param) {
ret = AVERROR(ENOMEM);
@@ -180,6 +201,11 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
if (!param_definition->mode && !constant_subblock_duration) {
subblock_duration = ffio_read_leb(pb);
+ if (duration - total_duration > subblock_duration) {
+ av_log(s, AV_LOG_ERROR, "Invalid subblock durations in parameter_id %u\n", parameter_id);
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
total_duration += subblock_duration;
} else if (i == nb_subblocks - 1)
subblock_duration = duration - i * constant_subblock_duration;
@@ -214,10 +240,10 @@ static int parameter_block_obu(AVFormatContext *s, IAMFDemuxContext *c,
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
AVIAMFReconGain *recon = subblock;
- const IAMFAudioElement *audio_element = param_definition->audio_element;
- const AVIAMFAudioElement *element = audio_element->celement;
+ const AVIAMFAudioElement *element;
- av_assert0(audio_element && element);
+ av_assert0(audio_element && audio_element->celement);
+ element = audio_element->celement;
for (int i = 0; i < element->nb_layers; i++) {
const AVIAMFLayer *layer = element->layers[i];
if (layer->flags & AV_IAMF_LAYER_FLAG_RECON_GAIN) {
diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
index 8617469aa7..840c47330f 100644
--- a/libavformat/iamf_writer.c
+++ b/libavformat/iamf_writer.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/iamf.h"
@@ -99,12 +100,18 @@ static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)
}
static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
- IAMFCodecConfig *codec_config)
+ IAMFCodecConfig *codec_config, void *log_ctx)
{
const AVStream *st = stg->streams[0];
IAMFCodecConfig **tmp;
int j, ret = 0;
+ if (!st->codecpar->frame_size) {
+ av_log(log_ctx, AV_LOG_ERROR, "frame_size is unset for stream id %d\n",
+ st->id);
+ return AVERROR(EINVAL);
+ }
+
codec_config->codec_id = st->codecpar->codec_id;
codec_config->codec_tag = st->codecpar->codec_tag;
switch (codec_config->codec_id) {
@@ -234,7 +241,7 @@ int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void
return AVERROR(EINVAL);
}
if (layer->ambisonics_mode >= AV_IAMF_AMBISONICS_MODE_PROJECTION) {
- av_log(log_ctx, AV_LOG_ERROR, "Unsuported ambisonics mode %d\n", layer->ambisonics_mode);
+ av_log(log_ctx, AV_LOG_ERROR, "Unsupported ambisonics mode %d\n", layer->ambisonics_mode);
return AVERROR_PATCHWELCOME;
}
for (int i = 0; i < stg->nb_streams; i++) {
@@ -243,18 +250,53 @@ int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void
return AVERROR(EINVAL);
}
}
- } else
+ } else {
+ AVBPrint bp;
+
+ if (iamf_audio_element->nb_layers < 1) {
+ av_log(log_ctx, AV_LOG_ERROR, "Invalid amount of layers for CHANNEL_BASED audio element. Must be >= 1\n");
+ return AVERROR(EINVAL);
+ }
+
for (int j, i = 0; i < iamf_audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = iamf_audio_element->layers[i];
+ const AVIAMFLayer *prev_layer;
+ uint64_t prev_mask;
+
for (j = 0; j < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); j++)
- if (!av_channel_layout_compare(&layer->ch_layout, &ff_iamf_scalable_ch_layouts[j]))
+ if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
+ av_channel_layout_subset(&ff_iamf_scalable_ch_layouts[j], UINT64_MAX))
break;
if (j >= FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts)) {
- av_log(log_ctx, AV_LOG_ERROR, "Unsupported channel layout in stream group #%d\n", i);
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_channel_layout_describe_bprint(&layer->ch_layout, &bp);
+ av_log(log_ctx, AV_LOG_ERROR, "Unsupported channel layout in Audio Element id %"PRId64
+ ", Layer %d: %s\n",
+ stg->id, i, bp.str);
+ av_bprint_finalize(&bp, NULL);
+ return AVERROR(EINVAL);
+ }
+
+ if (!i)
+ continue;
+
+ prev_layer = iamf_audio_element->layers[i-1];
+ prev_mask = av_channel_layout_subset(&prev_layer->ch_layout, UINT64_MAX);
+ if (av_channel_layout_subset(&layer->ch_layout, prev_mask) != prev_mask || (layer->ch_layout.nb_channels <=
+ prev_layer->ch_layout.nb_channels)) {
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&bp, "Channel layout \"");
+ av_channel_layout_describe_bprint(&layer->ch_layout, &bp);
+ av_bprintf(&bp, "\" can't follow channel layout \"");
+ av_channel_layout_describe_bprint(&prev_layer->ch_layout, &bp);
+ av_bprintf(&bp, "\" in Scalable Audio Element id %"PRId64, stg->id);
+ av_log(log_ctx, AV_LOG_ERROR, "%s\n", bp.str);
+ av_bprint_finalize(&bp, NULL);
return AVERROR(EINVAL);
}
}
+ }
for (int i = 0; i < iamf->nb_audio_elements; i++) {
if (stg->id == iamf->audio_elements[i]->audio_element_id) {
@@ -267,7 +309,7 @@ int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void
if (!codec_config)
return AVERROR(ENOMEM);
- ret = fill_codec_config(iamf, stg, codec_config);
+ ret = fill_codec_config(iamf, stg, codec_config, log_ctx);
if (ret < 0) {
av_free(codec_config);
return ret;
@@ -517,6 +559,25 @@ static inline int rescale_rational(AVRational q, int b)
return av_clip_int16(av_rescale(q.num, b, q.den));
}
+static void get_loudspeaker_layout(const AVIAMFLayer *layer, int *playout)
+{
+ int layout;
+
+ for (layout = 0; layout < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); layout++) {
+ if (!av_channel_layout_compare(&layer->ch_layout, &ff_iamf_scalable_ch_layouts[layout]))
+ break;
+ }
+ if (layout >= FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts)) {
+ for (layout = 0; layout < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); layout++)
+ if (av_channel_layout_subset(&layer->ch_layout, UINT64_MAX) ==
+ av_channel_layout_subset(&ff_iamf_scalable_ch_layouts[layout], UINT64_MAX))
+ break;
+ }
+ av_assert0(layout < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts));
+
+ *playout = layout;
+}
+
static int scalable_channel_layout_config(const IAMFAudioElement *audio_element,
AVIOContext *dyn_bc)
{
@@ -532,10 +593,8 @@ static int scalable_channel_layout_config(const IAMFAudioElement *audio_element,
for (int i = 0; i < element->nb_layers; i++) {
const AVIAMFLayer *layer = element->layers[i];
int layout;
- for (layout = 0; layout < FF_ARRAY_ELEMS(ff_iamf_scalable_ch_layouts); layout++) {
- if (!av_channel_layout_compare(&layer->ch_layout, &ff_iamf_scalable_ch_layouts[layout]))
- break;
- }
+
+ get_loudspeaker_layout(layer, &layout);
init_put_bits(&pb, header, sizeof(header));
put_bits(&pb, 4, layout);
put_bits(&pb, 1, !!layer->output_gain_flags);
@@ -650,27 +709,56 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
for (int i = 0; i < audio_element->nb_substreams; i++)
ffio_write_leb(dyn_bc, audio_element->substreams[i].audio_substream_id);
- if (element->nb_layers == 1)
- param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
- if (element->nb_layers > 1)
- param_definition_types |= AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
- if (codec_config->codec_tag == MKTAG('f','L','a','C') ||
- codec_config->codec_tag == MKTAG('i','p','c','m'))
- param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
+ /* When audio_element_type = 1, num_parameters SHALL be set to 0 */
+ if (element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
+ param_definition_types = 0;
+ else {
+ int layout = 0;
+ get_loudspeaker_layout(element->layers[0], &layout);
+ /* When the loudspeaker_layout = 15, the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
+ if (layout == 15) {
+ param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
+ /* expanded_loudspeaker_layout SHALL only be present when num_layers = 1 and loudspeaker_layout is set to 15 */
+ if (element->nb_layers > 1) {
+ av_log(log_ctx, AV_LOG_ERROR, "expanded_loudspeaker_layout present when using more than one layer in "
+ "Stream Group #%u\n",
+ audio_element->audio_element_id);
+ return AVERROR(EINVAL);
+ }
+ }
+ /* When the loudspeaker_layout of the (non-)scalable channel audio (i.e., num_layers = 1) is less than or equal to 3.1.2ch,
+ * (i.e., Mono, Stereo, or 3.1.2ch), the type PARAMETER_DEFINITION_DEMIXING SHALL NOT be present. */
+ else if (element->nb_layers == 1 && (layout == 0 || layout == 1 || layout == 8))
+ param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
+ /* When num_layers > 1, the type PARAMETER_DEFINITION_RECON_GAIN SHALL be present */
+ if (element->nb_layers > 1)
+ param_definition_types |= AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
+ /* When codec_id = fLaC or ipcm, the type PARAMETER_DEFINITION_RECON_GAIN SHALL NOT be present. */
+ if (codec_config->codec_tag == MKTAG('f','L','a','C') ||
+ codec_config->codec_tag == MKTAG('i','p','c','m'))
+ param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN;
+ if ((param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) && !element->demixing_info) {
+ if (element->nb_layers > 1) {
+ get_loudspeaker_layout(element->layers[element->nb_layers-1], &layout);
+ /* When the highest loudspeaker_layout of the scalable channel audio (i.e., num_layers > 1) is greater than 3.1.2ch,
+ * (i.e., 5.1.2ch, 5.1.4ch, 7.1.2ch, or 7.1.4ch), type PARAMETER_DEFINITION_DEMIXING SHALL be present. */
+ if (layout == 3 || layout == 4 || layout == 6 || layout == 7) {
+ av_log(log_ctx, AV_LOG_ERROR, "demixing_info needed but not set in Stream Group #%u\n",
+ audio_element->audio_element_id);
+ return AVERROR(EINVAL);
+ }
+ }
+ param_definition_types &= ~AV_IAMF_PARAMETER_DEFINITION_DEMIXING;
+ }
+ }
ffio_write_leb(dyn_bc, av_popcount(param_definition_types)); // num_parameters
- if (param_definition_types & 1) {
+ if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_DEMIXING) {
const AVIAMFParamDefinition *param = element->demixing_info;
const IAMFParamDefinition *param_def;
const AVIAMFDemixingInfo *demix;
- if (!param) {
- av_log(log_ctx, AV_LOG_ERROR, "demixing_info needed but not set in Stream Group #%u\n",
- audio_element->audio_element_id);
- return AVERROR(EINVAL);
- }
-
demix = av_iamf_param_definition_get_subblock(param, 0);
ffio_write_leb(dyn_bc, AV_IAMF_PARAMETER_DEFINITION_DEMIXING); // type
@@ -682,7 +770,7 @@ static int iamf_write_audio_element(const IAMFContext *iamf,
avio_w8(dyn_bc, demix->dmixp_mode << 5); // dmixp_mode
avio_w8(dyn_bc, element->default_w << 4); // default_w
}
- if (param_definition_types & 2) {
+ if (param_definition_types & AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN) {
const AVIAMFParamDefinition *param = element->recon_gain_info;
const IAMFParamDefinition *param_def;
@@ -813,6 +901,9 @@ static int iamf_write_mixing_presentation(const IAMFContext *iamf,
av_log(log_ctx, AV_LOG_ERROR, "Invalid Sound System value in a submix\n");
return AVERROR(EINVAL);
}
+ } else if (submix_layout->layout_type != AV_IAMF_SUBMIX_LAYOUT_TYPE_BINAURAL) {
+ av_log(log_ctx, AV_LOG_ERROR, "Unsupported Layout Type value in a submix\n");
+ return AVERROR(EINVAL);
}
init_put_bits(&pbc, header, sizeof(header));
put_bits(&pbc, 2, submix_layout->layout_type); // layout_type
@@ -1072,6 +1163,8 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
{
uint8_t header[MAX_IAMF_OBU_HEADER_SIZE];
PutBitContext pbc;
+ const IAMFAudioElement *audio_element;
+ IAMFCodecConfig *codec_config;
AVIOContext *dyn_bc;
const uint8_t *side_data;
uint8_t *dyn_buf = NULL;
@@ -1081,9 +1174,14 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
audio_substream_id + IAMF_OBU_IA_AUDIO_FRAME_ID0 : IAMF_OBU_IA_AUDIO_FRAME;
int ret;
+ audio_element = get_audio_element(iamf, audio_substream_id);
+ if (!audio_element)
+ return AVERROR(EINVAL);
+ codec_config = ff_iamf_get_codec_config(iamf, audio_element->codec_config_id);
+ if (!codec_config)
+ return AVERROR(EINVAL);
+
if (!pkt->size) {
- const IAMFAudioElement *audio_element;
- IAMFCodecConfig *codec_config;
size_t new_extradata_size;
const uint8_t *new_extradata = av_packet_get_side_data(pkt,
AV_PKT_DATA_NEW_EXTRADATA,
@@ -1091,12 +1189,6 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
if (!new_extradata || new_extradata_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
return AVERROR_INVALIDDATA;
- audio_element = get_audio_element(iamf, audio_substream_id);
- if (!audio_element)
- return AVERROR(EINVAL);
- codec_config = ff_iamf_get_codec_config(iamf, audio_element->codec_config_id);
- if (!codec_config)
- return AVERROR(EINVAL);
av_free(codec_config->extradata);
codec_config->extradata = av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
@@ -1119,6 +1211,15 @@ int ff_iamf_write_audio_frame(const IAMFContext *iamf, AVIOContext *pb,
discard_padding = AV_RL32(side_data + 4);
}
+ if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
+ // IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
+ if (!skip_samples)
+ skip_samples = pkt->dts < 0
+ ? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
+ : 0;
+ discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
+ }
+
ret = avio_open_dyn_buf(&dyn_bc);
if (ret < 0)
return ret;
diff --git a/libavformat/iamfdec.c b/libavformat/iamfdec.c
index 8feb06d9e6..02f01abc6c 100644
--- a/libavformat/iamfdec.c
+++ b/libavformat/iamfdec.c
@@ -109,7 +109,7 @@ static int iamf_read_header(AVFormatContext *s)
if (!i && !j && audio_element->layers[0].substream_count == 1)
st->disposition |= AV_DISPOSITION_DEFAULT;
- else
+ else if (audio_element->nb_layers > 1 || audio_element->layers[0].substream_count > 1)
st->disposition |= AV_DISPOSITION_DEPENDENT;
st->id = substream->audio_substream_id;
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
diff --git a/tests/ref/fate/iamf-5_1-copy b/tests/ref/fate/iamf-5_1-copy
index ed2046fe3b..62b77d8774 100644
--- a/tests/ref/fate/iamf-5_1-copy
+++ b/tests/ref/fate/iamf-5_1-copy
@@ -37,7 +37,7 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1
+channel_layout=6 channels (FL+FR+BL+BR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/iamf-5_1-demux b/tests/ref/fate/iamf-5_1-demux
index ed2046fe3b..62b77d8774 100644
--- a/tests/ref/fate/iamf-5_1-demux
+++ b/tests/ref/fate/iamf-5_1-demux
@@ -37,7 +37,7 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1
+channel_layout=6 channels (FL+FR+BL+BR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/iamf-5_1_4 b/tests/ref/fate/iamf-5_1_4
index fdee50b8e0..bb4a2d7a01 100644
--- a/tests/ref/fate/iamf-5_1_4
+++ b/tests/ref/fate/iamf-5_1_4
@@ -111,17 +111,17 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1
+channel_layout=6 channels (FL+FR+BL+BR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1.2
+channel_layout=8 channels (FL+FR+BL+BR+FC+LFE+TFL+TFR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1.4
+channel_layout=10 channels (FL+FR+BL+BR+FC+LFE+TFL+TFR+TBL+TBR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/iamf-7_1_4 b/tests/ref/fate/iamf-7_1_4
index ccce96ea84..4259e40135 100644
--- a/tests/ref/fate/iamf-7_1_4
+++ b/tests/ref/fate/iamf-7_1_4
@@ -127,17 +127,17 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=3.1.2
+channel_layout=6 channels (FL+FR+TFL+TFR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.2
+channel_layout=10 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.4
+channel_layout=12 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR+TBL+TBR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/mov-mp4-iamf-5_1_4 b/tests/ref/fate/mov-mp4-iamf-5_1_4
index 36106528ab..1890b408be 100644
--- a/tests/ref/fate/mov-mp4-iamf-5_1_4
+++ b/tests/ref/fate/mov-mp4-iamf-5_1_4
@@ -111,17 +111,17 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1
+channel_layout=6 channels (FL+FR+BL+BR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1.2
+channel_layout=8 channels (FL+FR+BL+BR+FC+LFE+TFL+TFR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=5.1.4
+channel_layout=10 channels (FL+FR+BL+BR+FC+LFE+TFL+TFR+TBL+TBR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/mov-mp4-iamf-7_1_4-video-first b/tests/ref/fate/mov-mp4-iamf-7_1_4-video-first
index d3b37896b2..d5a1fe1cad 100644
--- a/tests/ref/fate/mov-mp4-iamf-7_1_4-video-first
+++ b/tests/ref/fate/mov-mp4-iamf-7_1_4-video-first
@@ -158,17 +158,17 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=3.1.2
+channel_layout=6 channels (FL+FR+TFL+TFR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.2
+channel_layout=10 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.4
+channel_layout=12 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR+TBL+TBR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
diff --git a/tests/ref/fate/mov-mp4-iamf-7_1_4-video-last b/tests/ref/fate/mov-mp4-iamf-7_1_4-video-last
index ede4a40025..caf89d41f6 100644
--- a/tests/ref/fate/mov-mp4-iamf-7_1_4-video-last
+++ b/tests/ref/fate/mov-mp4-iamf-7_1_4-video-last
@@ -158,17 +158,17 @@ output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=3.1.2
+channel_layout=6 channels (FL+FR+TFL+TFR+FC+LFE)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.2
+channel_layout=10 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
[SUBCOMPONENT]
-channel_layout=7.1.4
+channel_layout=12 channels (FL+FR+TFL+TFR+FC+LFE+SL+SR+BL+BR+TBL+TBR)
output_gain_flags=0
output_gain=0/1
[/SUBCOMPONENT]
--
2.52.0
1
0