diff mbox

[FFmpeg-devel] lavc/jpeg2000dec: Read resolution box from jp2 files

Message ID 201705021614.58614.cehoyos@ag.or.at
State Superseded
Headers show

Commit Message

Carl Eugen Hoyos May 2, 2017, 2:14 p.m. UTC
Hi!

Attached patch allows reading the aspect ratio from jpeg2000 files.
Kakadu allows to produce samples, the "aspect" is defined as the 
horizontal and vertical resolution as in tiff.

Please comment, Carl Eugen
From 9955a76ea9abd6ad0c79b4e3d7fe74d4cf292aa6 Mon Sep 17 00:00:00 2001
From: Carl Eugen Hoyos <cehoyos@ag.or.at>
Date: Tue, 2 May 2017 16:01:02 +0200
Subject: [PATCH] lavc/jpeg2000dec: Read the resolution box from jp2 files.

---
 libavcodec/jpeg2000dec.c |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

Comments

Nicolas George May 2, 2017, 2:21 p.m. UTC | #1
Le tridi 13 floréal, an CCXXV, Carl Eugen Hoyos a écrit :
> Attached patch allows reading the aspect ratio from jpeg2000 files.
> Kakadu allows to produce samples, the "aspect" is defined as the 
> horizontal and vertical resolution as in tiff.

Did you test what happens with this patch if you try to read two frames
with the same context (for example with the image2 demuxer), the first
frame has a non-square-pixels resolution defined and the second has no
resolution indication at all?

The correct result would be to have a sample aspect ratio on the first
frame and not on the second.

But with this code, since the first resolution is stored in the context
and never cleared, it looks like it will be kept for the remaining
images.

Regards,
diff mbox

Patch

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index e9f5f51..3e1cc00 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -26,6 +26,7 @@ 
  */
 
 #include <inttypes.h>
+#include <math.h>
 
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
@@ -106,6 +107,7 @@  typedef struct Jpeg2000DecoderContext {
     int             tile_width, tile_height;
     unsigned        numXtiles, numYtiles;
     int             maxtilelen;
+    AVRational      resolution;
 
     Jpeg2000CodingStyle codsty[4];
     Jpeg2000QuantStyle  qntsty[4];
@@ -2043,6 +2045,34 @@  static int jp2_find_codestream(Jpeg2000DecoderContext *s)
                         if (cn < 4 && asoc < 4)
                             s->cdef[cn] = asoc;
                     }
+                } else if (atom2 == MKBETAG('r','e','s',' ') && atom2_size >= 18) {
+                    int64_t vnum, vden, hnum, hden, vexp, hexp;
+                    uint32_t resx;
+                    bytestream2_skip(&s->g, 4);
+                    resx = bytestream2_get_be32u(&s->g);
+                    if (resx != MKBETAG('r','e','s','c') && resx != MKBETAG('r','e','s','d')) {
+                        bytestream2_seek(&s->g, atom2_end, SEEK_SET);
+                        continue;
+                    }
+                    vnum = bytestream2_get_be16u(&s->g);
+                    vden = bytestream2_get_be16u(&s->g);
+                    hnum = bytestream2_get_be16u(&s->g);
+                    hden = bytestream2_get_be16u(&s->g);
+                    vexp = bytestream2_get_byteu(&s->g);
+                    hexp = bytestream2_get_byteu(&s->g);
+                    if (vexp > hexp) {
+                        vexp -= hexp;
+                        hexp = 0;
+                    } else {
+                        hexp -= vexp;
+                        vexp = 0;
+                    }
+                    if (   INT64_MAX / (hnum * vden) > pow(10, hexp)
+                        && INT64_MAX / (vnum * hden) > pow(10, vexp))
+                        av_reduce(&s->resolution.num, &s->resolution.den,
+                                  hnum * vden * pow(10, hexp),
+                                  vnum * hden * pow(10, vexp),
+                                  INT32_MAX);
                 }
                 bytestream2_seek(&s->g, atom2_end, SEEK_SET);
             } while (atom_end - atom2_end >= 8);
@@ -2125,6 +2155,13 @@  static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
 
     if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
         memcpy(picture->data[1], s->palette, 256 * sizeof(uint32_t));
+    if (   s->resolution.num && s->resolution.den
+        && INT64_MAX / avctx->width  > s->resolution.den
+        && INT64_MAX / avctx->height > s->resolution.num)
+        av_reduce(&avctx->sample_aspect_ratio.num, &avctx->sample_aspect_ratio.den,
+                  (int64_t)avctx->width  * s->resolution.den,
+                  (int64_t)avctx->height * s->resolution.num,
+                  INT32_MAX);
 
     return bytestream2_tell(&s->g);