Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
@ 2022-09-08 20:49 etemesicaleb
  2022-09-09 15:46 ` Michael Niedermayer
  2022-09-20 13:49 ` Tomas Härdin
  0 siblings, 2 replies; 13+ messages in thread
From: etemesicaleb @ 2022-09-08 20:49 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: caleb, pal

From: caleb <etemesicaleb@gmail.com>

Rebased this patch on master branch
---
 libavcodec/Makefile        |    2 +-
 libavcodec/j2kenc.c        |   26 +-
 libavcodec/jpeg2000.h      |  103 ++-
 libavcodec/jpeg2000dec.c   |  193 ++----
 libavcodec/jpeg2000htdec.c | 1212 ++++++++++++++++++++++++++++++++++++
 libavcodec/jpeg2000htdec.h |  210 +++++++
 6 files changed, 1599 insertions(+), 147 deletions(-)
 create mode 100644 libavcodec/jpeg2000htdec.c
 create mode 100644 libavcodec/jpeg2000htdec.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 945908e3b8..ecf5c47cad 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         += jacosubdec.o ass.o
 OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o jpeg2000.o \
                                           jpeg2000dwt.o
 OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \
-                                          jpeg2000dwt.o mqcdec.o mqc.o
+                                          jpeg2000dwt.o mqcdec.o mqc.o jpeg2000htdec.o
 OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
 OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
 OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index e883d5deb7..233d75e96d 100644
--- a/libavcodec/j2kenc.c
+++ b/libavcodec/j2kenc.c
@@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { // [dwt_type][band][rlevel] (multiplied
 typedef struct {
    Jpeg2000Component *comp;
    double *layer_rates;
-} Jpeg2000Tile;
+} Jpeg2000EncTile;
 
 typedef struct {
     AVClass *class;
@@ -131,7 +131,7 @@ typedef struct {
     Jpeg2000CodingStyle codsty;
     Jpeg2000QuantStyle  qntsty;
 
-    Jpeg2000Tile *tile;
+    Jpeg2000EncTile *tile;
     int layer_rates[100];
     uint8_t compression_rate_enc; ///< Is compression done using compression ratio?
 
@@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext* s)
     int layno, compno;
     for (i = 0; i < s->numYtiles; i++) {
         for (j = 0; j < s->numXtiles; j++) {
-            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
+            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
             for (compno = 0; compno < s->ncomponents; compno++) {
                 int tilew = tile->comp[compno].coord[0][1] - tile->comp[compno].coord[0][0];
                 int tileh = tile->comp[compno].coord[1][1] - tile->comp[compno].coord[1][0];
@@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
     s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
     s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
 
-    s->tile = av_calloc(s->numXtiles, s->numYtiles * sizeof(Jpeg2000Tile));
+    s->tile = av_calloc(s->numXtiles, s->numYtiles * sizeof(Jpeg2000EncTile));
     if (!s->tile)
         return AVERROR(ENOMEM);
     for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
         for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
-            Jpeg2000Tile *tile = s->tile + tileno;
+            Jpeg2000EncTile *tile = s->tile + tileno;
 
             tile->comp = av_calloc(s->ncomponents, sizeof(*tile->comp));
             if (!tile->comp)
@@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
         int tileno, compno, i, y, x;                                                                                        \
         const PIXEL *line;                                                                                                  \
         for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){                                                   \
-            Jpeg2000Tile *tile = s->tile + tileno;                                                                          \
+            Jpeg2000EncTile *tile = s->tile + tileno;                                                                          \
             if (s->planar){                                                                                                 \
                 for (compno = 0; compno < s->ncomponents; compno++){                                                        \
                     Jpeg2000Component *comp = tile->comp + compno;                                                          \
@@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1, int width, int height, int ban
         }
 }
 
-static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
+static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
                         int width, int height, int bandpos, int lev)
 {
     int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
@@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, in
     return 0;
 }
 
-static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno, int nlayers)
+static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile, int tileno, int nlayers)
 {
     int compno, reslevelno, layno, ret;
     Jpeg2000CodingStyle *codsty = &s->codsty;
@@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til
     return 0;
 }
 
-static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2000Tile* tile, int final)
+static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2000EncTile* tile, int final)
 {
     int compno, resno, bandno, precno, cblkno;
     int passno;
@@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2
     }
 }
 
-static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
+static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile)
 {
     int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno;
     int i;
@@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm)
     return res;
 }
 
-static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
+static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile)
 {
     int precno, compno, reslevelno, bandno, cblkno, lev;
     Jpeg2000CodingStyle *codsty = &s->codsty;
@@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
     }
 }
 
-static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
+static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile, int tileno)
 {
     int compno, reslevelno, bandno, ret;
     Jpeg2000T1Context t1;
@@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
 {
     int tileno, compno;
     for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
-        Jpeg2000Tile *tile = s->tile + tileno;
+        Jpeg2000EncTile *tile = s->tile + tileno;
         for (compno = 0; compno < s->ncomponents; compno++)
             ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
     }
diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
index e5ecb4cbf9..a5dd693392 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -33,8 +33,9 @@
 
 #include "avcodec.h"
 #include "mqc.h"
+#include "bytestream.h"
 #include "jpeg2000dwt.h"
-
+#include "jpeg2000dsp.h"
 enum Jpeg2000Markers {
     JPEG2000_SOC = 0xff4f, // start of codestream
     JPEG2000_SIZ = 0xff51, // image and tile size
@@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
     double disto;
     int cum_passes;
 } Jpeg2000Layer;
-
 typedef struct Jpeg2000Cblk {
     uint8_t npasses;
     uint8_t ninclpasses; // number coding of passes included in codestream
@@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
     uint16_t *lengthinc;
     uint8_t nb_lengthinc;
     uint8_t lblock;
+    uint8_t zbp;         // Zero bit planes
     uint8_t *data;
     size_t data_allocated;
     int nb_terminations;
@@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
     Jpeg2000Pass *passes;
     Jpeg2000Layer *layers;
     int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
+    int pass_lengths[2];
 } Jpeg2000Cblk; // code block
 
 typedef struct Jpeg2000Prec {
@@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
     uint8_t roi_shift; // ROI scaling value for the component
 } Jpeg2000Component;
 
+#define JP2_SIG_TYPE    0x6A502020
+#define JP2_SIG_VALUE   0x0D0A870A
+#define JP2_CODESTREAM  0x6A703263
+#define JP2_HEADER      0x6A703268
+
+#define HAD_COC 0x01
+#define HAD_QCC 0x02
+
+#define MAX_POCS 32
+
+typedef struct Jpeg2000POCEntry {
+    uint16_t LYEpoc;
+    uint16_t CSpoc;
+    uint16_t CEpoc;
+    uint8_t RSpoc;
+    uint8_t REpoc;
+    uint8_t Ppoc;
+} Jpeg2000POCEntry;
+
+typedef struct Jpeg2000POC {
+    Jpeg2000POCEntry poc[MAX_POCS];
+    int nb_poc;
+    int is_default;
+} Jpeg2000POC;
+
+typedef struct Jpeg2000TilePart {
+    uint8_t tile_index;                 // Tile index who refers the tile-part
+    const uint8_t *tp_end;
+    GetByteContext header_tpg;          // bit stream of header if PPM header is used
+    GetByteContext tpg;                 // bit stream in tile-part
+} Jpeg2000TilePart;
+
+/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
+ * one per component, so tile_part elements have a size of 3 */
+typedef struct Jpeg2000Tile {
+    Jpeg2000Component   *comp;
+    uint8_t             properties[4];
+    Jpeg2000CodingStyle codsty[4];
+    Jpeg2000QuantStyle  qntsty[4];
+    Jpeg2000POC         poc;
+    Jpeg2000TilePart    tile_part[32];
+    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}}
+} Jpeg2000DecTile;
+
+typedef struct Jpeg2000DecoderContext {
+    AVClass         *class;
+    AVCodecContext  *avctx;
+    GetByteContext  g;
+
+    int             width, height;
+    int             image_offset_x, image_offset_y;
+    int             tile_offset_x, tile_offset_y;
+    uint8_t         cbps[4];    // bits per sample in particular components
+    uint8_t         sgnd[4];    // if a component is signed
+    uint8_t         properties[4];
+
+    uint8_t         has_ppm;
+    uint8_t         *packed_headers; // contains packed headers. Used only along with PPM marker
+    int             packed_headers_size;
+    GetByteContext  packed_headers_stream;
+    uint8_t         in_tile_headers;
+
+    int             cdx[4], cdy[4];
+    int             precision;
+    int             ncomponents;
+    int             colour_space;
+    uint32_t        palette[256];
+    int8_t          pal8;
+    int             cdef[4];
+    int             tile_width, tile_height;
+    unsigned        numXtiles, numYtiles;
+    int             maxtilelen;
+    AVRational      sar;
+
+    Jpeg2000CodingStyle codsty[4];
+    Jpeg2000QuantStyle  qntsty[4];
+    Jpeg2000POC         poc;
+    uint8_t             roi_shift[4];
+
+    int             bit_index;
+
+    int             curtileno;
+
+    Jpeg2000DecTile *tile;
+    Jpeg2000DSPContext dsp;
+
+    /*options parameters*/
+    int             reduction_factor;
+    /*HTJ2K params*/
+    uint8_t         is_htj2k;
+} Jpeg2000DecoderContext;
+
 /* misc tools */
 static inline int ff_jpeg2000_ceildivpow2(int a, int b)
 {
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 7d9661f29f..b3bbc02977 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -27,7 +27,6 @@
 
 #include <inttypes.h>
 #include <math.h>
-
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
 #include "libavutil/common.h"
@@ -38,105 +37,11 @@
 #include "bytestream.h"
 #include "codec_internal.h"
 #include "decode.h"
-#include "thread.h"
 #include "jpeg2000.h"
 #include "jpeg2000dsp.h"
+#include "jpeg2000htdec.h"
 #include "profiles.h"
-
-#define JP2_SIG_TYPE    0x6A502020
-#define JP2_SIG_VALUE   0x0D0A870A
-#define JP2_CODESTREAM  0x6A703263
-#define JP2_HEADER      0x6A703268
-
-#define HAD_COC 0x01
-#define HAD_QCC 0x02
-
-#define MAX_POCS 32
-
-typedef struct Jpeg2000POCEntry {
-    uint16_t LYEpoc;
-    uint16_t CSpoc;
-    uint16_t CEpoc;
-    uint8_t RSpoc;
-    uint8_t REpoc;
-    uint8_t Ppoc;
-} Jpeg2000POCEntry;
-
-typedef struct Jpeg2000POC {
-    Jpeg2000POCEntry poc[MAX_POCS];
-    int nb_poc;
-    int is_default;
-} Jpeg2000POC;
-
-typedef struct Jpeg2000TilePart {
-    uint8_t tile_index;                 // Tile index who refers the tile-part
-    const uint8_t *tp_end;
-    GetByteContext header_tpg;          // bit stream of header if PPM header is used
-    GetByteContext tpg;                 // bit stream in tile-part
-} Jpeg2000TilePart;
-
-/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
- * one per component, so tile_part elements have a size of 3 */
-typedef struct Jpeg2000Tile {
-    Jpeg2000Component   *comp;
-    uint8_t             properties[4];
-    Jpeg2000CodingStyle codsty[4];
-    Jpeg2000QuantStyle  qntsty[4];
-    Jpeg2000POC         poc;
-    Jpeg2000TilePart    tile_part[32];
-    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 {
-    AVClass         *class;
-    AVCodecContext  *avctx;
-    GetByteContext  g;
-
-    int             width, height;
-    int             image_offset_x, image_offset_y;
-    int             tile_offset_x, tile_offset_y;
-    uint8_t         cbps[4];    // bits per sample in particular components
-    uint8_t         sgnd[4];    // if a component is signed
-    uint8_t         properties[4];
-
-    uint8_t         has_ppm;
-    uint8_t         *packed_headers; // contains packed headers. Used only along with PPM marker
-    int             packed_headers_size;
-    GetByteContext  packed_headers_stream;
-    uint8_t         in_tile_headers;
-
-    int             cdx[4], cdy[4];
-    int             precision;
-    int             ncomponents;
-    int             colour_space;
-    uint32_t        palette[256];
-    int8_t          pal8;
-    int             cdef[4];
-    int             tile_width, tile_height;
-    unsigned        numXtiles, numYtiles;
-    int             maxtilelen;
-    AVRational      sar;
-
-    Jpeg2000CodingStyle codsty[4];
-    Jpeg2000QuantStyle  qntsty[4];
-    Jpeg2000POC         poc;
-    uint8_t             roi_shift[4];
-
-    int             bit_index;
-
-    int             curtileno;
-
-    Jpeg2000Tile    *tile;
-    Jpeg2000DSPContext dsp;
-
-    /*options parameters*/
-    int             reduction_factor;
-} Jpeg2000DecoderContext;
+#include "thread.h"
 
 /* get_bits functions for JPEG2000 packet bitstream
  * It is a get_bit function with a bit-stuffing routine. If the value of the
@@ -369,7 +274,7 @@ static int get_siz(Jpeg2000DecoderContext *s)
     }
 
     for (i = 0; i < s->numXtiles * s->numYtiles; i++) {
-        Jpeg2000Tile *tile = s->tile + i;
+        Jpeg2000DecTile *tile = s->tile + i;
 
         tile->comp = av_mallocz(s->ncomponents * sizeof(*tile->comp));
         if (!tile->comp)
@@ -520,11 +425,11 @@ static int get_cox(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c)
     }
 
     c->cblk_style = bytestream2_get_byteu(&s->g);
-    if (c->cblk_style != 0) { // cblk style
-        if (c->cblk_style & JPEG2000_CTSY_HTJ2K_M || c->cblk_style & JPEG2000_CTSY_HTJ2K_F) {
-            av_log(s->avctx, AV_LOG_ERROR, "Support for High throughput JPEG 2000 is not yet available\n");
-            return AVERROR_PATCHWELCOME;
-        }
+    if (c->cblk_style & JPEG2000_CTSY_HTJ2K_M || c->cblk_style & JPEG2000_CTSY_HTJ2K_F){
+        av_log(s->avctx,AV_LOG_TRACE,"High Throughput jpeg 2000 codestream.\n");
+        s->is_htj2k = 1;
+    }
+    if (c->cblk_style != 0 && !(c->cblk_style & JPEG2000_CTSY_HTJ2K_F) /*Covers both partial and full htj2k stream */) { // cblk style
         av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style);
         if (c->cblk_style & JPEG2000_CBLK_BYPASS)
             av_log(s->avctx, AV_LOG_WARNING, "Selective arithmetic coding bypass\n");
@@ -851,7 +756,7 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
     tp->tp_end     = s->g.buffer + Psot - n - 2;
 
     if (!TPsot) {
-        Jpeg2000Tile *tile = s->tile + s->curtileno;
+        Jpeg2000DecTile *tile = s->tile + s->curtileno;
 
         /* copy defaults */
         memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(Jpeg2000CodingStyle));
@@ -966,7 +871,7 @@ static int get_ppm(Jpeg2000DecoderContext *s, int n)
 
 static int get_ppt(Jpeg2000DecoderContext *s, int n)
 {
-    Jpeg2000Tile *tile;
+    Jpeg2000DecTile *tile;
     void *new;
 
     if (n < 3) {
@@ -1005,7 +910,7 @@ static int init_tile(Jpeg2000DecoderContext *s, int tileno)
     int compno;
     int tilex = tileno % s->numXtiles;
     int tiley = tileno / s->numXtiles;
-    Jpeg2000Tile *tile = s->tile + tileno;
+    Jpeg2000DecTile *tile = s->tile + tileno;
 
     if (!tile->comp)
         return AVERROR(ENOMEM);
@@ -1075,7 +980,7 @@ static int getlblockinc(Jpeg2000DecoderContext *s)
     return res;
 }
 
-static inline void select_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+static inline void select_header(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile,
                                  int *tp_index)
 {
     s->g = tile->tile_part[*tp_index].header_tpg;
@@ -1086,7 +991,7 @@ static inline void select_header(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
     }
 }
 
-static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile,
                                  int *tp_index, Jpeg2000CodingStyle *codsty)
 {
     s->g = tile->tile_part[*tp_index].tpg;
@@ -1103,7 +1008,7 @@ static inline void select_stream(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
     }
 }
 
-static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, int *tp_index,
+static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile, int *tp_index,
                                   Jpeg2000CodingStyle *codsty,
                                   Jpeg2000ResLevel *rlevel, int precno,
                                   int layno, uint8_t *expn, int numgbits)
@@ -1152,9 +1057,10 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
                 return incl;
 
             if (!cblk->npasses) {
-                int v = expn[bandno] + numgbits - 1 -
-                        tag_tree_decode(s, prec->zerobits + cblkno, 100);
-                if (v < 0 || v > 30) {
+                int zbp = tag_tree_decode(s, prec->zerobits + cblkno, 100);
+                int v = expn[bandno] + numgbits - 1 - zbp;
+                cblk->zbp = zbp;
+                if (/*v < 0 ||*/ v > 30) {
                     av_log(s->avctx, AV_LOG_ERROR,
                            "nonzerobits %d invalid or unsupported\n", v);
                     return AVERROR_INVALIDDATA;
@@ -1198,9 +1104,22 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
                         break;
                     }
                 }
-
-                if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0)
-                    return ret;
+                if (newpasses > 1 && s->is_htj2k) {
+                    // retrieve pass lengths for each pass
+                    // for htj2k images
+                    int extra_bit = newpasses > 2 ? 1 : 0;
+                    if ((ret = get_bits(s, llen + 3)) < 0)
+                        return ret;
+                    cblk->pass_lengths[0] = ret;
+                    if ((ret = get_bits(s, llen + 3 + extra_bit)) < 0)
+                        return ret;
+                    cblk->pass_lengths[1] = ret;
+                    ret = cblk->pass_lengths[0] + cblk->pass_lengths[1];
+                } else {
+                    if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0)
+                        return ret;
+                    cblk->pass_lengths[0] = ret;
+                }
                 if (ret > cblk->data_allocated) {
                     size_t new_size = FFMAX(2*cblk->data_allocated, ret);
                     void *new = av_realloc(cblk->data, new_size);
@@ -1301,7 +1220,7 @@ skip_data:
     return 0;
 }
 
-static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
+static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile,
                                              int RSpoc, int CSpoc,
                                              int LYEpoc, int REpoc, int CEpoc,
                                              int Ppoc, int *tp_index)
@@ -1592,7 +1511,7 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2
     return ret;
 }
 
-static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static int jpeg2000_decode_packets(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile)
 {
     int ret = AVERROR_BUG;
     int i;
@@ -1900,7 +1819,7 @@ static void dequantization_int_97(int x, int y, Jpeg2000Cblk *cblk,
     }
 }
 
