diff mbox series

[FFmpeg-devel,v2,1/2] libavcodec/jpeg2000dec.c: Add functions and modify structs for PPT marker support

Message ID 20200327161602.1263-1-gautamramk@gmail.com
State Superseded
Headers show
Series [FFmpeg-devel,v2,1/2] libavcodec/jpeg2000dec.c: Add functions and modify structs for PPT marker support | expand

Checks

Context Check Description
andriy/ffmpeg-patchwork success Make fate finished

Commit Message

Gautam Ramakrishnan March 27, 2020, 4:16 p.m. UTC
From: Gautam Ramakrishnan <gautamramk@gmail.com>

This patch modifies the Jpeg2000Tile struct and breaks the
jpeg2000_decode_packet() function into two to decode packet
header and data separately.
---
 libavcodec/jpeg2000dec.c | 250 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 248 insertions(+), 2 deletions(-)

Comments

Carl Eugen Hoyos March 27, 2020, 5:28 p.m. UTC | #1
Am Fr., 27. März 2020 um 17:21 Uhr schrieb <gautamramk@gmail.com>:
>
> From: Gautam Ramakrishnan <gautamramk@gmail.com>
>
> This patch modifies the Jpeg2000Tile struct and breaks the
> jpeg2000_decode_packet() function into two to decode packet
> header and data separately.

The solution is also not to add functions that are unused at first.

I don't know if it is good to split the patch but you mentioned
that you had to split a particular function. That makes it sound
as if you should - with the first patch - split the function without
changing FFmpeg's behaviour, and then with a second patch
change FFmpeg's behaviour by adding the new functionality.
As said, I don't know if that simplifies the review in this
specific case.
Did you already look at the sample file I pointed out?

Carl Eugen
Gautam Ramakrishnan March 27, 2020, 5:48 p.m. UTC | #2
On Fri, Mar 27, 2020 at 10:59 PM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>
> Am Fr., 27. März 2020 um 17:21 Uhr schrieb <gautamramk@gmail.com>:
> >
> > From: Gautam Ramakrishnan <gautamramk@gmail.com>
> >
> > This patch modifies the Jpeg2000Tile struct and breaks the
> > jpeg2000_decode_packet() function into two to decode packet
> > header and data separately.
>
> The solution is also not to add functions that are unused at first.
>
> I don't know if it is good to split the patch but you mentioned
> that you had to split a particular function. That makes it sound
> as if you should - with the first patch - split the function without
> changing FFmpeg's behaviour, and then with a second patch
> change FFmpeg's behaviour by adding the new functionality.
> As said, I don't know if that simplifies the review in this
> specific case.
I was not too sure what to do in this case. Thought that splitting it
in the first patch could show what new functions are present.
> Did you already look at the sample file I pointed out?
Yep, am going through the sample file. I shall try to see what
is causing those errors. However I am assuming that the errors
could be due to other bugs in the decoder or due to some
unimplemented features?
>
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Carl Eugen Hoyos March 27, 2020, 5:57 p.m. UTC | #3
Am Fr., 27. März 2020 um 18:48 Uhr schrieb Gautam Ramakrishnan
<gautamramk@gmail.com>:
>
> On Fri, Mar 27, 2020 at 10:59 PM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> >
> > Am Fr., 27. März 2020 um 17:21 Uhr schrieb <gautamramk@gmail.com>:
> > >
> > > From: Gautam Ramakrishnan <gautamramk@gmail.com>
> > >
> > > This patch modifies the Jpeg2000Tile struct and breaks the
> > > jpeg2000_decode_packet() function into two to decode packet
> > > header and data separately.
> >
> > The solution is also not to add functions that are unused at first.
> >
> > I don't know if it is good to split the patch but you mentioned
> > that you had to split a particular function. That makes it sound
> > as if you should - with the first patch - split the function without
> > changing FFmpeg's behaviour, and then with a second patch
> > change FFmpeg's behaviour by adding the new functionality.
> > As said, I don't know if that simplifies the review in this
> > specific case.
> I was not too sure what to do in this case. Thought that splitting it
> in the first patch could show what new functions are present.

