This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit b917a0fe1e36cedef3d9d8a14f00853f84c92bd0 Author: Niklas Haas <[email protected]> AuthorDate: Wed Sep 30 14:37:26 2026 +0200 Commit: Niklas Haas <[email protected]> CommitDate: Wed Sep 30 14:37:26 2026 +0200 avutil/gain_map: add AVGainMapParams and side data type This commit just adds the public facing struct definitions and side data. The struct follows ISO 21496-1 exactly, with a validation function to check for representable and legal values. Signed-off-by: Niklas Haas <[email protected]> --- doc/APIchanges | 7 +++ libavutil/Makefile | 2 + libavutil/frame.h | 7 +++ libavutil/gain_map.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++ libavutil/gain_map.h | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ libavutil/side_data.c | 1 + libavutil/version.h | 2 +- 7 files changed, 243 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index a653e4e945..f0cfa8ac23 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,13 @@ The last version increases of all libraries were on 2026-06-23. API changes, most recent first: +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. + Add AVGainMapParams. + Add av_gain_map_params_validate(), av_gain_map_channels_identical(). + Add av_gain_map_params_alloc(), av_gain_map_params_create_side_data(). + 2026-09-27 - xxxxxxxxxx - lavc 63.15.100 - defs.h Add AV_PROFILE_MPEGH_3DA_MAIN, AV_PROFILE_MPEGH_3DA_HIGH AV_PROFILE_MPEGH_3DA_LC, AV_PROFILE_MPEGH_3DA_BL. diff --git a/libavutil/Makefile b/libavutil/Makefile index d12030688f..6e6246cb97 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -37,6 +37,7 @@ HEADERS = adler32.h \ file.h \ film_grain_params.h \ frame.h \ + gain_map.h \ hash.h \ hdr_dynamic_metadata.h \ hdr_dynamic_vivid_metadata.h \ @@ -146,6 +147,7 @@ OBJS = adler32.o \ film_grain_params.o \ fixed_dsp.o \ frame.o \ + gain_map.o \ hash.o \ hdr_dynamic_metadata.o \ hdr_dynamic_vivid_metadata.o \ diff --git a/libavutil/frame.h b/libavutil/frame.h index e8cc765e5d..1fd296aa83 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -305,6 +305,13 @@ enum AVFrameSideDataType { * The data is the AVDownmixMatrix struct defined in libavutil/downmix_info.h. */ AV_FRAME_DATA_DOWNMIX_MATRIX, + + /** + * Parameters describing how to combine this gain map with its base image + * to form an alternate rendition. The payload is the AVGainMapParams + * struct defined in libavutil/gain_map.h. + */ + AV_FRAME_DATA_GAIN_MAP_PARAMS, }; enum AVActiveFormatDescription { diff --git a/libavutil/gain_map.c b/libavutil/gain_map.c new file mode 100644 index 0000000000..83c5bd31cf --- /dev/null +++ b/libavutil/gain_map.c @@ -0,0 +1,110 @@ +/* + * 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 + */ + +#include "gain_map.h" +#include "mem.h" + +static void gain_map_params_default(AVGainMapParams *p) +{ + *p = (AVGainMapParams) { + .base_hdr_headroom = { 0, 1 }, + .alternate_hdr_headroom = { 0, 1 }, + .nb_channels = 1, + }; + + /* Pre-fill all three channels as a convenience */ + for (int c = 0; c < 3; c++) { + p->channels[c] = (struct AVGainMapChannel) { + .gain_map_min = { 0, 1 }, + .gain_map_max = { 0, 1 }, + .gamma = { 1, 1 }, + .base_offset = { 1, 64 }, + .alternate_offset = { 1, 64 }, + }; + } +} + +#define CHECK(cond) do { if (!(cond)) return AVERROR_INVALIDDATA; } while (0) +#define CHECK_SIGNED(q) CHECK((q).den > 0); +#define CHECK_UNSIGNED(q) CHECK((q).num >= 0 && (q).den > 0); + +int av_gain_map_params_validate(const AVGainMapParams *p) +{ + CHECK(0 <= p->version && p->version <= AV_ISO21496_VERSION); + CHECK(p->nb_channels == 1 || p->nb_channels == 3); + CHECK_UNSIGNED(p->base_hdr_headroom); + CHECK_UNSIGNED(p->alternate_hdr_headroom); + + for (int c = 0; c < p->nb_channels; c++) { + const struct AVGainMapChannel *const ch = &p->channels[c]; + CHECK_SIGNED(ch->gain_map_min); + CHECK_SIGNED(ch->gain_map_max); + CHECK_UNSIGNED(ch->gamma); + CHECK(ch->gamma.num != 0); + /** + * Note: The ISO spec declares these as signed, but a negative value + * makes no numeric sense and would result in infinities in the + * middle of the valid signal range; so just constrain them to be + * unsigned as a safeguard. Note that the Adobe hdrgm spec explicitly + * requires them to be nonnegative as well, so this avoids an + * inconsistency. + */ + CHECK_UNSIGNED(ch->base_offset); + CHECK_UNSIGNED(ch->alternate_offset); + CHECK(av_cmp_q(ch->gain_map_min, ch->gain_map_max) <= 0); + } + + return 0; +} + +int av_gain_map_channels_identical(const AVGainMapParams *p) +{ + static_assert(sizeof(p->channels[0]) == sizeof(int[2]) * 5, + "AVGainMapChannel struct is tightly packed"); + + return !memcmp(&p->channels[0], &p->channels[1], sizeof(p->channels[0])) && + !memcmp(&p->channels[0], &p->channels[2], sizeof(p->channels[0])); +} + +AVGainMapParams *av_gain_map_params_alloc(size_t *size) +{ + AVGainMapParams *p = av_malloc(sizeof(AVGainMapParams)); + if (!p) + return NULL; + + gain_map_params_default(p); + + if (size) + *size = sizeof(*p); + + return p; +} + +AVGainMapParams *av_gain_map_params_create_side_data(AVFrameSideData ***fsd, int *nb_sd) +{ + AVFrameSideData *sd; + sd = av_frame_side_data_new(fsd, nb_sd, AV_FRAME_DATA_GAIN_MAP_PARAMS, + sizeof(AVGainMapParams), + AV_FRAME_SIDE_DATA_FLAG_REPLACE); + if (!sd) + return NULL; + + AVGainMapParams *const p = (AVGainMapParams *) sd->data; + gain_map_params_default(p); + return p; +} diff --git a/libavutil/gain_map.h b/libavutil/gain_map.h new file mode 100644 index 0000000000..7d922d7b40 --- /dev/null +++ b/libavutil/gain_map.h @@ -0,0 +1,115 @@ +/* + * 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 AVUTIL_GAIN_MAP_H +#define AVUTIL_GAIN_MAP_H + +#include <stddef.h> + +#include "rational.h" +#include "frame.h" + +#define AV_ISO21496_VERSION 0 +#define AV_ISO21496_IDENTIFIER "urn:iso:std:iso:ts:21496:-1" + +/** + * Parameters describing how to combine a gain map rendition with its base + * rendition to recover the alternate rendition, as defined by + * ISO 21496-1:2025 "Digital photography - Gain map metadata for image + * conversion". + * + * Note: sizeof(AVGainMapParams) is not part of the ABI. New fields may be + * added at the end of the struct. + */ +typedef struct AVGainMapParams { + /** + * The version of this gain map struct. Reserved to allow future + * extensions of the struct. Must be <= AV_ISO21496_VERSION. + */ + int version; + + /** + * If non-zero, the gain map is applied in the colour space of the base + * rendition; otherwise in that of the alternate rendition. + */ + int use_base_color_space; + + /** + * log2 of the display headroom at which the base rendition is shown + * unmodified, and at which the map is applied in full. + */ + AVRational base_hdr_headroom; + AVRational alternate_hdr_headroom; + + struct AVGainMapChannel { + /** + * log2-domain minimum and maximum gain applied by the map, i.e. the + * values the map's 0.0 and 1.0 endpoints decode to. + */ + AVRational gain_map_min; + AVRational gain_map_max; + + /** + * Encoding gamma of the stored map values. Must be > 0. + */ + AVRational gamma; + + /** + * Small constants added before the log-domain math to avoid a + * singularity at zero. + */ + AVRational base_offset; + AVRational alternate_offset; + } channels[3]; /* R, G, B */ + + /** + * Must be 1 or 3. If 1, all channels share the same set of parameters. + */ + int nb_channels; +} AVGainMapParams; + +/** + * Returns >= 0 if the given AVGainMapParams struct contains valid data; + * or a negative AVERROR otherwise. + */ +int av_gain_map_params_validate(const AVGainMapParams *p); + +/** + * Returns 1 if all channels of the gain map have identical parameters, + * 0 otherwise. + */ +int av_gain_map_channels_identical(const AVGainMapParams *p); + +/** + * Allocate an AVGainMapParams structure and initialize it to default values. + * The resulting pointer must be freed using av_free(). + * + * @param size if non-NULL, set to sizeof(AVGainMapParams) + * @return the newly allocated struct, or NULL on failure + */ +AVGainMapParams *av_gain_map_params_alloc(size_t *size); + +/** + * Allocate and add an AVGainMapParams structure to an existing AVFrameSideData + * array as AV_FRAME_DATA_GAIN_MAP_PARAMS side data. + * + * @return the newly allocated struct, or NULL on failure + */ +AVGainMapParams *av_gain_map_params_create_side_data(AVFrameSideData ***sd, int *nb_sd); + +#endif /* AVUTIL_GAIN_MAP_H */ diff --git a/libavutil/side_data.c b/libavutil/side_data.c index 0b4869c941..0d0289a9b6 100644 --- a/libavutil/side_data.c +++ b/libavutil/side_data.c @@ -63,6 +63,7 @@ static const AVSideDataDescriptor sd_props[] = { [AV_FRAME_DATA_IAMF_RECON_GAIN_INFO_PARAM] = { "IAMF Recon Gain Info Parameter Data" }, [AV_FRAME_DATA_RAW_COLOR_PARAMS] = { "RAW camera color parameters", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT }, [AV_FRAME_DATA_DOWNMIX_MATRIX] = { "Downmix Matrix", AV_SIDE_DATA_PROP_CHANNEL_DEPENDENT }, + [AV_FRAME_DATA_GAIN_MAP_PARAMS] = { "Gain map parameters", AV_SIDE_DATA_PROP_GLOBAL | AV_SIDE_DATA_PROP_COLOR_DEPENDENT }, }; const AVSideDataDescriptor *av_frame_side_data_desc(enum AVFrameSideDataType type) diff --git a/libavutil/version.h b/libavutil/version.h index 1145f23acd..1a2406e75e 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 61 -#define LIBAVUTIL_VERSION_MINOR 9 +#define LIBAVUTIL_VERSION_MINOR 10 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