-static inline void mct_decode(const Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static inline void mct_decode(const Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile)
 {
     int i, csize = 1;
     void *src[3];
@@ -1941,17 +1860,20 @@ static inline void roi_scale_cblk(Jpeg2000Cblk *cblk,
     }
 }
 
-static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile)
 {
     Jpeg2000T1Context t1;
 
     int compno, reslevelno, bandno;
+    int subbandno;
 
     /* Loop on tile components */
     for (compno = 0; compno < s->ncomponents; compno++) {
-        Jpeg2000Component *comp     = tile->comp + compno;
-        Jpeg2000CodingStyle *codsty = tile->codsty + compno;
+        Jpeg2000Component *comp        = tile->comp + compno;
+        Jpeg2000CodingStyle *codsty    = tile->codsty + compno;
+        Jpeg2000QuantStyle *quantsty   = tile->qntsty + compno;
         int coded = 0;
+        subbandno = 0;
 
         t1.stride = (1<<codsty->log2_cblk_width) + 2;
 
@@ -1959,7 +1881,7 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
         for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) {
             Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
             /* Loop on bands */
-            for (bandno = 0; bandno < rlevel->nbands; bandno++) {
+            for (bandno = 0; bandno < rlevel->nbands; bandno++,subbandno++) {
                 int nb_precincts, precno;
                 Jpeg2000Band *band = rlevel->band + bandno;
                 int cblkno = 0, bandpos;
@@ -1979,12 +1901,21 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
                     for (cblkno = 0;
                          cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height;
                          cblkno++) {
-                        int x, y;
+                        int x, y, ret, magp;
                         Jpeg2000Cblk *cblk = prec->cblk + cblkno;
-                        int ret = decode_cblk(s, codsty, &t1, cblk,
-                                    cblk->coord[0][1] - cblk->coord[0][0],
-                                    cblk->coord[1][1] - cblk->coord[1][0],
-                                    bandpos, comp->roi_shift);
+                        // Annex E (Equation E-2) ISO/IEC 15444-1:2019
+                        magp = quantsty->expn[subbandno] + quantsty->nguardbits - 1;
+
+                        if (s->is_htj2k)
+                            ret = decode_htj2k(s, codsty, &t1, cblk,
+                                               cblk->coord[0][1] - cblk->coord[0][0],
+                                               cblk->coord[1][1] - cblk->coord[1][0],
+                                               magp, comp->roi_shift);
+                        else
+                            ret = decode_cblk(s, codsty, &t1, cblk,
+                                              cblk->coord[0][1] - cblk->coord[0][0],
+                                              cblk->coord[1][1] - cblk->coord[1][0],
+                                              bandpos, comp->roi_shift);
                         if (ret)
                             coded = 1;
                         else
@@ -2013,7 +1944,7 @@ static inline void tile_codeblocks(const Jpeg2000DecoderContext *s, Jpeg2000Tile
 }
 
 #define WRITE_FRAME(D, PIXEL)                                                                     \
-    static inline void write_frame_ ## D(const Jpeg2000DecoderContext * s, Jpeg2000Tile * tile,   \
+    static inline void write_frame_ ## D(const Jpeg2000DecoderContext * s, Jpeg2000DecTile * tile,   \
                                          AVFrame * picture, int precision)                        \
     {                                                                                             \
         const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->avctx->pix_fmt);               \
@@ -2084,7 +2015,7 @@ static int jpeg2000_decode_tile(AVCodecContext *avctx, void *td,
 {
     const Jpeg2000DecoderContext *s = avctx->priv_data;
     AVFrame *picture = td;
-    Jpeg2000Tile *tile = s->tile + jobnr;
+    Jpeg2000DecTile *tile = s->tile + jobnr;
 
     tile_codeblocks(s, tile);
 
@@ -2156,7 +2087,7 @@ static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
         if (marker >= 0xFF30 && marker <= 0xFF3F)
             continue;
         if (marker == JPEG2000_SOD) {
-            Jpeg2000Tile *tile;
+            Jpeg2000DecTile *tile;
             Jpeg2000TilePart *tp;
 
             if (!s->tile) {
@@ -2306,7 +2237,7 @@ static int jpeg2000_read_bitstream_packets(Jpeg2000DecoderContext *s)
     int tileno;
 
     for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++) {
-        Jpeg2000Tile *tile = s->tile + tileno;
+        Jpeg2000DecTile *tile = s->tile + tileno;
 
         if ((ret = init_tile(s, tileno)) < 0)
             return ret;
diff --git a/libavcodec/jpeg2000htdec.c b/libavcodec/jpeg2000htdec.c
new file mode 100644
index 0000000000..2e2ad20137
--- /dev/null
+++ b/libavcodec/jpeg2000htdec.c
@@ -0,0 +1,1212 @@
+/*
+* JPEG2000 High Throughput block decoder
+* Copyright (c) 2022 Caleb Etemesi<etemesicaleb@gmail.com>
+*
+* This file is part of FFmpeg.
+*
+* FFmpeg is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* FFmpeg is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with FFmpeg; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "jpeg2000htdec.h"
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "bytestream.h"
+
+#define J2K_Q1 0
+
+#define J2K_Q2 1
+
+#define HT_SHIFT_SIGMA 0
+#define HT_SHIFT_SCAN 4
+#define HT_SHIFT_REF 3
+#define HT_SHIFT_REF_IND 2
+/**
+* @brief Table 2 in clause 7.3.3
+*/
+const static uint8_t MEL_E[13] = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5};
+
+/**
+*  Given a precomputed c, checks whether n % d == 0
+*/
+static av_always_inline uint32_t is_divisible(uint32_t n, uint64_t c)
+{
+   return n * c <= c - 1;
+}
+
+/* Initializers */
+
+static void jpeg2000_init_zero(StateVars *s)
+{
+   s->bits_left = 0;
+   s->bit_buf = 0;
+   s->tmp = 0;
+   s->bits = 0;
+   s->pos = 0;
+   s->last = 0;
+}
+
+static void jpeg2000_init_mel(StateVars *s, uint32_t Pcup)
+{
+   jpeg2000_init_zero(s);
+   s->pos = Pcup;
+}
+
+static void jpeg2000_init_mag_ref(StateVars *s, uint32_t Lref)
+{
+   s->pos = Lref - 2;
+   s->bits = 0;
+   s->last = 0xFF;
+   s->tmp = 0;
+   s->bits_left = 0;
+   s->bit_buf = 0;
+}
+
+static void jpeg2000_init_mel_decoder(MelDecoderState *mel_state)
+{
+   mel_state->k = 0;
+   mel_state->run = 0;
+   mel_state->one = 0;
+}
+/**
+* @brief Refill the buffer backwards in little Endian while skipping
+* over stuffing bits
+*
+* Stuffing bits are those that appear in the position of any byte whose
+* LSBs are all 1's if the last consumed byte was larger than 0x8F
+*/
+static int jpeg2000_bitbuf_refill_backwards(StateVars *buffer,
+                                           const uint8_t *array)
+{
+   uint64_t tmp = 0;
+   int32_t position = buffer->pos;
+   uint32_t new_bits = 32;
+   uint32_t mask;
+
+   if (buffer->bits_left > 32)
+       return 0; // enough data, no need to pull in more bits
+
+   /*
+    * We are reading bits from end to start, and we need to handle them in LE.
+    * therefore, if we read bytes ABCD, we need to convert
+    * them to DCBA, but the bitstream is constructed in such a way that it is
+    * BE when reading from back to front,so we need to swap bytes
+    * but this doesn't work when position is less than 3,
+    * we end up reading bits from the MEL byte-stream which
+    * is a recipe for sleepless nights.
+    *
+    * So the trick is to branchlessly read and mask
+    * depending on whatever was the initial position,
+    * the mask is simply either 32 bits, 24 bits ,8 bits or 0 bits.
+    * depending on how many bytes are available, with this, we don't
+    * read past the end of the buffer,we mask
+    * bits we already read ensuring we don't read twice.
+    * and we can do it branchlessly without checking for positions.
+    *
+    * We need to watch out for negative shift values which are UB in C hence
+    * the MAX declarative.
+    */
+
+   position -= 4;
+   mask = (UINT64_C(1) << (FFMIN(4, FFMAX(buffer->pos, 0))) * 8) - 1;
+   tmp = (array[position + 1] << 24) + (array[position + 2] << 16) + (array[position + 3] << 8) + array[position + 4];
+   tmp &= mask;
+
+   // Branchlessly unstuff  bits
+
+   // load temporary byte, which preceeds the position we
+   // currently at, to ensure that we can also un-stuff if the
+   // stuffed bit is the bottom most bits
+   tmp <<= 8;
+   tmp |= array[buffer->pos + 1];
+
+   if ((tmp & 0x7FFF000000) > 0x7F8F000000) {
+       tmp &= 0x7FFFFFFFFF;
+       new_bits--;
+   }
+   if ((tmp & 0x007FFF0000) > 0x007F8F0000) {
+       tmp = (tmp & 0x007FFFFFFF) + ((tmp & 0xFF00000000) >> 1);
+       new_bits--;
+   }
+   if ((tmp & 0x00007FFF00) > 0x00007F8F00) {
+       tmp = (tmp & 0x00007FFFFF) + ((tmp & 0xFFFF000000) >> 1);
+       new_bits--;
+   }
+   if ((tmp & 0x0000007FFF) > 0x0000007F8F) {
+       tmp = (tmp & 0x0000007FFF) + ((tmp & 0xFFFFFF0000) >> 1);
+       new_bits--;
+   }
+   // remove temporary byte loaded.
+   tmp >>= 8;
+
+   // Add bits to the MSB of the bit buffer
+   buffer->bit_buf |= tmp << buffer->bits_left;
+   buffer->bits_left += new_bits;
+   buffer->pos = FFMAX(0, position);
+   return 0;
+}
+/**
+* @brief Refill the bit-buffer reading new bits going forward
+* in the stream while skipping over stuffed bits.
+*/
+static void jpeg2000_bitbuf_refill_forward(StateVars *buffer,
+                                          const uint8_t *array,
+                                          uint32_t length)
+{
+   while (buffer->bits_left < 32) {
+       buffer->tmp = 0xFF;
+       buffer->bits = (buffer->last == 0xFF) ? 7 : 8;
+       if (buffer->pos < length) {
+           buffer->tmp = array[buffer->pos];
+           buffer->pos += 1;
+           buffer->last = buffer->tmp;
+       }
+       buffer->bit_buf |= ((uint64_t)buffer->tmp) << buffer->bits_left;
+       buffer->bits_left += buffer->bits;
+   }
+}
+
+/**
+* @brief Drops bits from lower bits in the bit buffer
+*
+* @param buf: Struct containing bit buffers
+* @param nbits: Number of bits to remove.
+*/
+static av_always_inline void jpeg2000_bitbuf_drop_bits_lsb(StateVars *buf,
+                                                          uint8_t nbits)
+{
+   if (buf->bits_left < nbits) {
+       av_log(NULL, AV_LOG_ERROR, "Invalid bit read of %d, bits in buffer are %d\n", nbits, buf->bits_left);
+       av_assert0(0);
+   }
+   buf->bit_buf >>= nbits;
+   buf->bits_left -= nbits;
+}
+/**
+* @brief  Get bits from the bit buffer reading them
+* from the least significant bits moving to the most significant bits.
+*
+* In case there are fewer bits, refill from `buf` moving backwards.
+*/
+static av_always_inline uint64_t jpeg2000_bitbuf_get_bits_lsb(
+   StateVars *bit_stream, uint8_t nbits, const uint8_t *buf)
+{
+   uint64_t bits;
+   uint64_t mask = (1ull << nbits) - 1;
+   if (bit_stream->bits_left < nbits)
+       jpeg2000_bitbuf_refill_backwards(bit_stream, buf);
+   bits = bit_stream->bit_buf & mask;
+   jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits);
+   return bits;
+}
+/**
+* @brief Get bits from the bit buffer reading them
+* from the least significant bits moving to the most significant bits
+*
+* In case there are fewer bits, refill from `buf` moving forward
+*/
+static av_always_inline uint64_t jpeg2000_bitbuf_get_bits_lsb_forward(
+   StateVars *bit_stream, uint8_t nbits, const uint8_t *buf, uint32_t length)
+{
+   uint64_t bits;
+   uint64_t mask = (1ull << nbits) - 1;
+   if (bit_stream->bits_left <= nbits)
+       jpeg2000_bitbuf_refill_forward(bit_stream, buf, length);
+   bits = bit_stream->bit_buf & mask;
+   jpeg2000_bitbuf_drop_bits_lsb(bit_stream, nbits);
+   return bits;
+}
+/**
+* @brief Look ahead bit buffer without discarding bits
+*/
+static av_always_inline uint64_t
+jpeg2000_bitbuf_peek_bits_lsb(StateVars *stream, uint8_t nbits)
+{
+   uint64_t mask = (1ull << nbits) - 1;
+
+   return stream->bit_buf & mask;
+}
+
+/**
+* Variable Length Decoding Routines
+*/
+static void jpeg2000_init_vlc(StateVars *s, uint32_t Lcup, uint32_t Pcup, const uint8_t *Dcup)
+{
+   s->bits_left = 0;
+   s->bit_buf = 0;
+   s->pos = Lcup - 2 - Pcup;
+   s->last = Dcup[Lcup - 2];
+   s->tmp = (s->last) >> 4;
+   s->bits = ((s->tmp & 7) < 7) ? 4 : 3;
+   jpeg2000_bitbuf_refill_backwards(s, Dcup + Pcup);
+   jpeg2000_bitbuf_drop_bits_lsb(s, 4);
+}
+/**
+* Decode prefix codes for VLC segment.
+*/
+static int jpeg2000_decode_ctx_vlc(const Jpeg2000DecoderContext *s,
+                                  StateVars *vlc_stream,
+                                  const uint16_t *table,
+                                  const uint8_t *Dcup,
+                                  uint8_t *sig_pat,
+                                  uint8_t *res_off,
+                                  uint8_t *emb_pat_k,
+                                  uint8_t *emb_pat_1,
+                                  uint8_t pos,
+                                  uint32_t Pcup,
+                                  uint16_t context)
+{
+   // Described in clause 7.3.5
+   uint32_t value;
+   uint8_t len;
+   uint64_t index;
+   uint64_t code_word;
+
+   jpeg2000_bitbuf_refill_backwards(vlc_stream, Dcup + Pcup);
+
+   code_word = vlc_stream->bit_buf & 0x7f;
+   index = code_word + (context << 7);
+
+   // decode table has 1024 entries so ensure array access is in bounds
+   av_assert0(index < 1024);
+
+   value = table[index];
+
+   len = (value & 0x000F) >> 1;
+
+   res_off[pos] = (uint8_t)(value & 1);
+   sig_pat[pos] = (uint8_t)((value & 0x00F0) >> 4);
+   emb_pat_k[pos] = (uint8_t)((value & 0x0F00) >> 8);
+   emb_pat_1[pos] = (uint8_t)((value & 0xF000) >> 12);
+   jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, len);
+   return 0;
+}
+/**
+* @brief Decode variable length u-vlc prefix
+*/
+static av_always_inline uint8_t
+vlc_decode_u_prefix(StateVars *vlc_stream, const uint8_t *refill_array)
+{
+   // clause 7.3.6
+   // procedure : decodeUPrefix.
+   static uint8_t return_value[8] = {5, 1, 2, 1, 3, 1, 2, 1};
+   static uint8_t drop_bits[8] = {3, 1, 2, 1, 3, 1, 2, 1};
+
+   uint8_t bits;
+
+   if (vlc_stream->bits_left < 3)
+       jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array);
+
+   bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 3);
+
+   jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[bits]);
+   return return_value[bits];
+}
+/**
+* @brief Decode variable length u-vlc suffix
+*/
+static av_always_inline uint8_t vlc_decode_u_suffix(
+   StateVars *vlc_stream, uint8_t suffix, const uint8_t *refill_array)
+{
+   // clause 7.3.6
+   // procedure: decodeUSuffix
+
+   uint8_t bits;
+   if (suffix < 3)
+       return 0;
+
+   if (vlc_stream->bits_left < 5)
+       jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array);
+
+   bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 5);
+
+   if (suffix == 3) {
+       jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, 1);
+       return bits & 1;
+   }
+   jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, 5);
+
+   return bits;
+}
+
+/**
+* @brief Decode variable length u-vlc suffix
+*/
+static av_always_inline uint8_t vlc_decode_u_extension(
+   StateVars *vlc_stream, uint8_t suffix, const uint8_t *refill_array)
+{
+   // clause 7.3.6
+   // procedure decodeUExtension.
+   return jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 4 * (suffix >= 28), refill_array);
+}
+
+/**
+* Magnitude and Sign decode procedures
+*/
+
+static int32_t jpeg2000_decode_mag_sgn(StateVars *mag_sgn_stream, int32_t m_n, int32_t i_n, const uint8_t *buf, uint32_t length)
+{
+   // clause 7.3.8
+   // procedure: decodeMagSgnValue
+
+   int32_t val = 0;
+   if (m_n > 0) {
+       val = jpeg2000_bitbuf_get_bits_lsb_forward(mag_sgn_stream, m_n, buf, length);
+       val += (i_n << m_n);
+   }
+   return val;
+}
+
+static av_always_inline void
+recover_mag_sgn(StateVars *mag_sgn, uint8_t pos, uint16_t q, int32_t m_n[2], int32_t known_1[2], const uint8_t emb_pat_1[2], int32_t v[2][4], int32_t m[2][4], uint8_t *E, uint32_t *mu_n, const uint8_t *Dcup, uint32_t Pcup, uint32_t pLSB)
+{
+   for (int i = 0; i < 4; i++) {
+       int32_t n = 4 * q + i;
+       m_n[pos] = m[pos][i];
+       known_1[pos] = (emb_pat_1[pos] >> i) & 1;
+       v[pos][i] = jpeg2000_decode_mag_sgn(mag_sgn, m_n[pos], known_1[pos], Dcup, Pcup);
+       if (m_n[pos] != 0) {
+           E[n] = 32 - ff_clz(v[pos][i] | 1);
+           mu_n[n] = (v[pos][i] >> 1) + 1;
+           mu_n[n] <<= pLSB;
+           mu_n[n] |= ((uint32_t)(v[pos][i] & 1)) << 31; // sign bit.
+       }
+   }
+}
+
+/*MEL stream decoding procedure*/
+static int jpeg2000_import_bit(StateVars *stream, const uint8_t *array, uint32_t length)
+{
+   if (stream->bits == 0) {
+       stream->bits = (stream->tmp == 0xFF) ? 7 : 8;
+       if (stream->pos < length) {
+           stream->tmp = array[stream->pos];
+           stream->pos += 1;
+       } else
+           stream->tmp = 0xFF;
+   }
+   stream->bits -= 1;
+   return (stream->tmp >> stream->bits) & 1;
+}
+
+static int jpeg2000_decode_mel_sym(MelDecoderState *mel_state,
+                                  StateVars *mel_stream,
+                                  const uint8_t *Dcup,
+                                  uint32_t Lcup)
+{
+
+   if (mel_state->run == 0 && mel_state->one == 0) {
+       uint8_t eval;
+       uint8_t bit;
+
+       eval = MEL_E[mel_state->k];
+       bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup);
+       if (bit == 1) {
+           mel_state->run = 1 << eval;
+           mel_state->k = FFMIN(12, mel_state->k + 1);
+       } else {
+           mel_state->run = 0;
+           while (eval > 0) {
+               bit = jpeg2000_import_bit(mel_stream, Dcup, Lcup);
+               mel_state->run = (2 * (mel_state->run)) + bit;
+               eval -= 1;
+           }
+           mel_state->k = FFMAX(0, mel_state->k - 1);
+           mel_state->one = 1;
+       }
+   }
+   if (mel_state->run > 0) {
+       mel_state->run -= 1;
+       return 0;
+   } else {
+       mel_state->one = 0;
+       return 1;
+   }
+}
+/** Magref decoding procedures */
+static av_always_inline int jpeg2000_import_magref_bit(StateVars *stream, const uint8_t *array, uint32_t length)
+{
+   return jpeg2000_bitbuf_get_bits_lsb(stream, 1, array);
+}
+
+/* Signal EMB decode */
+static int
+jpeg2000_decode_sig_emb(const Jpeg2000DecoderContext *s, MelDecoderState *mel_state, StateVars *mel_stream, StateVars *vlc_stream, const uint16_t *vlc_table, const uint8_t *Dcup, uint8_t *sig_pat, uint8_t *res_off, uint8_t *emb_pat_k, uint8_t *emb_pat_1, uint8_t pos, uint16_t context, uint32_t Lcup, uint32_t Pcup)
+{
+   if (context == 0) {
+       uint8_t sym;
+       sym = jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup);
+       if (sym == 0) {
+           sig_pat[pos] = 0;
+           res_off[pos] = 0;
+           emb_pat_k[pos] = 0;
+           emb_pat_1[pos] = 0;
+           return 0;
+       }
+   }
+   return jpeg2000_decode_ctx_vlc(s, vlc_stream, vlc_table, Dcup, sig_pat,
+                                  res_off, emb_pat_k, emb_pat_1, pos, Pcup,
+                                  context);
+}
+
+static av_always_inline int jpeg2000_get_state(int x1, int x2, int width, int shift_by, const uint8_t *block_states)
+{
+   return (block_states[(x1 + 1) * (width + 2) + (x2 + 1)] >> shift_by) & 1;
+}
+static av_always_inline void jpeg2000_modify_state(int x1, int x2, int width, int value, uint8_t *block_states)
+{
+   block_states[(x1 + 1) * (width + 2) + (x2 + 1)] |= value;
+}
+
+static int jpeg2000_decode_ht_cleanup(
+   const Jpeg2000DecoderContext *s, Jpeg2000Cblk *cblk, Jpeg2000T1Context *t1, MelDecoderState *mel_state, StateVars *mel_stream, StateVars *vlc_stream, StateVars *mag_sgn_stream, const uint8_t *Dcup, uint32_t Lcup, uint32_t Pcup, uint8_t pLSB, int width, int height, int32_t *sample_buf, uint8_t *block_states)
+{
+   uint16_t q = 0; // Represents current quad position.
+   uint16_t q1, q2;
+   uint16_t context1, context2;
+   uint16_t context = 0;
+
+   uint8_t sig_pat[2] = {0};   // significance pattern
+   uint8_t res_off[2] = {0};   // residual offset
+   uint8_t emb_pat_k[2] = {0}; // Exponent Max Bound pattern K
+   uint8_t emb_pat_1[2] = {0}; // Exponent Max Bound pattern 1.
+   uint8_t gamma[2] = {0};
+
+   uint8_t E_n[2] = {0};
+   uint8_t E_ne[2] = {0};
+   uint8_t E_nw[2] = {0};
+   uint8_t E_nf[2] = {0};
+
+   uint8_t max_e[2] = {0};
+
+   uint8_t u_pfx[2] = {0};
+   uint8_t u_sfx[2] = {0};
+   uint8_t u_ext[2] = {0};
+
+   int32_t u[2] = {0};
+   int32_t U[2] = {0}; // Exponent bound (7.3.7)
+   int32_t m_n[2] = {0};
+   int32_t known_1[2] = {0};
+
+   int32_t m[2][4] = {0};
+   int32_t v[2][4] = {0};
+
+   uint8_t kappa[2] = {1, 1};
+   int ret = 0;
+
+   int sp;
+
+   uint64_t c;
+
+   uint8_t *sigma;
+   uint32_t *mu;
+
+   const uint8_t *vlc_buf = Dcup + Pcup;
+   // convert to raster-scan
+   const uint16_t is_border_x = width % 2;
+   const uint16_t is_border_y = height % 2;
+
+   int j1, j2;
+   int x1 = 0, x2 = 0, x3 = 0;
+
+   const uint16_t quad_width = ff_jpeg2000_ceildivpow2(width, 1);
+   const uint16_t quad_height = ff_jpeg2000_ceildivpow2(height, 1);
+
+   size_t buf_size = 4 * quad_width * quad_height;
+
+   uint8_t *sigma_n = av_calloc(buf_size, sizeof(uint8_t));
+   uint8_t *E = av_calloc(buf_size, sizeof(uint8_t));
+   uint32_t *mu_n = av_calloc(buf_size, sizeof(uint32_t));
+
+   if (!sigma_n || !E || !mu_n) {
+       ret = AVERROR(ENOMEM);
+       goto free;
+   }
+
+   sigma = sigma_n;
+   mu = mu_n;
+
+   while (q < quad_width - 1) {
+       q1 = q;
+       q2 = q1 + 1;
+
+       if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                          dec_CxtVLC_table0, Dcup, sig_pat, res_off,
+                                          emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup,
+                                          Pcup))
+           < 0)
+           goto free;
+       for (int i = 0; i < 4; i++)
+           sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1;
+
+       // calculate context
+       context = sigma_n[4 * q1];           // f
+       context |= sigma_n[4 * q1 + 1];      // sf
+       context += sigma_n[4 * q1 + 2] << 1; // w << 1
+       context += sigma_n[4 * q1 + 3] << 2;
+
+       if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                          dec_CxtVLC_table0, Dcup, sig_pat, res_off,
+                                          emb_pat_k, emb_pat_1, J2K_Q2, context, Lcup,
+                                          Pcup))
+           < 0)
+           goto free;
+
+       for (int i = 0; i < 4; i++)
+           sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1;
+
+       // calculate context for the next quad
+       context = sigma_n[4 * q2];           // f
+       context |= sigma_n[4 * q2 + 1];      // sf
+       context += sigma_n[4 * q2 + 2] << 1; // w << 1
+       context += sigma_n[4 * q2 + 3] << 2; // sw << 2
+
+       u[0] = 0;
+       u[1] = 0;
+
+       jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf);
+
+       if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) {
+
+           if (jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup) == 1) {
+
+               u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+               u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+               u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+               u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf);
+
+               u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+               u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf);
+
+               u[J2K_Q1] = 2 + u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4);
+               u[J2K_Q2] = 2 + u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4);
+
+           } else {
+               u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+               if (u_pfx[J2K_Q1] > 2) {
+                   u[J2K_Q2] = jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 1, vlc_buf) + 1;
+
+                   u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+
+                   u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+               } else {
+                   u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+                   u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+                   u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf);
+
+                   u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+                   u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf);
+
+                   u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] * 4);
+               }
+               // clause 7.3.6 (3)
+               u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4);
+           }
+
+       } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) {
+           uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1;
+
+           u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+           u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf);
+
+           u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf);
+
+           u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] * 4);
+       }
+       U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
+       U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2];
+
+       for (int i = 0; i < 4; i++) {
+           m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1);
+           m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1);
+       }
+
+       recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m,
+                       E, mu_n, Dcup, Pcup, pLSB);
+
+       recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m,
+                       E, mu_n, Dcup, Pcup, pLSB);
+
+       // prepare context for the next quad
+
+       // move to the next quad pair
+       q += 2;
+   }
+   if (quad_width % 2 == 1) {
+       q1 = q;
+
+       if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                          dec_CxtVLC_table0, Dcup, sig_pat, res_off,
+                                          emb_pat_k, emb_pat_1, J2K_Q1, context, Lcup,
+                                          Pcup))
+           < 0)
+           goto free;
+
+       for (int i = 0; i < 4; i++)
+           sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1;
+
+       u[J2K_Q1] = 0;
+
+       if (res_off[J2K_Q1] == 1) {
+           u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+           u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+           u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+           u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] * 4);
+       }
+
+       U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
+
+       for (int i = 0; i < 4; i++)
+           m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1);
+
+       recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m,
+                       E, mu_n, Dcup, Pcup, pLSB);
+
+       q++; // move to next quad pair
+   }
+   // initial line pair end.
+
+   /*
+    * As an optimization, we can replace modulo operations with
+    * checking if a number is divisible , since that's the only thing we need.
+    * this is paired with is_divisible.
+    * Credits to Daniel Lemire blog post:
+    * https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/
+    * It's UB on zero, but we can't have a quad being zero, the spec doesn't allow,
+    * so we error out early in case that's the case.
+    */
+
+   c = 1 + UINT64_C(0xffffffffffffffff) / quad_width;
+
+   for (int row = 1; row < quad_height; row++) {
+       while ((q - (row * quad_width)) < quad_width - 1 && q < (quad_height * quad_width)) {
+           q1 = q;
+           q2 = q + 1;
+           context1 = sigma_n[4 * (q1 - quad_width) + 1];
+           context1 += sigma_n[4 * (q1 - quad_width) + 3] << 2; // ne
+
+           if (!is_divisible(q1, c)) {
+               context1 |= sigma_n[4 * (q1 - quad_width) - 1];               // nw
+               context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 1; // sw| q
+           }
+           if (!is_divisible(q1 + 1, c))
+               context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2;
+
+           if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                              dec_CxtVLC_table1, Dcup, sig_pat, res_off,
+                                              emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup,
+                                              Pcup))
+               < 0)
+               goto free;
+
+           for (int i = 0; i < 4; i++)
+               sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1;
+
+           context2 = sigma_n[4 * (q2 - quad_width) + 1];
+           context2 += sigma_n[4 * (q2 - quad_width) + 3] << 2;
+
+           if (!is_divisible(q2, c)) {
+               context2 |= sigma_n[4 * (q2 - quad_width) - 1];
+               context2 += (sigma_n[4 * q2 - 1] | sigma_n[4 * q2 - 2]) << 1;
+           }
+           if (!is_divisible(q2 + 1, c))
+               context2 |= sigma_n[4 * (q2 - quad_width) + 5] << 2;
+
+           if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                              dec_CxtVLC_table1, Dcup, sig_pat, res_off,
+                                              emb_pat_k, emb_pat_1, J2K_Q2, context2, Lcup,
+                                              Pcup))
+               < 0)
+               goto free;
+
+           for (int i = 0; i < 4; i++)
+               sigma_n[4 * q2 + i] = (sig_pat[J2K_Q2] >> i) & 1;
+
+           u[J2K_Q1] = 0;
+           u[J2K_Q2] = 0;
+
+           jpeg2000_bitbuf_refill_backwards(vlc_stream, vlc_buf);
+
+           if (res_off[J2K_Q1] == 1 && res_off[J2K_Q2] == 1) {
+               u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+               u_pfx[J2K_Q2] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+               u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+               u_sfx[J2K_Q2] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q2], vlc_buf);
+
+               u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+               u_ext[J2K_Q2] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q2], vlc_buf);
+
+               u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2);
+               u[J2K_Q2] = u_pfx[J2K_Q2] + u_sfx[J2K_Q2] + (u_ext[J2K_Q2] << 2);
+
+           } else if (res_off[J2K_Q1] == 1 || res_off[J2K_Q2] == 1) {
+               uint8_t pos = res_off[J2K_Q1] == 1 ? 0 : 1;
+
+               u_pfx[pos] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+
+               u_sfx[pos] = vlc_decode_u_suffix(vlc_stream, u_pfx[pos], vlc_buf);
+
+               u_ext[pos] = vlc_decode_u_extension(vlc_stream, u_sfx[pos], vlc_buf);
+
+               u[pos] = u_pfx[pos] + u_sfx[pos] + (u_ext[pos] << 2);
+           }
+           sp = sig_pat[J2K_Q1];
+
+           gamma[J2K_Q1] = 1;
+
+           if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8)
+               gamma[J2K_Q1] = 0;
+
+           sp = sig_pat[J2K_Q2];
+
+           gamma[J2K_Q2] = 1;
+
+           if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8)
+               gamma[J2K_Q2] = 0;
+
+           E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1];
+           E_n[J2K_Q2] = E[4 * (q2 - quad_width) + 1];
+
+           E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3];
+           E_ne[J2K_Q2] = E[4 * (q2 - quad_width) + 3];
+
+           E_nw[J2K_Q1] = 0;
+           E_nw[J2K_Q2] = 0;
+
+           E_nf[J2K_Q1] = 0;
+           E_nf[J2K_Q2] = 0;
+
+           E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)];
+           E_nw[J2K_Q2] = (!is_divisible(q2, c)) * E[FFMAX((4 * (q2 - quad_width) - 1), 0)];
+
+           E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5];
+           E_nf[J2K_Q2] = (!is_divisible(q2 + 1, c)) * E[4 * (q2 - quad_width) + 5];
+
+           max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1]));
+           max_e[J2K_Q2] = FFMAX(E_nw[J2K_Q2], FFMAX3(E_n[J2K_Q2], E_ne[J2K_Q2], E_nf[J2K_Q2]));
+
+           kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1));
+           kappa[J2K_Q2] = FFMAX(1, gamma[J2K_Q2] * (max_e[J2K_Q2] - 1));
+
+           U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
+           U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2];
+
+           for (int i = 0; i < 4; i++) {
+               m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1);
+               m[J2K_Q2][i] = sigma_n[4 * q2 + i] * U[J2K_Q2] - ((emb_pat_k[J2K_Q2] >> i) & 1);
+           }
+           recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m,
+                           E, mu_n, Dcup, Pcup, pLSB);
+
+           recover_mag_sgn(mag_sgn_stream, J2K_Q2, q2, m_n, known_1, emb_pat_1, v, m,
+                           E, mu_n, Dcup, Pcup, pLSB);
+
+           // move to the next quad pair
+           q += 2;
+       }
+       if ((quad_width % 2) == 1) {
+           q1 = q;
+           // calculate context for current quad
+           context1 = sigma_n[4 * (q1 - quad_width) + 1];         // n
+           context1 += (sigma_n[4 * (q1 - quad_width) + 3] << 2); // ne
+
+           if (!is_divisible(q1, c)) {
+               context1 |= sigma_n[4 * (q1 - quad_width) - 1]; // nw
+               context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2])
+                   << 1; // (sw| w) << 1;
+           }
+           if (!is_divisible(q1 + 1, c))
+               context1 |= sigma_n[4 * (q1 - quad_width) + 5] << 2;
+
+           if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
+                                              dec_CxtVLC_table1, Dcup, sig_pat, res_off,
+                                              emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup,
+                                              Pcup))
+               < 0)
+               goto free;
+
+           for (int i = 0; i < 4; i++)
+               sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1;
+
+           u[J2K_Q1] = 0;
+
+           // Recover mag_sgn value
+           if (res_off[J2K_Q1] == 1) {
+               u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
+               u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
+               u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
+               u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2);
+           }
+
+           sp = sig_pat[J2K_Q1];
+
+           gamma[J2K_Q1] = 1;
+
+           if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8)
+               gamma[J2K_Q1] = 0;
+
+           E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1];
+
+           E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3];
+
+           E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)];
+
+           E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5];
+
+           max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1]));
+
+           kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1));
+
+           U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
+
+           for (int i = 0; i < 4; i++)
+               m[J2K_Q1][i] = sigma_n[4 * q1 + i] * U[J2K_Q1] - ((emb_pat_k[J2K_Q1] >> i) & 1);
+
+           recover_mag_sgn(mag_sgn_stream, J2K_Q1, q1, m_n, known_1, emb_pat_1, v, m,
+                           E, mu_n, Dcup, Pcup, pLSB);
+           // move to the next quad
+           q += 1;
+       }
+   }
+   // convert to raster-scan
+   for (int y = 0; y < quad_height; y++) {
+       for (int x = 0; x < quad_width; x++) {
+           j1 = 2 * y;
+           j2 = 2 * x;
+
+           sample_buf[j2 + (j1 * width)] = (int32_t)*mu;
+           jpeg2000_modify_state(j1, j2, width, *sigma, block_states);
+           sigma += 1;
+           mu += 1;
+
+           x1 = y != quad_height - 1 || is_border_y == 0;
+           sample_buf[j2 + ((j1 + 1) * width)] = ((int32_t)*mu) * x1;
+           jpeg2000_modify_state(j1 + 1, j2, width, (*sigma) * x1, block_states);
+           sigma += 1;
+           mu += 1;
+
+           x2 = x != quad_width - 1 || is_border_x == 0;
+           sample_buf[(j2 + 1) + (j1 * width)] = ((int32_t)*mu) * x2;
+           jpeg2000_modify_state(j1, j2 + 1, width, (*sigma) * x2, block_states);
+           sigma += 1;
+           mu += 1;
+
+           x3 = x1 | x2;
+           sample_buf[(j2 + 1) + (j1 + 1) * width] = ((int32_t)*mu) * x3;
+           jpeg2000_modify_state(j1 + 1, j2 + 1, width, (*sigma) * x3, block_states);
+           sigma += 1;
+           mu += 1;
+       }
+   }
+   ret = 1;
+free:
+   av_freep(&sigma_n);
+   av_freep(&E);
+   av_freep(&mu_n);
+   return ret;
+}
+
+static void jpeg2000_calc_mbr(uint8_t *mbr, const uint16_t i, const uint16_t j, const uint32_t mbr_info, uint8_t causal_cond, uint8_t *block_states, int width)
+{
+
+   int local_mbr = 0;
+   local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SIGMA, block_states);
+   local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_SIGMA, block_states);
+   local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SIGMA, block_states);
+
+   local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SIGMA, block_states);
+   local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SIGMA, block_states);
+
+   local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
+   local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
+   local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
+
+   local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states);
+   local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states);
+   local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SCAN, block_states);
+
+   local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SCAN, block_states);
+   local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SCAN, block_states);
+
+   local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SCAN, block_states) * causal_cond;
+   local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SCAN, block_states) * causal_cond;
+   local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_REF, block_states) * jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SCAN, block_states) * causal_cond;
+
+   *mbr |= local_mbr;
+}
+static void jpeg2000_process_stripes_block(StateVars *sig_prop, int i_s, int j_s, int width, int height, int stride, int pLSB, int32_t *sample_buf, uint8_t *block_states, uint8_t *magref_segment, uint32_t magref_length)
+{
+   int32_t *sp;
+   uint8_t causal_cond = 0;
+   uint8_t bit;
+   uint8_t mbr;
+   uint32_t mbr_info;
+
+   for (int j = j_s; j < j_s + width; j++) {
+       mbr_info = 0;
+       for (int i = i_s; i < i_s + height; i++) {
+           sp = &sample_buf[j + (i * (stride - 2))];
+           mbr = 0;
+           causal_cond = i != (i_s + height - 1);
+           if (jpeg2000_get_state(i, j, stride - 2, HT_SHIFT_SIGMA, block_states) == 0)
+               jpeg2000_calc_mbr(&mbr, i, j, mbr_info & 0x1EF, causal_cond, block_states, stride - 2);
+           mbr_info >>= 3;
+           if (mbr != 0) {
+               jpeg2000_modify_state(i, j, stride - 2, 1 << HT_SHIFT_REF_IND, block_states);
+               bit = jpeg2000_import_bit(sig_prop, magref_segment, magref_length);
+               jpeg2000_modify_state(i, j, stride - 2, 1 << HT_SHIFT_REF, block_states);
+               *sp |= bit << pLSB;
+           }
+           jpeg2000_modify_state(i, j, stride - 2, 1 << HT_SHIFT_SCAN, block_states);
+       }
+   }
+   for (int j = 0; j < j_s + width; j++) {
+       for (int i = 0; i < i_s + height; i++) {
+           sp = &sample_buf[j + (i * (stride - 2))];
+           if ((*sp & (1 << pLSB)) != 0)
+               *sp = (*sp & 0x7FFFFFFF) | (jpeg2000_import_bit(sig_prop, magref_segment, magref_length) << 31);
+       }
+   }
+}
+
+static void jpeg2000_decode_sigprop(Jpeg2000Cblk *cblk, uint16_t width, uint16_t height, uint8_t *magref_segment, uint32_t magref_length, uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states)
+{
+   // Described in clause 7.4
+   // procedure: decodeSigPropMag
+
+   StateVars sp_dec;
+   const uint16_t num_v_stripe = height / 4;
+   const uint16_t num_h_stripe = width / 4;
+   int b_width = 4;
+   int b_height = 4;
+   int stride = width + 2;
+   int last_width;
+   uint16_t i = 0, j = 0;
+
+   jpeg2000_init_zero(&sp_dec);
+
+   for (int n1 = 0; n1 < num_v_stripe; n1++) {
+       j = 0;
+       for (int n2 = 0; n2 < num_h_stripe; n2++) {
+           jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride,
+                                          pLSB, sample_buf, block_states, magref_segment,
+                                          magref_length);
+           j += 4;
+       }
+       last_width = width % 4;
+       if (last_width)
+           jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride,
+                                          pLSB, sample_buf, block_states, magref_segment,
+                                          magref_length);
+       i += 4;
+   }
+   // decode remaining height stripes
+   b_height = height % 4;
+   j = 0;
+   for (int n2 = 0; n2 < num_h_stripe; n2++) {
+       jpeg2000_process_stripes_block(&sp_dec, i, j, b_width, b_height, stride,
+                                      pLSB, sample_buf, block_states, magref_segment,
+                                      magref_length);
+       j += 4;
+   }
+   last_width = width % 4;
+   if (last_width)
+       jpeg2000_process_stripes_block(&sp_dec, i, j, last_width, b_height, stride,
+                                      pLSB, sample_buf, block_states, magref_segment,
+                                      magref_length);
+}
+
+static int jpeg2000_decode_magref(Jpeg2000Cblk *cblk, uint16_t width, uint16_t block_height, uint8_t *magref_segment, uint32_t magref_length, uint8_t pLSB, int32_t *sample_buf, uint8_t *block_states)
+{
+   // Described in clause 7.5
+   // procedure: decodeSigPropMag
+
+   StateVars mag_ref = {0};
+   const uint16_t num_v_stripe = block_height / 4;
+   uint16_t height = 4;
+   uint16_t i_start = 0;
+   int32_t *sp;
+
+   jpeg2000_init_mag_ref(&mag_ref, magref_length);
+
+   for (int n1 = 0; n1 < num_v_stripe; n1++) {
+       for (int j = 0; j < width; j++) {
+           for (int i = i_start; i < i_start + height; i++) {
+               // we move column wise, going from one quad to another
+               // see figure 7.
+               sp = &sample_buf[j + i * width];
+               if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) {
+                   jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states);
+                   *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB;
+               }
+           }
+       }
+       i_start += 4;
+   }
+   height = block_height % 4;
+   for (int j = 0; j < width; j++) {
+       for (int i = i_start; i < i_start + height; i++) {
+           sp = &sample_buf[j + i * width];
+           if (jpeg2000_get_state(i, j, width, HT_SHIFT_SIGMA, block_states) != 0) {
+               jpeg2000_modify_state(i, j, width, 1 << HT_SHIFT_REF_IND, block_states);
+               *sp |= jpeg2000_import_magref_bit(&mag_ref, magref_segment, magref_length) << pLSB;
+           }
+       }
+   }
+   return 1;
+}
+
+int decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, int width, int height, int magp, uint8_t roi_shift)
+{
+   uint8_t p0 = 0; // Number of placeholder passes.
+   uint32_t Lcup;  // Length of HT cleanup segment.
+   uint32_t Lref;  // Length of Refinement segment.
+   uint32_t Scup;  // HT cleanup segment suffix length.
+   uint32_t Pcup;  // HT cleanup segment prefix length.
+
+   uint8_t S_blk; // Number of skipped magnitude bitplanes;
+   uint8_t pLSB;
+
+   uint8_t *Dcup; // Byte of an HT cleanup segment.
+   uint8_t *Dref; // Byte of an HT refinement segment.
+
+   int z_blk; // Number of ht coding pass
+
+   uint8_t empty_passes;
+
+   StateVars mag_sgn;  // Magnitude and Sign
+   StateVars mel;      // Adaptive run-length coding
+   StateVars vlc;      // Variable Length coding
+   StateVars sig_prop; // Significance propagation
+
+   MelDecoderState mel_state;
+
+   int ret;
+
+   // Temporary buffers
+   int32_t *sample_buf;
+   uint8_t *block_states;
+
+   // Post-processing
+   int32_t n, val;
+
+   int32_t M_b = magp;
+   av_assert0(width <= 1024U && height <= 1024U);
+   av_assert0(width * height <= 4096);
+   av_assert0(width * height > 0);
+
+   memset(t1->data, 0, t1->stride * height * sizeof(*t1->data));
+   memset(t1->flags, 0, t1->stride * (height + 2) * sizeof(*t1->flags));
+
+   if (cblk->npasses == 0)
+       return 0;
+
+   if (cblk->npasses > 3)
+       // Currently use this as a dummy but should be fixed soon
+       p0 = 0;
+   else if (cblk->length == 0)
+       p0 = 1;
+
+   empty_passes = p0 * 3;
+   z_blk = cblk->npasses - empty_passes;
+
+   if (z_blk <= 0)
+       // no passes within this set, continue
+       return 0;
+
+   Lcup = cblk->pass_lengths[0];
+   Lref = cblk->pass_lengths[1];
+
+   if (Lcup < 2) {
+       av_log(s->avctx, AV_LOG_ERROR,
+              "Cleanup pass length must be at least 2 bytes in length\n");
+       return AVERROR_INVALIDDATA;
+   }
+   Dcup = cblk->data;
+   // Dref comes after the refinement segment.
+   Dref = cblk->data + Lcup;
+   S_blk = p0 + cblk->zbp;
+
+   pLSB = 30 - S_blk;
+
+   Scup = (Dcup[Lcup - 1] << 4) + (Dcup[Lcup - 2] & 0x0F);
+
+   if (Scup < 2 || Scup > Lcup || Scup > 4079) {
+       av_log(s->avctx, AV_LOG_ERROR, "Cleanup pass suffix length is invalid %d\n",
+              Scup);
+       ret = AVERROR_INVALIDDATA;
+       goto free;
+   }
+   Pcup = Lcup - Scup;
+
+   // modDcup shall be done before the creation of vlc instance.
+   Dcup[Lcup - 1] = 0xFF;
+   Dcup[Lcup - 2] |= 0x0F;
+   // Magnitude and refinement
+   jpeg2000_init_zero(&mag_sgn);
+   jpeg2000_bitbuf_refill_forward(&mag_sgn, Dcup, Pcup);
+   // Significance propagation
+   jpeg2000_init_zero(&sig_prop);
+   // Adaptive run length
+   jpeg2000_init_mel(&mel, Pcup);
+   // Variable Length coding.
+   jpeg2000_init_vlc(&vlc, Lcup, Pcup, Dcup);
+
+   jpeg2000_init_mel_decoder(&mel_state);
+
+   sample_buf = av_calloc((width + 4) * (height + 4), sizeof(int32_t));
+   block_states = av_calloc((width + 4) * (height + 4), sizeof(uint8_t));
+
+   if (!sample_buf || !block_states) {
+       ret = AVERROR(ENOMEM);
+       goto free;
+   }
+   if ((ret = jpeg2000_decode_ht_cleanup(s, cblk, t1, &mel_state, &mel, &vlc,
+                                         &mag_sgn, Dcup, Lcup, Pcup, pLSB, width,
+                                         height, sample_buf, block_states))
+       < 0)
+       goto free;
+
+   if (cblk->npasses > 1)
+       jpeg2000_decode_sigprop(cblk, width, height, Dref, Lref,
+                               pLSB - 1, sample_buf, block_states);
+
+   if (cblk->npasses > 2)
+       if ((ret = jpeg2000_decode_magref(cblk, width, height, Dref, Lref,
+                                         pLSB - 1, sample_buf, block_states))
+           < 0)
+           goto free;
+
+   pLSB = 31 - M_b;
+   // Reconstruct the values.
+   for (int y = 0; y < height; y++) {
+       for (int x = 0; x < width; x++) {
+           n = x + (y * t1->stride);
+           val = sample_buf[x + (y * width)];
+           // Convert sign-magnitude to twos complement.
+           val = val >> 31 ? 0x80000000 - val : val;
+           val >>= (pLSB - 1);
+           t1->data[n] = val;
+       }
+   }
+free:
+   av_freep(&sample_buf);
+   av_freep(&block_states);
+   return ret;
+}
diff --git a/libavcodec/jpeg2000htdec.h b/libavcodec/jpeg2000htdec.h
new file mode 100644
index 0000000000..a3204cecee
--- /dev/null
+++ b/libavcodec/jpeg2000htdec.h
@@ -0,0 +1,210 @@
+/*
+* JPEG2000 High Throughput block decoder
+* Copyright (c) 2022 Caleb Etemesi<etemesicaleb@gmail.com>
+*
+* This file is part of FFmpeg.
+*
+* FFmpeg is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* FFmpeg is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with FFmpeg; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef AVCODEC_JPEG2000HTDEC_H
+#define AVCODEC_JPEG2000HTDEC_H
+
+#include <stdint.h>
+#include "jpeg2000.h"
+
+typedef struct StateVars {
+  int32_t pos;
+  uint32_t bits;
+  uint32_t tmp;
+  uint32_t last;
+  uint8_t bits_left;
+  uint64_t bit_buf;
+} StateVars;
+
+typedef struct MelDecoderState {
+  uint8_t k;
+  uint8_t run;
+  uint8_t one;
+} MelDecoderState;
+
+
+
+int decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, int width, int height, int magp, uint8_t roi_shift);
+
+/**
+ * @brief  CtxVLC tables, borrowed from openhtj2k (https://github.com/osamu620/OpenHTJ2K) (credits to Osamu Watanabe)
+ */
+static const uint16_t dec_CxtVLC_table1[1024] = {
+    0x0016, 0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086,
+    0x003A, 0x0026, 0x00DE, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A,
+    0x0046, 0x007D, 0x0086, 0x01FD, 0x0026, 0x007E, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026,
+    0x111D, 0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x00EE, 0x0016, 0x00CA, 0x0046, 0x00BD,
+    0x0086, 0x005A, 0x0026, 0x11FF, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x2AAF, 0x0016,
+    0x006A, 0x0046, 0x00DD, 0x0086, 0x888B, 0x0026, 0x444D, 0x0016, 0x00AA, 0x0046, 0x88AD, 0x0086, 0x003A,
+    0x0026, 0x44EF, 0x0016, 0x00CA, 0x0046, 0x009D, 0x0086, 0x005A, 0x0026, 0x222D, 0x0016, 0x009A, 0x0046,
+    0x007D, 0x0086, 0x01FD, 0x0026, 0x00BE, 0x0016, 0x006A, 0x0046, 0x88CD, 0x0086, 0x888B, 0x0026, 0x111D,
+    0x0016, 0x00AA, 0x0046, 0x005D, 0x0086, 0x003A, 0x0026, 0x4CCF, 0x0016, 0x00CA, 0x0046, 0x00BD, 0x0086,
+    0x005A, 0x0026, 0x00FE, 0x0016, 0x009A, 0x0046, 0x003D, 0x0086, 0x04ED, 0x0026, 0x006F, 0x0002, 0x0088,
+    0x0002, 0x005C, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002,
+    0x007E, 0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x888F, 0x0002, 0x0028, 0x0002, 0x00FE,
+    0x0002, 0x003A, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00BE, 0x0002,
+    0x0028, 0x0002, 0x00BF, 0x0002, 0x004A, 0x0002, 0x006E, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018,
+    0x0002, 0x444F, 0x0002, 0x0028, 0x0002, 0x00EE, 0x0002, 0x003A, 0x0002, 0x113F, 0x0002, 0x0088, 0x0002,
+    0x005C, 0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x0028, 0x0002, 0x009C, 0x0002, 0x004A, 0x0002, 0x006F,
+    0x0002, 0x0088, 0x0002, 0x00CC, 0x0002, 0x0018, 0x0002, 0x009F, 0x0002, 0x0028, 0x0002, 0x00EF, 0x0002,
+    0x003A, 0x0002, 0x233F, 0x0002, 0x0088, 0x0002, 0x04FD, 0x0002, 0x0018, 0x0002, 0x00AF, 0x0002, 0x0028,
+    0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x005F, 0x0002, 0x0088, 0x0002, 0x00AC, 0x0002, 0x0018, 0x0002,
+    0x007F, 0x0002, 0x0028, 0x0002, 0x00DF, 0x0002, 0x003A, 0x0002, 0x111F, 0x0002, 0x0028, 0x0002, 0x005C,
+    0x0002, 0x008A, 0x0002, 0x00BF, 0x0002, 0x0018, 0x0002, 0x00FE, 0x0002, 0x00CC, 0x0002, 0x007E, 0x0002,
+    0x0028, 0x0002, 0x8FFF, 0x0002, 0x004A, 0x0002, 0x007F, 0x0002, 0x0018, 0x0002, 0x00DF, 0x0002, 0x00AC,
+    0x0002, 0x133F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x00BE, 0x0002, 0x0018, 0x0002,
+    0x44EF, 0x0002, 0x2AAD, 0x0002, 0x006E, 0x0002, 0x0028, 0x0002, 0x15FF, 0x0002, 0x004A, 0x0002, 0x009E,
+    0x0002, 0x0018, 0x0002, 0x00CF, 0x0002, 0x003C, 0x0002, 0x223F, 0x0002, 0x0028, 0x0002, 0x005C, 0x0002,
+    0x008A, 0x0002, 0x2BBF, 0x0002, 0x0018, 0x0002, 0x04EF, 0x0002, 0x00CC, 0x0002, 0x006F, 0x0002, 0x0028,
+    0x0002, 0x27FF, 0x0002, 0x004A, 0x0002, 0x009F, 0x0002, 0x0018, 0x0002, 0x00DE, 0x0002, 0x00AC, 0x0002,
+    0x444F, 0x0002, 0x0028, 0x0002, 0x222D, 0x0002, 0x008A, 0x0002, 0x8AAF, 0x0002, 0x0018, 0x0002, 0x00EE,
+    0x0002, 0x2AAD, 0x0002, 0x005F, 0x0002, 0x0028, 0x0002, 0x44FF, 0x0002, 0x004A, 0x0002, 0x888F, 0x0002,
+    0x0018, 0x0002, 0xAAAF, 0x0002, 0x003C, 0x0002, 0x111F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC,
+    0x008A, 0x66FF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x8AAF, 0x0004, 0x00FC, 0x0028,
+    0x133D, 0x0004, 0x00AC, 0x004A, 0x3BBF, 0x0004, 0x2BBD, 0x0018, 0x5FFF, 0x0004, 0x006C, 0x157D, 0x455F,
+    0x0004, 0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x44EF, 0x0004, 0x00CC, 0x0018, 0x4FFF, 0x0004,
+    0x007C, 0x003A, 0x447F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x00DE, 0x0004, 0x88BD,
+    0x0018, 0xAFFF, 0x0004, 0x115D, 0x1FFD, 0x444F, 0x0004, 0x8FFD, 0x0028, 0x005C, 0x0004, 0x00BC, 0x008A,
+    0x8CEF, 0x0004, 0x00CD, 0x0018, 0x111D, 0x0004, 0x009C, 0x003A, 0x888F, 0x0004, 0x00FC, 0x0028, 0x133D,
+    0x0004, 0x00AC, 0x004A, 0x44DF, 0x0004, 0x2BBD, 0x0018, 0x8AFF, 0x0004, 0x006C, 0x157D, 0x006F, 0x0004,
+    0x2FFD, 0x0028, 0x222D, 0x0004, 0x22AD, 0x008A, 0x00EE, 0x0004, 0x00CC, 0x0018, 0x2EEF, 0x0004, 0x007C,
+    0x003A, 0x277F, 0x0004, 0x04DD, 0x0028, 0x233D, 0x0004, 0x009D, 0x004A, 0x1BBF, 0x0004, 0x88BD, 0x0018,
+    0x37FF, 0x0004, 0x115D, 0x1FFD, 0x333F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x4CCF,
+    0x0002, 0x0048, 0x0002, 0x23FF, 0x0002, 0x001A, 0x0002, 0x888F, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002,
+    0x002A, 0x0002, 0x00AF, 0x0002, 0x0048, 0x0002, 0x22EF, 0x0002, 0x00AC, 0x0002, 0x005F, 0x0002, 0x0088,
+    0x0002, 0x444D, 0x0002, 0x00CA, 0x0002, 0xCCCF, 0x0002, 0x0048, 0x0002, 0x00FE, 0x0002, 0x001A, 0x0002,
+    0x006F, 0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009F, 0x0002, 0x0048, 0x0002, 0x00DF,
+    0x0002, 0x03FD, 0x0002, 0x222F, 0x0002, 0x0088, 0x0002, 0x02ED, 0x0002, 0x00CA, 0x0002, 0x8CCF, 0x0002,
+    0x0048, 0x0002, 0x11FF, 0x0002, 0x001A, 0x0002, 0x007E, 0x0002, 0x0088, 0x0002, 0x006C, 0x0002, 0x002A,
+    0x0002, 0x007F, 0x0002, 0x0048, 0x0002, 0x00EE, 0x0002, 0x00AC, 0x0002, 0x003E, 0x0002, 0x0088, 0x0002,
+    0x444D, 0x0002, 0x00CA, 0x0002, 0x00BE, 0x0002, 0x0048, 0x0002, 0x00BF, 0x0002, 0x001A, 0x0002, 0x003F,
+    0x0002, 0x0088, 0x0002, 0x005C, 0x0002, 0x002A, 0x0002, 0x009E, 0x0002, 0x0048, 0x0002, 0x00DE, 0x0002,
+    0x03FD, 0x0002, 0x111F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0x3FFF, 0x0004, 0xCFFD,
+    0x002A, 0x003D, 0x0004, 0x00BC, 0x005A, 0x8DDF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A,
+    0x99FF, 0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x009F, 0x0004, 0x2FFD, 0x0048, 0x007C,
+    0x0004, 0x44CD, 0x00CA, 0x67FF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x8CCF, 0x0004,
+    0x4FFD, 0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x4EEF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C,
+    0x001A, 0x222F, 0x0004, 0x8AED, 0x0048, 0x888D, 0x0004, 0x00DC, 0x00CA, 0xAFFF, 0x0004, 0xCFFD, 0x002A,
+    0x003D, 0x0004, 0x00BC, 0x005A, 0x11BF, 0x0004, 0x8FFD, 0x0048, 0x006C, 0x0004, 0x027D, 0x008A, 0x22EF,
+    0x0004, 0x00EC, 0x00FA, 0x003C, 0x0004, 0x00AC, 0x001A, 0x227F, 0x0004, 0x2FFD, 0x0048, 0x007C, 0x0004,
+    0x44CD, 0x00CA, 0x5DFF, 0x0004, 0x1FFD, 0x002A, 0x444D, 0x0004, 0x00AD, 0x005A, 0x006F, 0x0004, 0x4FFD,
+    0x0048, 0x445D, 0x0004, 0x01BD, 0x008A, 0x11DF, 0x0004, 0x45DD, 0x00FA, 0x111D, 0x0004, 0x009C, 0x001A,
+    0x155F, 0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x4DDF, 0x0006, 0x2AAD, 0x005A, 0x67FF,
+    0x0028, 0x223D, 0x00BC, 0xAAAF, 0x0006, 0x00EC, 0x0018, 0x5FFF, 0x0048, 0x006C, 0x008A, 0xCCCF, 0x0006,
+    0x009D, 0x00CA, 0x44EF, 0x0028, 0x003C, 0x8FFD, 0x137F, 0x0006, 0x8EED, 0x0018, 0x1FFF, 0x0048, 0x007C,
+    0x00AA, 0x4CCF, 0x0006, 0x227D, 0x005A, 0x1DDF, 0x0028, 0x444D, 0x4FFD, 0x155F, 0x0006, 0x00DC, 0x0018,
+    0x2EEF, 0x0048, 0x445D, 0x008A, 0x22BF, 0x0006, 0x009C, 0x00CA, 0x8CDF, 0x0028, 0x222D, 0x2FFD, 0x226F,
+    0x0006, 0x00FC, 0x0018, 0x111D, 0x0048, 0x888D, 0x00AA, 0x1BBF, 0x0006, 0x2AAD, 0x005A, 0x33FF, 0x0028,
+    0x223D, 0x00BC, 0x8AAF, 0x0006, 0x00EC, 0x0018, 0x9BFF, 0x0048, 0x006C, 0x008A, 0x8ABF, 0x0006, 0x009D,
+    0x00CA, 0x4EEF, 0x0028, 0x003C, 0x8FFD, 0x466F, 0x0006, 0x8EED, 0x0018, 0xCFFF, 0x0048, 0x007C, 0x00AA,
+    0x8CCF, 0x0006, 0x227D, 0x005A, 0xAEEF, 0x0028, 0x444D, 0x4FFD, 0x477F, 0x0006, 0x00DC, 0x0018, 0xAFFF,
+    0x0048, 0x445D, 0x008A, 0x2BBF, 0x0006, 0x009C, 0x00CA, 0x44DF, 0x0028, 0x222D, 0x2FFD, 0x133F, 0x00F6,
+    0xAFFD, 0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x11DF, 0x00F6, 0x45DD, 0x2FFB, 0x4EEF, 0x00DA, 0x177D,
+    0xCFFD, 0x377F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x1BBF, 0x00F6, 0x00CD, 0x00BA,
+    0x8DDF, 0x4FFB, 0x006C, 0x9BFD, 0x455F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x009F,
+    0x00F6, 0x00AD, 0x2FFB, 0x7FFF, 0x00DA, 0x004C, 0x5FFD, 0x477F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008,
+    0x008C, 0x005A, 0x888F, 0x00F6, 0x00CC, 0x00BA, 0x2EEF, 0x4FFB, 0x115D, 0x8AED, 0x113F, 0x00F6, 0xAFFD,
+    0x1FFB, 0x003C, 0x0008, 0x23BD, 0x007A, 0x1DDF, 0x00F6, 0x45DD, 0x2FFB, 0xBFFF, 0x00DA, 0x177D, 0xCFFD,
+    0x447F, 0x00F6, 0x3FFD, 0x8FFB, 0x111D, 0x0008, 0x009C, 0x005A, 0x277F, 0x00F6, 0x00CD, 0x00BA, 0x22EF,
+    0x4FFB, 0x006C, 0x9BFD, 0x444F, 0x00F6, 0x67FD, 0x1FFB, 0x002C, 0x0008, 0x00AC, 0x007A, 0x11BF, 0x00F6,
+    0x00AD, 0x2FFB, 0xFFFF, 0x00DA, 0x004C, 0x5FFD, 0x233F, 0x00F6, 0x00EC, 0x8FFB, 0x001C, 0x0008, 0x008C,
+    0x005A, 0x006F, 0x00F6, 0x00CC, 0x00BA, 0x8BBF, 0x4FFB, 0x115D, 0x8AED, 0x222F};
+
+static const uint16_t dec_CxtVLC_table0[1024] = {
+    0x0026, 0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x8DDF, 0x0026, 0x01BD, 0x0046, 0x5FFF, 0x0086,
+    0x027D, 0x005A, 0x155F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0xCCCF, 0x0026, 0x2EFD,
+    0x0046, 0x99FF, 0x0086, 0x009C, 0x00CA, 0x133F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018,
+    0x11DF, 0x0026, 0x4FFD, 0x0046, 0xCFFF, 0x0086, 0x009D, 0x005A, 0x007E, 0x0026, 0x003A, 0x0046, 0x1FFF,
+    0x0086, 0x88AD, 0x0018, 0x00BE, 0x0026, 0x8FFD, 0x0046, 0x4EEF, 0x0086, 0x888D, 0x00CA, 0x111F, 0x0026,
+    0x00AA, 0x0046, 0x006C, 0x0086, 0x8AED, 0x0018, 0x45DF, 0x0026, 0x01BD, 0x0046, 0x22EF, 0x0086, 0x027D,
+    0x005A, 0x227F, 0x0026, 0x003A, 0x0046, 0x444D, 0x0086, 0x4CCD, 0x0018, 0x11BF, 0x0026, 0x2EFD, 0x0046,
+    0x00FE, 0x0086, 0x009C, 0x00CA, 0x223F, 0x0026, 0x00AA, 0x0046, 0x445D, 0x0086, 0x8CCD, 0x0018, 0x00DE,
+    0x0026, 0x4FFD, 0x0046, 0xABFF, 0x0086, 0x009D, 0x005A, 0x006F, 0x0026, 0x003A, 0x0046, 0x6EFF, 0x0086,
+    0x88AD, 0x0018, 0x2AAF, 0x0026, 0x8FFD, 0x0046, 0x00EE, 0x0086, 0x888D, 0x00CA, 0x222F, 0x0004, 0x00CA,
+    0x0088, 0x027D, 0x0004, 0x4CCD, 0x0028, 0x00FE, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018,
+    0x00DE, 0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x11DF, 0x0004, 0x8AED, 0x0048, 0x003C,
+    0x0004, 0x888D, 0x0018, 0x111F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x88FF, 0x0004,
+    0x8BFD, 0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x00BE, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC,
+    0x0028, 0x00EE, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x007E, 0x0004, 0x00CA, 0x0088,
+    0x027D, 0x0004, 0x4CCD, 0x0028, 0x1FFF, 0x0004, 0x2AFD, 0x0048, 0x005C, 0x0004, 0x009D, 0x0018, 0x11BF,
+    0x0004, 0x01BD, 0x0088, 0x006C, 0x0004, 0x88AD, 0x0028, 0x22EF, 0x0004, 0x8AED, 0x0048, 0x003C, 0x0004,
+    0x888D, 0x0018, 0x227F, 0x0004, 0x00CA, 0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x4EEF, 0x0004, 0x8BFD,
+    0x0048, 0x444D, 0x0004, 0x009C, 0x0018, 0x2AAF, 0x0004, 0x4EFD, 0x0088, 0x445D, 0x0004, 0x00AC, 0x0028,
+    0x8DDF, 0x0004, 0x45DD, 0x0048, 0x222D, 0x0004, 0x003D, 0x0018, 0x155F, 0x0004, 0x005A, 0x0088, 0x006C,
+    0x0004, 0x88DD, 0x0028, 0x23FF, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x00BE, 0x0004,
+    0x137D, 0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x00DE, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D,
+    0x0018, 0x007E, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x00EE, 0x0004, 0x1FFD, 0x0048,
+    0x003C, 0x0004, 0x00AC, 0x0018, 0x555F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x477F,
+    0x0004, 0x4CDD, 0x0048, 0x8FFF, 0x0004, 0x009C, 0x0018, 0x222F, 0x0004, 0x005A, 0x0088, 0x006C, 0x0004,
+    0x88DD, 0x0028, 0x00FE, 0x0004, 0x11FD, 0x0048, 0x444D, 0x0004, 0x00AD, 0x0018, 0x888F, 0x0004, 0x137D,
+    0x0088, 0x155D, 0x0004, 0x00CC, 0x0028, 0x8CCF, 0x0004, 0x02ED, 0x0048, 0x111D, 0x0004, 0x009D, 0x0018,
+    0x006F, 0x0004, 0x005A, 0x0088, 0x455D, 0x0004, 0x44CD, 0x0028, 0x1DDF, 0x0004, 0x1FFD, 0x0048, 0x003C,
+    0x0004, 0x00AC, 0x0018, 0x227F, 0x0004, 0x47FD, 0x0088, 0x113D, 0x0004, 0x02BD, 0x0028, 0x22BF, 0x0004,
+    0x4CDD, 0x0048, 0x22EF, 0x0004, 0x009C, 0x0018, 0x233F, 0x0006, 0x4DDD, 0x4FFB, 0xCFFF, 0x0018, 0x113D,
+    0x005A, 0x888F, 0x0006, 0x23BD, 0x008A, 0x00EE, 0x002A, 0x155D, 0xAAFD, 0x277F, 0x0006, 0x44CD, 0x8FFB,
+    0x44EF, 0x0018, 0x467D, 0x004A, 0x2AAF, 0x0006, 0x00AC, 0x555B, 0x99DF, 0x1FFB, 0x003C, 0x5FFD, 0x266F,
+    0x0006, 0x1DDD, 0x4FFB, 0x6EFF, 0x0018, 0x177D, 0x005A, 0x1BBF, 0x0006, 0x88AD, 0x008A, 0x5DDF, 0x002A,
+    0x444D, 0x2FFD, 0x667F, 0x0006, 0x00CC, 0x8FFB, 0x2EEF, 0x0018, 0x455D, 0x004A, 0x119F, 0x0006, 0x009C,
+    0x555B, 0x8CCF, 0x1FFB, 0x111D, 0x8CED, 0x006E, 0x0006, 0x4DDD, 0x4FFB, 0x3FFF, 0x0018, 0x113D, 0x005A,
+    0x11BF, 0x0006, 0x23BD, 0x008A, 0x8DDF, 0x002A, 0x155D, 0xAAFD, 0x222F, 0x0006, 0x44CD, 0x8FFB, 0x00FE,
+    0x0018, 0x467D, 0x004A, 0x899F, 0x0006, 0x00AC, 0x555B, 0x00DE, 0x1FFB, 0x003C, 0x5FFD, 0x446F, 0x0006,
+    0x1DDD, 0x4FFB, 0x9BFF, 0x0018, 0x177D, 0x005A, 0x00BE, 0x0006, 0x88AD, 0x008A, 0xCDDF, 0x002A, 0x444D,
+    0x2FFD, 0x007E, 0x0006, 0x00CC, 0x8FFB, 0x4EEF, 0x0018, 0x455D, 0x004A, 0x377F, 0x0006, 0x009C, 0x555B,
+    0x8BBF, 0x1FFB, 0x111D, 0x8CED, 0x233F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x11DF,
+    0x0004, 0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x2BBF, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004,
+    0x00CC, 0x0028, 0x00EE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x007E, 0x0004, 0x00AA,
+    0x0088, 0x006D, 0x0004, 0x88CD, 0x0028, 0x00FE, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018,
+    0xAAAF, 0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x4CCF, 0x0004, 0x44ED, 0x0048, 0x4FFF,
+    0x0004, 0x223D, 0x0018, 0x111F, 0x0004, 0x00AA, 0x0088, 0x047D, 0x0004, 0x01DD, 0x0028, 0x99FF, 0x0004,
+    0x27FD, 0x0048, 0x005C, 0x0004, 0x8AAD, 0x0018, 0x00BE, 0x0004, 0x009C, 0x0088, 0x006C, 0x0004, 0x00CC,
+    0x0028, 0x00DE, 0x0004, 0x8CED, 0x0048, 0x222D, 0x0004, 0x888D, 0x0018, 0x444F, 0x0004, 0x00AA, 0x0088,
+    0x006D, 0x0004, 0x88CD, 0x0028, 0x2EEF, 0x0004, 0x19FD, 0x0048, 0x003C, 0x0004, 0x2AAD, 0x0018, 0x447F,
+    0x0004, 0x8BFD, 0x0088, 0x005D, 0x0004, 0x00BD, 0x0028, 0x009F, 0x0004, 0x44ED, 0x0048, 0x67FF, 0x0004,
+    0x223D, 0x0018, 0x133F, 0x0006, 0x00CC, 0x008A, 0x9DFF, 0x2FFB, 0x467D, 0x1FFD, 0x99BF, 0x0006, 0x2AAD,
+    0x002A, 0x66EF, 0x4FFB, 0x005C, 0x2EED, 0x377F, 0x0006, 0x89BD, 0x004A, 0x00FE, 0x8FFB, 0x006C, 0x67FD,
+    0x889F, 0x0006, 0x888D, 0x001A, 0x5DDF, 0x00AA, 0x222D, 0x89DD, 0x444F, 0x0006, 0x2BBD, 0x008A, 0xCFFF,
+    0x2FFB, 0x226D, 0x009C, 0x00BE, 0x0006, 0xAAAD, 0x002A, 0x1DDF, 0x4FFB, 0x003C, 0x4DDD, 0x466F, 0x0006,
+    0x8AAD, 0x004A, 0xAEEF, 0x8FFB, 0x445D, 0x8EED, 0x177F, 0x0006, 0x233D, 0x001A, 0x4CCF, 0x00AA, 0xAFFF,
+    0x88CD, 0x133F, 0x0006, 0x00CC, 0x008A, 0x77FF, 0x2FFB, 0x467D, 0x1FFD, 0x3BBF, 0x0006, 0x2AAD, 0x002A,
+    0x00EE, 0x4FFB, 0x005C, 0x2EED, 0x007E, 0x0006, 0x89BD, 0x004A, 0x4EEF, 0x8FFB, 0x006C, 0x67FD, 0x667F,
+    0x0006, 0x888D, 0x001A, 0x00DE, 0x00AA, 0x222D, 0x89DD, 0x333F, 0x0006, 0x2BBD, 0x008A, 0x57FF, 0x2FFB,
+    0x226D, 0x009C, 0x199F, 0x0006, 0xAAAD, 0x002A, 0x99DF, 0x4FFB, 0x003C, 0x4DDD, 0x155F, 0x0006, 0x8AAD,
+    0x004A, 0xCEEF, 0x8FFB, 0x445D, 0x8EED, 0x277F, 0x0006, 0x233D, 0x001A, 0x1BBF, 0x00AA, 0x3FFF, 0x88CD,
+    0x111F, 0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0xCCCF, 0x0006, 0x19BD, 0x004A, 0x22EF,
+    0x002A, 0x222D, 0x3FFD, 0x888F, 0x0006, 0x00CC, 0x008A, 0x00FE, 0x0018, 0x115D, 0xCFFD, 0x8AAF, 0x0006,
+    0x00AC, 0x003A, 0x8CDF, 0x1FFB, 0x133D, 0x66FD, 0x466F, 0x0006, 0x8CCD, 0x2FFB, 0x5FFF, 0x0018, 0x006C,
+    0x4FFD, 0xABBF, 0x0006, 0x22AD, 0x004A, 0x00EE, 0x002A, 0x233D, 0xAEFD, 0x377F, 0x0006, 0x2BBD, 0x008A,
+    0x55DF, 0x0018, 0x005C, 0x177D, 0x119F, 0x0006, 0x009C, 0x003A, 0x4CCF, 0x1FFB, 0x333D, 0x8EED, 0x444F,
+    0x0006, 0x45DD, 0x2FFB, 0x111D, 0x0018, 0x467D, 0x8FFD, 0x99BF, 0x0006, 0x19BD, 0x004A, 0x2EEF, 0x002A,
+    0x222D, 0x3FFD, 0x667F, 0x0006, 0x00CC, 0x008A, 0x4EEF, 0x0018, 0x115D, 0xCFFD, 0x899F, 0x0006, 0x00AC,
+    0x003A, 0x00DE, 0x1FFB, 0x133D, 0x66FD, 0x226F, 0x0006, 0x8CCD, 0x2FFB, 0x9BFF, 0x0018, 0x006C, 0x4FFD,
+    0x00BE, 0x0006, 0x22AD, 0x004A, 0x1DDF, 0x002A, 0x233D, 0xAEFD, 0x007E, 0x0006, 0x2BBD, 0x008A, 0xCEEF,
+    0x0018, 0x005C, 0x177D, 0x277F, 0x0006, 0x009C, 0x003A, 0x8BBF, 0x1FFB, 0x333D, 0x8EED, 0x455F, 0x1FF9,
+    0x1DDD, 0xAFFB, 0x00DE, 0x8FF9, 0x001C, 0xFFFB, 0x477F, 0x4FF9, 0x177D, 0x3FFB, 0x3BBF, 0x2FF9, 0xAEEF,
+    0x8EED, 0x444F, 0x1FF9, 0x22AD, 0x000A, 0x8BBF, 0x8FF9, 0x00FE, 0xCFFD, 0x007E, 0x4FF9, 0x115D, 0x5FFB,
+    0x577F, 0x2FF9, 0x8DDF, 0x2EED, 0x333F, 0x1FF9, 0x2BBD, 0xAFFB, 0x88CF, 0x8FF9, 0xBFFF, 0xFFFB, 0x377F,
+    0x4FF9, 0x006D, 0x3FFB, 0x00BE, 0x2FF9, 0x66EF, 0x9FFD, 0x133F, 0x1FF9, 0x009D, 0x000A, 0xABBF, 0x8FF9,
+    0xDFFF, 0x6FFD, 0x006E, 0x4FF9, 0x002C, 0x5FFB, 0x888F, 0x2FF9, 0xCDDF, 0x4DDD, 0x222F, 0x1FF9, 0x1DDD,
+    0xAFFB, 0x4CCF, 0x8FF9, 0x001C, 0xFFFB, 0x277F, 0x4FF9, 0x177D, 0x3FFB, 0x99BF, 0x2FF9, 0xCEEF, 0x8EED,
+    0x004E, 0x1FF9, 0x22AD, 0x000A, 0x00AE, 0x8FF9, 0x7FFF, 0xCFFD, 0x005E, 0x4FF9, 0x115D, 0x5FFB, 0x009E,
+    0x2FF9, 0x5DDF, 0x2EED, 0x003E, 0x1FF9, 0x2BBD, 0xAFFB, 0x00CE, 0x8FF9, 0xEFFF, 0xFFFB, 0x667F, 0x4FF9,
+    0x006D, 0x3FFB, 0x8AAF, 0x2FF9, 0x00EE, 0x9FFD, 0x233F, 0x1FF9, 0x009D, 0x000A, 0x1BBF, 0x8FF9, 0x4EEF,
+    0x6FFD, 0x455F, 0x4FF9, 0x002C, 0x5FFB, 0x008E, 0x2FF9, 0x99DF, 0x4DDD, 0x111F};
+#endif /* AVCODEC_JPEG2000HTDEC_H */
\ No newline at end of file
-- 
2.37.2

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-08 20:49 [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding etemesicaleb
@ 2022-09-09 15:46 ` Michael Niedermayer
  2022-09-09 16:52   ` Caleb Etemesi
  2022-09-20 13:49 ` Tomas Härdin
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Niedermayer @ 2022-09-09 15:46 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 11935 bytes --]

On Thu, Sep 08, 2022 at 11:49:53PM +0300, etemesicaleb@gmail.com wrote:
> From: caleb <etemesicaleb@gmail.com>
> 
> Rebased this patch on master branch
> ---
>  libavcodec/Makefile        |    2 +-
>  libavcodec/j2kenc.c        |   26 +-
>  libavcodec/jpeg2000.h      |  103 ++-
>  libavcodec/jpeg2000dec.c   |  193 ++----
>  libavcodec/jpeg2000htdec.c | 1212 ++++++++++++++++++++++++++++++++++++
>  libavcodec/jpeg2000htdec.h |  210 +++++++
>  6 files changed, 1599 insertions(+), 147 deletions(-)
>  create mode 100644 libavcodec/jpeg2000htdec.c
>  create mode 100644 libavcodec/jpeg2000htdec.h
> 
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 945908e3b8..ecf5c47cad 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         += jacosubdec.o ass.o
>  OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o jpeg2000.o \
>                                            jpeg2000dwt.o
>  OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o jpeg2000dsp.o \
> -                                          jpeg2000dwt.o mqcdec.o mqc.o
> +                                          jpeg2000dwt.o mqcdec.o mqc.o jpeg2000htdec.o
>  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
>  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
>  OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
> diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
> index e883d5deb7..233d75e96d 100644
> --- a/libavcodec/j2kenc.c
> +++ b/libavcodec/j2kenc.c
> @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { // [dwt_type][band][rlevel] (multiplied
>  typedef struct {
>     Jpeg2000Component *comp;
>     double *layer_rates;
> -} Jpeg2000Tile;
> +} Jpeg2000EncTile;
>  
>  typedef struct {
>      AVClass *class;
> @@ -131,7 +131,7 @@ typedef struct {
>      Jpeg2000CodingStyle codsty;
>      Jpeg2000QuantStyle  qntsty;
>  
> -    Jpeg2000Tile *tile;
> +    Jpeg2000EncTile *tile;
>      int layer_rates[100];
>      uint8_t compression_rate_enc; ///< Is compression done using compression ratio?
>  
> @@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext* s)
>      int layno, compno;
>      for (i = 0; i < s->numYtiles; i++) {
>          for (j = 0; j < s->numXtiles; j++) {
> -            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
> +            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
>              for (compno = 0; compno < s->ncomponents; compno++) {
>                  int tilew = tile->comp[compno].coord[0][1] - tile->comp[compno].coord[0][0];
>                  int tileh = tile->comp[compno].coord[1][1] - tile->comp[compno].coord[1][0];
> @@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>      s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
>      s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
>  
> -    s->tile = av_calloc(s->numXtiles, s->numYtiles * sizeof(Jpeg2000Tile));
> +    s->tile = av_calloc(s->numXtiles, s->numYtiles * sizeof(Jpeg2000EncTile));
>      if (!s->tile)
>          return AVERROR(ENOMEM);
>      for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
>          for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
> -            Jpeg2000Tile *tile = s->tile + tileno;
> +            Jpeg2000EncTile *tile = s->tile + tileno;
>  
>              tile->comp = av_calloc(s->ncomponents, sizeof(*tile->comp));
>              if (!tile->comp)
> @@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>          int tileno, compno, i, y, x;                                                                                        \
>          const PIXEL *line;                                                                                                  \
>          for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){                                                   \
> -            Jpeg2000Tile *tile = s->tile + tileno;                                                                          \
> +            Jpeg2000EncTile *tile = s->tile + tileno;                                                                          \
>              if (s->planar){                                                                                                 \
>                  for (compno = 0; compno < s->ncomponents; compno++){                                                        \
>                      Jpeg2000Component *comp = tile->comp + compno;                                                          \
> @@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1, int width, int height, int ban
>          }
>  }
>  
> -static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
> +static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
>                          int width, int height, int bandpos, int lev)
>  {
>      int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
> @@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext *s, Jpeg2000ResLevel *rlevel, in
>      return 0;
>  }
>  
> -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno, int nlayers)
> +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile, int tileno, int nlayers)
>  {
>      int compno, reslevelno, layno, ret;
>      Jpeg2000CodingStyle *codsty = &s->codsty;
> @@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int til
>      return 0;
>  }
>  
> -static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2000Tile* tile, int final)
> +static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2000EncTile* tile, int final)
>  {
>      int compno, resno, bandno, precno, cblkno;
>      int passno;
> @@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s, int layno, double thresh, Jpeg2
>      }
>  }
>  
> -static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
> +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile)
>  {
>      int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno;
>      int i;
> @@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t lambda, int dwt_norm)
>      return res;
>  }
>  
> -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
> +static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile)
>  {
>      int precno, compno, reslevelno, bandno, cblkno, lev;
>      Jpeg2000CodingStyle *codsty = &s->codsty;
> @@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
>      }
>  }
>  
> -static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile, int tileno)
> +static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile, int tileno)
>  {
>      int compno, reslevelno, bandno, ret;
>      Jpeg2000T1Context t1;
> @@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
>  {
>      int tileno, compno;
>      for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
> -        Jpeg2000Tile *tile = s->tile + tileno;
> +        Jpeg2000EncTile *tile = s->tile + tileno;
>          for (compno = 0; compno < s->ncomponents; compno++)
>              ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
>      }

Renaming Jpeg2000Tile could be in a seperate patch


> diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
> index e5ecb4cbf9..a5dd693392 100644
> --- a/libavcodec/jpeg2000.h
> +++ b/libavcodec/jpeg2000.h
> @@ -33,8 +33,9 @@
>  
>  #include "avcodec.h"
>  #include "mqc.h"
> +#include "bytestream.h"
>  #include "jpeg2000dwt.h"
> -
> +#include "jpeg2000dsp.h"
>  enum Jpeg2000Markers {
>      JPEG2000_SOC = 0xff4f, // start of codestream
>      JPEG2000_SIZ = 0xff51, // image and tile size

> @@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
>      double disto;
>      int cum_passes;
>  } Jpeg2000Layer;
> -
>  typedef struct Jpeg2000Cblk {
>      uint8_t npasses;
>      uint8_t ninclpasses; // number coding of passes included in codestream

unintended, i assume


> @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
>      uint16_t *lengthinc;
>      uint8_t nb_lengthinc;
>      uint8_t lblock;
> +    uint8_t zbp;         // Zero bit planes
>      uint8_t *data;
>      size_t data_allocated;
>      int nb_terminations;
> @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
>      Jpeg2000Pass *passes;
>      Jpeg2000Layer *layers;
>      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
> +    int pass_lengths[2];
>  } Jpeg2000Cblk; // code block

Please use doxygen compatible comments so it all appears on for example
https://ffmpeg.org/doxygen/trunk/structJpeg2000Cblk.html

>  
>  typedef struct Jpeg2000Prec {
> @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
>      uint8_t roi_shift; // ROI scaling value for the component
>  } Jpeg2000Component;
>  
> +#define JP2_SIG_TYPE    0x6A502020
> +#define JP2_SIG_VALUE   0x0D0A870A
> +#define JP2_CODESTREAM  0x6A703263
> +#define JP2_HEADER      0x6A703268
> +
> +#define HAD_COC 0x01
> +#define HAD_QCC 0x02
> +
> +#define MAX_POCS 32
> +
> +typedef struct Jpeg2000POCEntry {
> +    uint16_t LYEpoc;
> +    uint16_t CSpoc;
> +    uint16_t CEpoc;
> +    uint8_t RSpoc;
> +    uint8_t REpoc;
> +    uint8_t Ppoc;
> +} Jpeg2000POCEntry;
> +
> +typedef struct Jpeg2000POC {
> +    Jpeg2000POCEntry poc[MAX_POCS];
> +    int nb_poc;
> +    int is_default;
> +} Jpeg2000POC;
> +
> +typedef struct Jpeg2000TilePart {
> +    uint8_t tile_index;                 // Tile index who refers the tile-part
> +    const uint8_t *tp_end;
> +    GetByteContext header_tpg;          // bit stream of header if PPM header is used
> +    GetByteContext tpg;                 // bit stream in tile-part
> +} Jpeg2000TilePart;
> +
> +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
> + * one per component, so tile_part elements have a size of 3 */
> +typedef struct Jpeg2000Tile {
                  ^^^^^^^^^^^^ 
> +    Jpeg2000Component   *comp;
> +    uint8_t             properties[4];
> +    Jpeg2000CodingStyle codsty[4];
> +    Jpeg2000QuantStyle  qntsty[4];
> +    Jpeg2000POC         poc;
> +    Jpeg2000TilePart    tile_part[32];
> +    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}}
> +} Jpeg2000DecTile;
     ^^^^^^^^^^^^^^^
This difference appears unintended


> +
> +typedef struct Jpeg2000DecoderContext {

This is unneeded for the encoder
maybe a jpeg2000dec.h would be better for this
also code moving should be in a seperate patch from functional changes

[...]
> +#endif /* AVCODEC_JPEG2000HTDEC_H */

> \ No newline at end of file

needs newline

new decoder not reviewed, feel free to wait for someone to review it before reposting

thx


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-09 15:46 ` Michael Niedermayer
@ 2022-09-09 16:52   ` Caleb Etemesi
  2022-09-09 17:11     ` Caleb Etemesi
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-09 16:52 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Will address in the next iteration

On Fri, 9 Sept 2022, 18:46 Michael Niedermayer, <michael@niedermayer.cc>
wrote:

> On Thu, Sep 08, 2022 at 11:49:53PM +0300, etemesicaleb@gmail.com wrote:
> > From: caleb <etemesicaleb@gmail.com>
> >
> > Rebased this patch on master branch
> > ---
> >  libavcodec/Makefile        |    2 +-
> >  libavcodec/j2kenc.c        |   26 +-
> >  libavcodec/jpeg2000.h      |  103 ++-
> >  libavcodec/jpeg2000dec.c   |  193 ++----
> >  libavcodec/jpeg2000htdec.c | 1212 ++++++++++++++++++++++++++++++++++++
> >  libavcodec/jpeg2000htdec.h |  210 +++++++
> >  6 files changed, 1599 insertions(+), 147 deletions(-)
> >  create mode 100644 libavcodec/jpeg2000htdec.c
> >  create mode 100644 libavcodec/jpeg2000htdec.h
> >
> > diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> > index 945908e3b8..ecf5c47cad 100644
> > --- a/libavcodec/Makefile
> > +++ b/libavcodec/Makefile
> > @@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         +=
> jacosubdec.o ass.o
> >  OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o
> jpeg2000.o \
> >                                            jpeg2000dwt.o
> >  OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o
> jpeg2000dsp.o \
> > -                                          jpeg2000dwt.o mqcdec.o mqc.o
> > +                                          jpeg2000dwt.o mqcdec.o mqc.o
> jpeg2000htdec.o
> >  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
> >  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
> >  OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
> > diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
> > index e883d5deb7..233d75e96d 100644
> > --- a/libavcodec/j2kenc.c
> > +++ b/libavcodec/j2kenc.c
> > @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
> [dwt_type][band][rlevel] (multiplied
> >  typedef struct {
> >     Jpeg2000Component *comp;
> >     double *layer_rates;
> > -} Jpeg2000Tile;
> > +} Jpeg2000EncTile;
> >
> >  typedef struct {
> >      AVClass *class;
> > @@ -131,7 +131,7 @@ typedef struct {
> >      Jpeg2000CodingStyle codsty;
> >      Jpeg2000QuantStyle  qntsty;
> >
> > -    Jpeg2000Tile *tile;
> > +    Jpeg2000EncTile *tile;
> >      int layer_rates[100];
> >      uint8_t compression_rate_enc; ///< Is compression done using
> compression ratio?
> >
> > @@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext* s)
> >      int layno, compno;
> >      for (i = 0; i < s->numYtiles; i++) {
> >          for (j = 0; j < s->numXtiles; j++) {
> > -            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
> > +            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
> >              for (compno = 0; compno < s->ncomponents; compno++) {
> >                  int tilew = tile->comp[compno].coord[0][1] -
> tile->comp[compno].coord[0][0];
> >                  int tileh = tile->comp[compno].coord[1][1] -
> tile->comp[compno].coord[1][0];
> > @@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
> >      s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
> >      s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
> >
> > -    s->tile = av_calloc(s->numXtiles, s->numYtiles *
> sizeof(Jpeg2000Tile));
> > +    s->tile = av_calloc(s->numXtiles, s->numYtiles *
> sizeof(Jpeg2000EncTile));
> >      if (!s->tile)
> >          return AVERROR(ENOMEM);
> >      for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
> >          for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
> > -            Jpeg2000Tile *tile = s->tile + tileno;
> > +            Jpeg2000EncTile *tile = s->tile + tileno;
> >
> >              tile->comp = av_calloc(s->ncomponents, sizeof(*tile->comp));
> >              if (!tile->comp)
> > @@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
> >          int tileno, compno, i, y, x;
>                                                     \
> >          const PIXEL *line;
>                                                     \
> >          for (tileno = 0; tileno < s->numXtiles * s->numYtiles;
> tileno++){                                                   \
> > -            Jpeg2000Tile *tile = s->tile + tileno;
>                                                     \
> > +            Jpeg2000EncTile *tile = s->tile + tileno;
>                                                         \
> >              if (s->planar){
>                                                      \
> >                  for (compno = 0; compno < s->ncomponents; compno++){
>                                                     \
> >                      Jpeg2000Component *comp = tile->comp + compno;
>                                                     \
> > @@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1,
> int width, int height, int ban
> >          }
> >  }
> >
> > -static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
> *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
> > +static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
> *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
> >                          int width, int height, int bandpos, int lev)
> >  {
> >      int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
> > @@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext *s,
> Jpeg2000ResLevel *rlevel, in
> >      return 0;
> >  }
> >
> > -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile
> *tile, int tileno, int nlayers)
> > +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> *tile, int tileno, int nlayers)
> >  {
> >      int compno, reslevelno, layno, ret;
> >      Jpeg2000CodingStyle *codsty = &s->codsty;
> > @@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext
> *s, Jpeg2000Tile *tile, int til
> >      return 0;
> >  }
> >
> > -static void makelayer(Jpeg2000EncoderContext *s, int layno, double
> thresh, Jpeg2000Tile* tile, int final)
> > +static void makelayer(Jpeg2000EncoderContext *s, int layno, double
> thresh, Jpeg2000EncTile* tile, int final)
> >  {
> >      int compno, resno, bandno, precno, cblkno;
> >      int passno;
> > @@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s,
> int layno, double thresh, Jpeg2
> >      }
> >  }
> >
> > -static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
> > +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile *tile)
> >  {
> >      int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno;
> >      int i;
> > @@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t
> lambda, int dwt_norm)
> >      return res;
> >  }
> >
> > -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
> > +static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> *tile)
> >  {
> >      int precno, compno, reslevelno, bandno, cblkno, lev;
> >      Jpeg2000CodingStyle *codsty = &s->codsty;
> > @@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext *s,
> Jpeg2000Tile *tile)
> >      }
> >  }
> >
> > -static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile,
> int tileno)
> > +static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> *tile, int tileno)
> >  {
> >      int compno, reslevelno, bandno, ret;
> >      Jpeg2000T1Context t1;
> > @@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
> >  {
> >      int tileno, compno;
> >      for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
> > -        Jpeg2000Tile *tile = s->tile + tileno;
> > +        Jpeg2000EncTile *tile = s->tile + tileno;
> >          for (compno = 0; compno < s->ncomponents; compno++)
> >              ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
> >      }
>
> Renaming Jpeg2000Tile could be in a seperate patch
>
>
> > diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
> > index e5ecb4cbf9..a5dd693392 100644
> > --- a/libavcodec/jpeg2000.h
> > +++ b/libavcodec/jpeg2000.h
> > @@ -33,8 +33,9 @@
> >
> >  #include "avcodec.h"
> >  #include "mqc.h"
> > +#include "bytestream.h"
> >  #include "jpeg2000dwt.h"
> > -
> > +#include "jpeg2000dsp.h"
> >  enum Jpeg2000Markers {
> >      JPEG2000_SOC = 0xff4f, // start of codestream
> >      JPEG2000_SIZ = 0xff51, // image and tile size
>
> > @@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
> >      double disto;
> >      int cum_passes;
> >  } Jpeg2000Layer;
> > -
> >  typedef struct Jpeg2000Cblk {
> >      uint8_t npasses;
> >      uint8_t ninclpasses; // number coding of passes included in
> codestream
>
> unintended, i assume
>
>
> > @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
> >      uint16_t *lengthinc;
> >      uint8_t nb_lengthinc;
> >      uint8_t lblock;
> > +    uint8_t zbp;         // Zero bit planes
> >      uint8_t *data;
> >      size_t data_allocated;
> >      int nb_terminations;
> > @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
> >      Jpeg2000Pass *passes;
> >      Jpeg2000Layer *layers;
> >      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
> > +    int pass_lengths[2];
> >  } Jpeg2000Cblk; // code block
>
> Please use doxygen compatible comments so it all appears on for example
> https://ffmpeg.org/doxygen/trunk/structJpeg2000Cblk.html
>
> >
> >  typedef struct Jpeg2000Prec {
> > @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
> >      uint8_t roi_shift; // ROI scaling value for the component
> >  } Jpeg2000Component;
> >
> > +#define JP2_SIG_TYPE    0x6A502020
> > +#define JP2_SIG_VALUE   0x0D0A870A
> > +#define JP2_CODESTREAM  0x6A703263
> > +#define JP2_HEADER      0x6A703268
> > +
> > +#define HAD_COC 0x01
> > +#define HAD_QCC 0x02
> > +
> > +#define MAX_POCS 32
> > +
> > +typedef struct Jpeg2000POCEntry {
> > +    uint16_t LYEpoc;
> > +    uint16_t CSpoc;
> > +    uint16_t CEpoc;
> > +    uint8_t RSpoc;
> > +    uint8_t REpoc;
> > +    uint8_t Ppoc;
> > +} Jpeg2000POCEntry;
> > +
> > +typedef struct Jpeg2000POC {
> > +    Jpeg2000POCEntry poc[MAX_POCS];
> > +    int nb_poc;
> > +    int is_default;
> > +} Jpeg2000POC;
> > +
> > +typedef struct Jpeg2000TilePart {
> > +    uint8_t tile_index;                 // Tile index who refers the
> tile-part
> > +    const uint8_t *tp_end;
> > +    GetByteContext header_tpg;          // bit stream of header if PPM
> header is used
> > +    GetByteContext tpg;                 // bit stream in tile-part
> > +} Jpeg2000TilePart;
> > +
> > +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
> > + * one per component, so tile_part elements have a size of 3 */
> > +typedef struct Jpeg2000Tile {
>                   ^^^^^^^^^^^^
> > +    Jpeg2000Component   *comp;
> > +    uint8_t             properties[4];
> > +    Jpeg2000CodingStyle codsty[4];
> > +    Jpeg2000QuantStyle  qntsty[4];
> > +    Jpeg2000POC         poc;
> > +    Jpeg2000TilePart    tile_part[32];
> > +    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}}
> > +} Jpeg2000DecTile;
>      ^^^^^^^^^^^^^^^
> This difference appears unintended
>
>
> > +
> > +typedef struct Jpeg2000DecoderContext {
>
> This is unneeded for the encoder
> maybe a jpeg2000dec.h would be better for this
> also code moving should be in a seperate patch from functional changes
>
> [...]
> > +#endif /* AVCODEC_JPEG2000HTDEC_H */
>
> > \ No newline at end of file
>
> needs newline
>
> new decoder not reviewed, feel free to wait for someone to review it
> before reposting
>
> thx
>
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> Those who would give up essential Liberty, to purchase a little
> temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-09 16:52   ` Caleb Etemesi
@ 2022-09-09 17:11     ` Caleb Etemesi
  2022-09-09 21:34       ` Andreas Rheinhardt
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-09 17:11 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

> This is unneeded for the encoder
> maybe a jpeg2000dec.h would be better for this
> also code moving should be in a seperate patch
> from functional changes


This will be a circular dependence, since jpeg2000htdec.h needs the decoder
context, and jpeg2000.c needs jpeg2000htdec.c.



On Fri, 9 Sept 2022, 19:52 Caleb Etemesi, <etemesicaleb@gmail.com> wrote:

> Will address in the next iteration
>
> On Fri, 9 Sept 2022, 18:46 Michael Niedermayer, <michael@niedermayer.cc>
> wrote:
>
>> On Thu, Sep 08, 2022 at 11:49:53PM +0300, etemesicaleb@gmail.com wrote:
>> > From: caleb <etemesicaleb@gmail.com>
>> >
>> > Rebased this patch on master branch
>> > ---
>> >  libavcodec/Makefile        |    2 +-
>> >  libavcodec/j2kenc.c        |   26 +-
>> >  libavcodec/jpeg2000.h      |  103 ++-
>> >  libavcodec/jpeg2000dec.c   |  193 ++----
>> >  libavcodec/jpeg2000htdec.c | 1212 ++++++++++++++++++++++++++++++++++++
>> >  libavcodec/jpeg2000htdec.h |  210 +++++++
>> >  6 files changed, 1599 insertions(+), 147 deletions(-)
>> >  create mode 100644 libavcodec/jpeg2000htdec.c
>> >  create mode 100644 libavcodec/jpeg2000htdec.h
>> >
>> > diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> > index 945908e3b8..ecf5c47cad 100644
>> > --- a/libavcodec/Makefile
>> > +++ b/libavcodec/Makefile
>> > @@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         +=
>> jacosubdec.o ass.o
>> >  OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o
>> jpeg2000.o \
>> >                                            jpeg2000dwt.o
>> >  OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o
>> jpeg2000dsp.o \
>> > -                                          jpeg2000dwt.o mqcdec.o mqc.o
>> > +                                          jpeg2000dwt.o mqcdec.o mqc.o
>> jpeg2000htdec.o
>> >  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
>> >  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
>> >  OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
>> > diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
>> > index e883d5deb7..233d75e96d 100644
>> > --- a/libavcodec/j2kenc.c
>> > +++ b/libavcodec/j2kenc.c
>> > @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
>> [dwt_type][band][rlevel] (multiplied
>> >  typedef struct {
>> >     Jpeg2000Component *comp;
>> >     double *layer_rates;
>> > -} Jpeg2000Tile;
>> > +} Jpeg2000EncTile;
>> >
>> >  typedef struct {
>> >      AVClass *class;
>> > @@ -131,7 +131,7 @@ typedef struct {
>> >      Jpeg2000CodingStyle codsty;
>> >      Jpeg2000QuantStyle  qntsty;
>> >
>> > -    Jpeg2000Tile *tile;
>> > +    Jpeg2000EncTile *tile;
>> >      int layer_rates[100];
>> >      uint8_t compression_rate_enc; ///< Is compression done using
>> compression ratio?
>> >
>> > @@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext* s)
>> >      int layno, compno;
>> >      for (i = 0; i < s->numYtiles; i++) {
>> >          for (j = 0; j < s->numXtiles; j++) {
>> > -            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
>> > +            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
>> >              for (compno = 0; compno < s->ncomponents; compno++) {
>> >                  int tilew = tile->comp[compno].coord[0][1] -
>> tile->comp[compno].coord[0][0];
>> >                  int tileh = tile->comp[compno].coord[1][1] -
>> tile->comp[compno].coord[1][0];
>> > @@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>> >      s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
>> >      s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
>> >
>> > -    s->tile = av_calloc(s->numXtiles, s->numYtiles *
>> sizeof(Jpeg2000Tile));
>> > +    s->tile = av_calloc(s->numXtiles, s->numYtiles *
>> sizeof(Jpeg2000EncTile));
>> >      if (!s->tile)
>> >          return AVERROR(ENOMEM);
>> >      for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
>> >          for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
>> > -            Jpeg2000Tile *tile = s->tile + tileno;
>> > +            Jpeg2000EncTile *tile = s->tile + tileno;
>> >
>> >              tile->comp = av_calloc(s->ncomponents,
>> sizeof(*tile->comp));
>> >              if (!tile->comp)
>> > @@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>> >          int tileno, compno, i, y, x;
>>                                                       \
>> >          const PIXEL *line;
>>                                                       \
>> >          for (tileno = 0; tileno < s->numXtiles * s->numYtiles;
>> tileno++){                                                   \
>> > -            Jpeg2000Tile *tile = s->tile + tileno;
>>                                                       \
>> > +            Jpeg2000EncTile *tile = s->tile + tileno;
>>                                                         \
>> >              if (s->planar){
>>                                                      \
>> >                  for (compno = 0; compno < s->ncomponents; compno++){
>>                                                       \
>> >                      Jpeg2000Component *comp = tile->comp + compno;
>>                                                       \
>> > @@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1,
>> int width, int height, int ban
>> >          }
>> >  }
>> >
>> > -static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
>> *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
>> > +static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
>> *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
>> >                          int width, int height, int bandpos, int lev)
>> >  {
>> >      int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
>> > @@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext *s,
>> Jpeg2000ResLevel *rlevel, in
>> >      return 0;
>> >  }
>> >
>> > -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile
>> *tile, int tileno, int nlayers)
>> > +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>> *tile, int tileno, int nlayers)
>> >  {
>> >      int compno, reslevelno, layno, ret;
>> >      Jpeg2000CodingStyle *codsty = &s->codsty;
>> > @@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext
>> *s, Jpeg2000Tile *tile, int til
>> >      return 0;
>> >  }
>> >
>> > -static void makelayer(Jpeg2000EncoderContext *s, int layno, double
>> thresh, Jpeg2000Tile* tile, int final)
>> > +static void makelayer(Jpeg2000EncoderContext *s, int layno, double
>> thresh, Jpeg2000EncTile* tile, int final)
>> >  {
>> >      int compno, resno, bandno, precno, cblkno;
>> >      int passno;
>> > @@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s,
>> int layno, double thresh, Jpeg2
>> >      }
>> >  }
>> >
>> > -static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
>> > +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>> *tile)
>> >  {
>> >      int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno;
>> >      int i;
>> > @@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t
>> lambda, int dwt_norm)
>> >      return res;
>> >  }
>> >
>> > -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
>> > +static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>> *tile)
>> >  {
>> >      int precno, compno, reslevelno, bandno, cblkno, lev;
>> >      Jpeg2000CodingStyle *codsty = &s->codsty;
>> > @@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext
>> *s, Jpeg2000Tile *tile)
>> >      }
>> >  }
>> >
>> > -static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile,
>> int tileno)
>> > +static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>> *tile, int tileno)
>> >  {
>> >      int compno, reslevelno, bandno, ret;
>> >      Jpeg2000T1Context t1;
>> > @@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
>> >  {
>> >      int tileno, compno;
>> >      for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
>> > -        Jpeg2000Tile *tile = s->tile + tileno;
>> > +        Jpeg2000EncTile *tile = s->tile + tileno;
>> >          for (compno = 0; compno < s->ncomponents; compno++)
>> >              ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
>> >      }
>>
>> Renaming Jpeg2000Tile could be in a seperate patch
>>
>>
>> > diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
>> > index e5ecb4cbf9..a5dd693392 100644
>> > --- a/libavcodec/jpeg2000.h
>> > +++ b/libavcodec/jpeg2000.h
>> > @@ -33,8 +33,9 @@
>> >
>> >  #include "avcodec.h"
>> >  #include "mqc.h"
>> > +#include "bytestream.h"
>> >  #include "jpeg2000dwt.h"
>> > -
>> > +#include "jpeg2000dsp.h"
>> >  enum Jpeg2000Markers {
>> >      JPEG2000_SOC = 0xff4f, // start of codestream
>> >      JPEG2000_SIZ = 0xff51, // image and tile size
>>
>> > @@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
>> >      double disto;
>> >      int cum_passes;
>> >  } Jpeg2000Layer;
>> > -
>> >  typedef struct Jpeg2000Cblk {
>> >      uint8_t npasses;
>> >      uint8_t ninclpasses; // number coding of passes included in
>> codestream
>>
>> unintended, i assume
>>
>>
>> > @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
>> >      uint16_t *lengthinc;
>> >      uint8_t nb_lengthinc;
>> >      uint8_t lblock;
>> > +    uint8_t zbp;         // Zero bit planes
>> >      uint8_t *data;
>> >      size_t data_allocated;
>> >      int nb_terminations;
>> > @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
>> >      Jpeg2000Pass *passes;
>> >      Jpeg2000Layer *layers;
>> >      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
>> > +    int pass_lengths[2];
>> >  } Jpeg2000Cblk; // code block
>>
>> Please use doxygen compatible comments so it all appears on for example
>> https://ffmpeg.org/doxygen/trunk/structJpeg2000Cblk.html
>>
>> >
>> >  typedef struct Jpeg2000Prec {
>> > @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
>> >      uint8_t roi_shift; // ROI scaling value for the component
>> >  } Jpeg2000Component;
>> >
>> > +#define JP2_SIG_TYPE    0x6A502020
>> > +#define JP2_SIG_VALUE   0x0D0A870A
>> > +#define JP2_CODESTREAM  0x6A703263
>> > +#define JP2_HEADER      0x6A703268
>> > +
>> > +#define HAD_COC 0x01
>> > +#define HAD_QCC 0x02
>> > +
>> > +#define MAX_POCS 32
>> > +
>> > +typedef struct Jpeg2000POCEntry {
>> > +    uint16_t LYEpoc;
>> > +    uint16_t CSpoc;
>> > +    uint16_t CEpoc;
>> > +    uint8_t RSpoc;
>> > +    uint8_t REpoc;
>> > +    uint8_t Ppoc;
>> > +} Jpeg2000POCEntry;
>> > +
>> > +typedef struct Jpeg2000POC {
>> > +    Jpeg2000POCEntry poc[MAX_POCS];
>> > +    int nb_poc;
>> > +    int is_default;
>> > +} Jpeg2000POC;
>> > +
>> > +typedef struct Jpeg2000TilePart {
>> > +    uint8_t tile_index;                 // Tile index who refers the
>> tile-part
>> > +    const uint8_t *tp_end;
>> > +    GetByteContext header_tpg;          // bit stream of header if PPM
>> header is used
>> > +    GetByteContext tpg;                 // bit stream in tile-part
>> > +} Jpeg2000TilePart;
>> > +
>> > +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
>> > + * one per component, so tile_part elements have a size of 3 */
>> > +typedef struct Jpeg2000Tile {
>>                   ^^^^^^^^^^^^
>> > +    Jpeg2000Component   *comp;
>> > +    uint8_t             properties[4];
>> > +    Jpeg2000CodingStyle codsty[4];
>> > +    Jpeg2000QuantStyle  qntsty[4];
>> > +    Jpeg2000POC         poc;
>> > +    Jpeg2000TilePart    tile_part[32];
>> > +    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}}
>> > +} Jpeg2000DecTile;
>>      ^^^^^^^^^^^^^^^
>> This difference appears unintended
>>
>>
>> > +
>> > +typedef struct Jpeg2000DecoderContext {
>>
>> This is unneeded for the encoder
>> maybe a jpeg2000dec.h would be better for this
>> also code moving should be in a seperate patch from functional changes
>>
>> [...]
>> > +#endif /* AVCODEC_JPEG2000HTDEC_H */
>>
>> > \ No newline at end of file
>>
>> needs newline
>>
>> new decoder not reviewed, feel free to wait for someone to review it
>> before reposting
>>
>> thx
>>
>>
>> [...]
>> --
>> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>>
>> Those who would give up essential Liberty, to purchase a little
>> temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
>> _______________________________________________
>> 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".
>>
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-09 17:11     ` Caleb Etemesi
@ 2022-09-09 21:34       ` Andreas Rheinhardt
  2022-09-10  9:13         ` Caleb Etemesi
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Rheinhardt @ 2022-09-09 21:34 UTC (permalink / raw)
  To: ffmpeg-devel

Caleb Etemesi:
>> This is unneeded for the encoder
>> maybe a jpeg2000dec.h would be better for this
>> also code moving should be in a seperate patch
>> from functional changes
> 
> 
> This will be a circular dependence, since jpeg2000htdec.h needs the decoder
> context, and jpeg2000.c needs jpeg2000htdec.c.
> 

It seems like the only use of the decoder context in jpeg2000htdec.h is
in jpeg2000_decode_ctx_vlc() where the Jpeg2000DecoderContext is not
even used at all. And I fail to see the circular dependency even if
jpeg2000htdec.h needed the decoder context: after all, you are not
adding an inclusion of jpeg2000htdec.h to jpeg2000.h, so jpeg2000dec.h
will also not include jpeg2000htdec.h.

> 
> On Fri, 9 Sept 2022, 19:52 Caleb Etemesi, <etemesicaleb@gmail.com> wrote:
> 
>> Will address in the next iteration
>>
>> On Fri, 9 Sept 2022, 18:46 Michael Niedermayer, <michael@niedermayer.cc>
>> wrote:
>>
>>> On Thu, Sep 08, 2022 at 11:49:53PM +0300, etemesicaleb@gmail.com wrote:
>>>> From: caleb <etemesicaleb@gmail.com>
>>>>
>>>> Rebased this patch on master branch
>>>> ---
>>>>  libavcodec/Makefile        |    2 +-
>>>>  libavcodec/j2kenc.c        |   26 +-
>>>>  libavcodec/jpeg2000.h      |  103 ++-
>>>>  libavcodec/jpeg2000dec.c   |  193 ++----
>>>>  libavcodec/jpeg2000htdec.c | 1212 ++++++++++++++++++++++++++++++++++++
>>>>  libavcodec/jpeg2000htdec.h |  210 +++++++
>>>>  6 files changed, 1599 insertions(+), 147 deletions(-)
>>>>  create mode 100644 libavcodec/jpeg2000htdec.c
>>>>  create mode 100644 libavcodec/jpeg2000htdec.h
>>>>
>>>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>>>> index 945908e3b8..ecf5c47cad 100644
>>>> --- a/libavcodec/Makefile
>>>> +++ b/libavcodec/Makefile
>>>> @@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         +=
>>> jacosubdec.o ass.o
>>>>  OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o
>>> jpeg2000.o \
>>>>                                            jpeg2000dwt.o
>>>>  OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o
>>> jpeg2000dsp.o \
>>>> -                                          jpeg2000dwt.o mqcdec.o mqc.o
>>>> +                                          jpeg2000dwt.o mqcdec.o mqc.o
>>> jpeg2000htdec.o
>>>>  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
>>>>  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
>>>>  OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
>>>> diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
>>>> index e883d5deb7..233d75e96d 100644
>>>> --- a/libavcodec/j2kenc.c
>>>> +++ b/libavcodec/j2kenc.c
>>>> @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
>>> [dwt_type][band][rlevel] (multiplied
>>>>  typedef struct {
>>>>     Jpeg2000Component *comp;
>>>>     double *layer_rates;
>>>> -} Jpeg2000Tile;
>>>> +} Jpeg2000EncTile;
>>>>
>>>>  typedef struct {
>>>>      AVClass *class;
>>>> @@ -131,7 +131,7 @@ typedef struct {
>>>>      Jpeg2000CodingStyle codsty;
>>>>      Jpeg2000QuantStyle  qntsty;
>>>>
>>>> -    Jpeg2000Tile *tile;
>>>> +    Jpeg2000EncTile *tile;
>>>>      int layer_rates[100];
>>>>      uint8_t compression_rate_enc; ///< Is compression done using
>>> compression ratio?
>>>>
>>>> @@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext* s)
>>>>      int layno, compno;
>>>>      for (i = 0; i < s->numYtiles; i++) {
>>>>          for (j = 0; j < s->numXtiles; j++) {
>>>> -            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
>>>> +            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
>>>>              for (compno = 0; compno < s->ncomponents; compno++) {
>>>>                  int tilew = tile->comp[compno].coord[0][1] -
>>> tile->comp[compno].coord[0][0];
>>>>                  int tileh = tile->comp[compno].coord[1][1] -
>>> tile->comp[compno].coord[1][0];
>>>> @@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>>>>      s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
>>>>      s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
>>>>
>>>> -    s->tile = av_calloc(s->numXtiles, s->numYtiles *
>>> sizeof(Jpeg2000Tile));
>>>> +    s->tile = av_calloc(s->numXtiles, s->numYtiles *
>>> sizeof(Jpeg2000EncTile));
>>>>      if (!s->tile)
>>>>          return AVERROR(ENOMEM);
>>>>      for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
>>>>          for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
>>>> -            Jpeg2000Tile *tile = s->tile + tileno;
>>>> +            Jpeg2000EncTile *tile = s->tile + tileno;
>>>>
>>>>              tile->comp = av_calloc(s->ncomponents,
>>> sizeof(*tile->comp));
>>>>              if (!tile->comp)
>>>> @@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
>>>>          int tileno, compno, i, y, x;
>>>                                                       \
>>>>          const PIXEL *line;
>>>                                                       \
>>>>          for (tileno = 0; tileno < s->numXtiles * s->numYtiles;
>>> tileno++){                                                   \
>>>> -            Jpeg2000Tile *tile = s->tile + tileno;
>>>                                                       \
>>>> +            Jpeg2000EncTile *tile = s->tile + tileno;
>>>                                                         \
>>>>              if (s->planar){
>>>                                                      \
>>>>                  for (compno = 0; compno < s->ncomponents; compno++){
>>>                                                       \
>>>>                      Jpeg2000Component *comp = tile->comp + compno;
>>>                                                       \
>>>> @@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1,
>>> int width, int height, int ban
>>>>          }
>>>>  }
>>>>
>>>> -static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
>>> *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
>>>> +static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
>>> *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
>>>>                          int width, int height, int bandpos, int lev)
>>>>  {
>>>>      int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
>>>> @@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext *s,
>>> Jpeg2000ResLevel *rlevel, in
>>>>      return 0;
>>>>  }
>>>>
>>>> -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile
>>> *tile, int tileno, int nlayers)
>>>> +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>>> *tile, int tileno, int nlayers)
>>>>  {
>>>>      int compno, reslevelno, layno, ret;
>>>>      Jpeg2000CodingStyle *codsty = &s->codsty;
>>>> @@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext
>>> *s, Jpeg2000Tile *tile, int til
>>>>      return 0;
>>>>  }
>>>>
>>>> -static void makelayer(Jpeg2000EncoderContext *s, int layno, double
>>> thresh, Jpeg2000Tile* tile, int final)
>>>> +static void makelayer(Jpeg2000EncoderContext *s, int layno, double
>>> thresh, Jpeg2000EncTile* tile, int final)
>>>>  {
>>>>      int compno, resno, bandno, precno, cblkno;
>>>>      int passno;
>>>> @@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s,
>>> int layno, double thresh, Jpeg2
>>>>      }
>>>>  }
>>>>
>>>> -static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
>>>> +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>>> *tile)
>>>>  {
>>>>      int precno, compno, reslevelno, bandno, cblkno, lev, passno, layno;
>>>>      int i;
>>>> @@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t
>>> lambda, int dwt_norm)
>>>>      return res;
>>>>  }
>>>>
>>>> -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
>>>> +static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>>> *tile)
>>>>  {
>>>>      int precno, compno, reslevelno, bandno, cblkno, lev;
>>>>      Jpeg2000CodingStyle *codsty = &s->codsty;
>>>> @@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext
>>> *s, Jpeg2000Tile *tile)
>>>>      }
>>>>  }
>>>>
>>>> -static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile,
>>> int tileno)
>>>> +static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile
>>> *tile, int tileno)
>>>>  {
>>>>      int compno, reslevelno, bandno, ret;
>>>>      Jpeg2000T1Context t1;
>>>> @@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
>>>>  {
>>>>      int tileno, compno;
>>>>      for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
>>>> -        Jpeg2000Tile *tile = s->tile + tileno;
>>>> +        Jpeg2000EncTile *tile = s->tile + tileno;
>>>>          for (compno = 0; compno < s->ncomponents; compno++)
>>>>              ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
>>>>      }
>>>
>>> Renaming Jpeg2000Tile could be in a seperate patch
>>>
>>>
>>>> diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
>>>> index e5ecb4cbf9..a5dd693392 100644
>>>> --- a/libavcodec/jpeg2000.h
>>>> +++ b/libavcodec/jpeg2000.h
>>>> @@ -33,8 +33,9 @@
>>>>
>>>>  #include "avcodec.h"
>>>>  #include "mqc.h"
>>>> +#include "bytestream.h"
>>>>  #include "jpeg2000dwt.h"
>>>> -
>>>> +#include "jpeg2000dsp.h"
>>>>  enum Jpeg2000Markers {
>>>>      JPEG2000_SOC = 0xff4f, // start of codestream
>>>>      JPEG2000_SIZ = 0xff51, // image and tile size
>>>
>>>> @@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
>>>>      double disto;
>>>>      int cum_passes;
>>>>  } Jpeg2000Layer;
>>>> -
>>>>  typedef struct Jpeg2000Cblk {
>>>>      uint8_t npasses;
>>>>      uint8_t ninclpasses; // number coding of passes included in
>>> codestream
>>>
>>> unintended, i assume
>>>
>>>
>>>> @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
>>>>      uint16_t *lengthinc;
>>>>      uint8_t nb_lengthinc;
>>>>      uint8_t lblock;
>>>> +    uint8_t zbp;         // Zero bit planes
>>>>      uint8_t *data;
>>>>      size_t data_allocated;
>>>>      int nb_terminations;
>>>> @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
>>>>      Jpeg2000Pass *passes;
>>>>      Jpeg2000Layer *layers;
>>>>      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
>>>> +    int pass_lengths[2];
>>>>  } Jpeg2000Cblk; // code block
>>>
>>> Please use doxygen compatible comments so it all appears on for example
>>> https://ffmpeg.org/doxygen/trunk/structJpeg2000Cblk.html
>>>
>>>>
>>>>  typedef struct Jpeg2000Prec {
>>>> @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
>>>>      uint8_t roi_shift; // ROI scaling value for the component
>>>>  } Jpeg2000Component;
>>>>
>>>> +#define JP2_SIG_TYPE    0x6A502020
>>>> +#define JP2_SIG_VALUE   0x0D0A870A
>>>> +#define JP2_CODESTREAM  0x6A703263
>>>> +#define JP2_HEADER      0x6A703268
>>>> +
>>>> +#define HAD_COC 0x01
>>>> +#define HAD_QCC 0x02
>>>> +
>>>> +#define MAX_POCS 32
>>>> +
>>>> +typedef struct Jpeg2000POCEntry {
>>>> +    uint16_t LYEpoc;
>>>> +    uint16_t CSpoc;
>>>> +    uint16_t CEpoc;
>>>> +    uint8_t RSpoc;
>>>> +    uint8_t REpoc;
>>>> +    uint8_t Ppoc;
>>>> +} Jpeg2000POCEntry;
>>>> +
>>>> +typedef struct Jpeg2000POC {
>>>> +    Jpeg2000POCEntry poc[MAX_POCS];
>>>> +    int nb_poc;
>>>> +    int is_default;
>>>> +} Jpeg2000POC;
>>>> +
>>>> +typedef struct Jpeg2000TilePart {
>>>> +    uint8_t tile_index;                 // Tile index who refers the
>>> tile-part
>>>> +    const uint8_t *tp_end;
>>>> +    GetByteContext header_tpg;          // bit stream of header if PPM
>>> header is used
>>>> +    GetByteContext tpg;                 // bit stream in tile-part
>>>> +} Jpeg2000TilePart;
>>>> +
>>>> +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
>>>> + * one per component, so tile_part elements have a size of 3 */
>>>> +typedef struct Jpeg2000Tile {
>>>                   ^^^^^^^^^^^^
>>>> +    Jpeg2000Component   *comp;
>>>> +    uint8_t             properties[4];
>>>> +    Jpeg2000CodingStyle codsty[4];
>>>> +    Jpeg2000QuantStyle  qntsty[4];
>>>> +    Jpeg2000POC         poc;
>>>> +    Jpeg2000TilePart    tile_part[32];
>>>> +    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}}
>>>> +} Jpeg2000DecTile;
>>>      ^^^^^^^^^^^^^^^
>>> This difference appears unintended
>>>
>>>
>>>> +
>>>> +typedef struct Jpeg2000DecoderContext {
>>>
>>> This is unneeded for the encoder
>>> maybe a jpeg2000dec.h would be better for this
>>> also code moving should be in a seperate patch from functional changes
>>>
>>> [...]
>>>> +#endif /* AVCODEC_JPEG2000HTDEC_H */
>>>
>>>> \ No newline at end of file
>>>
>>> needs newline
>>>
>>> new decoder not reviewed, feel free to wait for someone to review it
>>> before reposting
>>>
>>> thx
>>>
>>>
>>> [...]
>>> --
>>> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>>>
>>> Those who would give up essential Liberty, to purchase a little
>>> temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-09 21:34       ` Andreas Rheinhardt
@ 2022-09-10  9:13         ` Caleb Etemesi
  0 siblings, 0 replies; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-10  9:13 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Ideally, what I wanted to achieve was following best practices of what I
saw,

most of the error reporting inside jpeg2000dec.c would log errors using
s->avctx, in case of things like corrupt bitstream errors, I did want also
the htj2k code to emulate this, and the only reason its present in
jpeg2000_decode_ctx_vlc was for it to report in case I read out of bounds,
(it was to replace the assert0(index < 1024))

That's the only reason I need a Jpeg2000DecoderContext in jpeg2000htdec.c

I later learnt you can pass NULL to av_log, and used that to report invalid
bit reads e.g at
https://github.com/etemesi254/FFmpeg/blob/87de24efb472c1cf60d920c433d710cf95a64ea5/libavcodec/jpeg2000htdec.c#L189-L191
since I saw the call stack was too deep to justify me passing around
Jpeg2000DecoderContext everywhere.

So since I'll be making changes to address these issues, what are your
thoughts?

For the circular reference, I forgot about inclusion guards, sorry about
that.

Regards,
Caleb





On Sat, Sep 10, 2022 at 12:34 AM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> Caleb Etemesi:
> >> This is unneeded for the encoder
> >> maybe a jpeg2000dec.h would be better for this
> >> also code moving should be in a seperate patch
> >> from functional changes
> >
> >
> > This will be a circular dependence, since jpeg2000htdec.h needs the
> decoder
> > context, and jpeg2000.c needs jpeg2000htdec.c.
> >
>
> It seems like the only use of the decoder context in jpeg2000htdec.h is
> in jpeg2000_decode_ctx_vlc() where the Jpeg2000DecoderContext is not
> even used at all. And I fail to see the circular dependency even if
> jpeg2000htdec.h needed the decoder context: after all, you are not
> adding an inclusion of jpeg2000htdec.h to jpeg2000.h, so jpeg2000dec.h
> will also not include jpeg2000htdec.h.
>
> >
> > On Fri, 9 Sept 2022, 19:52 Caleb Etemesi, <etemesicaleb@gmail.com>
> wrote:
> >
> >> Will address in the next iteration
> >>
> >> On Fri, 9 Sept 2022, 18:46 Michael Niedermayer, <michael@niedermayer.cc
> >
> >> wrote:
> >>
> >>> On Thu, Sep 08, 2022 at 11:49:53PM +0300, etemesicaleb@gmail.com
> wrote:
> >>>> From: caleb <etemesicaleb@gmail.com>
> >>>>
> >>>> Rebased this patch on master branch
> >>>> ---
> >>>>  libavcodec/Makefile        |    2 +-
> >>>>  libavcodec/j2kenc.c        |   26 +-
> >>>>  libavcodec/jpeg2000.h      |  103 ++-
> >>>>  libavcodec/jpeg2000dec.c   |  193 ++----
> >>>>  libavcodec/jpeg2000htdec.c | 1212
> ++++++++++++++++++++++++++++++++++++
> >>>>  libavcodec/jpeg2000htdec.h |  210 +++++++
> >>>>  6 files changed, 1599 insertions(+), 147 deletions(-)
> >>>>  create mode 100644 libavcodec/jpeg2000htdec.c
> >>>>  create mode 100644 libavcodec/jpeg2000htdec.h
> >>>>
> >>>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> >>>> index 945908e3b8..ecf5c47cad 100644
> >>>> --- a/libavcodec/Makefile
> >>>> +++ b/libavcodec/Makefile
> >>>> @@ -450,7 +450,7 @@ OBJS-$(CONFIG_JACOSUB_DECODER)         +=
> >>> jacosubdec.o ass.o
> >>>>  OBJS-$(CONFIG_JPEG2000_ENCODER)        += j2kenc.o mqcenc.o mqc.o
> >>> jpeg2000.o \
> >>>>                                            jpeg2000dwt.o
> >>>>  OBJS-$(CONFIG_JPEG2000_DECODER)        += jpeg2000dec.o jpeg2000.o
> >>> jpeg2000dsp.o \
> >>>> -                                          jpeg2000dwt.o mqcdec.o
> mqc.o
> >>>> +                                          jpeg2000dwt.o mqcdec.o
> mqc.o
> >>> jpeg2000htdec.o
> >>>>  OBJS-$(CONFIG_JPEGLS_DECODER)          += jpeglsdec.o jpegls.o
> >>>>  OBJS-$(CONFIG_JPEGLS_ENCODER)          += jpeglsenc.o jpegls.o
> >>>>  OBJS-$(CONFIG_JV_DECODER)              += jvdec.o
> >>>> diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
> >>>> index e883d5deb7..233d75e96d 100644
> >>>> --- a/libavcodec/j2kenc.c
> >>>> +++ b/libavcodec/j2kenc.c
> >>>> @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
> >>> [dwt_type][band][rlevel] (multiplied
> >>>>  typedef struct {
> >>>>     Jpeg2000Component *comp;
> >>>>     double *layer_rates;
> >>>> -} Jpeg2000Tile;
> >>>> +} Jpeg2000EncTile;
> >>>>
> >>>>  typedef struct {
> >>>>      AVClass *class;
> >>>> @@ -131,7 +131,7 @@ typedef struct {
> >>>>      Jpeg2000CodingStyle codsty;
> >>>>      Jpeg2000QuantStyle  qntsty;
> >>>>
> >>>> -    Jpeg2000Tile *tile;
> >>>> +    Jpeg2000EncTile *tile;
> >>>>      int layer_rates[100];
> >>>>      uint8_t compression_rate_enc; ///< Is compression done using
> >>> compression ratio?
> >>>>
> >>>> @@ -427,7 +427,7 @@ static void compute_rates(Jpeg2000EncoderContext*
> s)
> >>>>      int layno, compno;
> >>>>      for (i = 0; i < s->numYtiles; i++) {
> >>>>          for (j = 0; j < s->numXtiles; j++) {
> >>>> -            Jpeg2000Tile *tile = &s->tile[s->numXtiles * i + j];
> >>>> +            Jpeg2000EncTile *tile = &s->tile[s->numXtiles * i + j];
> >>>>              for (compno = 0; compno < s->ncomponents; compno++) {
> >>>>                  int tilew = tile->comp[compno].coord[0][1] -
> >>> tile->comp[compno].coord[0][0];
> >>>>                  int tileh = tile->comp[compno].coord[1][1] -
> >>> tile->comp[compno].coord[1][0];
> >>>> @@ -460,12 +460,12 @@ static int init_tiles(Jpeg2000EncoderContext *s)
> >>>>      s->numXtiles = ff_jpeg2000_ceildiv(s->width, s->tile_width);
> >>>>      s->numYtiles = ff_jpeg2000_ceildiv(s->height, s->tile_height);
> >>>>
> >>>> -    s->tile = av_calloc(s->numXtiles, s->numYtiles *
> >>> sizeof(Jpeg2000Tile));
> >>>> +    s->tile = av_calloc(s->numXtiles, s->numYtiles *
> >>> sizeof(Jpeg2000EncTile));
> >>>>      if (!s->tile)
> >>>>          return AVERROR(ENOMEM);
> >>>>      for (tileno = 0, tiley = 0; tiley < s->numYtiles; tiley++)
> >>>>          for (tilex = 0; tilex < s->numXtiles; tilex++, tileno++){
> >>>> -            Jpeg2000Tile *tile = s->tile + tileno;
> >>>> +            Jpeg2000EncTile *tile = s->tile + tileno;
> >>>>
> >>>>              tile->comp = av_calloc(s->ncomponents,
> >>> sizeof(*tile->comp));
> >>>>              if (!tile->comp)
> >>>> @@ -509,7 +509,7 @@ static int init_tiles(Jpeg2000EncoderContext *s)
> >>>>          int tileno, compno, i, y, x;
> >>>                                                       \
> >>>>          const PIXEL *line;
> >>>                                                       \
> >>>>          for (tileno = 0; tileno < s->numXtiles * s->numYtiles;
> >>> tileno++){                                                   \
> >>>> -            Jpeg2000Tile *tile = s->tile + tileno;
> >>>                                                       \
> >>>> +            Jpeg2000EncTile *tile = s->tile + tileno;
> >>>                                                         \
> >>>>              if (s->planar){
> >>>                                                      \
> >>>>                  for (compno = 0; compno < s->ncomponents; compno++){
> >>>                                                       \
> >>>>                      Jpeg2000Component *comp = tile->comp + compno;
> >>>                                                       \
> >>>> @@ -701,7 +701,7 @@ static void encode_clnpass(Jpeg2000T1Context *t1,
> >>> int width, int height, int ban
> >>>>          }
> >>>>  }
> >>>>
> >>>> -static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
> >>> *t1, Jpeg2000Cblk *cblk, Jpeg2000Tile *tile,
> >>>> +static void encode_cblk(Jpeg2000EncoderContext *s, Jpeg2000T1Context
> >>> *t1, Jpeg2000Cblk *cblk, Jpeg2000EncTile *tile,
> >>>>                          int width, int height, int bandpos, int lev)
> >>>>  {
> >>>>      int pass_t = 2, passno, x, y, max=0, nmsedec, bpno;
> >>>> @@ -935,7 +935,7 @@ static int encode_packet(Jpeg2000EncoderContext
> *s,
> >>> Jpeg2000ResLevel *rlevel, in
> >>>>      return 0;
> >>>>  }
> >>>>
> >>>> -static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000Tile
> >>> *tile, int tileno, int nlayers)
> >>>> +static int encode_packets(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> >>> *tile, int tileno, int nlayers)
> >>>>  {
> >>>>      int compno, reslevelno, layno, ret;
> >>>>      Jpeg2000CodingStyle *codsty = &s->codsty;
> >>>> @@ -1181,7 +1181,7 @@ static int encode_packets(Jpeg2000EncoderContext
> >>> *s, Jpeg2000Tile *tile, int til
> >>>>      return 0;
> >>>>  }
> >>>>
> >>>> -static void makelayer(Jpeg2000EncoderContext *s, int layno, double
> >>> thresh, Jpeg2000Tile* tile, int final)
> >>>> +static void makelayer(Jpeg2000EncoderContext *s, int layno, double
> >>> thresh, Jpeg2000EncTile* tile, int final)
> >>>>  {
> >>>>      int compno, resno, bandno, precno, cblkno;
> >>>>      int passno;
> >>>> @@ -1264,7 +1264,7 @@ static void makelayer(Jpeg2000EncoderContext *s,
> >>> int layno, double thresh, Jpeg2
> >>>>      }
> >>>>  }
> >>>>
> >>>> -static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile)
> >>>> +static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> >>> *tile)
> >>>>  {
> >>>>      int precno, compno, reslevelno, bandno, cblkno, lev, passno,
> layno;
> >>>>      int i;
> >>>> @@ -1365,7 +1365,7 @@ static int getcut(Jpeg2000Cblk *cblk, int64_t
> >>> lambda, int dwt_norm)
> >>>>      return res;
> >>>>  }
> >>>>
> >>>> -static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000Tile
> *tile)
> >>>> +static void truncpasses(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> >>> *tile)
> >>>>  {
> >>>>      int precno, compno, reslevelno, bandno, cblkno, lev;
> >>>>      Jpeg2000CodingStyle *codsty = &s->codsty;
> >>>> @@ -1399,7 +1399,7 @@ static void truncpasses(Jpeg2000EncoderContext
> >>> *s, Jpeg2000Tile *tile)
> >>>>      }
> >>>>  }
> >>>>
> >>>> -static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile,
> >>> int tileno)
> >>>> +static int encode_tile(Jpeg2000EncoderContext *s, Jpeg2000EncTile
> >>> *tile, int tileno)
> >>>>  {
> >>>>      int compno, reslevelno, bandno, ret;
> >>>>      Jpeg2000T1Context t1;
> >>>> @@ -1514,7 +1514,7 @@ static void reinit(Jpeg2000EncoderContext *s)
> >>>>  {
> >>>>      int tileno, compno;
> >>>>      for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
> >>>> -        Jpeg2000Tile *tile = s->tile + tileno;
> >>>> +        Jpeg2000EncTile *tile = s->tile + tileno;
> >>>>          for (compno = 0; compno < s->ncomponents; compno++)
> >>>>              ff_jpeg2000_reinit(tile->comp + compno, &s->codsty);
> >>>>      }
> >>>
> >>> Renaming Jpeg2000Tile could be in a seperate patch
> >>>
> >>>
> >>>> diff --git a/libavcodec/jpeg2000.h b/libavcodec/jpeg2000.h
> >>>> index e5ecb4cbf9..a5dd693392 100644
> >>>> --- a/libavcodec/jpeg2000.h
> >>>> +++ b/libavcodec/jpeg2000.h
> >>>> @@ -33,8 +33,9 @@
> >>>>
> >>>>  #include "avcodec.h"
> >>>>  #include "mqc.h"
> >>>> +#include "bytestream.h"
> >>>>  #include "jpeg2000dwt.h"
> >>>> -
> >>>> +#include "jpeg2000dsp.h"
> >>>>  enum Jpeg2000Markers {
> >>>>      JPEG2000_SOC = 0xff4f, // start of codestream
> >>>>      JPEG2000_SIZ = 0xff51, // image and tile size
> >>>
> >>>> @@ -171,7 +172,6 @@ typedef struct Jpeg2000Layer {
> >>>>      double disto;
> >>>>      int cum_passes;
> >>>>  } Jpeg2000Layer;
> >>>> -
> >>>>  typedef struct Jpeg2000Cblk {
> >>>>      uint8_t npasses;
> >>>>      uint8_t ninclpasses; // number coding of passes included in
> >>> codestream
> >>>
> >>> unintended, i assume
> >>>
> >>>
> >>>> @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
> >>>>      uint16_t *lengthinc;
> >>>>      uint8_t nb_lengthinc;
> >>>>      uint8_t lblock;
> >>>> +    uint8_t zbp;         // Zero bit planes
> >>>>      uint8_t *data;
> >>>>      size_t data_allocated;
> >>>>      int nb_terminations;
> >>>> @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
> >>>>      Jpeg2000Pass *passes;
> >>>>      Jpeg2000Layer *layers;
> >>>>      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
> >>>> +    int pass_lengths[2];
> >>>>  } Jpeg2000Cblk; // code block
> >>>
> >>> Please use doxygen compatible comments so it all appears on for example
> >>> https://ffmpeg.org/doxygen/trunk/structJpeg2000Cblk.html
> >>>
> >>>>
> >>>>  typedef struct Jpeg2000Prec {
> >>>> @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
> >>>>      uint8_t roi_shift; // ROI scaling value for the component
> >>>>  } Jpeg2000Component;
> >>>>
> >>>> +#define JP2_SIG_TYPE    0x6A502020
> >>>> +#define JP2_SIG_VALUE   0x0D0A870A
> >>>> +#define JP2_CODESTREAM  0x6A703263
> >>>> +#define JP2_HEADER      0x6A703268
> >>>> +
> >>>> +#define HAD_COC 0x01
> >>>> +#define HAD_QCC 0x02
> >>>> +
> >>>> +#define MAX_POCS 32
> >>>> +
> >>>> +typedef struct Jpeg2000POCEntry {
> >>>> +    uint16_t LYEpoc;
> >>>> +    uint16_t CSpoc;
> >>>> +    uint16_t CEpoc;
> >>>> +    uint8_t RSpoc;
> >>>> +    uint8_t REpoc;
> >>>> +    uint8_t Ppoc;
> >>>> +} Jpeg2000POCEntry;
> >>>> +
> >>>> +typedef struct Jpeg2000POC {
> >>>> +    Jpeg2000POCEntry poc[MAX_POCS];
> >>>> +    int nb_poc;
> >>>> +    int is_default;
> >>>> +} Jpeg2000POC;
> >>>> +
> >>>> +typedef struct Jpeg2000TilePart {
> >>>> +    uint8_t tile_index;                 // Tile index who refers the
> >>> tile-part
> >>>> +    const uint8_t *tp_end;
> >>>> +    GetByteContext header_tpg;          // bit stream of header if
> PPM
> >>> header is used
> >>>> +    GetByteContext tpg;                 // bit stream in tile-part
> >>>> +} Jpeg2000TilePart;
> >>>> +
> >>>> +/* RMK: For JPEG2000 DCINEMA 3 tile-parts in a tile
> >>>> + * one per component, so tile_part elements have a size of 3 */
> >>>> +typedef struct Jpeg2000Tile {
> >>>                   ^^^^^^^^^^^^
> >>>> +    Jpeg2000Component   *comp;
> >>>> +    uint8_t             properties[4];
> >>>> +    Jpeg2000CodingStyle codsty[4];
> >>>> +    Jpeg2000QuantStyle  qntsty[4];
> >>>> +    Jpeg2000POC         poc;
> >>>> +    Jpeg2000TilePart    tile_part[32];
> >>>> +    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}}
> >>>> +} Jpeg2000DecTile;
> >>>      ^^^^^^^^^^^^^^^
> >>> This difference appears unintended
> >>>
> >>>
> >>>> +
> >>>> +typedef struct Jpeg2000DecoderContext {
> >>>
> >>> This is unneeded for the encoder
> >>> maybe a jpeg2000dec.h would be better for this
> >>> also code moving should be in a seperate patch from functional changes
> >>>
> >>> [...]
> >>>> +#endif /* AVCODEC_JPEG2000HTDEC_H */
> >>>
> >>>> \ No newline at end of file
> >>>
> >>> needs newline
> >>>
> >>> new decoder not reviewed, feel free to wait for someone to review it
> >>> before reposting
> >>>
> >>> thx
> >>>
> >>>
> >>> [...]
> >>> --
> >>> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
> >>>
> >>> Those who would give up essential Liberty, to purchase a little
> >>> temporary Safety, deserve neither Liberty nor Safety -- Benjamin
> Franklin
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-08 20:49 [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding etemesicaleb
  2022-09-09 15:46 ` Michael Niedermayer
@ 2022-09-20 13:49 ` Tomas Härdin
  2022-09-21  8:13   ` Caleb Etemesi
  1 sibling, 1 reply; 13+ messages in thread
From: Tomas Härdin @ 2022-09-20 13:49 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

tor 2022-09-08 klockan 23:49 +0300 skrev etemesicaleb@gmail.com:
> 
> --- a/libavcodec/j2kenc.c
> +++ b/libavcodec/j2kenc.c
> @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
> [dwt_type][band][rlevel] (multiplied
>  typedef struct {
>     Jpeg2000Component *comp;
>     double *layer_rates;
> -} Jpeg2000Tile;
> +} Jpeg2000EncTile;
>  
>  typedef struct {
>      AVClass *class;
> @@ -131,7 +131,7 @@ typedef struct {
>      Jpeg2000CodingStyle codsty;
>      Jpeg2000QuantStyle  qntsty;
>  
> -    Jpeg2000Tile *tile;
> +    Jpeg2000EncTile *tile;

Please separate struct renaming into a separate patch

>  typedef struct Jpeg2000Cblk {
>      uint8_t npasses;
>      uint8_t ninclpasses; // number coding of passes included in
> codestream
> @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
>      uint16_t *lengthinc;
>      uint8_t nb_lengthinc;
>      uint8_t lblock;
> +    uint8_t zbp;         // Zero bit planes

Corresponds to µ_start, right?

>      uint8_t *data;
>      size_t data_allocated;
>      int nb_terminations;
> @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
>      Jpeg2000Pass *passes;
>      Jpeg2000Layer *layers;
>      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
> +    int pass_lengths[2];

Could also be called Lcup and Lref. But fine I suppose.

>  } Jpeg2000Cblk; // code block
>  
>  typedef struct Jpeg2000Prec {
> @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
>      uint8_t roi_shift; // ROI scaling value for the component
>  } Jpeg2000Component;
>  
> +#define JP2_SIG_TYPE    0x6A502020
> +#define JP2_SIG_VALUE   0x0D0A870A
> +#define JP2_CODESTREAM  0x6A703263
> +#define JP2_HEADER      0x6A703268
> +
> +#define HAD_COC 0x01
> +#define HAD_QCC 0x02
> +
> +#define MAX_POCS 32

Similarly with code movements. I can see this move adds is_htj2k to
Jpeg2000DecoderContext. Please separate such things. Makes reviewing
functional changes much easier.

> -static inline void tile_codeblocks(const Jpeg2000DecoderContext *s,
> Jpeg2000Tile *tile)
> +static inline void tile_codeblocks(const Jpeg2000DecoderContext *s,
> Jpeg2000DecTile *tile)
>  {
>      Jpeg2000T1Context t1;
>  
>      int compno, reslevelno, bandno;
> +    int subbandno;
>  
>      /* Loop on tile components */
>      for (compno = 0; compno < s->ncomponents; compno++) {
> -        Jpeg2000Component *comp     = tile->comp + compno;
> -        Jpeg2000CodingStyle *codsty = tile->codsty + compno;
> +        Jpeg2000Component *comp        = tile->comp + compno;
> +        Jpeg2000CodingStyle *codsty    = tile->codsty + compno;
> +        Jpeg2000QuantStyle *quantsty   = tile->qntsty + compno;

Cosmetic and functional changes don't mix

>          int coded = 0;
> +        subbandno = 0;
>  
>          t1.stride = (1<<codsty->log2_cblk_width) + 2;
>  
> @@ -1959,7 +1881,7 @@ static inline void tile_codeblocks(const
> Jpeg2000DecoderContext *s, Jpeg2000Tile
>          for (reslevelno = 0; reslevelno < codsty->nreslevels2decode;
> reslevelno++) {
>              Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
>              /* Loop on bands */
> -            for (bandno = 0; bandno < rlevel->nbands; bandno++) {
> +            for (bandno = 0; bandno < rlevel->nbands;
> bandno++,subbandno++) {
>                  int nb_precincts, precno;
>                  Jpeg2000Band *band = rlevel->band + bandno;
>                  int cblkno = 0, bandpos;
> @@ -1979,12 +1901,21 @@ static inline void tile_codeblocks(const
> Jpeg2000DecoderContext *s, Jpeg2000Tile
>                      for (cblkno = 0;
>                           cblkno < prec->nb_codeblocks_width * prec-
> >nb_codeblocks_height;
>                           cblkno++) {
> -                        int x, y;
> +                        int x, y, ret, magp;
>                          Jpeg2000Cblk *cblk = prec->cblk + cblkno;
> -                        int ret = decode_cblk(s, codsty, &t1, cblk,
> -                                    cblk->coord[0][1] - cblk-
> >coord[0][0],
> -                                    cblk->coord[1][1] - cblk-
> >coord[1][0],
> -                                    bandpos, comp->roi_shift);
> +                        // Annex E (Equation E-2) ISO/IEC 15444-
> 1:2019
> +                        magp = quantsty->expn[subbandno] + quantsty-
> >nguardbits - 1;

Is expn[] allocated for regular j2k? I'd move this inside the is_htj2k
block below

> +
> +                        if (s->is_htj2k)
> +                            ret = decode_htj2k(s, codsty, &t1, cblk,
> +                                               cblk->coord[0][1] -
> cblk->coord[0][0],
> +                                               cblk->coord[1][1] -
> cblk->coord[1][0],
> +                                               magp, comp-
> >roi_shift);

> --- /dev/null
> +++ b/libavcodec/jpeg2000htdec.c

No time to review this atm, hopefully later though

> --- /dev/null
> +++ b/libavcodec/jpeg2000htdec.h
> 
> +/**
> + * @brief  CtxVLC tables, borrowed from openhtj2k (       
> https://github.com/osamu620/OpenHTJ2K) (credits to Osamu Watanabe)
> + */
> +static const uint16_t dec_CxtVLC_table1[1024] = {
> +static const uint16_t dec_CxtVLC_table0[1024] = {

Why are these tables in here when they're only used by jpeg2000htdec.c?

/Tomas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-20 13:49 ` Tomas Härdin
@ 2022-09-21  8:13   ` Caleb Etemesi
  2022-09-21 10:30     ` Tomas Härdin
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-21  8:13 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

>> Please separate struct renaming into a separate patch

Will do in the next patch

>> Corresponds to µ_start, right?

Not sure what  µ_start here relates to, but this is the zero bit plane
information in *B.10.5*
of the jpeg2000 spec (ITU Rec. T.800 (06/2019))

>> Could also be called Lcup and Lref. But fine I suppose.

Will change in the next patch

>> No time to review this atm, hopefully later though

No problem.


>> Why are these tables in here when they're only used by jpeg2000htdec.c?

I wasn't aware of any table placing conventions and my personal preference
is usually to place them
inside header files.

On Tue, Sep 20, 2022 at 4:49 PM Tomas Härdin <tjoppen@acc.umu.se> wrote:

> tor 2022-09-08 klockan 23:49 +0300 skrev etemesicaleb@gmail.com:
> >
> > --- a/libavcodec/j2kenc.c
> > +++ b/libavcodec/j2kenc.c
> > @@ -106,7 +106,7 @@ static const int dwt_norms[2][4][10] = { //
> > [dwt_type][band][rlevel] (multiplied
> >  typedef struct {
> >     Jpeg2000Component *comp;
> >     double *layer_rates;
> > -} Jpeg2000Tile;
> > +} Jpeg2000EncTile;
> >
> >  typedef struct {
> >      AVClass *class;
> > @@ -131,7 +131,7 @@ typedef struct {
> >      Jpeg2000CodingStyle codsty;
> >      Jpeg2000QuantStyle  qntsty;
> >
> > -    Jpeg2000Tile *tile;
> > +    Jpeg2000EncTile *tile;
>
> Please separate struct renaming into a separate patch
>
> >  typedef struct Jpeg2000Cblk {
> >      uint8_t npasses;
> >      uint8_t ninclpasses; // number coding of passes included in
> > codestream
> > @@ -181,6 +181,7 @@ typedef struct Jpeg2000Cblk {
> >      uint16_t *lengthinc;
> >      uint8_t nb_lengthinc;
> >      uint8_t lblock;
> > +    uint8_t zbp;         // Zero bit planes
>
> Corresponds to µ_start, right?
>
> >      uint8_t *data;
> >      size_t data_allocated;
> >      int nb_terminations;
> > @@ -189,6 +190,7 @@ typedef struct Jpeg2000Cblk {
> >      Jpeg2000Pass *passes;
> >      Jpeg2000Layer *layers;
> >      int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
> > +    int pass_lengths[2];
>
> Could also be called Lcup and Lref. But fine I suppose.
>
> >  } Jpeg2000Cblk; // code block
> >
> >  typedef struct Jpeg2000Prec {
> > @@ -227,6 +229,103 @@ typedef struct Jpeg2000Component {
> >      uint8_t roi_shift; // ROI scaling value for the component
> >  } Jpeg2000Component;
> >
> > +#define JP2_SIG_TYPE    0x6A502020
> > +#define JP2_SIG_VALUE   0x0D0A870A
> > +#define JP2_CODESTREAM  0x6A703263
> > +#define JP2_HEADER      0x6A703268
> > +
> > +#define HAD_COC 0x01
> > +#define HAD_QCC 0x02
> > +
> > +#define MAX_POCS 32
>
> Similarly with code movements. I can see this move adds is_htj2k to
> Jpeg2000DecoderContext. Please separate such things. Makes reviewing
> functional changes much easier.
>
> > -static inline void tile_codeblocks(const Jpeg2000DecoderContext *s,
> > Jpeg2000Tile *tile)
> > +static inline void tile_codeblocks(const Jpeg2000DecoderContext *s,
> > Jpeg2000DecTile *tile)
> >  {
> >      Jpeg2000T1Context t1;
> >
> >      int compno, reslevelno, bandno;
> > +    int subbandno;
> >
> >      /* Loop on tile components */
> >      for (compno = 0; compno < s->ncomponents; compno++) {
> > -        Jpeg2000Component *comp     = tile->comp + compno;
> > -        Jpeg2000CodingStyle *codsty = tile->codsty + compno;
> > +        Jpeg2000Component *comp        = tile->comp + compno;
> > +        Jpeg2000CodingStyle *codsty    = tile->codsty + compno;
> > +        Jpeg2000QuantStyle *quantsty   = tile->qntsty + compno;
>
> Cosmetic and functional changes don't mix
>
> >          int coded = 0;
> > +        subbandno = 0;
> >
> >          t1.stride = (1<<codsty->log2_cblk_width) + 2;
> >
> > @@ -1959,7 +1881,7 @@ static inline void tile_codeblocks(const
> > Jpeg2000DecoderContext *s, Jpeg2000Tile
> >          for (reslevelno = 0; reslevelno < codsty->nreslevels2decode;
> > reslevelno++) {
> >              Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
> >              /* Loop on bands */
> > -            for (bandno = 0; bandno < rlevel->nbands; bandno++) {
> > +            for (bandno = 0; bandno < rlevel->nbands;
> > bandno++,subbandno++) {
> >                  int nb_precincts, precno;
> >                  Jpeg2000Band *band = rlevel->band + bandno;
> >                  int cblkno = 0, bandpos;
> > @@ -1979,12 +1901,21 @@ static inline void tile_codeblocks(const
> > Jpeg2000DecoderContext *s, Jpeg2000Tile
> >                      for (cblkno = 0;
> >                           cblkno < prec->nb_codeblocks_width * prec-
> > >nb_codeblocks_height;
> >                           cblkno++) {
> > -                        int x, y;
> > +                        int x, y, ret, magp;
> >                          Jpeg2000Cblk *cblk = prec->cblk + cblkno;
> > -                        int ret = decode_cblk(s, codsty, &t1, cblk,
> > -                                    cblk->coord[0][1] - cblk-
> > >coord[0][0],
> > -                                    cblk->coord[1][1] - cblk-
> > >coord[1][0],
> > -                                    bandpos, comp->roi_shift);
> > +                        // Annex E (Equation E-2) ISO/IEC 15444-
> > 1:2019
> > +                        magp = quantsty->expn[subbandno] + quantsty-
> > >nguardbits - 1;
>
> Is expn[] allocated for regular j2k? I'd move this inside the is_htj2k
> block below
>
> > +
> > +                        if (s->is_htj2k)
> > +                            ret = decode_htj2k(s, codsty, &t1, cblk,
> > +                                               cblk->coord[0][1] -
> > cblk->coord[0][0],
> > +                                               cblk->coord[1][1] -
> > cblk->coord[1][0],
> > +                                               magp, comp-
> > >roi_shift);
>
> > --- /dev/null
> > +++ b/libavcodec/jpeg2000htdec.c
>
> No time to review this atm, hopefully later though
>
> > --- /dev/null
> > +++ b/libavcodec/jpeg2000htdec.h
> >
> > +/**
> > + * @brief  CtxVLC tables, borrowed from openhtj2k (
> > https://github.com/osamu620/OpenHTJ2K) (credits to Osamu Watanabe)
> > + */
> > +static const uint16_t dec_CxtVLC_table1[1024] = {
> > +static const uint16_t dec_CxtVLC_table0[1024] = {
>
> Why are these tables in here when they're only used by jpeg2000htdec.c?
>
> /Tomas
>
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-21  8:13   ` Caleb Etemesi
@ 2022-09-21 10:30     ` Tomas Härdin
  2022-09-21 14:08       ` Tomas Härdin
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Härdin @ 2022-09-21 10:30 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

ons 2022-09-21 klockan 11:13 +0300 skrev Caleb Etemesi:
> > > Please separate struct renaming into a separate patch
> 
> Will do in the next patch
> 
> > > Corresponds to µ_start, right?
> 
> Not sure what  µ_start here relates to, but this is the zero bit
> plane
> information in *B.10.5*
> of the jpeg2000 spec (ITU Rec. T.800 (06/2019))
> 
> > > Could also be called Lcup and Lref. But fine I suppose.
> 
> Will change in the next patch
> 
> > > No time to review this atm, hopefully later though
> 
> No problem.
> 
> 
> > > Why are these tables in here when they're only used by
> > > jpeg2000htdec.c?
> 
> I wasn't aware of any table placing conventions and my personal
> preference
> is usually to place them
> inside header files.

You could have them in a separate file to make the code a bit easier to
read, but keeping them in a file that's included by both decoders is
kinda wrong. The compiler won't put them into the regular j2k decoder's
.o file since it doesn't use them, but still.

Tested this locally on some 4k sample files and it achieved 19 fps with
-lowres 2 on an Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz (4 cores). I'm
getting access to a better machine to test this on as well.

I will probably spend some time getting this to work with the improved
threading patchset I've posted on here, once the new mem.* stuff is in.
Hopefully that brings realtime 4k htj2k decoding to threadripper and
similar CPUs, with low seek latency thanks to slice threading. That
would bring ffmpeg's decoder "ahead" of libopenjpeg, since opj only
does threading on slice (maybe precinct) level not codeblock level

/Tomas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-21 10:30     ` Tomas Härdin
@ 2022-09-21 14:08       ` Tomas Härdin
  2022-09-22  4:07         ` Caleb Etemesi
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Härdin @ 2022-09-21 14:08 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

ons 2022-09-21 klockan 12:30 +0200 skrev Tomas Härdin:
> Tested this locally on some 4k sample files and it achieved 19 fps
> with
> -lowres 2 on an Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz (4 cores).
> I'm
> getting access to a better machine to test this on as well.

Ran some tests on a c5n.4xlarge instance, Intel(R) Xeon(R) Platinum
8124M CPU @ 3.00GHz, 16 vCPUs. Test sequence is 273 4k htj2k frames
from Disney encoded with OpenJPH version 0.7.3, 20-21 megs each. Tested
like so:

./ffmpeg -i ~/samples/htj2k-unwrapped/000000%03d.j2c -f null -

Achieved fps with a filled disk cache:
-lowres  this patch  libopenjpegdec
0        9.1         7.0
1        40          27
2        105         92
3        128         157
4        129         164

This is with the default frame-based threading. Not too bad. I suspect
the slower performance compared to opj with -lowres >= 3 is due to the
way parsing works. This is what's holding up my codeblock-threading
patchset's performance as well.

I have in mind to compare this with a regular j2k sample on the same
machine, but it's taking its sweet time transferring..

/Tomas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-21 14:08       ` Tomas Härdin
@ 2022-09-22  4:07         ` Caleb Etemesi
  2022-09-22  9:15           ` Tomas Härdin
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-22  4:07 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

There is one with way better performance on its way, especially with images
with magnitude refinement passes.

here @https://github.com/etemesi254/FFmpeg/tree/my-profile

And the associated runtime profile from running

`perf record -g -F 999 ./ffmpeg_g  -i ~/jpeg2000/meridian.ht.j2c  -v 32
 -bench
mark -f null  -`

Online version  - https://share.firefox.dev/3C0rI9e

Image - https://etemesi254.github.io/assets/imgs/gsoc/meridian.ht.j2c [ 4K
image]

Ffmpeg results from the benchmark

`
bench: utime=0.371s stime=0.036s rtime=0.408s
bench: maxrss=165900kB
`
The machine is an AMD Ryzen 6000U with 6 cores 128kb L1.

Perf reports it takes 826 ms,  because the decoder does two decodes per
image,(I think one for the demuxer then the decoder, probably a bug).
anf most of the time is spent on idwt

OpenJPH decodes the same image in ~90ms.

So I do think there is room for improvement.

On Wed, 21 Sept 2022, 17:08 Tomas Härdin, <tjoppen@acc.umu.se> wrote:

> ons 2022-09-21 klockan 12:30 +0200 skrev Tomas Härdin:
> > Tested this locally on some 4k sample files and it achieved 19 fps
> > with
> > -lowres 2 on an Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz (4 cores).
> > I'm
> > getting access to a better machine to test this on as well.
>
> Ran some tests on a c5n.4xlarge instance, Intel(R) Xeon(R) Platinum
> 8124M CPU @ 3.00GHz, 16 vCPUs. Test sequence is 273 4k htj2k frames
> from Disney encoded with OpenJPH version 0.7.3, 20-21 megs each. Tested
> like so:
>
> ./ffmpeg -i ~/samples/htj2k-unwrapped/000000%03d.j2c -f null -
>
> Achieved fps with a filled disk cache:
> -lowres  this patch  libopenjpegdec
> 0        9.1         7.0
> 1        40          27
> 2        105         92
> 3        128         157
> 4        129         164
>
> This is with the default frame-based threading. Not too bad. I suspect
> the slower performance compared to opj with -lowres >= 3 is due to the
> way parsing works. This is what's holding up my codeblock-threading
> patchset's performance as well.
>
> I have in mind to compare this with a regular j2k sample on the same
> machine, but it's taking its sweet time transferring..
>
> /Tomas
>
> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-22  4:07         ` Caleb Etemesi
@ 2022-09-22  9:15           ` Tomas Härdin
  2022-09-22 16:16             ` Caleb Etemesi
  0 siblings, 1 reply; 13+ messages in thread
From: Tomas Härdin @ 2022-09-22  9:15 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

[-- Attachment #1: Type: text/plain, Size: 2769 bytes --]

tor 2022-09-22 klockan 07:07 +0300 skrev Caleb Etemesi:
> There is one with way better performance on its way, especially with
> images
> with magnitude refinement passes.
> 
> here @https://github.com/etemesi254/FFmpeg/tree/my-profile
> 
> And the associated runtime profile from running
> 
> `perf record -g -F 999 ./ffmpeg_g  -i ~/jpeg2000/meridian.ht.j2c  -v
> 32
>  -bench
> mark -f null  -`
> 
> Online version  - https://share.firefox.dev/3C0rI9e
> 
> Image -
> https://etemesi254.github.io/assets/imgs/gsoc/meridian.ht.j2c [ 4K
> image]
> 
> Ffmpeg results from the benchmark
> 
> `
> bench: utime=0.371s stime=0.036s rtime=0.408s
> bench: maxrss=165900kB
> `
> The machine is an AMD Ryzen 6000U with 6 cores 128kb L1.
> 
> Perf reports it takes 826 ms,  because the decoder does two decodes
> per
> image,(I think one for the demuxer then the decoder, probably a bug).
> anf most of the time is spent on idwt

Yeah this is due to the way probing in lavf works. When I did
development on the Part 1 decoder I dummied out the first decode, which
always runs at full resolution btw, regardless of what -lowres is set
to.

Have you tested your patch with YUV samples or only RGB? For lossless
RGB it seems to work fine, even when roundtripping back through
OpenJPH. That is, using your decoder on files encoded losslessly with
OpenJPH and then encoding with OpenJPH again yields the exact same
bitstream (except the version number of OpenJPH in the header, 0.7.3 vs
0.9.0 for my samples)

I'm currently trying to convert one of SVT's open samples from Part 1
to Part 15, but unfortunately either OpenJPH isn't writing the right
metadata to say that is it YUV or your code is not probing the pixel
format correctly:

ftp://svtopencontent.svt.se/pub/svt_videotestsuite_natural_complexity/REC709/smoke_sauna_JPEG2000_SDR_3840x2160p50_YUV444_12bit_Lossless.mov

ffmpeg -i
smoke_sauna_JPEG2000_HDR_REC2100_3840x2160p50_YUV444_12bit_Lossless.mov
-vframes 1 sauna-yuv444p12le.yuv
ojph_compress -reversible true -dims '{3840,2160}' -num_comps 3 -signed
false -bit_depth 12 -downsamp '{1,1}' -i sauna-yuv444p12le.yuv -o
sauna.jph

Input vs output:
  Stream #0:0[0x1]: Video: jpeg2000 (JPEG 2000 codestream restriction
0) (mjp2 / 0x32706A6D), yuv444p12le(bt2020nc/bt2020/smpte2084,
progressive), 3840x2160, lossless, 5543461 kb/s, SAR 1:1 DAR 16:9, 50
fps, 50 tbr, 12800 tbn (default)
  Stream #0:0: Video: jpeg2000, rgb48le(12 bpc), 3840x2160, lossless,
25 fps, 25 tbr, 25 tbn

Transcoding the .jph to .png 

I have attached the first 64k of sauna.jph for everyone's sleuthing
benefits. I decoded, downscaled and encoded it to jpeg, see attachment.
It is what you'd expect when YUV is mistaken for RGB.

Your decoder doesn't seem to like partial files btw.

/Tomas

[-- Attachment #2: sauna-cut.jph --]
[-- Type: image/x-jp2-codestream, Size: 65536 bytes --]

[-- Attachment #3: sauna.jpg --]
[-- Type: image/jpeg, Size: 69545 bytes --]

[-- Attachment #4: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.
  2022-09-22  9:15           ` Tomas Härdin
@ 2022-09-22 16:16             ` Caleb Etemesi
  0 siblings, 0 replies; 13+ messages in thread
From: Caleb Etemesi @ 2022-09-22 16:16 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

[-- Attachment #1: Type: text/plain, Size: 4499 bytes --]

>> Yeah this is due to the way probing in lavf works. When I did
development on the Part 1 decoder I dummied out the first decode, which
always runs at full resolution btw, regardless of what -lowres is set
to.

Can this be fixed?

Decoding sauna-cut.jph errors out with

Post 14864313 too big which corresponds to
https://github.com/FFmpeg/FFmpeg/blob/db73ae0dc114aa6fae08e69f977944f056a24995/libavcodec/jpeg2000dec.c#L838-L841

I've tested with RGB samples only, but ffmpeg logs show that it is picking
the format as yuv for the attached image ([format @ 0x55d54132e880] Setting
'pix_fmts' to value 'yuvj420p|yuvj422p|yuvj444p')


>> Your decoder doesn't seem to like partial files btw.

Should partial files lead to panics?

Using `head  -c 10000 t1.j2c  &> t5.j2c` and followed by ffmpeg decoding
complains with the same error on Psot being too big. I didn't touch that
part


Also as to how the decoder is written, partial files should cause an
`av_assert()` for worst case or decode to invalid data for best case,
hence I might need some clarity on what the decoder "not liking partial
files" means

Attached t1.j2c

Kind regards


On Thu, Sep 22, 2022 at 12:15 PM Tomas Härdin <tjoppen@acc.umu.se> wrote:

> tor 2022-09-22 klockan 07:07 +0300 skrev Caleb Etemesi:
> > There is one with way better performance on its way, especially with
> > images
> > with magnitude refinement passes.
> >
> > here @https://github.com/etemesi254/FFmpeg/tree/my-profile
> >
> > And the associated runtime profile from running
> >
> > `perf record -g -F 999 ./ffmpeg_g  -i ~/jpeg2000/meridian.ht.j2c  -v
> > 32
> >  -bench
> > mark -f null  -`
> >
> > Online version  - https://share.firefox.dev/3C0rI9e
> >
> > Image -
> > https://etemesi254.github.io/assets/imgs/gsoc/meridian.ht.j2c [ 4K
> > image]
> >
> > Ffmpeg results from the benchmark
> >
> > `
> > bench: utime=0.371s stime=0.036s rtime=0.408s
> > bench: maxrss=165900kB
> > `
> > The machine is an AMD Ryzen 6000U with 6 cores 128kb L1.
> >
> > Perf reports it takes 826 ms,  because the decoder does two decodes
> > per
> > image,(I think one for the demuxer then the decoder, probably a bug).
> > anf most of the time is spent on idwt
>
> Yeah this is due to the way probing in lavf works. When I did
> development on the Part 1 decoder I dummied out the first decode, which
> always runs at full resolution btw, regardless of what -lowres is set
> to.
>
> Have you tested your patch with YUV samples or only RGB? For lossless
> RGB it seems to work fine, even when roundtripping back through
> OpenJPH. That is, using your decoder on files encoded losslessly with
> OpenJPH and then encoding with OpenJPH again yields the exact same
> bitstream (except the version number of OpenJPH in the header, 0.7.3 vs
> 0.9.0 for my samples)
>
> I'm currently trying to convert one of SVT's open samples from Part 1
> to Part 15, but unfortunately either OpenJPH isn't writing the right
> metadata to say that is it YUV or your code is not probing the pixel
> format correctly:
>
>
> ftp://svtopencontent.svt.se/pub/svt_videotestsuite_natural_complexity/REC709/smoke_sauna_JPEG2000_SDR_3840x2160p50_YUV444_12bit_Lossless.mov
>
> ffmpeg -i
> smoke_sauna_JPEG2000_HDR_REC2100_3840x2160p50_YUV444_12bit_Lossless.mov
> -vframes 1 sauna-yuv444p12le.yuv
> ojph_compress -reversible true -dims '{3840,2160}' -num_comps 3 -signed
> false -bit_depth 12 -downsamp '{1,1}' -i sauna-yuv444p12le.yuv -o
> sauna.jph
>
> Input vs output:
>   Stream #0:0[0x1]: Video: jpeg2000 (JPEG 2000 codestream restriction
> 0) (mjp2 / 0x32706A6D), yuv444p12le(bt2020nc/bt2020/smpte2084,
> progressive), 3840x2160, lossless, 5543461 kb/s, SAR 1:1 DAR 16:9, 50
> fps, 50 tbr, 12800 tbn (default)
>   Stream #0:0: Video: jpeg2000, rgb48le(12 bpc), 3840x2160, lossless,
> 25 fps, 25 tbr, 25 tbn
>
> Transcoding the .jph to .png
>
> I have attached the first 64k of sauna.jph for everyone's sleuthing
> benefits. I decoded, downscaled and encoded it to jpeg, see attachment.
> It is what you'd expect when YUV is mistaken for RGB.
>
> Your decoder doesn't seem to like partial files btw.
>
> /Tomas
> _______________________________________________
> 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".
>

[-- Attachment #2: t1.j2c --]
[-- Type: image/x-jp2-codestream, Size: 97765 bytes --]

[-- Attachment #3: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-09-22 16:16 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-08 20:49 [FFmpeg-devel] [PATCH v2] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding etemesicaleb
2022-09-09 15:46 ` Michael Niedermayer
2022-09-09 16:52   ` Caleb Etemesi
2022-09-09 17:11     ` Caleb Etemesi
2022-09-09 21:34       ` Andreas Rheinhardt
2022-09-10  9:13         ` Caleb Etemesi
2022-09-20 13:49 ` Tomas Härdin
2022-09-21  8:13   ` Caleb Etemesi
2022-09-21 10:30     ` Tomas Härdin
2022-09-21 14:08       ` Tomas Härdin
2022-09-22  4:07         ` Caleb Etemesi
2022-09-22  9:15           ` Tomas Härdin
2022-09-22 16:16             ` Caleb Etemesi

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git