j2k/jpeg2000: merge lowres code
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 27 May 2013 20:55:14 +0000 (22:55 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 27 May 2013 22:30:06 +0000 (00:30 +0200)
This also fixes lowres use with ffplay

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/j2k.c
libavcodec/j2k.h
libavcodec/j2kdec.c
libavcodec/j2kenc.c
libavcodec/jpeg2000dec.c

index e352c4a..2a86dce 100644 (file)
@@ -184,7 +184,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
     uint8_t log2_band_prec_width, log2_band_prec_height;
     int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1;
 
-    if (ret=ff_jpeg2000_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels-1, codsty->transform == FF_DWT53 ? FF_DWT53 : FF_DWT97_INT))
+    if (ret=ff_jpeg2000_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels2decode-1, codsty->transform == FF_DWT53 ? FF_DWT53 : FF_DWT97_INT))
         return ret;
     for (i = 0; i < 2; i++)
         csize *= comp->coord[i][1] - comp->coord[i][0];
@@ -206,7 +206,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
         for (i = 0; i < 2; i++)
             for (j = 0; j < 2; j++)
                 reslevel->coord[i][j] =
-                    ff_jpeg2000_ceildivpow2(comp->coord[i][j], declvl - 1);
+                    ff_jpeg2000_ceildivpow2(comp->coord_o[i][j], declvl - 1);
         // update precincts size: 2^n value
         reslevel->log2_prec_width  = codsty->log2_prec_widths[reslevelno];
         reslevel->log2_prec_height = codsty->log2_prec_heights[reslevelno];
@@ -300,7 +300,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 2; j++)
                         band->coord[i][j] =
-                            ff_jpeg2000_ceildivpow2(comp->coord[i][j] - comp->coord[i][0],
+                            ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0],
                                                     declvl - 1);
                 log2_band_prec_width  = reslevel->log2_prec_width;
                 log2_band_prec_height = reslevel->log2_prec_height;
@@ -316,7 +316,7 @@ int ff_j2k_init_component(Jpeg2000Component *comp,
                     for (j = 0; j < 2; j++)
                         /* Formula example for tbx_0 = ceildiv((tcx_0 - 2 ^ (declvl - 1) * x0_b) / declvl) */
                         band->coord[i][j] =
-                            ff_jpeg2000_ceildivpow2(comp->coord[i][j] - comp->coord[i][0] -
+                            ff_jpeg2000_ceildivpow2(comp->coord_o[i][j] - comp->coord_o[i][0] -
                                                     (((bandno + 1 >> i) & 1) << declvl - 1),
                                                     declvl);
                 /* TODO: Manage case of 3 band offsets here or
index d5742e1..aacd006 100644 (file)
@@ -129,6 +129,7 @@ typedef struct Jpeg2000TgtNode {
 
 typedef struct Jpeg2000CodingStyle {
     uint8_t nreslevels;       // number of resolution levels
+    uint8_t nreslevels2decode; // number of resolution levels to decode
     uint8_t log2_cblk_width,
             log2_cblk_height; // exponent of codeblock size
     uint8_t transform;        // DWT type
@@ -194,7 +195,8 @@ typedef struct Jpeg2000Component {
     Jpeg2000ResLevel *reslevel;
     DWTContext dwt;
     int *data;
-    uint16_t coord[2][2];   // border coordinates {{x0, x1}, {y0, y1}}
+    uint16_t coord[2][2];   // border coordinates {{x0, x1}, {y0, y1}} -- can be reduced with lowres option
+    uint16_t coord_o[2][2]; // border coordinates {{x0, x1}, {y0, y1}} -- original values from jpeg2000 headers
 } Jpeg2000Component;
 
 /* misc tools */
index 28c5f1c..40afced 100644 (file)
  * @author Kamil Nowosad
  */
 
+#include "libavutil/common.h"
+#include "libavutil/opt.h"
 #include "avcodec.h"
 #include "bytestream.h"
 #include "internal.h"
 #include "thread.h"
 #include "j2k.h"
-#include "libavutil/common.h"
 
 #define JP2_SIG_TYPE    0x6A502020
 #define JP2_SIG_VALUE   0x0D0A870A
@@ -74,6 +75,10 @@ typedef struct Jpeg2000DecoderContext {
     int             curtileno;
 
     Jpeg2000Tile    *tile;
+
+    /*options parameters*/
+    int             lowres;
+    int             reduction_factor;
 } Jpeg2000DecoderContext;
 
 static int get_bits(Jpeg2000DecoderContext *s, int n)
@@ -198,9 +203,11 @@ static int get_siz(Jpeg2000DecoderContext *s)
             return AVERROR(ENOMEM);
     }
 
-    s->avctx->width  = s->width  - s->image_offset_x;
-    s->avctx->height = s->height - s->image_offset_y;
-
+    /* compute image size with reduction factor */
+    s->avctx->width  = ff_jpeg2000_ceildivpow2(s->width  - s->image_offset_x,
+                                               s->reduction_factor);
+    s->avctx->height = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y,
+                                               s->reduction_factor);
     switch(s->ncomponents) {
     case 1:
         if (s->precision > 8) {
@@ -244,6 +251,12 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
         return AVERROR_INVALIDDATA;
     }
 
+    /* compute number of resolution levels to decode */
+    if (c->nreslevels < s->reduction_factor)
+        c->nreslevels2decode = 1;
+    else
+        c->nreslevels2decode = c->nreslevels - s->reduction_factor;
+
     c->log2_cblk_width  = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk width
     c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height
 
@@ -434,10 +447,15 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
         Jpeg2000QuantStyle  *qntsty = tile->qntsty + compno;
         int ret; // global bandno
 
-        comp->coord[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x);
-        comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width + s->tile_offset_x, s->width);
-        comp->coord[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y);
-        comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height + s->tile_offset_y, s->height);
+        comp->coord_o[0][0] = FFMAX(tilex       * s->tile_width  + s->tile_offset_x, s->image_offset_x);
+        comp->coord_o[0][1] = FFMIN((tilex + 1) * s->tile_width  + s->tile_offset_x, s->width);
+        comp->coord_o[1][0] = FFMAX(tiley       * s->tile_height + s->tile_offset_y, s->image_offset_y);
+        comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height);
+
+        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);
+        comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor);
+        comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor);
 
         if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno], s->avctx))
             return ret;
