Commit 7c71ef4f authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit '57bc64e2'

* commit '57bc64e2':
  jpeg2000: Use bytestream2
  jpeg2000: Clean up return paths and error messages
  jpeg2000: Define the maximum decomposition levels
  jpeg2000: Check code-block size
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents ffed7227 57bc64e2
...@@ -67,7 +67,9 @@ enum Jpeg2000Quantsty { // quantization style ...@@ -67,7 +67,9 @@ enum Jpeg2000Quantsty { // quantization style
#define JPEG2000_MAX_CBLKW 64 #define JPEG2000_MAX_CBLKW 64
#define JPEG2000_MAX_CBLKH 64 #define JPEG2000_MAX_CBLKH 64
#define JPEG2000_MAX_RESLEVELS 33
#define JPEG2000_MAX_DECLEVELS 32
#define JPEG2000_MAX_RESLEVELS (JPEG2000_MAX_DECLEVELS + 1)
// T1 flags // T1 flags
// flags determining significance of neighbor coefficients // flags determining significance of neighbor coefficients
...@@ -143,8 +145,8 @@ typedef struct Jpeg2000CodingStyle { ...@@ -143,8 +145,8 @@ typedef struct Jpeg2000CodingStyle {
} Jpeg2000CodingStyle; } Jpeg2000CodingStyle;
typedef struct Jpeg2000QuantStyle { typedef struct Jpeg2000QuantStyle {
uint8_t expn[32 * 3]; // quantization exponent uint8_t expn[JPEG2000_MAX_DECLEVELS * 3]; // quantization exponent
uint16_t mant[32 * 3]; // quantization mantissa uint16_t mant[JPEG2000_MAX_DECLEVELS * 3]; // quantization mantissa
uint8_t quantsty; // quantization style uint8_t quantsty; // quantization style
uint8_t nguardbits; // number of guard bits uint8_t nguardbits; // number of guard bits
} Jpeg2000QuantStyle; } Jpeg2000QuantStyle;
......
...@@ -163,7 +163,7 @@ static int get_siz(Jpeg2000DecoderContext *s) ...@@ -163,7 +163,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
int ncomponents; int ncomponents;
if (bytestream2_get_bytes_left(&s->g) < 36) if (bytestream2_get_bytes_left(&s->g) < 36)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz s->avctx->profile = bytestream2_get_be16u(&s->g); // Rsiz
s->width = bytestream2_get_be32u(&s->g); // Width s->width = bytestream2_get_be32u(&s->g); // Width
...@@ -178,18 +178,18 @@ static int get_siz(Jpeg2000DecoderContext *s) ...@@ -178,18 +178,18 @@ static int get_siz(Jpeg2000DecoderContext *s)
if (ncomponents <= 0 || ncomponents > 4) { if (ncomponents <= 0 || ncomponents > 4) {
av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", ncomponents); av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", ncomponents);
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
} }
s->ncomponents = ncomponents; s->ncomponents = ncomponents;
if (s->tile_width<=0 || s->tile_height<=0) if (s->tile_width<=0 || s->tile_height<=0)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
if (bytestream2_get_bytes_left(&s->g) < 3 * 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 for (i = 0; i < s->ncomponents; i++) { // Ssiz_i XRsiz_i, YRsiz_i
uint8_t x = bytestream2_get_byteu(&s->g); uint8_t x = bytestream2_get_byteu(&s->g);
s->cbps[i] = (x & 0x7f) + 1; s->cbps[i] = (x & 0x7f) + 1;
s->precision = FFMAX(s->cbps[i], s->precision); s->precision = FFMAX(s->cbps[i], s->precision);
s->sgnd[i] = !!(x & 0x80); s->sgnd[i] = !!(x & 0x80);
...@@ -265,7 +265,8 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) ...@@ -265,7 +265,8 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
uint8_t byte; uint8_t byte;
if (bytestream2_get_bytes_left(&s->g) < 5) if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
/* nreslevels = number of resolution levels /* nreslevels = number of resolution levels
= number of decomposition level +1 */ = number of decomposition level +1 */
c->nreslevels = bytestream2_get_byteu(&s->g) + 1; c->nreslevels = bytestream2_get_byteu(&s->g) + 1;
...@@ -284,7 +285,7 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c) ...@@ -284,7 +285,7 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height c->log2_cblk_height = (bytestream2_get_byteu(&s->g) & 15) + 2; // cblk height
if (c->log2_cblk_width > 10 || c->log2_cblk_height > 10 || if (c->log2_cblk_width > 10 || c->log2_cblk_height > 10 ||
c->log2_cblk_width + c->log2_cblk_height > 14) { c->log2_cblk_width + c->log2_cblk_height > 12) {
av_log(s->avctx, AV_LOG_ERROR, "cblk size invalid\n"); av_log(s->avctx, AV_LOG_ERROR, "cblk size invalid\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
...@@ -320,15 +321,15 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, ...@@ -320,15 +321,15 @@ static int get_cod(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
int compno, ret; int compno, ret;
if (bytestream2_get_bytes_left(&s->g) < 5) if (bytestream2_get_bytes_left(&s->g) < 5)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
tmp.csty = bytestream2_get_byteu(&s->g); tmp.csty = bytestream2_get_byteu(&s->g);
// get progression order // get progression order
tmp.prog_order = bytestream2_get_byteu(&s->g); tmp.prog_order = bytestream2_get_byteu(&s->g);
tmp.nlayers = bytestream2_get_be16u(&s->g); tmp.nlayers = bytestream2_get_be16u(&s->g);
tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation
if (tmp.mct && s->ncomponents < 3) { 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); av_log(s->avctx, AV_LOG_ERROR, "MCT %d with too few components (%d)\n", tmp.mct, s->ncomponents);
...@@ -352,7 +353,7 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c, ...@@ -352,7 +353,7 @@ static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
int compno, ret; int compno, ret;
if (bytestream2_get_bytes_left(&s->g) < 2) if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
compno = bytestream2_get_byteu(&s->g); compno = bytestream2_get_byteu(&s->g);
...@@ -377,7 +378,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q) ...@@ -377,7 +378,7 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
int i, x; int i, x;
if (bytestream2_get_bytes_left(&s->g) < 1) if (bytestream2_get_bytes_left(&s->g) < 1)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
x = bytestream2_get_byteu(&s->g); // Sqcd x = bytestream2_get_byteu(&s->g); // Sqcd
...@@ -386,25 +387,27 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q) ...@@ -386,25 +387,27 @@ static int get_qcx(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q)
if (q->quantsty == JPEG2000_QSTY_NONE) { if (q->quantsty == JPEG2000_QSTY_NONE) {
n -= 3; n -= 3;
if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n) if (bytestream2_get_bytes_left(&s->g) < n ||
return AVERROR(EINVAL); n > JPEG2000_MAX_DECLEVELS*3)
return AVERROR_INVALIDDATA;
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
q->expn[i] = bytestream2_get_byteu(&s->g) >> 3; q->expn[i] = bytestream2_get_byteu(&s->g) >> 3;
} else if (q->quantsty == JPEG2000_QSTY_SI) { } else if (q->quantsty == JPEG2000_QSTY_SI) {
if (bytestream2_get_bytes_left(&s->g) < 2) if (bytestream2_get_bytes_left(&s->g) < 2)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
x = bytestream2_get_be16u(&s->g); x = bytestream2_get_be16u(&s->g);
q->expn[0] = x >> 11; q->expn[0] = x >> 11;
q->mant[0] = x & 0x7ff; q->mant[0] = x & 0x7ff;
for (i = 1; i < 32 * 3; i++) { for (i = 1; i < JPEG2000_MAX_DECLEVELS * 3; i++) {
int curexpn = FFMAX(0, q->expn[0] - (i - 1) / 3); int curexpn = FFMAX(0, q->expn[0] - (i - 1) / 3);
q->expn[i] = curexpn; q->expn[i] = curexpn;
q->mant[i] = q->mant[0]; q->mant[i] = q->mant[0];
} }
} else { } else {
n = (n - 3) >> 1; n = (n - 3) >> 1;
if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n) if (bytestream2_get_bytes_left(&s->g) < 2 * n ||
return AVERROR(EINVAL); n > JPEG2000_MAX_DECLEVELS*3)
return AVERROR_INVALIDDATA;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
x = bytestream2_get_be16u(&s->g); x = bytestream2_get_be16u(&s->g);
q->expn[i] = x >> 11; q->expn[i] = x >> 11;
...@@ -419,10 +422,10 @@ static int get_qcd(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q, ...@@ -419,10 +422,10 @@ static int get_qcd(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q,
uint8_t *properties) uint8_t *properties)
{ {
Jpeg2000QuantStyle tmp; Jpeg2000QuantStyle tmp;
int compno; int compno, ret;
if (get_qcx(s, n, &tmp)) if ((ret = get_qcx(s, n, &tmp)) < 0)
return -1; return ret;
for (compno = 0; compno < s->ncomponents; compno++) for (compno = 0; compno < s->ncomponents; compno++)
if (!(properties[compno] & HAD_QCC)) if (!(properties[compno] & HAD_QCC))
memcpy(q + compno, &tmp, sizeof(tmp)); memcpy(q + compno, &tmp, sizeof(tmp));
...@@ -437,7 +440,7 @@ static int get_qcc(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q, ...@@ -437,7 +440,7 @@ static int get_qcc(Jpeg2000DecoderContext *s, int n, Jpeg2000QuantStyle *q,
int compno; int compno;
if (bytestream2_get_bytes_left(&s->g) < 1) if (bytestream2_get_bytes_left(&s->g) < 1)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
compno = bytestream2_get_byteu(&s->g); compno = bytestream2_get_byteu(&s->g);
if (compno >= s->ncomponents) { if (compno >= s->ncomponents) {
...@@ -458,12 +461,12 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) ...@@ -458,12 +461,12 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
uint8_t TPsot; uint8_t TPsot;
if (bytestream2_get_bytes_left(&s->g) < 8) if (bytestream2_get_bytes_left(&s->g) < 8)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot s->curtileno = Isot = bytestream2_get_be16u(&s->g); // Isot
if ((unsigned)s->curtileno >= s->numXtiles * s->numYtiles) { if ((unsigned)s->curtileno >= s->numXtiles * s->numYtiles) {
s->curtileno=0; s->curtileno=0;
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
} }
Psot = bytestream2_get_be32u(&s->g); // Psot Psot = bytestream2_get_be32u(&s->g); // Psot
TPsot = bytestream2_get_byteu(&s->g); // TPsot TPsot = bytestream2_get_byteu(&s->g); // TPsot
...@@ -675,7 +678,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, ...@@ -675,7 +678,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
|| sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2 || sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2
) )
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc); bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc);
cblk->length += cblk->lengthinc; cblk->length += cblk->lengthinc;
...@@ -687,7 +690,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, ...@@ -687,7 +690,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile) static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
{ {
int layno, reslevelno, compno, precno, ok_reslevel; int layno, reslevelno, compno, precno, ok_reslevel, ret;
int x, y; int x, y;
s->bit_index = 8; s->bit_index = 8;
...@@ -706,12 +709,12 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile ...@@ -706,12 +709,12 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
reslevelno; reslevelno;
ok_reslevel = 1; ok_reslevel = 1;
for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
if (jpeg2000_decode_packet(s, if ((ret = jpeg2000_decode_packet(s,
codsty, rlevel, codsty, rlevel,
precno, layno, precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) qntsty->nguardbits)) < 0)
return -1; return ret;
} }
} }
} }
...@@ -754,11 +757,11 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile ...@@ -754,11 +757,11 @@ static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
prcy = ff_jpeg2000_ceildivpow2(y, reducedresno) >> rlevel->log2_prec_height; prcy = ff_jpeg2000_ceildivpow2(y, reducedresno) >> rlevel->log2_prec_height;
precno = prcx + rlevel->num_precincts_x * prcy; precno = prcx + rlevel->num_precincts_x * prcy;
for (layno = 0; layno < tile->codsty[0].nlayers; layno++) { for (layno = 0; layno < tile->codsty[0].nlayers; layno++) {
if (jpeg2000_decode_packet(s, codsty, rlevel, if ((ret = jpeg2000_decode_packet(s, codsty, rlevel,
precno, layno, precno, layno,
qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0), qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
qntsty->nguardbits)) qntsty->nguardbits)) < 0)
return -1; return ret;
} }
} }
} }
...@@ -1253,7 +1256,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s) ...@@ -1253,7 +1256,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
len = bytestream2_get_be16(&s->g); 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)
return AVERROR(EINVAL); return AVERROR_INVALIDDATA;
switch (marker) { switch (marker) {
case JPEG2000_SIZ: case JPEG2000_SIZ:
ret = get_siz(s); ret = get_siz(s);
...@@ -1329,7 +1332,9 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) ...@@ -1329,7 +1332,9 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s)
uint32_t atom_size, atom; uint32_t atom_size, atom;
int found_codestream = 0, search_range = 10; int found_codestream = 0, search_range = 10;
while (!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) { while (!found_codestream && search_range
&&
bytestream2_get_bytes_left(&s->g) >= 8) {
atom_size = bytestream2_get_be32u(&s->g); atom_size = bytestream2_get_be32u(&s->g);
atom = bytestream2_get_be32u(&s->g); atom = bytestream2_get_be32u(&s->g);
if (atom == JP2_CODESTREAM) { if (atom == JP2_CODESTREAM) {
...@@ -1363,7 +1368,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, ...@@ -1363,7 +1368,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
s->reduction_factor = s->lowres; s->reduction_factor = s->lowres;
if (bytestream2_get_bytes_left(&s->g) < 2) { if (bytestream2_get_bytes_left(&s->g) < 2) {
ret = AVERROR(EINVAL); ret = AVERROR_INVALIDDATA;
goto end; goto end;
} }
...@@ -1374,17 +1379,19 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, ...@@ -1374,17 +1379,19 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
(bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) { (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) {
if (!jp2_find_codestream(s)) { if (!jp2_find_codestream(s)) {
av_log(avctx, AV_LOG_ERROR, av_log(avctx, AV_LOG_ERROR,
"couldn't find jpeg2k codestream atom\n"); "Could not find Jpeg2000 codestream atom.\n");
ret = -1; ret = AVERROR_INVALIDDATA;
goto end; goto end;
} }
} else { } else {
bytestream2_seek(&s->g, 0, SEEK_SET); 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) { if (bytestream2_get_be16u(&s->g) != JPEG2000_SOC) {
av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n"); av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
ret = -1; ret = AVERROR_INVALIDDATA;
goto end; goto end;
} }
if (ret = jpeg2000_read_main_headers(s)) if (ret = jpeg2000_read_main_headers(s))
...@@ -1408,6 +1415,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, ...@@ -1408,6 +1415,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
*got_frame = 1; *got_frame = 1;
return bytestream2_tell(&s->g); return bytestream2_tell(&s->g);
end: end:
jpeg2000_dec_cleanup(s); jpeg2000_dec_cleanup(s);
return ret; return ret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment