diff mbox series

[FFmpeg-devel,1/1] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding.

Message ID 20220907192417.140381-1-etemesicaleb@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/1] avcodec/jpeg2000: Add support for High-Throughput JPEG 2000 (HTJ2K) decoding. | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch

Commit Message

Caleb Etemesi Sept. 7, 2022, 7:24 p.m. UTC
This patch satisfies the GSoC 2022 project with the goal of adding a native htj2k decoder
to ffmpeg.

HTJ2K is specified in Rec. ITU-T 814 | ISO/IEC 15444-15 (https://www.itu.int/rec/T-REC-T.814-201906-I/en)

---
 libavcodec/j2kenc.c        |   28 +-
 libavcodec/jpeg2000.h      |  115 +++-
 libavcodec/jpeg2000dec.c   |  294 +++++----
 libavcodec/jpeg2000htdec.c | 1228 ++++++++++++++++++++++++++++++++++++
 libavcodec/jpeg2000htdec.h |  210 ++++++
 5 files changed, 1731 insertions(+), 144 deletions(-)
 create mode 100644 libavcodec/jpeg2000htdec.c
 create mode 100644 libavcodec/jpeg2000htdec.h
diff mbox series

Patch

diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index 0b761d0b00..7218e0f68f 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?
 
@@ -171,7 +171,7 @@  static void dump(Jpeg2000EncoderContext *s, FILE *fd)
             s->width, s->height, s->tile_width, s->tile_height,
             s->numXtiles, s->numYtiles, s->ncomponents);
     for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
-        Jpeg2000Tile *tile = s->tile + tileno;
+        Jpeg2000EncTile *tile = s->tile + tileno;
         nspaces(fd, 2);
         fprintf(fd, "tile %d:\n", tileno);
         for(compno = 0; compno < s->ncomponents; compno++){
@@ -429,7 +429,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];
@@ -462,12 +462,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)
@@ -511,7 +511,7 @@  static int init_tiles(Jpeg2000EncoderContext *s)
         int tileno, compno, i, y, x;                                                                                        \
         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;                                                          \
@@ -703,7 +703,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;
@@ -937,7 +937,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;
@@ -1183,7 +1183,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;
@@ -1266,7 +1266,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;
@@ -1367,7 +1367,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;
@@ -1401,7 +1401,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;
@@ -1516,7 +1516,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 10b9c4b9b3..88c9c2869f 100644
--- a/libavcodec/jpeg2000.h
+++ b/libavcodec/jpeg2000.h
@@ -34,6 +34,8 @@ 
 #include "avcodec.h"
 #include "mqc.h"
 #include "jpeg2000dwt.h"