@@ -785,7 +803,7 @@ static int decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
         Jpeg2000CodingStyle *codsty = tile->codsty + compno;
 
         /* Loop on resolution levels */
-        for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++) {
+        for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) {
             Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
             /* Loop on bands */
             for (bandno = 0; bandno < rlevel->nbands; bandno++) {
@@ -1025,6 +1043,9 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
     bytestream2_init(&s->g, avpkt->data, avpkt->size);
     s->curtileno = -1;
 
+    // reduction factor, i.e number of resolution levels to skip
+    s->reduction_factor = avctx->lowres;
+
     if (bytestream2_get_bytes_left(&s->g) < 2) {
         ret = AVERROR(EINVAL);
         goto err_out;
@@ -1072,6 +1093,15 @@ static void jpeg2000_init_static_data(AVCodec *codec)
     ff_jpeg2000_init_tier1_luts();
 }
 
+#define OFFSET(x) offsetof(Jpeg2000DecoderContext, x)
+#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+
+static const AVOption options[] = {
+    { "lowres",  "Lower the decoding resolution by a power of two",
+        OFFSET(lowres), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, JPEG2000_MAX_RESLEVELS - 1, VD },
+    { NULL },
+};
+
 static const AVProfile profiles[] = {
     { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0,  "JPEG 2000 codestream restriction 0"   },
     { FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1,  "JPEG 2000 codestream restriction 1"   },
@@ -1081,6 +1111,13 @@ static const AVProfile profiles[] = {
     { FF_PROFILE_UNKNOWN },
 };
 
+static const AVClass class = {
+    .class_name = "j2k",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 AVCodec ff_j2k_decoder = {
     .name             = "j2k",
     .long_name        = NULL_IF_CONFIG_SMALL("JPEG 2000"),
@@ -1090,5 +1127,7 @@ AVCodec ff_j2k_decoder = {
     .priv_data_size   = sizeof(Jpeg2000DecoderContext),
     .init_static_data = jpeg2000_init_static_data,
     .decode           = jpeg2000_decode_frame,
+    .priv_class       = &class,
+    .max_lowres       = 5,
     .profiles         = NULL_IF_CONFIG_SMALL(profiles)
 };
index 528b9a7..da50856 100644 (file)
@@ -357,14 +357,14 @@ static int init_tiles(Jpeg2000EncoderContext *s)
                 Jpeg2000Component *comp = tile->comp + compno;
                 int ret, i, j;
 
-                comp->coord[0][0] = tilex * s->tile_width;
-                comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width, s->width);
-                comp->coord[1][0] = tiley * s->tile_height;
-                comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height, s->height);
+                comp->coord[0][0] = comp->coord_o[0][0] = tilex * s->tile_width;
+                comp->coord[0][1] = comp->coord_o[0][1] = FFMIN((tilex+1)*s->tile_width, s->width);
+                comp->coord[1][0] = comp->coord_o[1][0] = tiley * s->tile_height;
+                comp->coord[1][1] = comp->coord_o[1][1] = FFMIN((tiley+1)*s->tile_height, s->height);
                 if (compno > 0)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 2; j++)
-                            comp->coord[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]);
+                            comp->coord[i][j] = comp->coord_o[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], s->chroma_shift[i]);
 
                 if (ret = ff_j2k_init_component(comp,
                                                 codsty,
@@ -982,6 +982,7 @@ static av_cold int j2kenc_init(AVCodecContext *avctx)
     // TODO: implement setting non-standard precinct size
     memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths ));
     memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights));
+    codsty->nreslevels2decode=
     codsty->nreslevels       = 7;
     codsty->log2_cblk_width  = 4;
     codsty->log2_cblk_height = 4;
index 68312a0..3b0bf65 100644 (file)
@@ -543,12 +543,10 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
         comp->coord_o[1][0] = FFMAX(tiley       * s->tile_height + s->tile_offset_y, s->image_offset_y);
         comp->coord_o[1][1] = FFMIN((tiley + 1) * s->tile_height + s->tile_offset_y, s->height);
 
-        // FIXME: add a dcinema profile check ?
-        // value is guaranteed by profile (orig=0, 1 tile)
-        comp->coord[0][0] = 0;
-        comp->coord[0][1] = s->avctx->width;
-        comp->coord[1][0] = 0;
-        comp->coord[1][1] = s->avctx->height;
+        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);
+        comp->coord[1][0] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][0], s->reduction_factor);
+        comp->coord[1][1] = ff_jpeg2000_ceildivpow2(comp->coord_o[1][1], s->reduction_factor);
 
         if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty,
                                              s->cbps[compno], s->cdx[compno],
@@ -1369,5 +1367,6 @@ AVCodec ff_jpeg2000_decoder = {
     .pix_fmts         = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12,
                                                  AV_PIX_FMT_GRAY8,
                                                  -1 },
+    .max_lowres       = 5,
     .profiles         = NULL_IF_CONFIG_SMALL(profiles)
 };