This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 1b4ca126d814f95e3ec546cbe8839275f5e5def5 Author: Niklas Haas <[email protected]> AuthorDate: Fri Aug 21 16:29:40 2026 +0200 Commit: Niklas Haas <[email protected]> CommitDate: Wed Sep 30 14:37:59 2026 +0200 avcodec/mjpegenc: add support for writing ISO 21496-1 gain map metadata This is automatically emitted as an APP2 blob following the ISO 21496-1 specification. To ensure that writing the gain map will succeed, we validate the paramaters when allocating space, and error out if invalid data is encountered. Signed-off-by: Niklas Haas <[email protected]> --- libavcodec/Makefile | 6 +++--- libavcodec/mjpegenc_common.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ libavcodec/mjpegenc_common.h | 2 ++ libavcodec/mpegvideo_enc.c | 3 +++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7785638c77..5ee0c00bc6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -239,7 +239,7 @@ OBJS-$(CONFIG_AMRWB_DECODER) += amrwbdec.o celp_filters.o \ acelp_pitch_delay.o OBJS-$(CONFIG_AMRNB_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_AMRWB_MEDIACODEC_DECODER) += mediacodecdec.o -OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o +OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o gain_map.o OBJS-$(CONFIG_ANM_DECODER) += anm.o OBJS-$(CONFIG_ANULL_DECODER) += null.o OBJS-$(CONFIG_ANULL_ENCODER) += null.o @@ -520,7 +520,7 @@ OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o OBJS-$(CONFIG_LEAD_DECODER) += leaddec.o jpegquanttables.o -OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o +OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc_common.o gain_map.o OBJS-$(CONFIG_LOCO_DECODER) += loco.o OBJS-$(CONFIG_LSCR_DECODER) += lscrdec.o png.o pngdec.o pngdsp.o OBJS-$(CONFIG_M101_DECODER) += m101.o @@ -537,7 +537,7 @@ OBJS-$(CONFIG_MISC4_DECODER) += misc4.o OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o mjpegdec_common.o OBJS-$(CONFIG_MJPEG_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \ - mjpegenc_huffman.o + mjpegenc_huffman.o gain_map.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o OBJS-$(CONFIG_MJPEG_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 5effbdbc32..a4464c3f90 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -31,6 +31,7 @@ #include "jpegtables.h" #include "put_bits.h" #include "mjpegenc.h" +#include "gain_map.h" #include "mjpegenc_common.h" #include "mjpeg.h" #include "version.h" @@ -159,6 +160,30 @@ int ff_mjpeg_add_icc_profile_size(AVCodecContext *avctx, const AVFrame *frame, return 0; } +int ff_mjpeg_add_gain_map_size(AVCodecContext *avctx, const AVFrame *frame, + size_t *max_pkt_size) +{ + if (avctx->codec_id != AV_CODEC_ID_MJPEG) + return 0; + + AVFrameSideData *sd; + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_GAIN_MAP_PARAMS); + if (!sd || sd->size < sizeof(AVGainMapParams)) + return 0; + + const AVGainMapParams *params = (const AVGainMapParams *) sd->data; + int ret = av_gain_map_params_validate(params); + if (ret < 0) + return ret; + + size_t app2_size = 4 + sizeof(AV_ISO21496_IDENTIFIER) + FF_GAIN_MAP_MAX_PAYLOAD_SIZE; + size_t new_pkt_size = *max_pkt_size + app2_size; + if (new_pkt_size < *max_pkt_size) /* overflow */ + return AVERROR_INVALIDDATA; + *max_pkt_size = new_pkt_size; + return 0; +} + static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p, const AVFrame *frame) { @@ -221,6 +246,25 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p, av_assert1(!remaining); } + /* ISO 21496-1 gain map metadata */ + sd = avctx->codec_id == AV_CODEC_ID_MJPEG ? + av_frame_get_side_data(frame, AV_FRAME_DATA_GAIN_MAP_PARAMS) : NULL; + if (sd && sd->size >= sizeof(AVGainMapParams)) { + put_marker(p, APP2); + flush_put_bits(p); + ptr = put_bits_ptr(p); + put_bits(p, 16, 0); /* patched later */ + ff_put_string(p, AV_ISO21496_IDENTIFIER, 1); + flush_put_bits(p); + + /* pre-validated by ff_mjpeg_add_gain_map_size() */ + const AVGainMapParams *params = (const AVGainMapParams *) sd->data; + size = ff_gain_map_params_to_iso21496(params, put_bits_ptr(p)); + av_assert0(size >= 0); + skip_put_bytes(p, size); + AV_WB16(ptr, 2 + sizeof(AV_ISO21496_IDENTIFIER) + size); + } + /* comment */ if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { put_marker(p, COM); diff --git a/libavcodec/mjpegenc_common.h b/libavcodec/mjpegenc_common.h index 0cf5a72706..4d1e2a5477 100644 --- a/libavcodec/mjpegenc_common.h +++ b/libavcodec/mjpegenc_common.h @@ -30,6 +30,8 @@ struct MJpegContext; int ff_mjpeg_add_icc_profile_size(AVCodecContext *avctx, const AVFrame *frame, size_t *max_pkt_size); +int ff_mjpeg_add_gain_map_size(AVCodecContext *avctx, const AVFrame *frame, + size_t *max_pkt_size); void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, const AVFrame *frame, const struct MJpegContext *m, const uint8_t intra_matrix_permutation[64], diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 2bbbe01b82..592334473a 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1939,6 +1939,9 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, ret = ff_mjpeg_add_icc_profile_size(avctx, s->new_pic, &pkt_size); if (ret < 0) return ret; + ret = ff_mjpeg_add_gain_map_size(avctx, s->new_pic, &pkt_size); + if (ret < 0) + return ret; } if ((ret = ff_alloc_packet(avctx, pkt, pkt_size)) < 0) return ret; -- 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]