+#include "jpeg2000dsp.h"
+#include "bytestream.h"
 
 enum Jpeg2000Markers {
   JPEG2000_SOC = 0xff4f, // start of codestream
@@ -112,7 +114,8 @@  enum Jpeg2000Quantsty { // quantization style
 #define JPEG2000_CSTY_PREC      0x01 // Precincts defined in coding style
 #define JPEG2000_CSTY_SOP       0x02 // SOP marker present
 #define JPEG2000_CSTY_EPH       0x04 // EPH marker present
-
+#define JPEG2000_CTSY_HTJ2K_F   0x40 // Only HT code-blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) are present
+#define JPEG2000_CTSY_HTJ2K_M   0xC0 // HT code blocks (Rec. ITU-T T.814 | ISO/IEC 15444-15) can be present
 // Progression orders
 #define JPEG2000_PGOD_LRCP      0x00  // Layer-resolution level-component-position progression
 #define JPEG2000_PGOD_RLCP      0x01  // Resolution level-layer-component-position progression
@@ -120,6 +123,19 @@  enum Jpeg2000Quantsty { // quantization style
 #define JPEG2000_PGOD_PCRL      0x03  // Position-component-resolution level-layer progression
 #define JPEG2000_PGOD_CPRL      0x04  // Component-position-resolution level-layer progression
 
+#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
+
+// misc constants
+#define JPEG2000_RSIZ_BIT  (1<<14)
+
 typedef struct Jpeg2000T1Context {
     int data[6144];
     uint16_t flags[6156];
@@ -181,6 +197,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;
@@ -188,7 +205,8 @@  typedef struct Jpeg2000Cblk {
     int *data_start;
     Jpeg2000Pass *passes;
     Jpeg2000Layer *layers;
-    int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}}
+    int coord[2][2];       // border coordinates {{x0, x1}, {y0, y1}}
+    int pass_lengths[2];   // Length of each pass
 } Jpeg2000Cblk; // code block
 
 typedef struct Jpeg2000Prec {
@@ -227,6 +245,99 @@  typedef struct Jpeg2000Component {
     uint8_t roi_shift; // ROI scaling value for the component
 } Jpeg2000Component;
 
+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;
+
+    /*Extended capabilities */
+    uint8_t  is_htj2k; // set to 1 to indicate image uses HTJ2K bitstream, 0 otherwise
+
+    uint32_t pcap;
+    uint16_t ccap[32];
+
+    uint16_t *pcpf; //Pcpf_i , found in CPF marker , see section A.6 of HTJ2K spec
+
+} Jpeg2000DecoderContext;
 /* misc tools */
 static inline int ff_jpeg2000_ceildivpow2(int a, int b)
 {
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 92966b11f5..cf492c38e9 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -42,101 +42,8 @@ 
 #include "jpeg2000.h"
 #include "jpeg2000dsp.h"
 #include "profiles.h"
+#include "jpeg2000htdec.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;
 
 /* 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 +276,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,7 +427,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_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");
@@ -626,7 +537,63 @@  static int get_coc(Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *c,
     c->init = 1;
     return 0;
 }
+/* Parse extended capabilities marker */
+static int get_cap(Jpeg2000DecoderContext *s, int len)
+{
+    int pcap_ones; // contains number of set bits in pcap that are equal to 1.
+    int lcap;
+
+    if (len < 8 || len > 70) {
+        // spec requires cap length to be between 8-70
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid CAP length '%d'. Length should be between 8-70\n", len);
+        return AVERROR_INVALIDDATA;
+    }
+
+    s->pcap = bytestream2_get_be32u(&(s->g));
+
+    lcap = (len - 6) / 2;
+    pcap_ones = av_popcount_c(s->pcap);
+
+    if (lcap != pcap_ones) {
+        // according to the spec ,length is the same as number of set bits in pcap header.
+        av_log(s->avctx, AV_LOG_ERROR,
+               "Length of marker`%d` not equal to set bits in Pcap segment(bits set to 1 in Pcap are %d).\n", lcap, pcap_ones);
+        return AVERROR_INVALIDDATA;
+    }
+    /*  According to the spec again Ccapⁱ exists if and only if the ith bit of Pcap is set.
+     *  Since pcap can have 32 bits, we loop until we read all Ccaps'  of set bits
+     *
+     *  Also since the spec addresses Pcap¹ as the most significant bit of 1(31st bit),the
+     *  array also takes that into account, storing at ccap[1] if (Pcap & 1<<31) == 1
+     */
+    for (int i = 1; i < 32; i++)
+        if (s->pcap & (1 << (32 - i)))
+            s->ccap[i] = bytestream2_get_be16u(&(s->g));
+
+    return 0;
+}
+static int get_cpf(Jpeg2000DecoderContext *s, int len)
+{
+    int n;
+
+    if ((len < 4) || (len > 65534)) {
+        av_log(s->avctx, AV_LOG_ERROR, "CPF marker length %d not in range 4-65534", len);
+        return AVERROR_INVALIDDATA;
+    }
 
+    n = (len - 2) / 2;
+
+    s->pcpf = av_calloc(n, sizeof(uint16_t));
+
+    if (!s->pcpf) {
+        av_log(s->avctx, AV_LOG_FATAL, "Out of memory. Cannot reserve space of size %d for Pcpf", n);
+        return AVERROR_BUG;
+    }
+    for (int i = 0; i < n; i++)
+        s->pcpf[i] = bytestream2_get_be16u(&(s->g));
+
+    return 0;
+}
 static int get_rgn(Jpeg2000DecoderContext *s, int n)
 {
     uint16_t compno;
@@ -804,7 +771,6 @@  static int get_poc(Jpeg2000DecoderContext *s, int size, Jpeg2000POC *p)
     return 0;
 }
 
-
 /* Get start of tile segment. */
 static int get_sot(Jpeg2000DecoderContext *s, int n)
 {
@@ -847,7 +813,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));
@@ -962,7 +928,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) {
@@ -1001,7 +967,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);
@@ -1036,9 +1002,9 @@  static int init_tile(Jpeg2000DecoderContext *s, int tileno)
             comp->roi_shift = s->roi_shift[compno];
         if (!codsty->init)
             return AVERROR_INVALIDDATA;
-        if (ret = ff_jpeg2000_init_component(comp, codsty, qntsty,
+        if ((ret = ff_jpeg2000_init_component(comp, codsty, qntsty,
                                              s->cbps[compno], s->cdx[compno],
-                                             s->cdy[compno], s->avctx))
+                                             s->cdy[compno], s->avctx)))
             return ret;
     }
     return 0;
