This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 42344c7cbb7d03a8ba64bcb0aa6439702037442b
Author:     Niklas Haas <[email protected]>
AuthorDate: Fri Oct 2 17:20:38 2026 +0200
Commit:     James Almer <[email protected]>
CommitDate: Fri Oct 23 20:33:53 2026 +0000

    avcodec: implement ISO 21496 gain map parsing
    
    The parsing logic for this already existed in libavcodec, but was unused
    until now. This commit adds the APP2 extraction logic and the necessary
    scaffolding to make this metadata survive the decoder.
    
    Since the base layer of a JPEG Ultra HDR image also contains a stub
    copy of the same gain map params struct, we ignore that one here. (It's
    only useful for the demuxer, not the decoder)
    
    Signed-off-by: Niklas Haas <[email protected]>
---
 libavcodec/Makefile   |  2 +-
 libavcodec/mjpegdec.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/mjpegdec.h |  4 ++++
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 53c638c878..2ea4f9417e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -535,7 +535,7 @@ OBJS-$(CONFIG_METASOUND_DECODER)       += metasound.o 
twinvq.o
 OBJS-$(CONFIG_MICRODVD_DECODER)        += microdvddec.o ass.o
 OBJS-$(CONFIG_MIMIC_DECODER)           += mimic.o
 OBJS-$(CONFIG_MISC4_DECODER)           += misc4.o
-OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpegdec_common.o
+OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpegdec_common.o 
gain_map.o
 OBJS-$(CONFIG_MJPEG_QSV_DECODER)       += qsvdec.o
 OBJS-$(CONFIG_MJPEG_ENCODER)           += mjpegenc.o mjpegenc_common.o \
                                           mjpegenc_huffman.o gain_map.o
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index cbb7268ed9..3716bbf753 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -44,6 +44,7 @@
 #include "decode.h"
 #include "exif.h"
 #include "exif_internal.h"
+#include "gain_map.h"
 #include "hwaccel_internal.h"
 #include "hwconfig.h"
 #include "idctdsp.h"
@@ -2126,6 +2127,38 @@ static int mjpeg_decode_app(MJpegDecodeContext *s, int 
start_code)
             av_log(s->avctx, AV_LOG_WARNING, "Read more ICC markers than are 
supposed to be coded\n");
     }
 
+    if (start_code == APP2 && id == AV_RB32("urn:")) {
+        bytestream2_seek(&s->gB, -4, SEEK_CUR); /* include `urn:` in the 
string */
+        len += 4;
+
+        if (len >= sizeof(AV_ISO21496_IDENTIFIER) &&
+            !memcmp(s->gB.buffer, AV_ISO21496_IDENTIFIER, 
sizeof(AV_ISO21496_IDENTIFIER)))
+        {
+            bytestream2_skipu(&s->gB, sizeof(AV_ISO21496_IDENTIFIER));
+            len -= sizeof(AV_ISO21496_IDENTIFIER);
+
+            /* Discard gain map version stubs from base layer */
+            if (len <= sizeof(uint16_t[2]))
+                goto out;
+            else if (s->gain_map) {
+                av_log(s->avctx, AV_LOG_WARNING, "Multiple ISO 21496 gain map 
headers\n");
+                goto out;
+            }
+
+            s->gain_map = av_gain_map_params_alloc(&s->gain_map_size);
+            if (!s->gain_map)
+                return AVERROR(ENOMEM);
+
+            ret = av_gain_map_params_from_iso21496(s->gain_map, s->gB.buffer, 
len);
+            if (ret < 0) {
+                av_log(s->avctx, AV_LOG_WARNING, "Failed to parse ISO 21496 
gain map header\n");
+                av_freep(&s->gain_map);
+                s->gain_map_size = 0;
+                goto out;
+            }
+        }
+    }
+
 out:
     /* slow but needed for extreme adobe jpegs */
     if (len < 0)
@@ -2399,6 +2432,7 @@ int ff_mjpeg_decode_frame_from_buf(AVCodecContext *avctx, 
AVFrame *frame,
 
     av_exif_free(&s->exif_metadata);
     av_freep(&s->stereo3d);
+    av_freep(&s->gain_map);
     s->adobe_transform = -1;
 
     if (s->iccnum != 0)
@@ -2831,6 +2865,18 @@ the_end:
         av_freep(&s->stereo3d);
     }
 
+    if (s->gain_map) {
+        AVFrameSideData *sd;
+        ret = ff_frame_new_side_data(avctx, frame, 
AV_FRAME_DATA_GAIN_MAP_PARAMS, s->gain_map_size, &sd);
+        if (ret < 0)
+            return ret;
+
+        if (sd)
+            memcpy(sd->data, s->gain_map, s->gain_map_size);
+        av_freep(&s->gain_map);
+        s->gain_map_size = 0;
+    }
+
     if (s->iccnum != 0 && s->iccnum == s->iccread) {
         AVFrameSideData *sd;
         size_t offset = 0;
@@ -2904,6 +2950,8 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
     av_freep(&s->stereo3d);
     av_freep(&s->ljpeg_buffer);
     s->ljpeg_buffer_size = 0;
+    av_freep(&s->gain_map);
+    s->gain_map_size = 0;
 
     for (i = 0; i < 3; i++) {
         for (j = 0; j < 4; j++)
diff --git a/libavcodec/mjpegdec.h b/libavcodec/mjpegdec.h
index 9162de851f..30f6947eaa 100644
--- a/libavcodec/mjpegdec.h
+++ b/libavcodec/mjpegdec.h
@@ -29,6 +29,7 @@
 #ifndef AVCODEC_MJPEGDEC_H
 #define AVCODEC_MJPEGDEC_H
 
+#include "libavutil/gain_map.h"
 #include "libavutil/log.h"
 #include "libavutil/mem_internal.h"
 #include "libavutil/pixdesc.h"
@@ -153,6 +154,9 @@ typedef struct MJpegDecodeContext {
 
     AVStereo3D *stereo3d; ///!< stereoscopic information (cached, since it is 
read before frame allocation)
 
+    AVGainMapParams *gain_map;
+    size_t gain_map_size;
+
     const AVPixFmtDescriptor *pix_desc;
 
     ICCEntry *iccentries;

-- 
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]

Reply via email to