]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/jpeg2000dec.c
Merge commit 'b1803c79dcd6d0a345fa1cbe18dd8e2149717121'
[ffmpeg] / libavcodec / jpeg2000dec.c
index 20e5c9cc93d894f608b4894885ebab0d6b0651de..2a71d1dc1993b7d276e4456ba5ccac87c246cfb4 100644 (file)
@@ -635,7 +635,14 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s,
             Jpeg2000Cblk *cblk = prec->cblk + cblkno;
             if (s->buf_end - s->buf < cblk->lengthinc)
                 return AVERROR(EINVAL);
-            bytestream_get_buffer(&s->buf, cblk->data, cblk->lengthinc);
+            /* 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;
+            }
             cblk->length   += cblk->lengthinc;
             cblk->lengthinc = 0;
         }
@@ -853,12 +860,15 @@ static int decode_cblk(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty,
 {
     int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y;
 
-    for (y = 0; y < height + 2; y++)
-        memset(t1->flags[y], 0, (width + 2) * sizeof(width));
-
     for (y = 0; y < height; y++)
         memset(t1->data[y], 0, width * sizeof(width));
 
+    /* If code-block contains no compressed data: nothing to do. */
+    if (!cblk->length)
+        return 0;
+    for (y = 0; y < height + 2; y++)
+        memset(t1->flags[y], 0, (width + 2) * sizeof(width));
+
     ff_mqc_initdec(&t1->mqc, cblk->data);
     cblk->data[cblk->length]     = 0xff;
     cblk->data[cblk->length + 1] = 0xff;
@@ -1255,8 +1265,6 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
     // reduction factor, i.e number of resolution levels to skip
     s->reduction_factor = s->lowres;
 
-    ff_jpeg2000_init_tier1_luts();
-
     if (s->buf_end - s->buf < 2)
         return AVERROR(EINVAL);
 
@@ -1269,6 +1277,8 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
                    "couldn't find jpeg2k codestream atom\n");
             return -1;
         }
+    } else if (AV_RB16(s->buf) != JPEG2000_SOC && AV_RB32(s->buf + 4) == JP2_CODESTREAM) {
+        s->buf += 8;
     }
 
     if (bytestream_get_be16(&s->buf) != JPEG2000_SOC) {
@@ -1276,26 +1286,34 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
         return -1;
     }
     if (ret = jpeg2000_read_main_headers(s))
-        return ret;
+        goto end;
 
     /* get picture buffer */
     if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "ff_thread_get_buffer() failed.\n");
-        return ret;
+        goto end;
     }
     picture->pict_type = AV_PICTURE_TYPE_I;
     picture->key_frame = 1;
 
     if (ret = jpeg2000_read_bitstream_packets(s))
-        return ret;
+        goto end;
     for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++)
         if (ret = jpeg2000_decode_tile(s, s->tile + tileno, picture))
-            return ret;
+            goto end;
     jpeg2000_dec_cleanup(s);
 
     *got_frame = 1;
 
     return s->buf - s->buf_start;
+end:
+    jpeg2000_dec_cleanup(s);
+    return ret;
+}
+
+static void jpeg2000_init_static_data(AVCodec *codec)
+{
+    ff_jpeg2000_init_tier1_luts();
 }
 
 #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x)
@@ -1324,16 +1342,17 @@ static const AVClass class = {
 };
 
 AVCodec ff_jpeg2000_decoder = {
-    .name           = "jpeg2000",
-    .long_name      = NULL_IF_CONFIG_SMALL("JPEG 2000"),
-    .type           = AVMEDIA_TYPE_VIDEO,
-    .id             = AV_CODEC_ID_JPEG2000,
-    .capabilities   = CODEC_CAP_FRAME_THREADS,
-    .priv_data_size = sizeof(Jpeg2000DecoderContext),
-    .decode         = jpeg2000_decode_frame,
-    .priv_class     = &class,
-    .pix_fmts       = (enum PixelFormat[]) { AV_PIX_FMT_XYZ12,
-                                             AV_PIX_FMT_GRAY8,
-                                             -1 },
-    .profiles       = NULL_IF_CONFIG_SMALL(profiles)
+    .name             = "jpeg2000",
+    .long_name        = NULL_IF_CONFIG_SMALL("JPEG 2000"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_JPEG2000,
+    .capabilities     = CODEC_CAP_FRAME_THREADS,
+    .priv_data_size   = sizeof(Jpeg2000DecoderContext),
+    .init_static_data = jpeg2000_init_static_data,
+    .decode           = jpeg2000_decode_frame,
+    .priv_class       = &class,
+    .pix_fmts         = (enum PixelFormat[]) { AV_PIX_FMT_XYZ12,
+                                               AV_PIX_FMT_GRAY8,
+                                               -1 },
+    .profiles         = NULL_IF_CONFIG_SMALL(profiles)
 };