X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fjpeg2000dec.c;h=7d081eadd1fe07c4d90131e808c62a388c87fc2a;hb=452860d7e056f9a894cac2fe52cdedeae4c38251;hp=1b409121526fca7f9f1a9bc59c10a409fea29282;hpb=2c3901b2c34b5e1f556d0e19c4cc218fdcbec695;p=ffmpeg diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 1b409121526..7d081eadd1f 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -25,6 +25,9 @@ * JPEG 2000 image decoder */ +#include + +#include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/opt.h" #include "avcodec.h" @@ -41,9 +44,8 @@ #define HAD_QCC 0x02 typedef struct Jpeg2000TilePart { - uint16_t tp_idx; // Tile-part index uint8_t tile_index; // Tile index who refers the tile-part - uint32_t tp_len; // Length of tile-part + const uint8_t *tp_end; GetByteContext tpg; // bit stream in tile-part } Jpeg2000TilePart; @@ -55,6 +57,7 @@ typedef struct Jpeg2000Tile { Jpeg2000CodingStyle codsty[4]; Jpeg2000QuantStyle qntsty[4]; Jpeg2000TilePart tile_part[3]; + uint16_t tp_idx; // Tile-part index } Jpeg2000Tile; typedef struct Jpeg2000DecoderContext { @@ -84,8 +87,7 @@ typedef struct Jpeg2000DecoderContext { Jpeg2000Tile *tile; /*options parameters*/ - int16_t lowres; - int16_t reduction_factor; + int reduction_factor; } Jpeg2000DecoderContext; /* get_bits functions for JPEG2000 packet bitstream @@ -120,6 +122,9 @@ static int tag_tree_decode(Jpeg2000DecoderContext *s, Jpeg2000TgtNode *node, Jpeg2000TgtNode *stack[30]; int sp = -1, curval = 0; + if (!node) + return AVERROR_INVALIDDATA; + while (node && !node->vis) { stack[++sp] = node; node = node->parent; @@ -236,37 +241,35 @@ static int get_siz(Jpeg2000DecoderContext *s) s->avctx->height = ff_jpeg2000_ceildivpow2(s->height - s->image_offset_y, s->reduction_factor); - switch (s->avctx->profile) { - case FF_PROFILE_JPEG2000_DCINEMA_2K: - case FF_PROFILE_JPEG2000_DCINEMA_4K: - /* XYZ color-space for digital cinema profiles */ - s->avctx->pix_fmt = AV_PIX_FMT_XYZ12; + switch (s->ncomponents) { + case 1: + if (s->precision > 8) + s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; + else + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; break; - default: - /* For other profiles selects color-space according number of - * components and bit depth precision. */ - switch (s->ncomponents) { - case 1: - if (s->precision > 8) - s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; - else - s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + case 3: + switch (s->avctx->profile) { + case FF_PROFILE_JPEG2000_DCINEMA_2K: + case FF_PROFILE_JPEG2000_DCINEMA_4K: + /* XYZ color-space for digital cinema profiles */ + s->avctx->pix_fmt = AV_PIX_FMT_XYZ12; break; - case 3: + default: if (s->precision > 8) s->avctx->pix_fmt = AV_PIX_FMT_RGB48; else s->avctx->pix_fmt = AV_PIX_FMT_RGB24; break; - case 4: - s->avctx->pix_fmt = AV_PIX_FMT_BGRA; - break; - default: - /* pixel format can not be identified */ - s->avctx->pix_fmt = AV_PIX_FMT_NONE; - break; } break; + case 4: + s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; + default: + /* pixel format can not be identified */ + s->avctx->pix_fmt = AV_PIX_FMT_NONE; + break; } return 0; } @@ -343,6 +346,13 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, tmp.nlayers = bytestream2_get_be16u(&s->g); tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation + if (tmp.mct && s->ncomponents < 3) { + av_log(s->avctx, AV_LOG_ERROR, + "MCT %"PRIu8" with too few components (%d)\n", + tmp.mct, s->ncomponents); + return AVERROR_INVALIDDATA; + } + if ((ret = get_cox(s, &tmp)) < 0) return ret; @@ -490,33 +500,27 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) bytestream2_get_byteu(&s->g); // TNsot if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) { - av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot); + av_log(s->avctx, AV_LOG_ERROR, "Psot %"PRIu32" too big\n", Psot); return AVERROR_INVALIDDATA; } if (TPsot >= FF_ARRAY_ELEMS(s->tile[Isot].tile_part)) { - avpriv_request_sample(s->avctx, "Support for %d components", TPsot); + avpriv_request_sample(s->avctx, "Support for %"PRIu8" components", TPsot); return AVERROR_PATCHWELCOME; } - tp = s->tile[s->curtileno].tile_part + TPsot; + s->tile[Isot].tp_idx = TPsot; + tp = s->tile[Isot].tile_part + TPsot; tp->tile_index = Isot; - tp->tp_len = Psot; - tp->tp_idx = TPsot; - - /* Start of bit stream. Pointer to SOD marker - * Check SOD marker is present. */ - if (JPEG2000_SOD == bytestream2_get_be16(&s->g)) { - bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_len - n - 4); - bytestream2_skip(&s->g, tp->tp_len - n - 4); - } else { - av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n"); - return AVERROR_INVALIDDATA; - } + tp->tp_end = s->g.buffer + Psot - n - 2; - /* End address of bit stream = - * start address + (Psot - size of SOT HEADER(n) - * - size of SOT MARKER(2) - size of SOD marker(2) */ + if (!TPsot) { + Jpeg2000Tile *tile = s->tile + s->curtileno; + + /* copy defaults */ + memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(Jpeg2000CodingStyle)); + memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(Jpeg2000QuantStyle)); + } return 0; } @@ -569,35 +573,25 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno) int tilex = tileno % s->numXtiles; int tiley = tileno / s->numXtiles; Jpeg2000Tile *tile = s->tile + tileno; - Jpeg2000CodingStyle *codsty; - Jpeg2000QuantStyle *qntsty; if (!tile->comp) return AVERROR(ENOMEM); - /* copy codsty, qnsty to tile. TODO: Is it the best way? - * codsty, qnsty is an array of 4 structs Jpeg2000CodingStyle - * and Jpeg2000QuantStyle */ - memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(*codsty)); - memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(*qntsty)); - for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + Jpeg2000QuantStyle *qntsty = tile->qntsty + compno; int ret; // global bandno - codsty = tile->codsty + compno; - qntsty = tile->qntsty + compno; 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); - // 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], @@ -724,6 +718,13 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, } cblk->length += cblk->lengthinc; cblk->lengthinc = 0; + + if (cblk->length > sizeof(cblk->data)) { + av_log(s->avctx, AV_LOG_ERROR, + "Block length %"PRIu16" > data size %zd\n", + cblk->length, sizeof(cblk->data)); + return AVERROR_INVALIDDATA; + } } } return 0; @@ -731,13 +732,12 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) { - int layno, reslevelno, compno, precno, ok_reslevel, ret; - uint8_t prog_order = tile->codsty[0].prog_order; - uint16_t x; - uint16_t y; + int ret = 0; + int layno, reslevelno, compno, precno, ok_reslevel; + int x, y; s->bit_index = 8; - switch (prog_order) { + switch (tile->codsty[0].prog_order) { case JPEG2000_PGOD_LRCP: for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { ok_reslevel = 1; @@ -811,6 +811,21 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile } break; + case JPEG2000_PGOD_RLCP: + avpriv_request_sample(s->avctx, "Progression order RLCP"); + ret = AVERROR_PATCHWELCOME; + break; + + case JPEG2000_PGOD_RPCL: + avpriv_request_sample(s->avctx, "Progression order RPCL"); + ret = AVERROR_PATCHWELCOME; + break; + + case JPEG2000_PGOD_PCRL: + avpriv_request_sample(s->avctx, "Progression order PCRL"); + ret = AVERROR_PATCHWELCOME; + break; + default: break; } @@ -818,37 +833,38 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile /* EOC marker reached */ bytestream2_skip(&s->g, 2); - return 0; + return ret; } /* TIER-1 routines */ static void decode_sigpass(Jpeg2000T1Context *t1, int width, int height, - int bpno, int bandno) + int bpno, int bandno, int bpass_csty_symbol, + int vert_causal_ctx_csty_symbol) { int mask = 3 << (bpno - 1), y0, x, y; for (y0 = 0; y0 < height; y0 += 4) for (x = 0; x < width; x++) - for (y = y0; y < height && y < y0 + 4; y++) - if ((t1->flags[y + 1][x + 1] & JPEG2000_T1_SIG_NB) - && !(t1->flags[y + 1][x + 1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) { - if (ff_mqc_decode(&t1->mqc, - t1->mqc.cx_states + - ff_jpeg2000_getsigctxno(t1->flags[y + 1][x + 1], - bandno))) { - int xorbit, ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y + 1][x + 1], - &xorbit); - - t1->data[y][x] = - (ff_mqc_decode(&t1->mqc, - t1->mqc.cx_states + ctxno) ^ xorbit) - ? -mask : mask; + for (y = y0; y < height && y < y0 + 4; y++) { + if ((t1->flags[y+1][x+1] & JPEG2000_T1_SIG_NB) + && !(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) { + int flags_mask = -1; + if (vert_causal_ctx_csty_symbol && y == y0 + 3) + flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE); + if (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1] & flags_mask, bandno))) { + int xorbit, ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1], &xorbit); + if (bpass_csty_symbol) + t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask; + else + t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ? + -mask : mask; ff_jpeg2000_set_significance(t1, x, y, t1->data[y][x] < 0); } t1->flags[y + 1][x + 1] |= JPEG2000_T1_VIS; } + } } static void decode_refpass(Jpeg2000T1Context *t1, int width, int height, @@ -875,11 +891,11 @@ static void decode_refpass(Jpeg2000T1Context *t1, int width, int height, static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1, int width, int height, int bpno, int bandno, - int seg_symbols) + int seg_symbols, int vert_causal_ctx_csty_symbol) { int mask = 3 << (bpno - 1), y0, x, y, runlen, dec; - for (y0 = 0; y0 < height; y0 += 4) + for (y0 = 0; y0 < height; y0 += 4) { for (x = 0; x < width; x++) { if (y0 + 3 < height && !((t1->flags[y0 + 1][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) || @@ -901,11 +917,13 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1, for (y = y0 + runlen; y < y0 + 4 && y < height; y++) { if (!dec) { - if (!(t1->flags[y + 1][x + 1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) - dec = ff_mqc_decode(&t1->mqc, - t1->mqc.cx_states + - ff_jpeg2000_getsigctxno(t1->flags[y + 1][x + 1], - bandno)); + if (!(t1->flags[y+1][x+1] & (JPEG2000_T1_SIG | JPEG2000_T1_VIS))) { + int flags_mask = -1; + if (vert_causal_ctx_csty_symbol && y == y0 + 3) + flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE); + dec = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_jpeg2000_getsigctxno(t1->flags[y+1][x+1] & flags_mask, + bandno)); + } } if (dec) { int xorbit; @@ -921,6 +939,7 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1, t1->flags[y + 1][x + 1] &= ~JPEG2000_T1_VIS; } } + } if (seg_symbols) { int val; val = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI); @@ -938,14 +957,18 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, int width, int height, int bandpos) { int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y; + int clnpass_cnt = 0; + int bpass_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_BYPASS; + int vert_causal_ctx_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_VSC; for (y = 0; y < height; y++) - memset(t1->data[y], 0, width * sizeof(width)); + memset(t1->data[y], 0, width * sizeof(**t1->data)); + /* If code-block contains no compressed data: nothing to do. */ if (!cblk->length) return 0; for (y = 0; y < height + 2; y++) - memset(t1->flags[y], 0, (width + 2) * sizeof(width)); + memset(t1->flags[y], 0, (width + 2) * sizeof(**t1->flags)); ff_mqc_initdec(&t1->mqc, cblk->data); cblk->data[cblk->length] = 0xff; @@ -954,14 +977,22 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, while (passno--) { switch (pass_t) { case 0: - decode_sigpass(t1, width, height, bpno + 1, bandpos); + decode_sigpass(t1, width, height, bpno + 1, bandpos, + bpass_csty_symbol && (clnpass_cnt >= 4), + vert_causal_ctx_csty_symbol); break; case 1: decode_refpass(t1, width, height, bpno + 1); + if (bpass_csty_symbol && clnpass_cnt >= 4) + ff_mqc_initdec(&t1->mqc, cblk->data); break; case 2: decode_clnpass(s, t1, width, height, bpno + 1, bandpos, - codsty->cblk_style & JPEG2000_CBLK_SEGSYM); + codsty->cblk_style & JPEG2000_CBLK_SEGSYM, + vert_causal_ctx_csty_symbol); + clnpass_cnt = clnpass_cnt + 1; + if (bpass_csty_symbol && clnpass_cnt >= 4) + ff_mqc_initdec(&t1->mqc, cblk->data); break; } @@ -985,13 +1016,14 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk, Jpeg2000Component *comp, Jpeg2000T1Context *t1, Jpeg2000Band *band) { - int i, j, idx; - float *datap = &comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]; - for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) - for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) { - idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i; - datap[idx] = (float)(t1->data[j][i]) * ((float)band->stepsize); - } + int i, j; + int w = cblk->coord[0][1] - cblk->coord[0][0]; + for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) { + float *datap = &comp->f_data[(comp->coord[0][1] - comp->coord[0][0]) * (y + j) + x]; + int *src = t1->data[j]; + for (i = 0; i < w; ++i) + datap[i] = src[i] * band->f_stepsize; + } } /* Integer dequantization of a codeblock.*/ @@ -999,15 +1031,14 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk, Jpeg2000Component *comp, Jpeg2000T1Context *t1, Jpeg2000Band *band) { - int i, j, idx; - int32_t *datap = - (int32_t *) &comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x]; - for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) - for (i = 0; i < (cblk->coord[0][1] - cblk->coord[0][0]); ++i) { - idx = (comp->coord[0][1] - comp->coord[0][0]) * j + i; - datap[idx] = - ((int32_t)(t1->data[j][i]) * ((int32_t)band->stepsize) + (1 << 15)) >> 16; - } + int i, j; + int w = cblk->coord[0][1] - cblk->coord[0][0]; + for (j = 0; j < (cblk->coord[1][1] - cblk->coord[1][0]); ++j) { + int32_t *datap = &comp->i_data[(comp->coord[0][1] - comp->coord[0][0]) * (y + j) + x]; + int *src = t1->data[j]; + for (i = 0; i < w; ++i) + datap[i] = (src[i] * band->i_stepsize + (1 << 15)) >> 16; + } } /* Inverse ICT parameters in float and integer. @@ -1033,9 +1064,9 @@ static void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) for (i = 0; i < 3; i++) if (tile->codsty[0].transform == FF_DWT97) - srcf[i] = tile->comp[i].data; + srcf[i] = tile->comp[i].f_data; else - src[i] = (int32_t *)tile->comp[i].data; + src [i] = tile->comp[i].i_data; for (i = 0; i < 2; i++) csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0]; @@ -1098,6 +1129,10 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int cblkno = 0, bandpos; bandpos = bandno + (reslevelno > 0); + if (band->coord[0][0] == band->coord[0][1] || + band->coord[1][0] == band->coord[1][1]) + continue; + nb_precincts = rlevel->num_precincts_x * rlevel->num_precincts_y; /* Loop on precincts */ for (precno = 0; precno < nb_precincts; precno++) { @@ -1112,42 +1147,35 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->coord[1][1] - cblk->coord[1][0], bandpos); - /* Manage band offsets */ x = cblk->coord[0][0]; y = cblk->coord[1][0]; - if ((reslevelno > 0) && ((bandno + 1) & 1)) { - Jpeg2000ResLevel *pres = comp->reslevel + (reslevelno - 1); - x += pres->coord[0][1] - pres->coord[0][0]; - } - if ((reslevelno > 0) && ((bandno + 1) & 2)) { - Jpeg2000ResLevel *pres = comp->reslevel + (reslevelno - 1); - y += pres->coord[1][1] - pres->coord[1][0]; - } - if (s->avctx->flags & CODEC_FLAG_BITEXACT) - dequantization_int(x, y, cblk, comp, &t1, band); - else + if (codsty->transform == FF_DWT97) dequantization_float(x, y, cblk, comp, &t1, band); + else + dequantization_int(x, y, cblk, comp, &t1, band); } /* end cblk */ } /*end prec */ } /* end band */ } /* end reslevel */ /* inverse DWT */ - ff_dwt_decode(&comp->dwt, comp->data); + ff_dwt_decode(&comp->dwt, codsty->transform == FF_DWT97 ? (void*)comp->f_data : (void*)comp->i_data); } /*end comp */ /* inverse MCT transformation */ if (tile->codsty[0].mct) mct_decode(s, tile); - if (s->avctx->pix_fmt == AV_PIX_FMT_BGRA) // RGBA -> BGRA - FFSWAP(float *, tile->comp[0].data, tile->comp[2].data); - if (s->precision <= 8) { for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; - int32_t *datap = (int32_t *)comp->data; + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + 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; + y = tile->comp[compno].coord[1][0] - s->image_offset_y; line = picture->data[0] + y * picture->linesize[0]; for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) { @@ -1156,14 +1184,24 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, x = tile->comp[compno].coord[0][0] - s->image_offset_x; dst = line + x * s->ncomponents + compno; - for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) { - *datap += 1 << (s->cbps[compno] - 1); - if (*datap < 0) - *datap = 0; - else if (*datap >= (1 << s->cbps[compno])) - *datap = (1 << s->cbps[compno]) - 1; - *dst = *datap++; - dst += s->ncomponents; + if (codsty->transform == FF_DWT97) { + for (; x < w; x += s->cdx[compno]) { + int val = lrintf(*datap) + (1 << (cbps - 1)); + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ + val = av_clip(val, 0, (1 << cbps) - 1); + *dst = val << (8 - cbps); + datap++; + dst += s->ncomponents; + } + } else { + for (; x < w; x += s->cdx[compno]) { + int val = *i_datap + (1 << (cbps - 1)); + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ + val = av_clip(val, 0, (1 << cbps) - 1); + *dst = val << (8 - cbps); + i_datap++; + dst += s->ncomponents; + } } line += picture->linesize[0]; } @@ -1171,9 +1209,12 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } else { for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; - float *datap = comp->data; - int32_t *i_datap = (int32_t *) comp->data; + Jpeg2000CodingStyle *codsty = tile->codsty + compno; + float *datap = comp->f_data; + int32_t *i_datap = comp->i_data; uint16_t *linel; + int cbps = s->cbps[compno]; + int w = tile->comp[compno].coord[0][1] - s->image_offset_x; y = tile->comp[compno].coord[1][0] - s->image_offset_y; linel = (uint16_t *)picture->data[0] + y * (picture->linesize[0] >> 1); @@ -1181,24 +1222,32 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, uint16_t *dst; x = tile->comp[compno].coord[0][0] - s->image_offset_x; dst = linel + (x * s->ncomponents + compno); - for (; x < s->avctx->width; x += s->cdx[compno]) { - int16_t val; - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - if (s->avctx->flags & CODEC_FLAG_BITEXACT) - val = *i_datap + (1 << (s->cbps[compno] - 1)); - else - val = lrintf(*datap) + (1 << (s->cbps[compno] - 1)); - val = av_clip(val, 0, (1 << s->cbps[compno]) - 1); - /* align 12 bit values in little-endian mode */ - *dst = val << 4; - datap++; - i_datap++; - dst += s->ncomponents; + if (codsty->transform == FF_DWT97) { + for (; x < w; x += s-> cdx[compno]) { + int val = lrintf(*datap) + (1 << (cbps - 1)); + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ + val = av_clip(val, 0, (1 << cbps) - 1); + /* align 12 bit values in little-endian mode */ + *dst = val << (16 - cbps); + datap++; + dst += s->ncomponents; + } + } else { + for (; x < w; x += s-> cdx[compno]) { + int val = *i_datap + (1 << (cbps - 1)); + /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ + val = av_clip(val, 0, (1 << cbps) - 1); + /* align 12 bit values in little-endian mode */ + *dst = val << (16 - cbps); + i_datap++; + dst += s->ncomponents; + } } linel += picture->linesize[0] >> 1; } } } + return 0; } @@ -1215,6 +1264,7 @@ static void jpeg2000_dec_cleanup(Jpeg2000DecoderContext *s) av_freep(&s->tile[tileno].comp); } av_freep(&s->tile); + s->numXtiles = s->numYtiles = 0; } static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) @@ -1236,6 +1286,26 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) marker = bytestream2_get_be16u(&s->g); oldpos = bytestream2_tell(&s->g); + if (marker == JPEG2000_SOD) { + Jpeg2000Tile *tile; + Jpeg2000TilePart *tp; + + if (s->curtileno < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Missing SOT\n"); + return AVERROR_INVALIDDATA; + } + if (!s->tile) { + av_log(s->avctx, AV_LOG_ERROR, "Missing SIZ\n"); + return AVERROR_INVALIDDATA; + } + + tile = s->tile + s->curtileno; + tp = tile->tile_part + tile->tp_idx; + bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer); + bytestream2_skip(&s->g, tp->tp_end - s->g.buffer); + + continue; + } if (marker == JPEG2000_EOC) break; @@ -1260,7 +1330,11 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) ret = get_qcd(s, len, qntsty, properties); break; case JPEG2000_SOT: - ret = get_sot(s, len); + if (!(ret = get_sot(s, len))) { + codsty = s->tile[s->curtileno].codsty; + qntsty = s->tile[s->curtileno].qntsty; + properties = s->tile[s->curtileno].properties; + } break; case JPEG2000_COM: // the comment is ignored @@ -1272,14 +1346,15 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) break; default: av_log(s->avctx, AV_LOG_ERROR, - "unsupported marker 0x%.4X at pos 0x%X\n", + "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n", marker, bytestream2_tell(&s->g) - 4); bytestream2_skip(&s->g, len - 2); break; } - if (((bytestream2_tell(&s->g) - oldpos != len) && (marker != JPEG2000_SOT)) || ret) { + if (bytestream2_tell(&s->g) - oldpos != len || ret) { av_log(s->avctx, AV_LOG_ERROR, - "error during processing marker segment %.4x\n", marker); + "error during processing marker segment %.4"PRIx16"\n", + marker); return ret ? ret : -1; } } @@ -1290,12 +1365,18 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s) { int ret = 0; - Jpeg2000Tile *tile = s->tile + s->curtileno; + int tileno; - if (ret = init_tile(s, s->curtileno)) - return ret; - if (ret = jpeg2000_decode_packets(s, tile)) - return ret; + for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) { + Jpeg2000Tile *tile = s->tile + tileno; + + if (ret = init_tile(s, tileno)) + return ret; + + s->g = tile->tile_part[0].tpg; + if (ret = jpeg2000_decode_packets(s, tile)) + return ret; + } return 0; } @@ -1337,11 +1418,10 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, bytestream2_init(&s->g, avpkt->data, avpkt->size); s->curtileno = 0; // TODO: only one tile in DCI JP2K. to implement for more tiles - // reduction factor, i.e number of resolution levels to skip - s->reduction_factor = s->lowres; - - if (bytestream2_get_bytes_left(&s->g) < 2) - return AVERROR_INVALIDDATA; + if (bytestream2_get_bytes_left(&s->g) < 2) { + ret = AVERROR_INVALIDDATA; + goto end; + } // check if the image is in jp2 format if (bytestream2_get_bytes_left(&s->g) >= 12 && @@ -1351,17 +1431,17 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, if (!jp2_find_codestream(s)) { av_log(avctx, AV_LOG_ERROR, "Could not find Jpeg2000 codestream atom.\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto end; } } else { bytestream2_seek(&s->g, 0, SEEK_SET); - if (bytestream2_peek_be16(&s->g) != JPEG2000_SOC) - bytestream2_skip(&s->g, 8); } if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) { av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto end; } if (ret = jpeg2000_read_main_headers(s)) goto end; @@ -1380,6 +1460,8 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, if (ret = jpeg2000_decode_tile(s, s->tile + tileno, picture)) goto end; + jpeg2000_dec_cleanup(s); + *got_frame = 1; return bytestream2_tell(&s->g); @@ -1389,9 +1471,10 @@ end: return ret; } -static void jpeg2000_init_static_data(AVCodec *codec) +static av_cold void jpeg2000_init_static_data(AVCodec *codec) { ff_jpeg2000_init_tier1_luts(); + ff_mqc_init_context_tables(); } #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x) @@ -1399,7 +1482,7 @@ static void jpeg2000_init_static_data(AVCodec *codec) 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 }, + OFFSET(reduction_factor), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, JPEG2000_MAX_RESLEVELS - 1, VD }, { NULL }, }; @@ -1429,8 +1512,5 @@ AVCodec ff_jpeg2000_decoder = { .init_static_data = jpeg2000_init_static_data, .decode = jpeg2000_decode_frame, .priv_class = &class, - .pix_fmts = (enum AVPixelFormat[]) { AV_PIX_FMT_XYZ12, - AV_PIX_FMT_GRAY8, - -1 }, .profiles = NULL_IF_CONFIG_SMALL(profiles) };