static int get_siz(Jpeg2000DecoderContext *s)
{
int i;
- return AVERROR(EINVAL);
+ int ncomponents;
+
+ if (bytestream2_get_bytes_left(&s->g) < 36)
++ return AVERROR_INVALIDDATA;
- if (s->buf_end - s->buf < 36)
+ s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz
+ s->width = bytestream2_get_be32u(&s->g); // Width
+ s->height = bytestream2_get_be32u(&s->g); // Height
+ s->image_offset_x = bytestream2_get_be32u(&s->g); // X0Siz
+ s->image_offset_y = bytestream2_get_be32u(&s->g); // Y0Siz
+ s->tile_width = bytestream2_get_be32u(&s->g); // XTSiz
+ s->tile_height = bytestream2_get_be32u(&s->g); // YTSiz
+ s->tile_offset_x = bytestream2_get_be32u(&s->g); // XT0Siz
+ s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
+ ncomponents = bytestream2_get_be16u(&s->g); // CSiz
+
+ if (ncomponents <= 0 || ncomponents > 4) {
+ av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", ncomponents);
- return AVERROR(EINVAL);
++ return AVERROR_INVALIDDATA;
+ }
+ s->ncomponents = ncomponents;
+
+ if (s->tile_width<=0 || s->tile_height<=0)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- s->avctx->profile = bytestream_get_be16(&s->buf); // Rsiz
- s->width = bytestream_get_be32(&s->buf); // Width
- s->height = bytestream_get_be32(&s->buf); // Height
- s->image_offset_x = bytestream_get_be32(&s->buf); // X0Siz
- s->image_offset_y = bytestream_get_be32(&s->buf); // Y0Siz
- s->tile_width = bytestream_get_be32(&s->buf); // XTSiz
- s->tile_height = bytestream_get_be32(&s->buf); // YTSiz
- s->tile_offset_x = bytestream_get_be32(&s->buf); // XT0Siz
- s->tile_offset_y = bytestream_get_be32(&s->buf); // YT0Siz
- s->ncomponents = bytestream_get_be16(&s->buf); // CSiz
-
- if (s->buf_end - s->buf < 2 * s->ncomponents)
+ if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i
- uint8_t x = bytestream_get_byte(&s->buf);
+ uint8_t x = bytestream2_get_byteu(&s->g);
s->cbps[i] = (x & 0x7f) + 1;
s->precision = FFMAX(s->cbps[i], s->precision);
- s->sgnd[i] = (x & 0x80) == 1;
- s->cdx[i] = bytestream_get_byte(&s->buf);
- s->cdy[i] = bytestream_get_byte(&s->buf);
+ s->sgnd[i] = !!(x & 0x80);
+ s->cdx[i] = bytestream2_get_byteu(&s->g);
+ 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;
+ }
}
s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width);
{
uint8_t byte;
- if (s->buf_end - s->buf < 5)
- return AVERROR(EINVAL);
+ if (bytestream2_get_bytes_left(&s->g) < 5)
- return AVERROR(EINVAL);
++ return AVERROR_INVALIDDATA;
/* nreslevels = number of resolution levels
= number of decomposition level +1 */
- c->nreslevels = bytestream_get_byte(&s->buf) + 1;
-
- if (c->nreslevels > JPEG2000_MAX_RESLEVELS)
+ c->nreslevels = bytestream2_get_byteu(&s->g) + 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)
uint8_t *properties)
{
Jpeg2000CodingStyle tmp;
- int compno;
+ int compno, ret;
- if (s->buf_end - s->buf < 5)
+ if (bytestream2_get_bytes_left(&s->g) < 5)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- tmp.log2_prec_width =
- tmp.log2_prec_height = 15;
-
- tmp.csty = bytestream_get_byte(&s->buf);
+ tmp.csty = bytestream2_get_byteu(&s->g);
// get progression order
- tmp.prog_order = bytestream_get_byte(&s->buf);
+ tmp.prog_order = bytestream2_get_byteu(&s->g);
+
+ tmp.nlayers = bytestream2_get_be16u(&s->g);
+ tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation
- tmp.nlayers = bytestream_get_be16(&s->buf);
- tmp.mct = bytestream_get_byte(&s->buf); // multiple component transformation
+ 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;
- get_cox(s, &tmp);
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 (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- compno = bytestream_get_byte(&s->buf);
+ compno = bytestream2_get_byteu(&s->g);
+
+ if (compno >= s->ncomponents) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid compno %d\n", compno);
+ return AVERROR_INVALIDDATA;
+ }
c += compno;
- c->csty = bytestream_get_byte(&s->buf);
- get_cox(s, c);
+ c->csty = bytestream2_get_byteu(&s->g);
+
+ if ((ret = get_cox(s, c)) < 0)
+ return ret;
properties[compno] |= HAD_COC;
return 0;
{
int i, x;
- if (s->buf_end - s->buf < 1)
+ if (bytestream2_get_bytes_left(&s->g) < 1)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- x = bytestream_get_byte(&s->buf); // Sqcd
+ x = bytestream2_get_byteu(&s->g); // Sqcd
q->nguardbits = x >> 5;
q->quantsty = x & 0x1f;
if (q->quantsty == JPEG2000_QSTY_NONE) {
n -= 3;
- if (s->buf_end - s->buf < n)
+ if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
for (i = 0; i < n; i++)
- q->expn[i] = bytestream_get_byte(&s->buf) >> 3;
+ q->expn[i] = bytestream2_get_byteu(&s->g) >> 3;
} else if (q->quantsty == JPEG2000_QSTY_SI) {
- if (s->buf_end - s->buf < 2)
+ if (bytestream2_get_bytes_left(&s->g) < 2)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- x = bytestream_get_be16(&s->buf);
+ x = bytestream2_get_be16u(&s->g);
q->expn[0] = x >> 11;
q->mant[0] = x & 0x7ff;
for (i = 1; i < JPEG2000_MAX_DECLEVELS * 3; i++) {
}
} else {
n = (n - 3) >> 1;
- if (s->buf_end - s->buf < n)
+ if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
for (i = 0; i < n; i++) {
- x = bytestream_get_be16(&s->buf);
+ x = bytestream2_get_be16u(&s->g);
q->expn[i] = x >> 11;
q->mant[i] = x & 0x7ff;
}
{
int compno;
- if (s->buf_end - s->buf < 1)
+ if (bytestream2_get_bytes_left(&s->g) < 1)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- compno = bytestream_get_byte(&s->buf);
+ 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);
}
uint32_t Psot;
uint8_t TPsot;
- if (s->buf_end - s->buf < 4)
+ if (bytestream2_get_bytes_left(&s->g) < 8)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- Isot = bytestream_get_be16(&s->buf); // Isot
- if (Isot) {
- avpriv_request_sample(s->avctx, "Support for more than one tile");
- return AVERROR_PATCHWELCOME;
+ s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot
+ if ((unsigned)s->curtileno >= s->numXtiles * s->numYtiles) {
+ s->curtileno=0;
- return AVERROR(EINVAL);
++ return AVERROR_INVALIDDATA;
}
- Psot = bytestream_get_be32(&s->buf); // Psot
- TPsot = bytestream_get_byte(&s->buf); // TPsot
+ Psot = bytestream2_get_be32u(&s->g); // Psot
+ TPsot = bytestream2_get_byteu(&s->g); // TPsot
/* Read TNSot but not used */
- bytestream_get_byte(&s->buf); // TNsot
+ bytestream2_get_byteu(&s->g); // TNsot
- tp = s->tile[s->curtileno].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 == bytestream_get_be16(&s->buf))
- tp->tp_start_bstrm = s->buf;
- else {
- av_log(s->avctx, AV_LOG_ERROR, "SOD marker not found \n");
+ if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) {
+ av_log(s->avctx, AV_LOG_ERROR, "Psot %d too big\n", Psot);
return AVERROR_INVALIDDATA;
}
+ if (TPsot >= FF_ARRAY_ELEMS(s->tile[s->curtileno].tile_part)) {
+ av_log(s->avctx, AV_LOG_ERROR, "TPsot %d too big\n", TPsot);
+ return AVERROR_PATCHWELCOME;
+ }
- /* End address of bit stream =
- * start address + (Psot - size of SOT HEADER(n)
- * - size of SOT MARKER(2) - size of SOD marker(2) */
- tp->tp_end_bstrm = s->buf + (tp->tp_len - n - 4);
+ s->tile[s->curtileno].tp_idx = TPsot;
+ tp = s->tile[s->curtileno].tile_part + TPsot;
+ tp->tile_index = Isot;
+ tp->tp_end = s->g.buffer + Psot - n - 2;
- // set buffer pointer to end of tile part header
- s->buf = tp->tp_end_bstrm;
+ 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;
}
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
- if (s->buf_end - s->buf < cblk->lengthinc)
+ if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
+ || sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2
+ )
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- /* Code-block data can be empty. In that case initialize data
- * with 0xFFFF. */
- if (cblk->lengthinc > 0) {
- bytestream_get_buffer(&s->buf, cblk->data, cblk->lengthinc);
- } else {
- cblk->data[0] = 0xFF;
- cblk->data[1] = 0xFF;
- }
+
+ bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc);
cblk->length += cblk->lengthinc;
cblk->lengthinc = 0;
}
static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
{
- int layno, reslevelno, compno, precno, ok_reslevel;
+ int layno, reslevelno, compno, precno, ok_reslevel, ret;
- uint8_t prog_order = tile->codsty[0].prog_order;
- uint16_t x;
- uint16_t y;
+ int x, y;
s->bit_index = 8;
- switch (prog_order) {
+ switch (tile->codsty[0].prog_order) {
case JPEG2000_PGOD_LRCP:
+ case JPEG2000_PGOD_RLCP:
for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
ok_reslevel = 1;
for (reslevelno = 0; ok_reslevel; reslevelno++) {
Jpeg2000QuantStyle *qntsty = tile->qntsty + compno;
if (reslevelno < codsty->nreslevels) {
Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
- reslevelno;
+ reslevelno;
ok_reslevel = 1;
for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
- if (jpeg2000_decode_packet(s,
- codsty, rlevel,
- precno, layno,
- qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
- qntsty->nguardbits))
- return -1;
+ if ((ret = jpeg2000_decode_packet(s,
+ codsty, rlevel,
+ precno, layno,
+ qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+ qntsty->nguardbits)) < 0)
+ return ret;
}
}
}
if (marker == JPEG2000_EOC)
break;
- if (s->buf_end - s->buf < 2)
+ len = bytestream2_get_be16(&s->g);
+ if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2)
- return AVERROR(EINVAL);
+ return AVERROR_INVALIDDATA;
- len = bytestream_get_be16(&s->buf);
switch (marker) {
case JPEG2000_SIZ:
ret = get_siz(s);
// reduction factor, i.e number of resolution levels to skip
s->reduction_factor = s->lowres;
- if (s->buf_end - s->buf < 2)
- return AVERROR_INVALIDDATA;
+ if (bytestream2_get_bytes_left(&s->g) < 2) {
- ret = AVERROR(EINVAL);
++ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
// check if the image is in jp2 format
- if ((AV_RB32(s->buf) == 12) &&
- (AV_RB32(s->buf + 4) == JP2_SIG_TYPE) &&
- (AV_RB32(s->buf + 8) == JP2_SIG_VALUE)) {
+ if (bytestream2_get_bytes_left(&s->g) >= 12 &&
+ (bytestream2_get_be32u(&s->g) == 12) &&
+ (bytestream2_get_be32u(&s->g) == JP2_SIG_TYPE) &&
+ (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) {
if (!jp2_find_codestream(s)) {
av_log(avctx, AV_LOG_ERROR,
- "couldn't find jpeg2k codestream atom\n");
- ret = -1;
+ "Could not find Jpeg2000 codestream atom.\n");
- return AVERROR_INVALIDDATA;
++ ret = AVERROR_INVALIDDATA;
+ goto end;
}
+ } else {
+ bytestream2_seek(&s->g, 0, SEEK_SET);
}
- if (bytestream_get_be16(&s->buf) != JPEG2000_SOC) {
+ if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) {
av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
- ret = -1;
- return AVERROR_INVALIDDATA;
++ ret = AVERROR_INVALIDDATA;
+ goto end;
}
if (ret = jpeg2000_read_main_headers(s))
goto end;