diff mbox series

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

Message ID 20200328154641.1515-1-gautamramk@gmail.com
State New
Headers show
Series [FFmpeg-devel,v6,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 28, 2020, 3:46 p.m. UTC
From: Gautam Ramakrishnan <gautamramk@gmail.com>

This patch adds support for the PPT marker. It breaks down the
jpeg2000_decode_packet() function to decode headers and data
separately.
---
 libavcodec/jpeg2000dec.c | 202 +++++++++++++++++++++++++++++++++------
 1 file changed, 172 insertions(+), 30 deletions(-)

Comments

Michael Niedermayer March 30, 2020, 1:01 a.m. UTC | #1
On Sat, Mar 28, 2020 at 09:16:40PM +0530, gautamramk@gmail.com wrote:
> From: Gautam Ramakrishnan <gautamramk@gmail.com>
> 
> This patch adds support for the PPT marker. It breaks down the
> jpeg2000_decode_packet() function to decode headers and data
> separately.
> ---
>  libavcodec/jpeg2000dec.c | 202 +++++++++++++++++++++++++++++++++------
>  1 file changed, 172 insertions(+), 30 deletions(-)
> 

[...]

> @@ -927,30 +965,38 @@ static int getlblockinc(Jpeg2000DecoderContext *s)
>      return res;
>  }
>  
> -static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
> -                                  Jpeg2000CodingStyle *codsty,
> -                                  Jpeg2000ResLevel *rlevel, int precno,
> -                                  int layno, uint8_t *expn, int numgbits)
> +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;
> -    int cwsno;
>  
> -    if (layno < rlevel->band[0].prec[precno].decoded_layers)
> +    if (layno < rlevel->band[0].prec[precno].decoded_layers) {
> +        *process_data = 0;
>          return 0;
> +    }
>      rlevel->band[0].prec[precno].decoded_layers = layno + 1;
>  
> -    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 (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 (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);
> -        return 0;
> +        *process_data = 0;
> +        goto end;
>      } else if (ret < 0)
>          return ret;
>  
> @@ -1055,6 +1101,34 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
>          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;
> @@ -1097,6 +1171,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
>              av_freep(&cblk->lengthinc);
>          }
>      }
> +    tile->tile_part[*tp_index].tpg = s->g;
>      return 0;
>  }

I think this function spliting should be in a seperate patch from adding 
ppt support.
It would make the changes more readable in the git log

thanks

[...]
Gautam Ramakrishnan March 30, 2020, 2:46 a.m. UTC | #2
On Mon, Mar 30, 2020 at 6:31 AM Michael Niedermayer
<michael@niedermayer.cc> wrote:
>
> On Sat, Mar 28, 2020 at 09:16:40PM +0530, gautamramk@gmail.com wrote:
> > From: Gautam Ramakrishnan <gautamramk@gmail.com>
> >
> > This patch adds support for the PPT marker. It breaks down the
> > jpeg2000_decode_packet() function to decode headers and data
> > separately.
> > ---
> >  libavcodec/jpeg2000dec.c | 202 +++++++++++++++++++++++++++++++++------
> >  1 file changed, 172 insertions(+), 30 deletions(-)
> >
>
> [...]
>
> > @@ -927,30 +965,38 @@ static int getlblockinc(Jpeg2000DecoderContext *s)
> >      return res;
> >  }
> >
> > -static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
> > -                                  Jpeg2000CodingStyle *codsty,
> > -                                  Jpeg2000ResLevel *rlevel, int precno,
> > -                                  int layno, uint8_t *expn, int numgbits)
> > +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;
> > -    int cwsno;
> >
> > -    if (layno < rlevel->band[0].prec[precno].decoded_layers)
> > +    if (layno < rlevel->band[0].prec[precno].decoded_layers) {
> > +        *process_data = 0;
> >          return 0;
> > +    }
> >      rlevel->band[0].prec[precno].decoded_layers = layno + 1;
> >
> > -    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 (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 (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);
> > -        return 0;
> > +        *process_data = 0;
> > +        goto end;
> >      } else if (ret < 0)
> >          return ret;
> >
> > @@ -1055,6 +1101,34 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
> >          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;
> > @@ -1097,6 +1171,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
> >              av_freep(&cblk->lengthinc);
> >          }
> >      }
> > +    tile->tile_part[*tp_index].tpg = s->g;
> >      return 0;
> >  }
>
> I think this function spliting should be in a seperate patch from adding
> ppt support.
> It would make the changes more readable in the git log
>
I have had lot of trouble understanding how to do this and took the easy route.
I shall just split the function without creating the two new functions
in one patch
as mentioned by Carl.
> thanks
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> I have never wished to cater to the crowd; for what I know they do not
> approve, and what they approve I do not know. -- Epicurus
> _______________________________________________
> 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".
diff mbox series

Patch

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 7103cd6ceb..55fab00152 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 {
@@ -855,6 +859,40 @@  static int get_plt(Jpeg2000DecoderContext *s, int n)
     return 0;
 }
 
+static int get_ppt(Jpeg2000DecoderContext *s, int n)
+{
+    Jpeg2000Tile *tile;
+
+    if (s->curtileno < 0)
+        return AVERROR_INVALIDDATA;
+
+    tile = &s->tile[s->curtileno];
+
+    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;
@@ -927,30 +965,38 @@  static int getlblockinc(Jpeg2000DecoderContext *s)
     return res;
 }
 