Michael will have to comment.

> > Did you already look at the sample file I pointed out?
> Yep, am going through the sample file. I shall try to see what
> is causing those errors. However I am assuming that the errors
> could be due to other bugs in the decoder or due to some
> unimplemented features?

Could be, I don't know, please find out.

Carl Eugen
Gautam Ramakrishnan March 27, 2020, 6:24 p.m. UTC | #4
On Fri, Mar 27, 2020 at 11:27 PM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>
> Am Fr., 27. März 2020 um 18:48 Uhr schrieb Gautam Ramakrishnan
> <gautamramk@gmail.com>:
> >
> > On Fri, Mar 27, 2020 at 10:59 PM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> > >
> > > Am Fr., 27. März 2020 um 17:21 Uhr schrieb <gautamramk@gmail.com>:
> > > >
> > > > From: Gautam Ramakrishnan <gautamramk@gmail.com>
> > > >
> > > > This patch modifies the Jpeg2000Tile struct and breaks the
> > > > jpeg2000_decode_packet() function into two to decode packet
> > > > header and data separately.
> > >
> > > The solution is also not to add functions that are unused at first.
> > >
> > > I don't know if it is good to split the patch but you mentioned
> > > that you had to split a particular function. That makes it sound
> > > as if you should - with the first patch - split the function without
> > > changing FFmpeg's behaviour, and then with a second patch
> > > change FFmpeg's behaviour by adding the new functionality.
> > > As said, I don't know if that simplifies the review in this
> > > specific case.
> > I was not too sure what to do in this case. Thought that splitting it
> > in the first patch could show what new functions are present.
>
> Michael will have to comment.
>
> > > Did you already look at the sample file I pointed out?
> > Yep, am going through the sample file. I shall try to see what
> > is causing those errors. However I am assuming that the errors
> > could be due to other bugs in the decoder or due to some
> > unimplemented features?
>
> Could be, I don't know, please find out.
>
The mxf demuxer says: error getting stream index 67174400
Does this mean that the mxf demuxer is unable to read the mxf
packet itself? Looking at the error thrown by the jpeg2000 decoder,
looks like the jpeg2000 frame is corrupt.
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Carl Eugen Hoyos March 27, 2020, 7:14 p.m. UTC | #5
Am Fr., 27. März 2020 um 19:24 Uhr schrieb Gautam Ramakrishnan
<gautamramk@gmail.com>:

> > > > Did you already look at the sample file I pointed out?
> > > Yep, am going through the sample file. I shall try to see what
> > > is causing those errors. However I am assuming that the errors
> > > could be due to other bugs in the decoder or due to some
> > > unimplemented features?
> >
> > Could be, I don't know, please find out.
> >
> The mxf demuxer says: error getting stream index 67174400
> Does this mean that the mxf demuxer is unable to read the mxf
> packet itself? Looking at the error thrown by the jpeg2000 decoder,
> looks like the jpeg2000 frame is corrupt.

I don't think so, you can test with libopenjpeg.

