mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avcodec/jpeg2000dec: Fix Selective arithmetic coding bypass and Multiple codeword segments
These 2 are highly related so they are in the same commit Fixes part of Ticket4605 Fixes p0_04.j2k Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
eea92133a1
commit
dc73c7adc0
@ -468,7 +468,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp,
|
|||||||
cblk->zero = 0;
|
cblk->zero = 0;
|
||||||
cblk->lblock = 3;
|
cblk->lblock = 3;
|
||||||
cblk->length = 0;
|
cblk->length = 0;
|
||||||
cblk->lengthinc = 0;
|
memset(cblk->lengthinc, 0, sizeof(cblk->lengthinc));
|
||||||
cblk->npasses = 0;
|
cblk->npasses = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,11 +163,15 @@ typedef struct Jpeg2000Cblk {
|
|||||||
uint8_t ninclpasses; // number coding of passes included in codestream
|
uint8_t ninclpasses; // number coding of passes included in codestream
|
||||||
uint8_t nonzerobits;
|
uint8_t nonzerobits;
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
uint16_t lengthinc;
|
uint16_t lengthinc[JPEG2000_MAX_PASSES];
|
||||||
|
uint8_t nb_lengthinc;
|
||||||
uint8_t lblock;
|
uint8_t lblock;
|
||||||
uint8_t zero;
|
uint8_t zero;
|
||||||
uint8_t data[8192];
|
uint8_t data[8192];
|
||||||
Jpeg2000Pass passes[100];
|
int nb_terminations;
|
||||||
|
int nb_terminationsinc;
|
||||||
|
int data_start[JPEG2000_MAX_PASSES];
|
||||||
|
Jpeg2000Pass passes[JPEG2000_MAX_PASSES];
|
||||||
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
|
uint16_t coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
|
||||||
} Jpeg2000Cblk; // code block
|
} Jpeg2000Cblk; // code block
|
||||||
|
|
||||||
@ -264,4 +268,21 @@ void ff_jpeg2000_reinit(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty);
|
|||||||
|
|
||||||
void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty);
|
void ff_jpeg2000_cleanup(Jpeg2000Component *comp, Jpeg2000CodingStyle *codsty);
|
||||||
|
|
||||||
|
static inline int needs_termination(int style, int passno) {
|
||||||
|
if (style & JPEG2000_CBLK_BYPASS) {
|
||||||
|
int type = passno % 3;
|
||||||
|
passno /= 3;
|
||||||
|
if (type == 0 && passno > 2)
|
||||||
|
return 2;
|
||||||
|
if (type == 2 && passno > 2)
|
||||||
|
return 1;
|
||||||
|
if (style & JPEG2000_CBLK_TERMALL) {
|
||||||
|
return passno > 2 ? 2 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (style & JPEG2000_CBLK_TERMALL)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* AVCODEC_JPEG2000_H */
|
#endif /* AVCODEC_JPEG2000_H */
|
||||||
|
@ -764,6 +764,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
|
|||||||
int layno, uint8_t *expn, int numgbits)
|
int layno, uint8_t *expn, int numgbits)
|
||||||
{
|
{
|
||||||
int bandno, cblkno, ret, nb_code_blocks;
|
int bandno, cblkno, ret, nb_code_blocks;
|
||||||
|
int cwsno;
|
||||||
|
|
||||||
if (!(ret = get_bits(s, 1))) {
|
if (!(ret = get_bits(s, 1))) {
|
||||||
jpeg2000_flush(s);
|
jpeg2000_flush(s);
|
||||||
@ -819,16 +820,32 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cblk->lblock += llen;
|
cblk->lblock += llen;
|
||||||
if ((ret = get_bits(s, av_log2(newpasses) + cblk->lblock)) < 0)
|
|
||||||
return ret;
|
cblk->nb_lengthinc = 0;
|
||||||
if (ret > sizeof(cblk->data)) {
|
cblk->nb_terminationsinc = 0;
|
||||||
avpriv_request_sample(s->avctx,
|
do {
|
||||||
"Block with lengthinc greater than %"SIZE_SPECIFIER"",
|
int newpasses1 = 0;
|
||||||
sizeof(cblk->data));
|
|
||||||
return AVERROR_PATCHWELCOME;
|
while (newpasses1 < newpasses) {
|
||||||
}
|
newpasses1 ++;
|
||||||
cblk->lengthinc = ret;
|
if (needs_termination(codsty->cblk_style, cblk->npasses + newpasses1 - 1)) {
|
||||||
cblk->npasses += newpasses;
|
cblk->nb_terminationsinc ++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret > sizeof(cblk->data)) {
|
||||||
|
avpriv_request_sample(s->avctx,
|
||||||
|
"Block with lengthinc greater than %"SIZE_SPECIFIER"",
|
||||||
|
sizeof(cblk->data));
|
||||||
|
return AVERROR_PATCHWELCOME;
|
||||||
|
}
|
||||||
|
cblk->lengthinc[cblk->nb_lengthinc++] = ret;
|
||||||
|
cblk->npasses += newpasses1;
|
||||||
|
newpasses -= newpasses1;
|
||||||
|
} while(newpasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jpeg2000_flush(s);
|
jpeg2000_flush(s);
|
||||||
@ -847,18 +864,27 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
|
|||||||
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
|
nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width;
|
||||||
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
|
for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
|
||||||
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
|
Jpeg2000Cblk *cblk = prec->cblk + cblkno;
|
||||||
if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc
|
for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) {
|
||||||
|| sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2
|
if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc[cwsno]
|
||||||
) {
|
|| 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",
|
av_log(s->avctx, AV_LOG_ERROR,
|
||||||
cblk->length, cblk->lengthinc);
|
"Block length %"PRIu16" or lengthinc %d is too large\n",
|
||||||
return AVERROR_INVALIDDATA;
|
cblk->length, cblk->lengthinc[cwsno]);
|
||||||
}
|
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[cwsno]);
|
||||||
cblk->length += cblk->lengthinc;
|
cblk->length += cblk->lengthinc[cwsno];
|
||||||
cblk->lengthinc = 0;
|
cblk->lengthinc[cwsno] = 0;
|
||||||
|
if (cblk->nb_terminationsinc) {
|
||||||
|
cblk->nb_terminationsinc--;
|
||||||
|
cblk->nb_terminations++;
|
||||||
|
cblk->data[cblk->length++] = 0xFF;
|
||||||
|
cblk->data[cblk->length++] = 0xFF;
|
||||||
|
cblk->data_start[cblk->nb_terminations] = cblk->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1012,7 +1038,7 @@ static void decode_sigpass(Jpeg2000T1Context *t1, int width, int height,
|
|||||||
flags_mask &= ~(JPEG2000_T1_SIG_S | JPEG2000_T1_SIG_SW | JPEG2000_T1_SIG_SE);
|
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))) {
|
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], &xorbit);
|
||||||
if (bpass_csty_symbol)
|
if (t1->mqc.raw)
|
||||||
t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask;
|
t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask;
|
||||||
else
|
else
|
||||||
t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ?
|
t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ?
|
||||||
@ -1116,9 +1142,11 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
|
|||||||
int width, int height, int bandpos)
|
int width, int height, int bandpos)
|
||||||
{
|
{
|
||||||
int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y;
|
int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y;
|
||||||
int clnpass_cnt = 0;
|
int pass_cnt = 0;
|
||||||
int bpass_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_BYPASS;
|
int bpass_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_BYPASS;
|
||||||
int vert_causal_ctx_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_VSC;
|
int vert_causal_ctx_csty_symbol = codsty->cblk_style & JPEG2000_CBLK_VSC;
|
||||||
|
int term_cnt = 0;
|
||||||
|
int coder_type;
|
||||||
|
|
||||||
av_assert0(width <= JPEG2000_MAX_CBLKW);
|
av_assert0(width <= JPEG2000_MAX_CBLKW);
|
||||||
av_assert0(height <= JPEG2000_MAX_CBLKH);
|
av_assert0(height <= JPEG2000_MAX_CBLKH);
|
||||||
@ -1141,24 +1169,33 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
|
|||||||
switch(pass_t) {
|
switch(pass_t) {
|
||||||
case 0:
|
case 0:
|
||||||
decode_sigpass(t1, width, height, bpno + 1, bandpos,
|
decode_sigpass(t1, width, height, bpno + 1, bandpos,
|
||||||
bpass_csty_symbol && (clnpass_cnt >= 4),
|
bpass_csty_symbol && (pass_cnt >= 3*3),
|
||||||
vert_causal_ctx_csty_symbol);
|
vert_causal_ctx_csty_symbol);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
decode_refpass(t1, width, height, bpno + 1);
|
decode_refpass(t1, width, height, bpno + 1);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
av_assert2(!t1->mqc.raw);
|
||||||
decode_clnpass(s, t1, width, height, bpno + 1, bandpos,
|
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);
|
vert_causal_ctx_csty_symbol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((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;
|
||||||
|
}
|
||||||
|
ff_mqc_initdec(&t1->mqc, cblk->data + cblk->data_start[++term_cnt], coder_type == 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pass_t++;
|
pass_t++;
|
||||||
if (pass_t == 3) {
|
if (pass_t == 3) {
|
||||||
bpno--;
|
bpno--;
|
||||||
pass_t = 0;
|
pass_t = 0;
|
||||||
}
|
}
|
||||||
|
pass_cnt ++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user