-static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
-                                  Jpeg2000CodingStyle *codsty,
-                                  Jpeg2000ResLevel *rlevel, int precno,
-                                  int layno, uint8_t *expn, int numgbits)
+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;
-    int cwsno;
 
-    if (layno < rlevel->band[0].prec[precno].decoded_layers)
+    if (layno < rlevel->band[0].prec[precno].decoded_layers) {
+        *process_data = 0;
         return 0;
+    }
     rlevel->band[0].prec[precno].decoded_layers = layno + 1;
 
-    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 (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 (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);
-        return 0;
+        *process_data = 0;
+        goto end;
     } else if (ret < 0)
         return ret;
 
@@ -1055,6 +1101,34 @@  static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
         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;
@@ -1097,6 +1171,7 @@  static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
             av_freep(&cblk->lengthinc);
         }
     }
+    tile->tile_part[*tp_index].tpg = s->g;
     return 0;
 }
 
@@ -1124,13 +1199,25 @@  static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
                         Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
                                                 reslevelno;
                         ok_reslevel = 1;
-                        for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
-                            if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
+                        for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
+                            int process_data = 1;
+                            if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits, &process_data)) < 0)
+                                return ret;
+
+                            if (!process_data)
+                                continue;
+
+                            if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
                                                               codsty, rlevel,
                                                               precno, layno,
                                                               qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
                                                               qntsty->nguardbits)) < 0)
                                 return ret;
+                        }
                     }
                 }
             }
@@ -1150,13 +1237,25 @@  static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
                         Jpeg2000ResLevel *rlevel = tile->comp[compno].reslevel +
                                                 reslevelno;
                         ok_reslevel = 1;
-                        for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++)
-                            if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
+                        for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++) {
+                            int process_data = 1;
+                            if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits, &process_data)) < 0)
+                                return ret;
+
+                            if (!process_data)
+                                continue;
+
+                            if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
                                                               codsty, rlevel,
                                                               precno, layno,
                                                               qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
                                                               qntsty->nguardbits)) < 0)
                                 return ret;
+                        }
                     }
                 }
             }
@@ -1218,7 +1317,19 @@  static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
                         }
 
                         for (layno = 0; layno < LYEpoc; layno++) {
-                            if ((ret = jpeg2000_decode_packet(s, tile, tp_index, codsty, rlevel,
+                            int process_data = 1;
+                            if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits, &process_data)) < 0)
+                                return ret;
+
+                            if (!process_data)
+                                continue;
+
+                            if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+                                                              codsty, rlevel,
                                                               precno, layno,
                                                               qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
                                                               qntsty->nguardbits)) < 0)
@@ -1288,14 +1399,25 @@  static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
                             continue;
                         }
 
-                            for (layno = 0; layno < LYEpoc; layno++) {
-                                if ((ret = jpeg2000_decode_packet(s, tile, tp_index,
-                                                                codsty, rlevel,
-                                                                precno, layno,
-                                                                qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                                qntsty->nguardbits)) < 0)
-                                    return ret;
-                            }
+                        for (layno = 0; layno < LYEpoc; layno++) {
+                            int process_data = 1;
+                            if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits, &process_data)) < 0)
+                                return ret;
+
+                            if (!process_data)
+                                continue;
+
+                            if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits)) < 0)
+                                return ret;
+                        }
                     }
                 }
             }
@@ -1359,7 +1481,19 @@  static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
                         }
 
                         for (layno = 0; layno < LYEpoc; layno++) {
-                            if ((ret = jpeg2000_decode_packet(s, tile, tp_index, codsty, rlevel,
+                            int process_data = 1;
+                            if ((ret = jpeg2000_decode_packet_header(s, tile, tp_index,
+                                                              codsty, rlevel,
+                                                              precno, layno,
+                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
+                                                              qntsty->nguardbits, &process_data)) < 0)
+                                return ret;
+
+                            if (!process_data)
+                                continue;
+
+                            if ((ret = jpeg2000_decode_packet_data(s, tile, tp_index,
+                                                              codsty, rlevel,
                                                               precno, layno,
                                                               qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
                                                               qntsty->nguardbits)) < 0)
@@ -1929,6 +2063,11 @@  static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
                 av_log(s->avctx, AV_LOG_ERROR, "Invalid tpend\n");
                 return AVERROR_INVALIDDATA;
             }
+
+            if (tile->has_ppt && tile->tp_idx == 0) {
+                bytestream2_init(&tile->packed_headers_stream, tile->packed_headers, tile->packed_headers_size);
+            }
+
             bytestream2_init(&tp->tpg, s->g.buffer, tp->tp_end - s->g.buffer);
             bytestream2_skip(&s->g, tp->tp_end - s->g.buffer);
 
@@ -1991,6 +2130,10 @@  static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
             // Packet length, tile-part header
             ret = get_plt(s, len);
             break;
+        case JPEG2000_PPT:
+            // Packed headers, tile-part header
+            ret = get_ppt(s, len);
+            break;
         default:
             av_log(s->avctx, AV_LOG_ERROR,
                    "unsupported marker 0x%.4"PRIX16" at pos 0x%X\n",
@@ -2020,7 +2163,6 @@  static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s)
         if ((ret = init_tile(s, tileno)) < 0)
             return ret;
 
-        s->g = tile->tile_part[0].tpg;
         if ((ret = jpeg2000_decode_packets(s, tile)) < 0)
             return ret;
     }