You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +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:
		| @@ -468,7 +468,7 @@ int ff_jpeg2000_init_component(Jpeg2000Component *comp, | ||||
|                     cblk->zero      = 0; | ||||
|                     cblk->lblock    = 3; | ||||
|                     cblk->length    = 0; | ||||
|                     cblk->lengthinc = 0; | ||||
|                     memset(cblk->lengthinc, 0, sizeof(cblk->lengthinc)); | ||||
|                     cblk->npasses   = 0; | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -163,11 +163,15 @@ typedef struct Jpeg2000Cblk { | ||||
|     uint8_t ninclpasses; // number coding of passes included in codestream | ||||
|     uint8_t nonzerobits; | ||||
|     uint16_t length; | ||||
|     uint16_t lengthinc; | ||||
|     uint16_t lengthinc[JPEG2000_MAX_PASSES]; | ||||
|     uint8_t nb_lengthinc; | ||||
|     uint8_t lblock; | ||||
|     uint8_t zero; | ||||
|     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}} | ||||
| } Jpeg2000Cblk; // code block | ||||
|  | ||||
| @@ -264,4 +268,21 @@ void ff_jpeg2000_reinit(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 */ | ||||
|   | ||||
| @@ -764,6 +764,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, | ||||
|                                   int layno, uint8_t *expn, int numgbits) | ||||
| { | ||||
|     int bandno, cblkno, ret, nb_code_blocks; | ||||
|     int cwsno; | ||||
|  | ||||
|     if (!(ret = get_bits(s, 1))) { | ||||
|         jpeg2000_flush(s); | ||||
| @@ -819,16 +820,32 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, | ||||
|             } | ||||
|  | ||||
|             cblk->lblock += llen; | ||||
|             if ((ret = get_bits(s, av_log2(newpasses) + 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 = ret; | ||||
|             cblk->npasses  += newpasses; | ||||
|  | ||||
|             cblk->nb_lengthinc = 0; | ||||
|             cblk->nb_terminationsinc = 0; | ||||
|             do { | ||||
|                 int newpasses1 = 0; | ||||
|  | ||||
|                 while (newpasses1 < newpasses) { | ||||
|                     newpasses1 ++; | ||||
|                     if (needs_termination(codsty->cblk_style, cblk->npasses + newpasses1 - 1)) { | ||||
|                         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); | ||||
| @@ -847,18 +864,27 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, | ||||
|         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 (   bytestream2_get_bytes_left(&s->g) < cblk->lengthinc | ||||
|                 || sizeof(cblk->data) < cblk->length + cblk->lengthinc + 2 | ||||
|             ) { | ||||
|                 av_log(s->avctx, AV_LOG_ERROR, | ||||
|                        "Block length %"PRIu16" or lengthinc %d is too large\n", | ||||
|                        cblk->length, cblk->lengthinc); | ||||
|                 return AVERROR_INVALIDDATA; | ||||
|             } | ||||
|             for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) { | ||||
|                 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", | ||||
|                         cblk->length, cblk->lengthinc[cwsno]); | ||||
|                     return AVERROR_INVALIDDATA; | ||||
|                 } | ||||
|  | ||||
|             bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc); | ||||
|             cblk->length   += cblk->lengthinc; | ||||
|             cblk->lengthinc = 0; | ||||
|                 bytestream2_get_bufferu(&s->g, cblk->data + cblk->length, cblk->lengthinc[cwsno]); | ||||
|                 cblk->length   += cblk->lengthinc[cwsno]; | ||||
|                 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; | ||||
| @@ -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); | ||||
|                     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); | ||||
|                         if (bpass_csty_symbol) | ||||
|                         if (t1->mqc.raw) | ||||
|                              t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask; | ||||
|                         else | ||||
|                              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 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 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(height <= JPEG2000_MAX_CBLKH); | ||||
| @@ -1141,24 +1169,33 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, | ||||
|         switch(pass_t) { | ||||
|         case 0: | ||||
|             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); | ||||
|             break; | ||||
|         case 1: | ||||
|             decode_refpass(t1, width, height, bpno + 1); | ||||
|             break; | ||||
|         case 2: | ||||
|             av_assert2(!t1->mqc.raw); | ||||
|             decode_clnpass(s, t1, width, height, bpno + 1, bandpos, | ||||
|                            codsty->cblk_style & JPEG2000_CBLK_SEGSYM, | ||||
|                            vert_causal_ctx_csty_symbol); | ||||
|             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++; | ||||
|         if (pass_t == 3) { | ||||
|             bpno--; | ||||
|             pass_t = 0; | ||||
|         } | ||||
|         pass_cnt ++; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user