@@ -1071,7 +1037,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;
@@ -1082,7 +1048,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;
@@ -1099,7 +1065,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)
@@ -1148,9 +1114,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;
@@ -1194,9 +1161,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);
@@ -1297,7 +1277,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)
@@ -1588,7 +1568,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;
@@ -1896,7 +1876,7 @@  static void dequantization_int_97(int x, int y, Jpeg2000Cblk *cblk,
     }
 }
 
-static inline void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static inline void mct_decode(Jpeg2000DecoderContext *s, Jpeg2000DecTile *tile)
 {
     int i, csize = 1;
     void *src[3];
@@ -1937,20 +1917,22 @@  static inline void roi_scale_cblk(Jpeg2000Cblk *cblk,
     }
 }
 
-static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile)
+static inline void tile_codeblocks(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;
-
+        t1.stride = (1 << codsty->log2_cblk_width) + 2;
         /* Loop on resolution levels */
         for (reslevelno = 0; reslevelno < codsty->nreslevels2decode; reslevelno++) {
             Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno;
@@ -1975,12 +1957,21 @@  static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
                     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
@@ -1998,6 +1989,7 @@  static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
                             dequantization_int(x, y, cblk, comp, &t1, band);
                    } /* end cblk */
                 } /*end prec */
+                subbandno+=1;
             } /* end band */
         } /* end reslevel */
 
@@ -2009,7 +2001,7 @@  static inline void tile_codeblocks(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile
 }
 
 #define WRITE_FRAME(D, PIXEL)                                                                     \
-    static inline void write_frame_ ## D(Jpeg2000DecoderContext * s, Jpeg2000Tile * tile,         \
+    static inline void write_frame_ ## D(Jpeg2000DecoderContext * s, Jpeg2000DecTile * tile,         \
                                          AVFrame * picture, int precision)                        \
     {                                                                                             \
         const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->avctx->pix_fmt);               \
