X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fjpeg2000dec.c;h=8f38c1d784acb55cb317b6d827504c98bb6cbc10;hb=0416b5e0330c5eb226f92cf6c150eb6b7daa8b92;hp=21cc67d0b89d39c0f501766a0c2323191aad28ae;hpb=ad072a134fc02a1387107710acbdf29d21c8abc5;p=ffmpeg diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 21cc67d0b89..8f38c1d784a 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -60,7 +60,7 @@ typedef struct Jpeg2000Tile { uint8_t properties[4]; Jpeg2000CodingStyle codsty[4]; Jpeg2000QuantStyle qntsty[4]; - Jpeg2000TilePart tile_part[6]; + Jpeg2000TilePart tile_part[256]; uint16_t tp_idx; // Tile-part index } Jpeg2000Tile; @@ -133,8 +133,10 @@ static int tag_tree_decode(Jpeg2000DecoderContext *s, Jpeg2000TgtNode *node, Jpeg2000TgtNode *stack[30]; int sp = -1, curval = 0; - if (!node) + if (!node) { + av_log(s->avctx, AV_LOG_ERROR, "missing node\n"); return AVERROR_INVALIDDATA; + } while (node && !node->vis) { stack[++sp] = node; @@ -237,8 +239,10 @@ static int get_siz(Jpeg2000DecoderContext *s) const enum AVPixelFormat *possible_fmts = NULL; int possible_fmts_nb = 0; - if (bytestream2_get_bytes_left(&s->g) < 36) + if (bytestream2_get_bytes_left(&s->g) < 36) { + av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for SIZ\n"); return AVERROR_INVALIDDATA; + } s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz s->width = bytestream2_get_be32u(&s->g); // Width @@ -276,8 +280,10 @@ static int get_siz(Jpeg2000DecoderContext *s) return AVERROR_INVALIDDATA; } - if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents) + if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents) { + av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for %d components in SIZ\n", s->ncomponents); return AVERROR_INVALIDDATA; + } for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i uint8_t x = bytestream2_get_byteu(&s->g); @@ -398,8 +404,10 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) { uint8_t byte; - if (bytestream2_get_bytes_left(&s->g) < 5) + if (bytestream2_get_bytes_left(&s->g) < 5) { + av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for COX\n"); return AVERROR_INVALIDDATA; + } /* nreslevels = number of resolution levels = number of decomposition level +1 */ @@ -468,8 +476,10 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, Jpeg2000CodingStyle tmp; int compno, ret; - if (bytestream2_get_bytes_left(&s->g) < 5) + if (bytestream2_get_bytes_left(&s->g) < 5) { + av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for COD\n"); return AVERROR_INVALIDDATA; + } tmp.csty = bytestream2_get_byteu(&s->g); @@ -502,8 +512,10 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, { int compno, ret; - if (bytestream2_get_bytes_left(&s->g) < 2) + if (bytestream2_get_bytes_left(&s->g) < 2) { + av_log(s->avctx, AV_LOG_ERROR, "Insufficient space for COC\n"); return AVERROR_INVALIDDATA; + } compno = bytestream2_get_byteu(&s->g); @@ -615,7 +627,7 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) Jpeg2000TilePart *tp; uint16_t Isot; uint32_t Psot; - uint8_t TPsot; + unsigned TPsot; if (bytestream2_get_bytes_left(&s->g) < 8) return AVERROR_INVALIDDATA; @@ -640,10 +652,7 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) return AVERROR_INVALIDDATA; } - if (TPsot >= FF_ARRAY_ELEMS(s->tile[Isot].tile_part)) { - avpriv_request_sample(s->avctx, "Support for %"PRIu8" components", TPsot); - return AVERROR_PATCHWELCOME; - } + av_assert0(TPsot < FF_ARRAY_ELEMS(s->tile[Isot].tile_part)); s->tile[Isot].tp_idx = TPsot; tp = s->tile[Isot].tile_part + TPsot; @@ -800,6 +809,9 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, } } + if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES) + bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH); + if (!(ret = get_bits(s, 1))) { jpeg2000_flush(s); return 0; @@ -903,8 +915,8 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, || sizeof(cblk->data) < cblk->length + cblk->lengthinc[cwsno] + 4 ) { av_log(s->avctx, AV_LOG_ERROR, - "Block length %"PRIu16" or lengthinc %d is too large\n", - cblk->length, cblk->lengthinc[cwsno]); + "Block length %"PRIu16" or lengthinc %d is too large, left %d\n", + cblk->length, cblk->lengthinc[cwsno], bytestream2_get_bytes_left(&s->g)); return AVERROR_INVALIDDATA; } @@ -961,6 +973,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile break; case JPEG2000_PGOD_LRCP: + av_log(s->avctx, AV_LOG_DEBUG, "Progression order LRCP\n"); for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { ok_reslevel = 1; for (reslevelno = 0; ok_reslevel; reslevelno++) { @@ -986,6 +999,7 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile break; case JPEG2000_PGOD_CPRL: + av_log(s->avctx, AV_LOG_DEBUG, "Progression order CPRL\n"); for (compno = 0; compno < s->ncomponents; compno++) { Jpeg2000Component *comp = tile->comp + compno; Jpeg2000CodingStyle *codsty = tile->codsty + compno; @@ -1085,6 +1099,9 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile int xc = x / s->cdx[compno]; int yc = y / s->cdy[compno]; + if (reslevelno >= codsty->nreslevels) + continue; + if (yc % (1 << (rlevel->log2_prec_height + reducedresno))) continue; @@ -1099,16 +1116,13 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile precno = prcx + rlevel->num_precincts_x * prcy; + ok_reslevel = 1; if (prcx >= rlevel->num_precincts_x || prcy >= rlevel->num_precincts_y) { av_log(s->avctx, AV_LOG_WARNING, "prc %d %d outside limits %d %d\n", prcx, prcy, rlevel->num_precincts_x, rlevel->num_precincts_y); continue; } - if (reslevelno < codsty->nreslevels) { - Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel + - reslevelno; - ok_reslevel = 1; for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { if ((ret = jpeg2000_decode_packet(s, tile, &tp_index, codsty, rlevel, @@ -1117,7 +1131,6 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile qntsty->nguardbits)) < 0) return ret; } - } } } } @@ -1211,13 +1224,13 @@ static void decode_sigpass(Jpeg2000T1Context *t1, int width, int height, 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) + 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 | JPEG2000_T1_SGN_S); + if ((t1->flags[y+1][x+1] & JPEG2000_T1_SIG_NB & flags_mask) && !(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); + int xorbit, ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y+1][x+1] & flags_mask, &xorbit); if (t1->mqc.raw) t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask; else @@ -1233,7 +1246,7 @@ static void decode_sigpass(Jpeg2000T1Context *t1, int width, int height, } static void decode_refpass(Jpeg2000T1Context *t1, int width, int height, - int bpno) + int bpno, int vert_causal_ctx_csty_symbol) { int phalf, nhalf; int y0, x, y; @@ -1245,7 +1258,9 @@ static void decode_refpass(Jpeg2000T1Context *t1, int width, int height, 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 | JPEG2000_T1_VIS)) == JPEG2000_T1_SIG) { - int ctxno = ff_jpeg2000_getrefctxno(t1->flags[y + 1][x + 1]); + int flags_mask = (vert_causal_ctx_csty_symbol && y == y0 + 3) ? + ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE | JPEG2000_T1_SGN_S) : -1; + int ctxno = ff_jpeg2000_getrefctxno(t1->flags[y + 1][x + 1] & flags_mask); int r = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? phalf : nhalf; @@ -1262,11 +1277,14 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1, for (y0 = 0; y0 < height; y0 += 4) { for (x = 0; x < width; x++) { + int flags_mask = -1; + if (vert_causal_ctx_csty_symbol) + flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE | JPEG2000_T1_SGN_S); if (y0 + 3 < height && !((t1->flags[y0 + 1][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) || (t1->flags[y0 + 2][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) || (t1->flags[y0 + 3][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)) || - (t1->flags[y0 + 4][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG)))) { + (t1->flags[y0 + 4][x + 1] & (JPEG2000_T1_SIG_NB | JPEG2000_T1_VIS | JPEG2000_T1_SIG) & flags_mask))) { if (!ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL)) continue; runlen = ff_mqc_decode(&t1->mqc, @@ -1281,18 +1299,18 @@ static void decode_clnpass(Jpeg2000DecoderContext *s, Jpeg2000T1Context *t1, } for (y = y0 + runlen; y < y0 + 4 && y < height; y++) { + 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 | JPEG2000_T1_SGN_S); if (!dec) { 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; - int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y + 1][x + 1], + int ctxno = ff_jpeg2000_getsgnctxno(t1->flags[y + 1][x + 1] & flags_mask, &xorbit); t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ @@ -1351,7 +1369,7 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, vert_causal_ctx_csty_symbol); break; case 1: - decode_refpass(t1, width, height, bpno + 1); + decode_refpass(t1, width, height, bpno + 1, vert_causal_ctx_csty_symbol); break; case 2: av_assert2(!t1->mqc.raw); @@ -1363,7 +1381,7 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, if (codsty->cblk_style & JPEG2000_CBLK_RESET) // XXX no testcase for just this ff_mqc_init_contexts(&t1->mqc); - if ((coder_type = needs_termination(codsty->cblk_style, pass_cnt))) { + if (passno && (coder_type = needs_termination(codsty->cblk_style, pass_cnt))) { if (term_cnt >= cblk->nb_terminations) { av_log(s->avctx, AV_LOG_ERROR, "Missing needed termination \n"); return AVERROR_INVALIDDATA; @@ -1378,6 +1396,12 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, } pass_cnt ++; } + + if (cblk->data + cblk->length - 2*(term_cnt < cblk->nb_terminations) != t1->mqc.bp) { + av_log(s->avctx, AV_LOG_WARNING, "End mismatch %"PTRDIFF_SPECIFIER"\n", + cblk->data + cblk->length - 2*(term_cnt < cblk->nb_terminations) - t1->mqc.bp); + } + return 0; } @@ -1505,8 +1529,8 @@ static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->coord[1][1] - cblk->coord[1][0], bandpos); - x = cblk->coord[0][0]; - y = cblk->coord[1][0]; + x = cblk->coord[0][0] - band->coord[0][0]; + y = cblk->coord[1][0] - band->coord[1][0]; if (codsty->transform == FF_DWT97) dequantization_float(x, y, cblk, comp, &t1, band); @@ -1700,8 +1724,10 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) break; len = bytestream2_get_be16(&s->g); - if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) + if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len, bytestream2_get_bytes_left(&s->g)); return AVERROR_INVALIDDATA; + } switch (marker) { case JPEG2000_SIZ: @@ -1767,11 +1793,11 @@ static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s) for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) { Jpeg2000Tile *tile = s->tile + tileno; - if (ret = init_tile(s, tileno)) + if ((ret = init_tile(s, tileno)) < 0) return ret; s->g = tile->tile_part[0].tpg; - if (ret = jpeg2000_decode_packets(s, tile)) + if ((ret = jpeg2000_decode_packets(s, tile)) < 0) return ret; }