From bd89b2b22ac71aae4ec5c6a27adb88d877b7b76e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 26 May 2013 21:50:17 +0200 Subject: j2k/jpeg2000: log2_prec size cleanup This also changes the cblk size storage method to what jpeg2000 uses Signed-off-by: Michael Niedermayer --- libavcodec/j2k.c | 63 ++++++++++++++++++++++++++++++++++-------------- libavcodec/j2k.h | 4 +-- libavcodec/j2kdec.c | 30 ++++++++++++++--------- libavcodec/j2kenc.c | 12 ++++----- libavcodec/jpeg2000.h | 2 -- libavcodec/jpeg2000dec.c | 10 +++++--- 6 files changed, 78 insertions(+), 43 deletions(-) diff --git a/libavcodec/j2k.c b/libavcodec/j2k.c index d575b840de..c779480803 100644 --- a/libavcodec/j2k.c +++ b/libavcodec/j2k.c @@ -174,6 +174,7 @@ void ff_j2k_set_significant(Jpeg2000T1Context *t1, int x, int y, int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, Jpeg2000QuantStyle *qntsty, int cbps, int dx, int dy) { + uint8_t log2_band_prec_width, log2_band_prec_height; int reslevelno, bandno, gbandno = 0, ret, i, j, csize = 1; if (ret=ff_j2k_dwt_init(&comp->dwt, comp->coord, codsty->nreslevels-1, codsty->transform)) @@ -195,6 +196,9 @@ int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, for (j = 0; j < 2; j++) reslevel->coord[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[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]; if (reslevelno == 0) reslevel->nbands = 1; @@ -204,14 +208,14 @@ int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, if (reslevel->coord[0][1] == reslevel->coord[0][0]) reslevel->num_precincts_x = 0; else - reslevel->num_precincts_x = ff_jpeg2000_ceildivpow2(reslevel->coord[0][1], codsty->log2_prec_width) - - (reslevel->coord[0][0] >> codsty->log2_prec_width); + reslevel->num_precincts_x = ff_jpeg2000_ceildivpow2(reslevel->coord[0][1], reslevel->log2_prec_width) + - (reslevel->coord[0][0] >> reslevel->log2_prec_width); if (reslevel->coord[1][1] == reslevel->coord[1][0]) reslevel->num_precincts_y = 0; else - reslevel->num_precincts_y = ff_jpeg2000_ceildivpow2(reslevel->coord[1][1], codsty->log2_prec_height) - - (reslevel->coord[1][0] >> codsty->log2_prec_height); + reslevel->num_precincts_y = ff_jpeg2000_ceildivpow2(reslevel->coord[1][1], reslevel->log2_prec_height) + - (reslevel->coord[1][0] >> reslevel->log2_prec_height); reslevel->band = av_malloc_array(reslevel->nbands, sizeof(*reslevel->band)); if (!reslevel->band) @@ -233,22 +237,45 @@ int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, } else band->stepsize = 1 << 13; - if (reslevelno == 0) { // the same everywhere - band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width-1); - band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height-1); + if (reslevelno == 0) { + /* for reslevelno = 0, only one band, x0_b = y0_b = 0 */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) - band->coord[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j], declvl-1); + band->coord[i][j] = + ff_jpeg2000_ceildivpow2(comp->coord[i][j], + declvl - 1); + + log2_band_prec_width = reslevel->log2_prec_width; + log2_band_prec_height = reslevel->log2_prec_height; + /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ + band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, + reslevel->log2_prec_width); + band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, + reslevel->log2_prec_height); } else{ - band->codeblock_width = 1 << FFMIN(codsty->log2_cblk_width, codsty->log2_prec_width); - band->codeblock_height = 1 << FFMIN(codsty->log2_cblk_height, codsty->log2_prec_height); - + /* 3 bands x0_b = 1 y0_b = 0; x0_b = 0 y0_b = 1; x0_b = y0_b = 1 */ + /* x0_b and y0_b are computed with ((bandno + 1 >> i) & 1) */ for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) - band->coord[i][j] = ff_jpeg2000_ceildivpow2(comp->coord[i][j] - (((bandno+1>>i)&1) << declvl-1), declvl); + /* 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] - + (((bandno + 1 >> i) & 1) << declvl - 1), + declvl); + /* TODO: Manage case of 3 band offsets here or + * in coding/decoding function? */ + + /* see ISO/IEC 15444-1:2002 eq. B-17 and eq. B-15 */ + band->log2_cblk_width = FFMIN(codsty->log2_cblk_width, + reslevel->log2_prec_width - 1); + band->log2_cblk_height = FFMIN(codsty->log2_cblk_height, + reslevel->log2_prec_height - 1); + + log2_band_prec_width = reslevel->log2_prec_width - 1; + log2_band_prec_height = reslevel->log2_prec_height - 1; } - band->cblknx = ff_jpeg2000_ceildiv(band->coord[0][1], band->codeblock_width) - band->coord[0][0] / band->codeblock_width; - band->cblkny = ff_jpeg2000_ceildiv(band->coord[1][1], band->codeblock_height) - band->coord[1][0] / band->codeblock_height; + band->cblknx = ff_jpeg2000_ceildivpow2(band->coord[0][1], band->log2_cblk_width) - (band->coord[0][0] >> band->log2_cblk_width); + band->cblkny = ff_jpeg2000_ceildivpow2(band->coord[1][1], band->log2_cblk_height) - (band->coord[1][0] >> band->log2_cblk_height); for (j = 0; j < 2; j++) band->coord[0][j] = ff_jpeg2000_ceildiv(band->coord[0][j], dx); @@ -279,11 +306,11 @@ int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, } y0 = band->coord[1][0]; - y1 = ((band->coord[1][0] + (1<log2_prec_height)) & ~((1<log2_prec_height)-1)) - y0; + y1 = ((band->coord[1][0] + (1<log2_prec_height)) & ~((1<log2_prec_height)-1)) - y0; yi0 = 0; yi1 = ff_jpeg2000_ceildivpow2(y1 - y0, codsty->log2_cblk_height) << codsty->log2_cblk_height; yi1 = FFMIN(yi1, band->cblkny); - cblkperprech = 1<<(codsty->log2_prec_height - codsty->log2_cblk_height); + cblkperprech = 1<<(reslevel->log2_prec_height - codsty->log2_cblk_height); for (precy = 0, precno = 0; precy < reslevel->num_precincts_y; precy++) { for (precx = 0; precx < reslevel->num_precincts_x; precx++, precno++) { band->prec[precno].yi0 = yi0; @@ -294,12 +321,12 @@ int ff_j2k_init_component(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty, yi1 = FFMIN(yi1, band->cblkny); } x0 = band->coord[0][0]; - x1 = ((band->coord[0][0] + (1<log2_prec_width)) & ~((1<log2_prec_width)-1)) - x0; + x1 = ((band->coord[0][0] + (1<log2_prec_width)) & ~((1<log2_prec_width)-1)) - x0; xi0 = 0; xi1 = ff_jpeg2000_ceildivpow2(x1 - x0, codsty->log2_cblk_width) << codsty->log2_cblk_width; xi1 = FFMIN(xi1, band->cblknx); - cblkperprecw = 1<<(codsty->log2_prec_width - codsty->log2_cblk_width); + cblkperprecw = 1<<(reslevel->log2_prec_width - codsty->log2_cblk_width); for (precx = 0, precno = 0; precx < reslevel->num_precincts_x; precx++) { for (precy = 0; precy < reslevel->num_precincts_y; precy++, precno = 0) { Jpeg2000Prec *prec = band->prec + precno; diff --git a/libavcodec/j2k.h b/libavcodec/j2k.h index 1c077f9cf1..c3959455e1 100644 --- a/libavcodec/j2k.h +++ b/libavcodec/j2k.h @@ -130,8 +130,6 @@ typedef struct Jpeg2000CodingStyle { log2_cblk_height; // exponent of codeblock size uint8_t transform; // DWT type uint8_t csty; // coding style - uint8_t log2_prec_width, - log2_prec_height; // precinct size uint8_t nlayers; // number of layers uint8_t mct; // multiple component transformation uint8_t cblk_style; // codeblock coding style @@ -172,7 +170,7 @@ typedef struct Jpeg2000Prec { typedef struct Jpeg2000Band { uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} - uint16_t codeblock_width, codeblock_height; + uint16_t log2_cblk_width, log2_cblk_height; uint16_t cblknx, cblkny; uint32_t stepsize; // quantization stepsize (* 2^13) Jpeg2000Prec *prec; diff --git a/libavcodec/j2kdec.c b/libavcodec/j2kdec.c index f3b9ad13cd..a368a6477a 100644 --- a/libavcodec/j2kdec.c +++ b/libavcodec/j2kdec.c @@ -230,9 +230,15 @@ static int get_siz(Jpeg2000DecoderContext *s) /** get common part for COD and COC segments */ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) { + uint8_t byte; + if (bytestream2_get_bytes_left(&s->g) < 5) return AVERROR(EINVAL); - c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1 + c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1 + if (c->nreslevels >= JPEG2000_MAX_RESLEVELS) { + av_log(s->avctx, AV_LOG_ERROR, "nreslevels %d is invalid\n", c->nreslevels); + return AVERROR_INVALIDDATA; + } 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 @@ -250,9 +256,14 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) c->transform = bytestream2_get_byteu(&s->g); // transformation if (c->csty & JPEG2000_CSTY_PREC) { int i; - - for (i = 0; i < c->nreslevels; i++) - bytestream2_get_byte(&s->g); + for (i = 0; i < c->nreslevels; i++) { + byte = bytestream2_get_byte(&s->g); + c->log2_prec_widths[i] = byte & 0x0F; // precinct PPx + c->log2_prec_heights[i] = (byte >> 4) & 0x0F; // precinct PPy + } + } else { + memset(c->log2_prec_widths , 15, sizeof(c->log2_prec_widths )); + memset(c->log2_prec_heights, 15, sizeof(c->log2_prec_heights)); } return 0; } @@ -266,9 +277,6 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, uint8_t *p if (bytestream2_get_bytes_left(&s->g) < 5) return AVERROR(EINVAL); - tmp.log2_prec_width = - tmp.log2_prec_height = 15; - tmp.csty = bytestream2_get_byteu(&s->g); // get progression order @@ -756,7 +764,7 @@ static int decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0]; y0 = yy0; - yy1 = FFMIN(ff_jpeg2000_ceildiv(band->coord[1][0] + 1, band->codeblock_height) * band->codeblock_height, + yy1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[1][0] + 1, band->log2_cblk_height) << band->log2_cblk_height, band->coord[1][1]) - band->coord[1][0] + yy0; if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1]) @@ -768,7 +776,7 @@ static int decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) else xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0]; x0 = xx0; - xx1 = FFMIN(ff_jpeg2000_ceildiv(band->coord[0][0] + 1, band->codeblock_width) * band->codeblock_width, + xx1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[0][0] + 1, band->log2_cblk_width) << band->log2_cblk_width, band->coord[0][1]) - band->coord[0][0] + xx0; for (cblkx = 0; cblkx < band->cblknx; cblkx++, cblkno++) { @@ -792,10 +800,10 @@ static int decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) } } xx0 = xx1; - xx1 = FFMIN(xx1 + band->codeblock_width, band->coord[0][1] - band->coord[0][0] + x0); + xx1 = FFMIN(xx1 + (1 << band->log2_cblk_width), band->coord[0][1] - band->coord[0][0] + x0); } yy0 = yy1; - yy1 = FFMIN(yy1 + band->codeblock_height, band->coord[1][1] - band->coord[1][0] + y0); + yy1 = FFMIN(yy1 + (1 << band->log2_cblk_height), band->coord[1][1] - band->coord[1][0] + y0); } } } diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index c8ff66e79a..4c047c3a67 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -821,7 +821,7 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos; yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0]; y0 = yy0; - yy1 = FFMIN(ff_jpeg2000_ceildiv(band->coord[1][0] + 1, band->codeblock_height) * band->codeblock_height, + yy1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[1][0] + 1, band->log2_cblk_height) << band->log2_cblk_height, band->coord[1][1]) - band->coord[1][0] + yy0; if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1]) @@ -835,7 +835,7 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno else xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0]; x0 = xx0; - xx1 = FFMIN(ff_jpeg2000_ceildiv(band->coord[0][0] + 1, band->codeblock_width) * band->codeblock_width, + xx1 = FFMIN(ff_jpeg2000_ceildivpow2(band->coord[0][0] + 1, band->log2_cblk_width) << band->log2_cblk_width, band->coord[0][1]) - band->coord[0][0] + xx0; for (cblkx = 0; cblkx < band->cblknx; cblkx++, cblkno++){ @@ -860,10 +860,10 @@ static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno encode_cblk(s, &t1, band->cblk + cblkno, tile, xx1 - xx0, yy1 - yy0, bandpos, codsty->nreslevels - reslevelno - 1); xx0 = xx1; - xx1 = FFMIN(xx1 + band->codeblock_width, band->coord[0][1] - band->coord[0][0] + x0); + xx1 = FFMIN(xx1 + (1 << band->log2_cblk_width), band->coord[0][1] - band->coord[0][0] + x0); } yy0 = yy1; - yy1 = FFMIN(yy1 + band->codeblock_height, band->coord[1][1] - band->coord[1][0] + y0); + yy1 = FFMIN(yy1 + (1 << band->log2_cblk_height), band->coord[1][1] - band->coord[1][0] + y0); } } } @@ -969,8 +969,8 @@ static av_cold int j2kenc_init(AVCodecContext *avctx) // defaults: // TODO: implement setting non-standard precinct size - codsty->log2_prec_width = 15; - codsty->log2_prec_height = 15; + memset(codsty->log2_prec_widths , 15, sizeof(codsty->log2_prec_widths )); + memset(codsty->log2_prec_heights, 15, sizeof(codsty->log2_prec_heights)); codsty->nreslevels = 7; codsty->log2_cblk_width = 4; codsty->log2_cblk_height = 4; diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h index c2d6d90789..e15fa788ef 100644 --- a/libavcodec/jpeg2000.h +++ b/libavcodec/jpeg2000.h @@ -134,8 +134,6 @@ typedef struct Jpeg2000CodingStyle { log2_cblk_height; // exponent of codeblock size uint8_t transform; // DWT type uint8_t csty; // coding style - uint8_t log2_prec_width, - log2_prec_height; // precinct size uint8_t nlayers; // number of layers uint8_t mct; // multiple component transformation uint8_t cblk_style; // codeblock coding style diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 6bd9eb01a4..99b6643763 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -256,6 +256,10 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) if (bytestream2_get_bytes_left(&s->g) < 5) return AVERROR(EINVAL); c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1 + if (c->nreslevels >= JPEG2000_MAX_RESLEVELS) { + av_log(s->avctx, AV_LOG_ERROR, "nreslevels %d is invalid\n", c->nreslevels); + return AVERROR_INVALIDDATA; + } /* compute number of resolution levels to decode */ if (c->nreslevels < s->reduction_factor) @@ -289,6 +293,9 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) c->log2_prec_widths[i] = byte & 0x0F; // precinct PPx c->log2_prec_heights[i] = (byte >> 4) & 0x0F; // precinct PPy } + } else { + memset(c->log2_prec_widths , 15, sizeof(c->log2_prec_widths )); + memset(c->log2_prec_heights, 15, sizeof(c->log2_prec_heights)); } return 0; } @@ -303,9 +310,6 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, if (bytestream2_get_bytes_left(&s->g) < 5) return AVERROR(EINVAL); - tmp.log2_prec_width = - tmp.log2_prec_height = 15; - tmp.csty = bytestream2_get_byteu(&s->g); // get progression order -- cgit v1.2.3