@@ -2080,7 +2072,7 @@  static int jpeg2000_decode_tile(AVCodecContext *avctx, void *td,
 {
     Jpeg2000DecoderContext *s = avctx->priv_data;
     AVFrame *picture = td;
-    Jpeg2000Tile *tile = s->tile + jobnr;
+    Jpeg2000DecTile *tile = s->tile + jobnr;
 
     tile_codeblocks(s, tile);
 
@@ -2152,9 +2144,30 @@  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 (codsty->cblk_style & JPEG2000_CTSY_HTJ2K_F) {
+                /* Confirm Marker constrains according to Annex A of Rec. ITU-T T.814 | ISO/IEC 15444-15 */
+                // A.2
+                if (!(s->avctx->profile & JPEG2000_RSIZ_BIT)) {
+                    av_log(s->avctx, AV_LOG_ERROR, "Bit 14 of Rsiz is not equal to 1\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                // A.5
+                for (int i = 0; i < 4; i++) {
+                    if (s->roi_shift[i] > 37) {
+                        av_log(s->avctx, AV_LOG_ERROR, "ROI coefficient %d is greater than 37.\n", s->roi_shift[i]);
+                        return AVERROR_INVALIDDATA;
+                    }
+                }
+                // A.3.1
+                if (!(s->pcap & (1 << (17)))) { // 15th MSB of Pcap
+                    av_log(s->avctx, AV_LOG_ERROR, "Bit 15 of Pcap is not equal to 1\n");
+                    return AVERROR_INVALIDDATA;
+                }
+            }
+
             if (!s->tile) {
                 av_log(s->avctx, AV_LOG_ERROR, "Missing SIZ\n");
                 return AVERROR_INVALIDDATA;
@@ -2210,6 +2223,31 @@  static int jpeg2000_read_main_headers(Jpeg2000DecoderContext *s)
             if (!s->tile)
                 s->numXtiles = s->numYtiles = 0;
             break;
+        case JPEG2000_CAP:
+            if (!(s->ncomponents)) {
+                av_log(s->avctx, AV_LOG_ERROR,
+                       "Cannot decode a CAP marker without previously decoding a SIZ marker\n");
+                return AVERROR_INVALIDDATA;
+            }
+            /*
+             * According to the spec decoding a CAP marker is mandatory only if the 14th bit of Rsiz is set to 1.
+             * To indicate the decoder needs to implement extended capabilities to decode the image.
+             * If the bit is not set, we skip over parsing the CAP segment.
+             */
+            if (s->avctx->profile & JPEG2000_RSIZ_BIT) {
+                if (s->in_tile_headers) {
+                    av_log(s->avctx, AV_LOG_ERROR, "CAP marker can only be in main header");
+                    return AVERROR_INVALIDDATA;
+                }
+                ret = get_cap(s, len);
+            } else {
+                av_log(s->avctx, AV_LOG_INFO, "Skipping parsing of the CAP segment");
+                bytestream2_skip(&(s->g), len - 2);
+            }
+            break;
+        case JPEG2000_CPF:
+            ret = get_cpf(s, len);
+            break;
         case JPEG2000_COC:
             ret = get_coc(s, codsty, properties);
             break;
@@ -2302,7 +2340,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..a926e9e933
--- /dev/null
+++ b/libavcodec/jpeg2000htdec.c
@@ -0,0 +1,1228 @@ 
+/*
+ * 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(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.
+
+    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);
+
+    if (bits & 0b1) {
+        jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, 1);
+        return 1;
+    }
+    if (bits & 0b10) {
+        jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, 2);
+        return 2;
+    }
+    jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, 3);
+
+    if (bits & 0b100)
+        return 3;
+    return 5;
+}
+/**
+ * @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.
+    if (suffix < 28)
+        return 0;
+    return jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 4, 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(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(
+    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;
+
+    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;
+
+            if (!is_divisible(q1, c))
+                E_nw[J2K_Q1] = E[4 * (q1 - quad_width) - 1];
+            if (!is_divisible(q2, c))
+                E_nw[J2K_Q2] = E[4 * (q2 - quad_width) - 1];
+
+            if (!is_divisible(q1 + 1, c))
+                E_nf[J2K_Q1] = E[4 * (q1 - quad_width) + 5];
+            if (!is_divisible(q2 + 1, c))
+                E_nf[J2K_Q2] = 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] = 0;
+
+            E_nf[J2K_Q1] = 0;
+
+            if (!is_divisible(q1, c))
+                E_nw[J2K_Q1] = E[4 * (q1 - quad_width) - 1];
+
+            if (!is_divisible(q1 + 1, c))
+                E_nf[J2K_Q1] = 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;
+
+            // set sample
+            sample_buf[j2 + (j1 * width)] = (int32_t)*mu;
+            jpeg2000_modify_state(j1, j2, width, *sigma, block_states);
+
+            sigma += 1;
+            mu += 1;
+
+            if (y != quad_height - 1 || is_border_y == 0) {
+                sample_buf[j2 + ((j1 + 1) * width)] = (int32_t)*mu;
+                jpeg2000_modify_state(j1 + 1, j2, width, *sigma, block_states);
+            }
+
+            sigma += 1;
+            mu += 1;
+
+            if (x != quad_width - 1 || is_border_x == 0) {
+                sample_buf[(j2 + 1) + (j1 * width)] = (int32_t)*mu;
+                jpeg2000_modify_state(j1, j2 + 1, width, *sigma, block_states);
+            }
+
+            sigma += 1;
+            mu += 1;
+
+            if ((y != quad_height - 1 || is_border_y == 0) && (x != quad_width - 1 || is_border_x == 0)) {
+                sample_buf[(j2 + 1) + (j1 + 1) * width] = (int32_t)*mu;
+                jpeg2000_modify_state(j1 + 1, j2 + 1, width, *sigma, 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(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, sign;
+
+    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 * height, 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)];
+            sign = val & 0x80000000;
+            val &= 0x7fffffff;
+            // convert sign-magnitude to twos complement form
+            if (sign)
+                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..9e5692810a
--- /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(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