[FFmpeg-devel] [RFC PATCH] libavcodec/jpeg2000: Make corrections jpeg2000 decoder

gautamramk at gmail.com gautamramk at gmail.com
Thu Jun 18 21:25:20 EEST 2020


From: Gautam Ramakrishnan <gautamramk at gmail.com>

This is with reference to my previous email on the mailing list
with subject: "query on pixel formats".
I wish to cleanup some errors in the decoder code. These changes
would allow the samples p1_01.j2k and p1_07.j2k to be decoded.
However, I am facing issues with pixel format selection and have
currently forced the pixel formats to demonstrate the changes made.
Would be grateful if anyone could suggest modifications to the pix
format selection.
---
 libavcodec/jpeg2000.c    |  3 ---
 libavcodec/jpeg2000dec.c | 53 ++++++++++++++++++++++++++--------------
 2 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index 73206d17f3..1aca31ffa4 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -509,9 +509,6 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
         // update precincts size: 2^n value
         reslevel->log2_prec_width  = codsty->log2_prec_widths[reslevelno];
         reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno];
-        if (!reslevel->log2_prec_width || !reslevel->log2_prec_height) {
-            return AVERROR_INVALIDDATA;
-        }
 
         /* Number of bands for each resolution level */
         if (reslevelno == 0)
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index ab36009a2d..ae63c68ca8 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -269,6 +269,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
     const enum AVPixelFormat *possible_fmts = NULL;
     int possible_fmts_nb = 0;
     int ret;
+    int dimx, dimy;
 
     if (bytestream2_get_bytes_left(&s->g) < 36) {
         av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for SIZ\n");
@@ -286,10 +287,6 @@ static int get_siz(Jpeg2000DecoderContext *s)
     s->tile_offset_y  = bytestream2_get_be32u(&s->g); // YT0Siz
     ncomponents       = bytestream2_get_be16u(&s->g); // CSiz
 
-    if (s->image_offset_x || s->image_offset_y) {
-        avpriv_request_sample(s->avctx, "Support for image offsets");
-        return AVERROR_PATCHWELCOME;
-    }
     if (av_image_check_size2(s->width, s->height, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) {
         avpriv_request_sample(s->avctx, "Large Dimensions");
         return AVERROR_PATCHWELCOME;
@@ -371,11 +368,18 @@ static int get_siz(Jpeg2000DecoderContext *s)
     }
 
     /* compute image size with reduction factor */
-    ret = ff_set_dimensions(s->avctx,
-            ff_jpeg2000_ceildivpow2(s->width  - s->image_offset_x,
-                                               s->reduction_factor),
-            ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y,
-                                               s->reduction_factor));
+    dimx = ff_jpeg2000_ceildivpow2(s->width  - s->image_offset_x,
+                                               s->reduction_factor);
+    dimy = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y,
+                                               s->reduction_factor);
+    dimx = ff_jpeg2000_ceildiv(dimx, s->cdx[0]);
+    dimy = ff_jpeg2000_ceildiv(dimy, s->cdy[0]);
+    for (i = 1; i < s->ncomponents; i++) {
+        dimx = FFMAX(dimx, ff_jpeg2000_ceildiv(dimx, s->cdx[i]));
+        dimy = FFMAX(dimy, ff_jpeg2000_ceildiv(dimy, s->cdy[i]));
+    }
+
+    ret = ff_set_dimensions(s->avctx, dimx, dimy);
     if (ret < 0)
         return ret;
 
@@ -427,6 +431,13 @@ static int get_siz(Jpeg2000DecoderContext *s)
                 s->cdef[3] = 3;
                 i = 0;
             }
+        } else if (ncomponents == 2) {
+            s->avctx->pix_fmt = AV_PIX_FMT_YA8;
+            i = 0;
+        } else if (ncomponents == 1) {
+            s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+            i = 0;
+            s->cdef[0] = 0;
         }
     }
 
@@ -969,12 +980,11 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
         comp->coord_o[0][1] = tile->coord[0][1];
         comp->coord_o[1][0] = tile->coord[1][0];
         comp->coord_o[1][1] = tile->coord[1][1];
-        if (compno) {
-            comp->coord_o[0][0] /= s->cdx[compno];
-            comp->coord_o[0][1] /= s->cdx[compno];
-            comp->coord_o[1][0] /= s->cdy[compno];
-            comp->coord_o[1][1] /= s->cdy[compno];
-        }
+
+        comp->coord_o[0][0] = ff_jpeg2000_ceildiv(comp->coord_o[0][0], s->cdx[compno]);
+        comp->coord_o[0][1] = ff_jpeg2000_ceildiv(comp->coord_o[0][1], s->cdx[compno]);
+        comp->coord_o[1][0] = ff_jpeg2000_ceildiv(comp->coord_o[1][0], s->cdy[compno]);
+        comp->coord_o[1][1] = ff_jpeg2000_ceildiv(comp->coord_o[1][1], s->cdy[compno]);
 
         comp->coord[0][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][0], s->reduction_factor);
         comp->coord[0][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[0][1], s->reduction_factor);
@@ -1927,18 +1937,23 @@ static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
             float *datap     = comp->f_data;                                                      \
             int32_t *i_datap = comp->i_data;                                                      \
             int cbps         = s->cbps[compno];                                                   \
-            int w            = tile->comp[compno].coord[0][1] - s->image_offset_x;                \
+            int w            = tile->comp[compno].coord[0][1] -                                   \
+                               ff_jpeg2000_ceildiv(s->image_offset_x, s->cdx[compno]);            \
+            int h            = tile->comp[compno].coord[1][1] -                                   \
+                               ff_jpeg2000_ceildiv(s->image_offset_y, s->cdy[compno]);            \
             int plane        = 0;                                                                 \
                                                                                                   \
             if (planar)                                                                           \
                 plane = s->cdef[compno] ? s->cdef[compno]-1 : (s->ncomponents-1);                 \
                                                                                                   \
-            y    = tile->comp[compno].coord[1][0] - s->image_offset_y / s->cdy[compno];           \
+            y    = tile->comp[compno].coord[1][0] -                                               \
+                   ff_jpeg2000_ceildiv(s->image_offset_y, s->cdy[compno]);                        \
             line = (PIXEL *)picture->data[plane] + y * (picture->linesize[plane] / sizeof(PIXEL));\
-            for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y++) {                 \
+            for (; y < h; y++) {                                                                  \
                 PIXEL *dst;                                                                       \
                                                                                                   \
-                x   = tile->comp[compno].coord[0][0] - s->image_offset_x / s->cdx[compno];        \
+                x   = tile->comp[compno].coord[0][0] -                                            \
+                      ff_jpeg2000_ceildiv(s->image_offset_x, s->cdx[compno]);                     \
                 dst = line + x * pixelsize + compno*!planar;                                      \
                                                                                                   \
                 if (codsty->transform == FF_DWT97) {                                              \
-- 
2.17.1



More information about the ffmpeg-devel mailing list