Carl Eugen
Gautam Ramakrishnan March 27, 2020, 7:49 p.m. UTC | #6
On Sat, Mar 28, 2020 at 12:45 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>
> Am Fr., 27. März 2020 um 19:24 Uhr schrieb Gautam Ramakrishnan
> <gautamramk@gmail.com>:
>
> > > > > Did you already look at the sample file I pointed out?
> > > > Yep, am going through the sample file. I shall try to see what
> > > > is causing those errors. However I am assuming that the errors
> > > > could be due to other bugs in the decoder or due to some
> > > > unimplemented features?
> > >
> > > Could be, I don't know, please find out.
> > >
> > The mxf demuxer says: error getting stream index 67174400
> > Does this mean that the mxf demuxer is unable to read the mxf
> > packet itself? Looking at the error thrown by the jpeg2000 decoder,
> > looks like the jpeg2000 frame is corrupt.
>
> I don't think so, you can test with libopenjpeg.
>
I tried using libopenjpeg as the decoder. I run the command
./ffmpeg -c:v libopenjpeg -i ~/Downloads/jpeg2000_mxf_first_10mb.mxf
-r 1/1 out%03d.bmp
I get only 3 .bmp images as output.
I get the same images compared to when I use the native decoder.
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Carl Eugen Hoyos March 27, 2020, 8:21 p.m. UTC | #7
Am Fr., 27. März 2020 um 20:57 Uhr schrieb Gautam Ramakrishnan
<gautamramk@gmail.com>:
>
> On Sat, Mar 28, 2020 at 12:45 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> >
> > Am Fr., 27. März 2020 um 19:24 Uhr schrieb Gautam Ramakrishnan
> > <gautamramk@gmail.com>:
> >
> > > > > > Did you already look at the sample file I pointed out?
> > > > > Yep, am going through the sample file. I shall try to see what
> > > > > is causing those errors. However I am assuming that the errors
> > > > > could be due to other bugs in the decoder or due to some
> > > > > unimplemented features?
> > > >
> > > > Could be, I don't know, please find out.
> > > >
> > > The mxf demuxer says: error getting stream index 67174400
> > > Does this mean that the mxf demuxer is unable to read the mxf
> > > packet itself? Looking at the error thrown by the jpeg2000 decoder,
> > > looks like the jpeg2000 frame is corrupt.
> >
> > I don't think so, you can test with libopenjpeg.
> >
> I tried using libopenjpeg as the decoder. I run the command
> ./ffmpeg -c:v libopenjpeg -i ~/Downloads/jpeg2000_mxf_first_10mb.mxf
> -r 1/1 out%03d.bmp
> I get only 3 .bmp images as output.
> I get the same images compared to when I use the native decoder.

rm "-r 1/1"
It is supposed to produce 84 frames

Carl Eugen
Gautam Ramakrishnan March 27, 2020, 8:29 p.m. UTC | #8
On Sat, Mar 28, 2020 at 1:52 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
>
> Am Fr., 27. März 2020 um 20:57 Uhr schrieb Gautam Ramakrishnan
> <gautamramk@gmail.com>:
> >
> > On Sat, Mar 28, 2020 at 12:45 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> > >
> > > Am Fr., 27. März 2020 um 19:24 Uhr schrieb Gautam Ramakrishnan
> > > <gautamramk@gmail.com>:
> > >
> > > > > > > Did you already look at the sample file I pointed out?
> > > > > > Yep, am going through the sample file. I shall try to see what
> > > > > > is causing those errors. However I am assuming that the errors
> > > > > > could be due to other bugs in the decoder or due to some
> > > > > > unimplemented features?
> > > > >
> > > > > Could be, I don't know, please find out.
> > > > >
> > > > The mxf demuxer says: error getting stream index 67174400
> > > > Does this mean that the mxf demuxer is unable to read the mxf
> > > > packet itself? Looking at the error thrown by the jpeg2000 decoder,
> > > > looks like the jpeg2000 frame is corrupt.
> > >
> > > I don't think so, you can test with libopenjpeg.
> > >
> > I tried using libopenjpeg as the decoder. I run the command
> > ./ffmpeg -c:v libopenjpeg -i ~/Downloads/jpeg2000_mxf_first_10mb.mxf
> > -r 1/1 out%03d.bmp
> > I get only 3 .bmp images as output.
> > I get the same images compared to when I use the native decoder.
>
> rm "-r 1/1"
> It is supposed to produce 84 frames
>
Got 84 frames. I'll try the native decoder.
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Gautam Ramakrishnan March 28, 2020, 3:17 a.m. UTC | #9
On Sat, Mar 28, 2020 at 1:59 AM Gautam Ramakrishnan
<gautamramk@gmail.com> wrote:
>
> On Sat, Mar 28, 2020 at 1:52 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> >
> > Am Fr., 27. März 2020 um 20:57 Uhr schrieb Gautam Ramakrishnan
> > <gautamramk@gmail.com>:
> > >
> > > On Sat, Mar 28, 2020 at 12:45 AM Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> > > >
> > > > Am Fr., 27. März 2020 um 19:24 Uhr schrieb Gautam Ramakrishnan
> > > > <gautamramk@gmail.com>:
> > > >
> > > > > > > > Did you already look at the sample file I pointed out?
> > > > > > > Yep, am going through the sample file. I shall try to see what
> > > > > > > is causing those errors. However I am assuming that the errors
> > > > > > > could be due to other bugs in the decoder or due to some
> > > > > > > unimplemented features?
> > > > > >
> > > > > > Could be, I don't know, please find out.
> > > > > >
> > > > > The mxf demuxer says: error getting stream index 67174400
> > > > > Does this mean that the mxf demuxer is unable to read the mxf
> > > > > packet itself? Looking at the error thrown by the jpeg2000 decoder,
> > > > > looks like the jpeg2000 frame is corrupt.
> > > >
> > > > I don't think so, you can test with libopenjpeg.
> > > >
> > > I tried using libopenjpeg as the decoder. I run the command
> > > ./ffmpeg -c:v libopenjpeg -i ~/Downloads/jpeg2000_mxf_first_10mb.mxf
> > > -r 1/1 out%03d.bmp
> > > I get only 3 .bmp images as output.
> > > I get the same images compared to when I use the native decoder.
> >
> > rm "-r 1/1"
> > It is supposed to produce 84 frames
> >
> Got 84 frames. I'll try the native decoder.
> > Carl Eugen
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> > To unsubscribe, visit link above, or email
> > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
>
>
> --
> -------------
> Gautam |

