X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fjpeg2000dec.c;h=cc154c3522dc1f335f163880448dcfe0ca58da15;hb=d711d839ca6714a5ef5b53ee51bc7632e62cf203;hp=15dfc2bcd35e722a934f65f571f2832732ce6449;hpb=daeb4e3042f2ecae2d41aaa4cae0bed932539788;p=ffmpeg diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 15dfc2bcd35..cc154c3522d 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -41,9 +41,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 +54,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 { @@ -119,6 +119,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; @@ -503,24 +506,18 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) 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; } @@ -577,12 +574,6 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno) 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(*tile->codsty)); - memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(*tile->qntsty)); - for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; Jpeg2000CodingStyle *codsty = tile->codsty + compno; @@ -724,6 +715,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 %d > data size %zd\n", + cblk->length, sizeof(cblk->data)); + return AVERROR_INVALIDDATA; + } } } return 0; @@ -731,13 +729,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 +808,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 +830,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 +888,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 +914,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 +936,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,6 +954,9 @@ 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(**t1->data)); @@ -955,14 +974,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; } @@ -986,13 +1013,14 @@ static void dequantization_float(int x, int y, Jpeg2000Cblk *cblk, Jpeg2000Component *comp, Jpeg2000T1Context *t1, Jpeg2000Band *band) { - int i, j, idx; - float *datap = &comp->f_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]) * band->f_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.*/ @@ -1000,14 +1028,14 @@ static void dequantization_int(int x, int y, Jpeg2000Cblk *cblk, Jpeg2000Component *comp, Jpeg2000T1Context *t1, Jpeg2000Band *band) { - int i, j, idx; - int32_t *datap = &comp->i_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]) * band->i_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. @@ -1098,6 +1126,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++) { @@ -1135,8 +1167,12 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, if (s->precision <= 8) { for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; + 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]) { @@ -1145,18 +1181,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]) { - int val; - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - if (tile->codsty->transform == FF_DWT97) - val = lrintf(*datap) + (1 << (s->cbps[compno] - 1)); - else - val = *i_datap + (1 << (s->cbps[compno] - 1)); - val = av_clip(val, 0, (1 << s->cbps[compno]) - 1); - *dst = val << (8 - s->cbps[compno]); - 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); + *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]; } @@ -1164,9 +1206,12 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } else { for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; + 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); @@ -1174,24 +1219,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]) { - int val; - /* DC level shift and clip see ISO 15444-1:2002 G.1.2 */ - if (tile->codsty->transform == FF_DWT97) - val = lrintf(*datap) + (1 << (s->cbps[compno] - 1)); - else - val = *i_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 << (16 - s->cbps[compno]); - 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; } @@ -1208,6 +1261,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) @@ -1237,6 +1291,10 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) 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; @@ -1269,7 +1327,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 @@ -1286,7 +1348,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) 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); return ret ? ret : -1; @@ -1299,12 +1361,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; } @@ -1402,6 +1470,7 @@ end: static void jpeg2000_init_static_data(AVCodec *codec) { ff_jpeg2000_init_tier1_luts(); + ff_mqc_init_context_tables(); } #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x)