[FFmpeg-devel] [PATCH v8 2/3] libavcodec/jpeg2000dec.c: Add support for PPT marker

gautamramk at gmail.com gautamramk at gmail.com
Mon Mar 30 19:21:54 EEST 2020


From: Gautam Ramakrishnan <gautamramk at gmail.com>

This patch adds functional changes to support the
PPT marker.
---
 libavcodec/jpeg2000dec.c | 209 ++++++++++++++++++++++++++++++---------
 1 file changed, 162 insertions(+), 47 deletions(-)

diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 9d52969821..23e43ff052 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -859,6 +859,39 @@ 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); // Zppt is skipped and not used
+    if (!tile->packed_headers) {
+        tile->packed_headers = av_malloc_array(n - 3, 1);
+        memcpy(tile->packed_headers, s->g.buffer, n - 3);
+        tile->packed_headers_size = n - 3;
+    } else {
+        tile->packed_headers = av_realloc_array(tile->packed_headers,
+                                                tile->packed_headers_size + n - 3,
+                                                1);
+        memcpy(tile->packed_headers + tile->packed_headers_size,
+               s->g.buffer, 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;
@@ -931,20 +964,21 @@ 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;
 
-// This part decodes the packet header
-
-    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;
-    // Select appropriate stream to read from
+    // Select stream to read from
     if (tile->has_ppt) {
         s->g = tile->packed_headers_stream;
     } else {
@@ -960,12 +994,8 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
 
     if (!(ret = get_bits(s, 1))) {
         jpeg2000_flush(s);
-        // Save state of stream
-        if (tile->has_ppt)
-            tile->packed_headers_stream = s->g;
-        else
-            tile->tile_part[*tp_index].tpg = s->g;
-        return 0;
+        *process_data = 0;
+        goto end;
     } else if (ret < 0)
         return ret;
 
@@ -1070,14 +1100,24 @@ 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:
+    // Save state of stream
     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;
 
-// This part decodes the packet data.
-    // Select appropriate stream to read from
     s->g = tile->tile_part[*tp_index].tpg;
     if (tile->has_ppt) {
         if (bytestream2_get_bytes_left(&s->g) == 0 && s->bit_index == 8) {
@@ -1158,13 +1198,27 @@ 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,
-                                                              codsty, rlevel,
-                                                              precno, layno,
-                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                              qntsty->nguardbits)) < 0)
+                        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;
+                        }
                     }
                 }
             }
@@ -1184,13 +1238,27 @@ 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,
-                                                              codsty, rlevel,
-                                                              precno, layno,
-                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                              qntsty->nguardbits)) < 0)
+                        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;
+                        }
                     }
                 }
             }
@@ -1252,10 +1320,24 @@ 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,
-                                                              precno, layno,
-                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                              qntsty->nguardbits)) < 0)
+                            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;
                         }
                     }
@@ -1322,14 +1404,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;
+                        }
                     }
                 }
             }
@@ -1393,10 +1486,24 @@ 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,
-                                                              precno, layno,
-                                                              qntsty->expn + (reslevelno ? 3 * (reslevelno - 1) + 1 : 0),
-                                                              qntsty->nguardbits)) < 0)
+                            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;
                         }
                     }
@@ -1963,6 +2070,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);
 
@@ -2025,6 +2137,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",
@@ -2054,7 +2170,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;
     }
-- 
2.17.1



More information about the ffmpeg-devel mailing list