* JPEG 2000 image decoder
*/
+#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "avcodec.h"
uint8_t properties[4];
Jpeg2000CodingStyle codsty[4];
Jpeg2000QuantStyle qntsty[4];
- Jpeg2000TilePart tile_part[3];
+ Jpeg2000TilePart tile_part[4];
uint16_t tp_idx; // Tile-part index
} Jpeg2000Tile;
s->cdy[i] = bytestream2_get_byteu(&s->g);
if (s->cdx[i] != 1 || s->cdy[i] != 1) {
av_log(s->avctx, AV_LOG_ERROR, "unsupported/ CDxy values %d %d for component %d\n", s->cdx[i], s->cdy[i], i);
+ if (!s->cdx[i] || !s->cdy[i])
+ return AVERROR_INVALIDDATA;
}
}
uint8_t *properties)
{
Jpeg2000CodingStyle tmp;
- int compno;
+ int compno, ret;
if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL);
tmp.nlayers = bytestream2_get_be16u(&s->g);
tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation
- get_cox(s, &tmp);
+ if (tmp.mct && s->ncomponents < 3) {
+ av_log(s->avctx, AV_LOG_ERROR, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if ((ret = get_cox(s, &tmp)) < 0)
+ return ret;
+
for (compno = 0; compno < s->ncomponents; compno++)
if (!(properties[compno] & HAD_COC))
memcpy(c + compno, &tmp, sizeof(tmp));
static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
uint8_t *properties)
{
- int compno;
+ int compno, ret;
if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL);
c += compno;
c->csty = bytestream2_get_byteu(&s->g);
- get_cox(s, c);
+
+ if ((ret = get_cox(s, c)) < 0)
+ return ret;
properties[compno] |= HAD_COC;
return 0;
return AVERROR(EINVAL);
compno = bytestream2_get_byteu(&s->g);
+ if (compno >= s->ncomponents) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid compno\n");
+ return AVERROR_INVALIDDATA;
+ }
+
properties[compno] |= HAD_QCC;
return get_qcx(s, n - 1, q + compno);
}
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];
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];
}
} 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);
x = tile->comp[compno].coord[0][0] - s->image_offset_x;
dst = linel + (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);
- /* 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;
}
oldpos = bytestream2_tell(&s->g);
if (marker == JPEG2000_SOD) {
- Jpeg2000Tile *tile = s->tile + s->curtileno;
- Jpeg2000TilePart *tp = tile->tile_part + tile->tp_idx;
+ Jpeg2000Tile *tile;
+ Jpeg2000TilePart *tp;
+ if (s->curtileno < 0) {
+ av_log(s->avctx, AV_LOG_ERROR, "Missing SOT\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);
break;
case JPEG2000_SOT:
if (!(ret = get_sot(s, len))) {
+ av_assert1(s->curtileno >= 0);
codsty = s->tile[s->curtileno].codsty;
qntsty = s->tile[s->curtileno].qntsty;
properties = s->tile[s->curtileno].properties;
goto end;
/* get picture buffer */
- if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "ff_thread_get_buffer() failed.\n");
+ if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
goto end;
- }
picture->pict_type = AV_PICTURE_TYPE_I;
picture->key_frame = 1;