Commit caa5824750 for ffmpeg
commit caa5824750c6571cb13979be8ef183a3e2f2ea0b
Author: Niklas Haas <git@haasn.dev>
Date: Wed Sep 30 14:37:55 2026 +0200
avformat: add AV_STREAM_GROUP_PARAMS_GAIN_MAP
To identify ISO 21496-1 gain maps.
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/doc/APIchanges b/doc/APIchanges
index f0cfa8ac23..a4b11e2efc 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2026-06-23.
API changes, most recent first:
+2026-08-xx - xxxxxxxxxx - lavf 63.7.100 - avformat.h
+ Add AV_STREAM_GROUP_PARAMS_GAIN_MAP.
+
2026-09-30 - xxxxxxxxxx - lavu 61.10.100 - frame.h gain_map.h
Add AV_FRAME_DATA_GAIN_MAP_PARAMS.
Add AV_ISO21496_VERSION, AV_ISO21496_IDENTIFIER.
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 221d9dae0a..5d2eb4d1e3 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1226,6 +1226,19 @@ that specifies the language for the "value" string. "key" must be the same as th
all sub-mix element's @var{annotations}s
@end table
+@item gain_map
+Groups together a base @var{stream} with a gain map, which together form a
+pair of renditions (e.g. HDR and SDR) as per ISO 21496-1.
+
+For this group @var{type}, the following options are available
+
+@table @option
+@item el_index
+Index of the gain map stream within the group. Defaults to 0.
+@item video_size
+Size of the final image for presentation.
+@end table
+
@end table
E.g. to create an scalable 5.1 IAMF file from several WAV input files
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index a01a6b756e..48ff8bc7e5 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -2610,6 +2610,7 @@ static int of_map_group(Muxer *mux, AVDictionary **dict, AVBPrint *bp, const cha
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_TREF:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
break;
default:
av_log(mux, AV_LOG_ERROR, "Unsupported mapped group type %d.\n", stg->type);
@@ -2637,6 +2638,8 @@ static int of_parse_group_token(Muxer *mux, const char *token, char *ptr)
{ .i64 = AV_STREAM_GROUP_PARAMS_LCEVC }, .unit = "type" },
{ "tref", NULL, 0, AV_OPT_TYPE_CONST,
{ .i64 = AV_STREAM_GROUP_PARAMS_TREF }, .unit = "type" },
+ { "gain_map", NULL, 0, AV_OPT_TYPE_CONST,
+ { .i64 = AV_STREAM_GROUP_PARAMS_GAIN_MAP }, .unit = "type" },
{ NULL },
};
const AVClass class = {
diff --git a/libavformat/avformat.c b/libavformat/avformat.c
index 5d9d8c3697..d0cda8f3b4 100644
--- a/libavformat/avformat.c
+++ b/libavformat/avformat.c
@@ -109,6 +109,7 @@ void ff_free_stream_group(AVStreamGroup **pstg)
break;
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
av_opt_free(stg->params.layered_video);
av_freep(&stg->params.layered_video);
break;
@@ -275,6 +276,7 @@ const char *avformat_stream_group_name(enum AVStreamGroupParamsType type)
case AV_STREAM_GROUP_PARAMS_LCEVC: return "LCEVC (Split video and enhancement)";
case AV_STREAM_GROUP_PARAMS_TREF: return "Track Reference";
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION: return "Dolby Vision (Split base and enhancement layer)";
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP: return "Gain Map (Split base rendition and gain map)";
}
return NULL;
}
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 792f45c60c..d8c1478b5f 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -1089,8 +1089,9 @@ typedef struct AVStreamGroupTileGrid {
* AVStreamGroupLayeredVideo is meant to define the relation between a base
* layer video stream and a separate enhancement layer stream that together
* form a single layered video presentation (for example a video stream and a
- * data stream containing LCEVC enhancement layer NALUs, or Dolby Vision
- * Profile 7 dual-layer encoding).
+ * data stream containing LCEVC enhancement layer NALUs, Dolby Vision
+ * Profile 7 dual-layer encoding, or a base rendition accompanied by an
+ * ISO 21496-1 gain map).
*
* The enhancement layer stream is identified by @ref el_index.
*/
@@ -1155,6 +1156,7 @@ enum AVStreamGroupParamsType {
AV_STREAM_GROUP_PARAMS_LCEVC,
AV_STREAM_GROUP_PARAMS_TREF,
AV_STREAM_GROUP_PARAMS_DOLBY_VISION,
+ AV_STREAM_GROUP_PARAMS_GAIN_MAP,
};
struct AVIAMFAudioElement;
diff --git a/libavformat/options.c b/libavformat/options.c
index 54dafdf5bf..042fe494cf 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -403,6 +403,7 @@ static void *stream_group_child_next(void *obj, void *prev)
return stg->params.tref;
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
return stg->params.layered_video;
default:
break;
@@ -436,6 +437,7 @@ static const AVClass *stream_group_child_iterate(void **opaque)
break;
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
ret = &layered_video_class;
break;
default:
@@ -516,6 +518,7 @@ AVStreamGroup *avformat_stream_group_create(AVFormatContext *s,
break;
case AV_STREAM_GROUP_PARAMS_LCEVC:
case AV_STREAM_GROUP_PARAMS_DOLBY_VISION:
+ case AV_STREAM_GROUP_PARAMS_GAIN_MAP:
stg->params.layered_video = av_mallocz(sizeof(*stg->params.layered_video));
if (!stg->params.layered_video)
goto fail;
diff --git a/libavformat/version.h b/libavformat/version.h
index 7db373e8dd..70c554c19c 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,7 +32,7 @@
#include "version_major.h"
#define LIBAVFORMAT_VERSION_MINOR 7
-#define LIBAVFORMAT_VERSION_MICRO 101
+#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \