PR #23090 opened by Ramiro Polla (ramiro)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23090
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23090.patch

A couple of patches from an earlier work of cleaning up mjpegdec that might be 
useful for !22917.


>From 0d3f242f76b253e7af1d98f474123df1318dc99a Mon Sep 17 00:00:00 2001
From: Ramiro Polla <[email protected]>
Date: Fri, 13 Feb 2026 19:55:11 +0100
Subject: [PATCH 1/2] avcodec/mjpegdec: remove redundant vpred variable for
 bayer

The vpred variable in ljpeg_decode_rgb_scan() is redundant with
buffer[0][i], which is used by the generic codepath.
---
 libavcodec/mjpegdec.c | 16 ++--------------
 1 file changed, 2 insertions(+), 14 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index f037d9f7aa..6e849ee80a 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -1093,7 +1093,6 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
     const int mask     = ((1 << s->bits) - 1) << point_transform;
     int resync_mb_y = 0;
     int resync_mb_x = 0;
-    int vpred[6];
     int ret;
 
     if (!s->bayer && s->nb_components < 3)
@@ -1109,10 +1108,6 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
             return AVERROR_INVALIDDATA;
     }
 
-
-    for (i = 0; i < 6; i++)
-        vpred[i] = 1 << (s->bits - 1);
-
     if (s->bayer)
         width = s->mb_width / nb_components; /* Interleaved, width stored is 
the total so need to divide */
     else
@@ -1166,19 +1161,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
                 topleft[i] = top[i];
                 top[i]     = buffer[mb_x][i];
 
+                PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
+
                 ret = mjpeg_decode_dc(s, s->dc_index[i], &dc);
                 if (ret < 0)
                     return ret;
 
-                if (!s->bayer || mb_x) {
-                    pred = left[i];
-                } else { /* This path runs only for the first line in bayer 
images */
-                    vpred[i] += dc;
-                    pred = vpred[i] - dc;
-                }
-
-                PREDICT(pred, topleft[i], top[i], pred, modified_predictor);
-
                 left[i] = buffer[mb_x][i] =
                     mask & (pred + (unsigned)(dc * (1 << point_transform)));
             }
-- 
2.52.0


>From 3435bd4a5c1d8d8bfd34ad25662ab5b1f2486a79 Mon Sep 17 00:00:00 2001
From: Ramiro Polla <[email protected]>
Date: Fri, 13 Feb 2026 22:34:13 +0100
Subject: [PATCH 2/2] avcodec/mjpegdec: simplify bayer width handling

Double s->avctx->width directly, simplifying width-related code in
ljpeg_decode_rgb_scan().
---
 libavcodec/mjpegdec.c | 41 ++++++++++++++++++-----------------------
 1 file changed, 18 insertions(+), 23 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 6e849ee80a..e6c4f4acfc 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -426,19 +426,6 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
         return AVERROR_PATCHWELCOME;
     }
 
-    if (s->bayer) {
-        if (nb_components == 2) {
-            /* Bayer images embedded in DNGs can contain 2 interleaved 
components and the
-               width stored in their SOF3 markers is the width of each one.  
We only output
-               a single component, therefore we need to adjust the output 
image width.  We
-               handle the deinterleaving (but not the debayering) in this 
file. */
-            width *= 2;
-        }
-        /* They can also contain 1 component, which is double the width and 
half the height
-            of the final image (rows are interleaved).  We don't handle the 
decoding in this
-            file, but leave that to the TIFF/DNG decoder. */
-    }
-
     /* if different size, realloc/alloc picture */
     if (width != s->width || height != s->height || bits != s->bits ||
         memcmp(s->h_count, h_count, sizeof(h_count))                ||
@@ -475,6 +462,19 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
             s->orig_height < height)
             s->avctx->height = AV_CEIL_RSHIFT(s->orig_height, 
s->avctx->lowres);
 
+        if (s->bayer) {
+            if (nb_components == 2) {
+                /* Bayer images embedded in DNGs can contain 2 interleaved 
components and the
+                 * width stored in their SOF3 markers is the width of each 
one.  We only output
+                 * a single component, therefore we need to adjust the output 
image width.  We
+                 * handle the deinterleaving (but not the debayering) in this 
file. */
+                s->avctx->width *= 2;
+            }
+            /* They can also contain 1 component, which is double the width 
and half the height
+             * of the final image (rows are interleaved).  We don't handle the 
decoding in this
+             * file, but leave that to the TIFF/DNG decoder. */
+        }
+
         s->first_picture = 0;
     } else {
         size_change = 0;
@@ -1086,7 +1086,6 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
     int predictor = s->Ss;
     int point_transform = s->Al;
     int i, mb_x, mb_y;
-    unsigned width;
     uint16_t (*buffer)[4];
     int left[4], top[4], topleft[4];
     const int linesize = s->linesize[0];
@@ -1108,12 +1107,8 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
             return AVERROR_INVALIDDATA;
     }
 
-    if (s->bayer)
-        width = s->mb_width / nb_components; /* Interleaved, width stored is 
the total so need to divide */
-    else
-        width = s->mb_width;
-
-    av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * 
sizeof(s->ljpeg_buffer[0][0]));
+    av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size,
+                   (unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0]));
     if (!s->ljpeg_buffer)
         return AVERROR(ENOMEM);
 
@@ -1133,7 +1128,7 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
         for (i = 0; i < 4; i++)
             top[i] = left[i] = topleft[i] = buffer[0][i];
 
-        for (mb_x = 0; mb_x < width; mb_x++) {
+        for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
             int modified_predictor = predictor;
             int restart;
 
@@ -1210,10 +1205,10 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s)
                 return AVERROR_PATCHWELCOME;
             if (nb_components == 1) {
                 /* Leave decoding to the TIFF/DNG decoder (see comment in 
ff_mjpeg_decode_sof) */
-                for (mb_x = 0; mb_x < width; mb_x++)
+                for (mb_x = 0; mb_x < s->mb_width; mb_x++)
                     ((uint16_t*)ptr)[mb_x] = buffer[mb_x][0];
             } else if (nb_components == 2) {
-                for (mb_x = 0; mb_x < width; mb_x++) {
+                for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
                     ((uint16_t*)ptr)[2 * mb_x + 0] = buffer[mb_x][0];
                     ((uint16_t*)ptr)[2 * mb_x + 1] = buffer[mb_x][1];
                 }
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to