Looks like the stream is missing an EOC marker. Even openjpeg throws
the same error.

On replacing (in read_main_headers() )
if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) {
    av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len,
bytestream2_get_bytes_left(&s->g));
    return AVERROR_INVALIDDATA;
}

with

if (len < 2 || bytestream2_get_bytes_left(&s->g) < len - 2) {
    av_log(s->avctx, AV_LOG_ERROR, "Invalid len %d left=%d\n", len,
bytestream2_get_bytes_left(&s->g));
    av_log(s->avctx, AV_LOG_WARNING, "Stream does not end with EOC.\n");
    return 0;
}
the code runs correctly. Openjpeg also has a check wherein if the
number of bytes left is 0,
but there is no EOC marker, just return as done. Not sure what to do about this.
diff mbox series

Patch

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 019dc81f56..7236e9b7bb 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -83,8 +83,12 @@  typedef struct Jpeg2000Tile {
     Jpeg2000QuantStyle  qntsty[4];
     Jpeg2000POC         poc;
     Jpeg2000TilePart    tile_part[32];
-    uint16_t tp_idx;                    // Tile-part index
-    int coord[2][2];                    // border coordinates {{x0, x1}, {y0, y1}}
+    uint8_t             has_ppt;                // whether this tile has a ppt marker
+    uint8_t             *packed_headers;        // contains packed headers. Used only along with PPT marker
+    int                 packed_headers_size;    // size in bytes of the packed headers
+    GetByteContext      packed_headers_stream;  // byte context corresponding to packed headers
+    uint16_t tp_idx;                            // Tile-part index
+    int coord[2][2];                            // border coordinates {{x0, x1}, {y0, y1}}
 } Jpeg2000Tile;
 
 typedef struct Jpeg2000DecoderContext {
@@ -851,6 +855,38 @@  static int get_plt(Jpeg2000DecoderContext *s, int n)
     return 0;
 }
 
