Commit 9f9b954858 for ffmpeg
commit 9f9b9548583ff7fbd633a5e6debe057d391f162c
Author: Kacper Michajłow <kasper93@gmail.com>
Date: Sat Oct 24 07:46:52 2026 +0200
avcodec/jpeg2000dec: decode code-blocks without coded bit-planes
A code-block has Mb - P coded bit-planes, where P is the number of
missing most significant bit-planes from the packet header and Mb the
number of bit-planes of its band from Equation E-2 of Rec. ITU-T T.800,
raised by the scaling value with an ROI. The missing bit-planes are
zero (T.800, B.10.5), so with P >= Mb the code-block is zero. The
packet decoder rejected P > Mb as invalid data and failed the whole
frame. A 2K DCP contains such code-blocks, P = 13 in bands with Mb = 10
or 12 and one empty coding pass.
Store zero coded bit-planes for P > Mb and return early from
decode_cblk() for code-blocks without coded bit-planes, like for those
without data. The magnitude bits of HT code-blocks are placed by P
(Rec. ITU-T T.814, clause 7.6), so they are not zero with P >= Mb, and
P > Mb is still rejected when the coding style has HT code-blocks. A
zero bit-plane count of 100 means its tag tree is not resolved and
stays rejected.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 7acb11710b..a235edcec3 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -1206,13 +1206,14 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
if (incl) {
int zbp = tag_tree_decode(s, prec->zerobits + cblkno, 100);
int v = expn[bandno] + numgbits - 1 - (zbp - tile->comp->roi_shift);
- if (v < 0 || v > 30) {
+ if (zbp >= 100 || v > 30 ||
+ (v < 0 && (cblk->modes & JPEG2000_CTSY_HTJ2K_F))) {
av_log(s->avctx, AV_LOG_ERROR,
"nonzerobits %d invalid or unsupported\n", v);
return AVERROR_INVALIDDATA;
}
cblk->incl = 1;
- cblk->nonzerobits = v;
+ cblk->nonzerobits = FFMAX(v, 0);
cblk->zbp = zbp;
cblk->lblock = 3;
}
@@ -2029,8 +2030,8 @@ static int decode_cblk(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *cod
memset(t1->data, 0, t1->stride * height * sizeof(*t1->data));
- /* If code-block contains no compressed data: nothing to do. */
- if (!cblk->length)
+ /* If code-block contains no compressed data or no coded bit-planes: nothing to do. */
+ if (!cblk->length || !cblk->nonzerobits)
return 0;
memset(t1->flags, 0, t1->stride * (height + 2) * sizeof(*t1->flags));