+static int get_ppt(Jpeg2000DecoderContext *s, int n)
+{
+    Jpeg2000Tile *tile;
+
+    tile = &s->tile[s->curtileno];
+
+    av_assert1(s->curtileno >= 0);
+    if (tile->tp_idx != 0) {
+        av_log(s->avctx, AV_LOG_ERROR,
+               "PPT marker can occur only on first tile part of a tile.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    tile->has_ppt = 1;  // this tile has a ppt marker
+/*    Zppt = */ bytestream2_get_byte(&s->g);
+    if (!tile->packed_headers) {
+        tile->packed_headers = av_malloc_array(n - 3, sizeof(uint8_t));
+        memcpy(tile->packed_headers, s->g.buffer, sizeof(uint8_t)*(n - 3));
+        tile->packed_headers_size = n - 3;
+    } else {
+        tile->packed_headers = av_realloc_array(tile->packed_headers,
+                                                tile->packed_headers_size + n - 3,
+                                                sizeof(uint8_t));
+        memcpy(tile->packed_headers + tile->packed_headers_size,
+               s->g.buffer, sizeof(uint8_t)*(n - 3));
+        tile->packed_headers_size += n - 3;
+    }
+    bytestream2_skip(&s->g, n - 3);
+
+    return 0;
+}
+
 static int init_tile(Jpeg2000DecoderContext *s, int tileno)
 {
     int compno;
@@ -923,6 +959,216 @@  static int getlblockinc(Jpeg2000DecoderContext *s)
     return res;
 }
 
+static int jpeg2000_decode_packet_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+                                         int *tp_index,
+                                         Jpeg2000CodingStyle *codsty,
+                                         Jpeg2000ResLevel *rlevel, int precno,
+                                         int layno, uint8_t *expn, int numgbits,
+                                         int *process_data)
+{
+    int bandno, cblkno, ret, nb_code_blocks;
+
+    if (layno < rlevel->band[0].prec[precno].decoded_layers) {
+        *process_data = 0;
+        return 0;
+    }
+    rlevel->band[0].prec[precno].decoded_layers = layno + 1;
+
+    if (tile->has_ppt) {
+        s->g = tile->packed_headers_stream;
+    } else {
+            s->g = tile->tile_part[*tp_index].tpg;
+            if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
+                if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) {
+                    s->g = tile->tile_part[++(*tp_index)].tpg;
+            }
+        }
+        if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES)
+            bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH);
+    }
+
+    if (!(ret = get_bits(s, 1))) {
+        jpeg2000_flush(s);
+        *process_data = 0;
+        goto end;
+    } else if (ret < 0)
+        return ret;
+
+    for (bandno = 0; bandno < rlevel->nbands; bandno++) {
+        Jpeg2000Band *band = rlevel->band + bandno;
+        Jpeg2000Prec *prec = band->prec + precno;
+
+        if (band->coord[0][0] == band->coord[0][1] ||
+            band->coord[1][0] == band->coord[1][1])
+            continue;
+        nb_code_blocks =  prec->nb_codeblocks_height *
+                          prec->nb_codeblocks_width;
+        for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) {
+            Jpeg2000Cblk *cblk = prec->cblk + cblkno;
+            int incl, newpasses, llen;
+            void *tmp;
+
+            if (cblk->npasses)
+                incl = get_bits(s, 1);
+            else
+                incl = tag_tree_decode(s, prec->cblkincl + cblkno, layno + 1) == layno;
+            if (!incl)
+                continue;
+            else if (incl < 0)
+                return incl;
+
+            if (!cblk->npasses) {
+                int v = expn[bandno] + numgbits - 1 -
+                        tag_tree_decode(s, prec->zerobits + cblkno, 100);
+                if (v < 0 || v > 30) {
+                    av_log(s->avctx, AV_LOG_ERROR,
+                           "nonzerobits %d invalid or unsupported\n", v);
+                    return AVERROR_INVALIDDATA;
+                }
+                cblk->nonzerobits = v;
+            }
+            if ((newpasses = getnpasses(s)) < 0)
+                return newpasses;
+            av_assert2(newpasses > 0);
+            if (cblk->npasses + newpasses >= JPEG2000_MAX_PASSES) {
+                avpriv_request_sample(s->avctx, "Too many passes");
+                return AVERROR_PATCHWELCOME;
+            }
+            if ((llen = getlblockinc(s)) < 0)
+                return llen;
+            if (cblk->lblock + llen + av_log2(newpasses) > 16) {
+                avpriv_request_sample(s->avctx,
+                                      "Block with length beyond 16 bits");
+                return AVERROR_PATCHWELCOME;
+            }
+
+            cblk->lblock += llen;
+
+            cblk->nb_lengthinc = 0;
+            cblk->nb_terminationsinc = 0;
+            av_free(cblk->lengthinc);
+            cblk->lengthinc  = av_mallocz_array(newpasses    , sizeof(*cblk->lengthinc));
+            if (!cblk->lengthinc)
+                return AVERROR(ENOMEM);
+            tmp = av_realloc_array(cblk->data_start, cblk->nb_terminations + newpasses + 1, sizeof(*cblk->data_start));
+            if (!tmp)
+                return AVERROR(ENOMEM);
+            cblk->data_start = tmp;
+            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 > cblk->data_allocated) {
+                    size_t new_size = FFMAX(2*cblk->data_allocated, ret);
+                    void *new = av_realloc(cblk->data, new_size);
+                    if (new) {
+                        cblk->data = new;
+                        cblk->data_allocated = new_size;
+                    }
+                }
+                if (ret > cblk->data_allocated) {
+                    avpriv_request_sample(s->avctx,
+                                        "Block with lengthinc greater than %"SIZE_SPECIFIER"",
+                                        cblk->data_allocated);
+                    return AVERROR_PATCHWELCOME;
+                }
+                cblk->lengthinc[cblk->nb_lengthinc++] = ret;
+                cblk->npasses  += newpasses1;
+                newpasses -= newpasses1;
+            } while(newpasses);
+        }
+    }
+    jpeg2000_flush(s);
+
+    if (codsty->csty & JPEG2000_CSTY_EPH) {
+        if (bytestream2_peek_be16(&s->g) == JPEG2000_EPH)
+            bytestream2_skip(&s->g, 2);
+        else
+            av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found. instead %X\n", bytestream2_peek_be32(&s->g));
+    }
+end:
+    if (tile->has_ppt)
+        tile->packed_headers_stream = s->g;
+    else
+        tile->tile_part[*tp_index].tpg = s->g;
+    return 0;
+}
+
+static int jpeg2000_decode_packet_data(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+                                       int *tp_index,
+                                       Jpeg2000CodingStyle *codsty,
+                                       Jpeg2000ResLevel *rlevel, int precno,
+                                       int layno, uint8_t *expn, int numgbits)
+{
+    int bandno, cblkno, nb_code_blocks;
+    int cwsno;
+
+    s->g = tile->tile_part[*tp_index].tpg;
+    if (tile->has_ppt) {
+        if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
+            if (*tp_index < FF_ARRAY_ELEMS(tile->tile_part) - 1) {
+                s->g = tile->tile_part[++(*tp_index)].tpg;
+            }
+        }
+        if (bytestream2_peek_be32(&s->g) == JPEG2000_SOP_FIXED_BYTES)
+            bytestream2_skip(&s->g, JPEG2000_SOP_BYTE_LENGTH);
+    }
+
+
+    for (bandno = 0; bandno < rlevel->nbands; bandno++) {
+        Jpeg2000Band *band = rlevel->band + bandno;
+        Jpeg2000Prec *prec = band->prec + precno;
+
+        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 (!cblk->nb_terminationsinc && !cblk->lengthinc)
+                continue;
+            for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) {
+                if (cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4) {
+                    size_t new_size = FFMAX(2*cblk->data_allocated, cblk->length + cblk->lengthinc[cwsno] + 4);
+                    void *new = av_realloc(cblk->data, new_size);
+                    if (new) {
+                        cblk->data = new;
+                        cblk->data_allocated = new_size;
+                    }
+                }
+                if (   bytestream2_get_bytes_left(&s->g) < cblk->lengthinc[cwsno]
+                    || cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4
+                ) {
+                    av_log(s->avctx, AV_LOG_ERROR,
+                        "Block length %"PRIu16" or lengthinc %d is too large, left %d\n",
+                        cblk->length, cblk->lengthinc[cwsno], bytestream2_get_bytes_left(&s->g));
+                    return AVERROR_INVALIDDATA;
+                }
+
+                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;
+                }
+            }
+            av_freep(&cblk->lengthinc);
+        }
+    }
+    tile->tile_part[*tp_index].tpg = s->g;
+    return 0;
+}
+
 static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
                                   Jpeg2000CodingStyle *codsty,
                                   Jpeg2000ResLevel *rlevel, int precno,