FFmpeg/libavcodec/jpeg2000htdec.c
Andreas Rheinhardt 790f793844 avutil/common: Don't auto-include mem.h
There are lots of files that don't need it: The number of object
files that actually need it went down from 2011 to 884 here.

Keep it for external users in order to not cause breakages.

Also improve the other headers a bit while just at it.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2024-03-31 00:08:43 +01:00

1475 lines
65 KiB
C

/*
* 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
*/
/*
* Copyright 2019 - 2021, Osamu Watanabe
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include "libavutil/attributes.h"
#include "libavutil/common.h"
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
#include "jpeg2000htdec.h"
#include "jpeg2000.h"
#include "jpeg2000dec.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
/* See Rec. ITU-T T.800, Table 2 */
const static uint8_t mel_e[13] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5 };
static const uint16_t dec_cxt_vlc_table1[1024];
static const uint16_t dec_cxt_vlc_table0[1024];
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;
/**
* Given a precomputed c, checks whether n % d == 0. c is precomputed from d
* using precompute_c().
*/
av_always_inline
static uint32_t is_divisible(uint32_t n, uint64_t c)
{
return n * c <= c - 1;
}
/**
* Precompute the number c used by is_divisible().
*/
av_always_inline
static uint64_t precompute_c(uint32_t d)
{
return 1 + (0xffffffffffffffffull / d);
}
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;
}
/**
* 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 - 4;
uint32_t new_bits = 32;
if (buffer->bits_left >= 32)
return 0; // enough data, no need to pull in more bits
/**
* Unstuff bits. Load a temporary byte, which precedes the position we
* currently at, to ensure that we can also un-stuff if the stuffed bit is
* the bottom most bits.
*/
for(int i = FFMAX(0, position + 1); i <= buffer->pos + 1; i++)
tmp = 256*tmp + array[i];
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--;
}
tmp >>= 8; // Remove temporary byte loaded
/* 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;
}
/**
* 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;
}
}
/**
* Drops bits from lower bits in the bit buffer. buf contains the bit buffers.
* nbits is the number of bits to remove.
*/
av_always_inline
static void jpeg2000_bitbuf_drop_bits_lsb(StateVars *buf, uint8_t nbits)
{
av_assert2(buf->bits_left >= nbits); // cannot read more bits than available
buf->bit_buf >>= nbits;
buf->bits_left -= nbits;
}
/**
* 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.
*/
av_always_inline
static 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;
}
/**
* 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.
*/
av_always_inline
static 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;
}
/**
* Look ahead bit buffer without discarding bits.
*/
av_always_inline
static uint64_t jpeg2000_bitbuf_peek_bits_lsb(StateVars *stream, uint8_t nbits)
{
uint64_t mask = (1ull << nbits) - 1;
return stream->bit_buf & mask;
}
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. See Rec. ITU-T T.814, 7.3.5.
*/
av_always_inline
static int jpeg2000_decode_ctx_vlc(const Jpeg2000DecoderContext *s,
StateVars *vlc_stream, const uint16_t *table,
const uint8_t *Dcup, uint8_t *sig_pat,
uint8_t *res_off, uint8_t *emb_pat_k,
uint8_t *emb_pat_1, uint8_t pos,
uint32_t Pcup, uint16_t context)
{
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);
av_assert0(index < 1024); // The CxtVLC table has 1024 entries.
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;
}
/**
* Decode variable length u-vlc prefix. See decodeUPrefix procedure at Rec.
* ITU-T T.814, 7.3.6.
*/
av_always_inline
static uint8_t vlc_decode_u_prefix(StateVars *vlc_stream, const uint8_t *refill_array)
{
static const uint8_t return_value[8] = { 5, 1, 2, 1, 3, 1, 2, 1 };
static const uint8_t drop_bits[8] = { 3, 1, 2, 1, 3, 1, 2, 1 };
uint8_t bits;
if (vlc_stream->bits_left < 3)
jpeg2000_bitbuf_refill_backwards(vlc_stream, refill_array);
bits = jpeg2000_bitbuf_peek_bits_lsb(vlc_stream, 3);
jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[bits]);
return return_value[bits];
}
/**
* Decode variable length u-vlc suffix. See decodeUSuffix procedure at Rec.
* ITU-T T.814, 7.3.6.
*/
av_always_inline
static uint8_t vlc_decode_u_suffix(StateVars *vlc_stream, uint8_t suffix,
const uint8_t *refill_array)
{
static const int mask[] = { 1, 31 };
static const int drop_bits[] = { 1, 5 };
uint8_t bits;
int cond = suffix != 3;
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);
jpeg2000_bitbuf_drop_bits_lsb(vlc_stream, drop_bits[cond]);
return bits & mask[cond];
}
/**
* Decode u-vlc extension values. See decodeUExtension procedure at Rec. ITU-T
* T.814, 7.3.6.
*/
av_always_inline
static uint8_t vlc_decode_u_extension(StateVars *vlc_stream, uint8_t suffix,
const uint8_t *refill_array)
{
return jpeg2000_bitbuf_get_bits_lsb(vlc_stream, 4 * (suffix >= 28), refill_array);
}
/**
* Magnitude and Sign decode procedures. See decodeMagSgnValue procedure at Rec.
* ITU-T T.814, 7.3.8.
*/
av_always_inline
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)
{
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;
}
av_always_inline
static 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.
}
}
}
static int jpeg2000_import_bit(StateVars *stream, const uint8_t *array, uint32_t length)
{
int cond = stream->pos <= length;
int pos = FFMIN(stream->pos, length);
if (stream->bits == 0) {
stream->bits = (stream->tmp == 0xFF) ? 7 : 8;
stream->pos += cond;
stream->tmp = cond ? array[pos] : 0xFF;
}
stream->bits -= 1;
return (stream->tmp >> stream->bits) & 1;
}
static int jpeg2000_peek_bit(StateVars *stream, const uint8_t *array, uint32_t length)
{
if (stream->bits == 0) {
int cond = stream->pos <= length;
int pos = FFMIN(stream->pos, length);
stream->bits = (stream->tmp == 0xFF) ? 7 : 8;
stream->pos += cond;
stream->tmp = cond ? array[pos] : 0xFF;
}
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.
*/
av_always_inline
static int jpeg2000_import_magref_bit(StateVars *stream, const uint8_t *array,
uint32_t length)
{
return jpeg2000_bitbuf_get_bits_lsb(stream, 1, array);
}
/**
* Signal EMB decode.
*/
static int jpeg2000_decode_sig_emb(const Jpeg2000DecoderContext *s, MelDecoderState *mel_state,
StateVars *mel_stream, StateVars *vlc_stream,
const uint16_t *vlc_table, const uint8_t *Dcup,
uint8_t *sig_pat, uint8_t *res_off, uint8_t *emb_pat_k,
uint8_t *emb_pat_1, uint8_t pos, uint16_t context,
uint32_t Lcup, uint32_t Pcup)
{
if (context == 0) {
uint8_t sym;
sym = jpeg2000_decode_mel_sym(mel_state, mel_stream, Dcup, Lcup);
if (sym == 0) {
sig_pat[pos] = 0;
res_off[pos] = 0;
emb_pat_k[pos] = 0;
emb_pat_1[pos] = 0;
return 0;
}
}
return jpeg2000_decode_ctx_vlc(s, vlc_stream, vlc_table, Dcup, sig_pat,
res_off, emb_pat_k, emb_pat_1, pos, Pcup,
context);
}
av_always_inline
static 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;
}
av_always_inline
static 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;
}
av_always_inline
static int jpeg2000_decode_ht_cleanup_segment(const Jpeg2000DecoderContext *s,
Jpeg2000Cblk *cblk, Jpeg2000T1Context *t1,
MelDecoderState *mel_state,
StateVars *mel_stream, StateVars *vlc_stream,
StateVars *mag_sgn_stream, const uint8_t *Dcup,
uint32_t Lcup, uint32_t Pcup, uint8_t pLSB,
int width, int height, int32_t *sample_buf,
uint8_t *block_states)
{
uint16_t q = 0; // Represents current quad position
uint16_t q1, q2;
uint16_t context1, context2;
uint16_t context = 0;
uint8_t sig_pat[2] = { 0 }; // significance pattern
uint8_t res_off[2] = { 0 }; // residual offset
uint8_t emb_pat_k[2] = { 0 }; // exponent Max Bound pattern K
uint8_t emb_pat_1[2] = { 0 }; // exponent Max Bound pattern 1
uint8_t gamma[2] = { 0 };
uint8_t E_n[2] = { 0 };
uint8_t E_ne[2] = { 0 };
uint8_t E_nw[2] = { 0 };
uint8_t E_nf[2] = { 0 };
uint8_t max_e[2] = { 0 };
uint8_t u_pfx[2] = { 0 };
uint8_t u_sfx[2] = { 0 };
uint8_t u_ext[2] = { 0 };
int32_t u[2] = { 0 };
int32_t U[2] = { 0 }; // exponent bound
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, *sigma_n, *E;
uint32_t *mu, *mu_n;
const uint8_t *vlc_buf = Dcup + Pcup;
/*
* Bound on the precision needed to process the codeblock. The number of
* decoded bit planes is equal to at most cblk->zbp + 2 since S_blk = P if
* there are no placeholder passes or HT Sets and P = cblk->zbp. See Rec.
* ITU-T T.814, 7.6.
*/
int maxbp = cblk->zbp + 2;
/* convert to raster-scan */
const uint16_t is_border_x = width % 2;
const uint16_t is_border_y = height % 2;
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;
/* do we have enough precision, assuming a 32-bit decoding path */
if (maxbp >= 32)
return AVERROR_INVALIDDATA;
sigma_n = av_calloc(buf_size, sizeof(uint8_t));
E = av_calloc(buf_size, sizeof(uint8_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_cxt_vlc_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_cxt_vlc_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);
}
/* See Rec. ITU-T T.814, 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];
if (U[J2K_Q1] > maxbp || U[J2K_Q2] > maxbp) {
ret = AVERROR_INVALIDDATA;
goto free;
}
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);
q += 2; // Move to the next quad pair
}
if (quad_width % 2 == 1) {
q1 = q;
if ((ret = jpeg2000_decode_sig_emb(s, mel_state, mel_stream, vlc_stream,
dec_cxt_vlc_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];
if (U[J2K_Q1] > maxbp) {
ret = AVERROR_INVALIDDATA;
goto free;
}
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 [1].
*
* [1]
* 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 the spec doesn't allow a quad being zero, so we
* error out early in case that's the case.
*/
c = precompute_c(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_cxt_vlc_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_cxt_vlc_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] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)];
E_nw[J2K_Q2] = (!is_divisible(q2, c)) * E[FFMAX((4 * (q2 - quad_width) - 1), 0)];
E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5];
E_nf[J2K_Q2] = (!is_divisible(q2 + 1, c)) * E[4 * (q2 - quad_width) + 5];
max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1]));
max_e[J2K_Q2] = FFMAX(E_nw[J2K_Q2], FFMAX3(E_n[J2K_Q2], E_ne[J2K_Q2], E_nf[J2K_Q2]));
kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1));
kappa[J2K_Q2] = FFMAX(1, gamma[J2K_Q2] * (max_e[J2K_Q2] - 1));
U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
U[J2K_Q2] = kappa[J2K_Q2] + u[J2K_Q2];
if (U[J2K_Q1] > maxbp || U[J2K_Q2] > maxbp) {
ret = AVERROR_INVALIDDATA;
goto free;
}
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);
q += 2; // Move to the next quad pair
}
if (quad_width % 2 == 1) {
q1 = q;
/* calculate context for current quad */
context1 = sigma_n[4 * (q1 - quad_width) + 1];
context1 += (sigma_n[4 * (q1 - quad_width) + 3] << 2);
if (!is_divisible(q1, c)) {
context1 |= sigma_n[4 * (q1 - quad_width) - 1];
context1 += (sigma_n[4 * q1 - 1] | sigma_n[4 * q1 - 2]) << 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_cxt_vlc_table1, Dcup, sig_pat, res_off,
emb_pat_k, emb_pat_1, J2K_Q1, context1, Lcup,
Pcup)) < 0)
goto free;
for (int i = 0; i < 4; i++)
sigma_n[4 * q1 + i] = (sig_pat[J2K_Q1] >> i) & 1;
u[J2K_Q1] = 0;
/* Recover mag_sgn value */
if (res_off[J2K_Q1] == 1) {
u_pfx[J2K_Q1] = vlc_decode_u_prefix(vlc_stream, vlc_buf);
u_sfx[J2K_Q1] = vlc_decode_u_suffix(vlc_stream, u_pfx[J2K_Q1], vlc_buf);
u_ext[J2K_Q1] = vlc_decode_u_extension(vlc_stream, u_sfx[J2K_Q1], vlc_buf);
u[J2K_Q1] = u_pfx[J2K_Q1] + u_sfx[J2K_Q1] + (u_ext[J2K_Q1] << 2);
}
sp = sig_pat[J2K_Q1];
gamma[J2K_Q1] = 1;
if (sp == 0 || sp == 1 || sp == 2 || sp == 4 || sp == 8)
gamma[J2K_Q1] = 0;
E_n[J2K_Q1] = E[4 * (q1 - quad_width) + 1];
E_ne[J2K_Q1] = E[4 * (q1 - quad_width) + 3];
E_nw[J2K_Q1] = (!is_divisible(q1, c)) * E[FFMAX((4 * (q1 - quad_width) - 1), 0)];
E_nf[J2K_Q1] = (!is_divisible(q1 + 1, c)) * E[4 * (q1 - quad_width) + 5];
max_e[J2K_Q1] = FFMAX(E_nw[J2K_Q1], FFMAX3(E_n[J2K_Q1], E_ne[J2K_Q1], E_nf[J2K_Q1]));
kappa[J2K_Q1] = FFMAX(1, gamma[J2K_Q1] * (max_e[J2K_Q1] - 1));
U[J2K_Q1] = kappa[J2K_Q1] + u[J2K_Q1];
if (U[J2K_Q1] > maxbp) {
ret = AVERROR_INVALIDDATA;
goto free;
}
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 += 1;
}
}
// convert to raster-scan
for (int y = 0; y < quad_height; y++) {
for (int x = 0; x < quad_width; x++) {
int j1, j2;
int x1, x2 , x3;
j1 = 2 * y;
j2 = 2 * x;
sample_buf[j2 + (j1 * width)] = (int32_t)*mu;
jpeg2000_modify_state(j1, j2, width, *sigma, block_states);
sigma += 1;
mu += 1;
x1 = y != quad_height - 1 || is_border_y == 0;
sample_buf[j2 + ((j1 + 1) * width)] = ((int32_t)*mu) * x1;
jpeg2000_modify_state(j1 + 1, j2, width, (*sigma) * x1, block_states);
sigma += 1;
mu += 1;
x2 = x != quad_width - 1 || is_border_x == 0;
sample_buf[(j2 + 1) + (j1 * width)] = ((int32_t)*mu) * x2;
jpeg2000_modify_state(j1, j2 + 1, width, (*sigma) * x2, block_states);
sigma += 1;
mu += 1;
x3 = x1 | x2;
sample_buf[(j2 + 1) + (j1 + 1) * width] = ((int32_t)*mu) * x3;
jpeg2000_modify_state(j1 + 1, j2 + 1, width, (*sigma) * x3, block_states);
sigma += 1;
mu += 1;
}
}
ret = 1;
free:
av_freep(&sigma_n);
av_freep(&E);
av_freep(&mu_n);
return ret;
}
static void jpeg2000_calc_mbr(uint8_t *mbr, const uint16_t i, const uint16_t j,
const uint32_t mbr_info, uint8_t causal_cond,
uint8_t *block_states, int width)
{
int local_mbr = 0;
local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SIGMA, block_states);
local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_SIGMA, block_states);
local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SIGMA, block_states);
local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SIGMA, block_states);
local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SIGMA, block_states);
local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SIGMA, block_states) * causal_cond;
local_mbr |= jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states);
local_mbr |= jpeg2000_get_state(i - 1, j + 0, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i - 1, j - 1, width, HT_SHIFT_SCAN, block_states);
local_mbr |= jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i - 1, j + 1, width, HT_SHIFT_SCAN, block_states);
local_mbr |= jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i + 0, j - 1, width, HT_SHIFT_SCAN, block_states);
local_mbr |= jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i + 0, j + 1, width, HT_SHIFT_SCAN, block_states);
local_mbr |= jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i + 1, j - 1, width, HT_SHIFT_SCAN, block_states) * causal_cond;
local_mbr |= jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i + 1, j + 0, width, HT_SHIFT_SCAN, block_states) * causal_cond;
local_mbr |= jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_REF, block_states) *
jpeg2000_get_state(i + 1, j + 1, width, HT_SHIFT_SCAN, block_states) * causal_cond;
*mbr |= local_mbr;
}
static void jpeg2000_process_stripes_block(StateVars *sig_prop, int i_s, int j_s,
int width, int height, int stride, int pLSB,
int32_t *sample_buf, uint8_t *block_states,
uint8_t *magref_segment, uint32_t magref_length)
{
for (int j = j_s; j < j_s + width; j++) {
uint32_t mbr_info = 0;
for (int i = i_s; i < i_s + height; i++) {
int modify_state, cond;
uint8_t bit;
uint8_t causal_cond = i != (i_s + height - 1);
int32_t *sp = &sample_buf[j + (i * (stride - 2))];
uint8_t mbr = 0;
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;
cond = mbr != 0;
bit = jpeg2000_peek_bit(sig_prop, magref_segment, magref_length);
*sp |= (bit * cond) << pLSB;
sig_prop->bits -= cond;
modify_state = (((1 << HT_SHIFT_REF_IND) | (1 << HT_SHIFT_REF)) * cond) | 1 << HT_SHIFT_SCAN;
jpeg2000_modify_state(i, j, stride - 2, modify_state, block_states);
}
}
}
/**
* See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.4.
*/
av_noinline
static void jpeg2000_decode_sigprop_segment(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)
{
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);
}
/**
* See procedure decodeSigPropMag at Rec. ITU-T T.814, 7.5.
*/
static int
jpeg2000_decode_magref_segment( 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)
{
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
* Rec. ITU-T T.814, 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
ff_jpeg2000_decode_htj2k(const Jpeg2000DecoderContext *s, Jpeg2000CodingStyle *codsty, Jpeg2000T1Context *t1, Jpeg2000Cblk *cblk,
int width, int height, int magp, uint8_t roi_shift)
{
uint8_t p0 = 0; // Number of placeholder passes
uint32_t Lcup; // Length of HT cleanup segment
uint32_t Lref; // Length of Refinement segment
uint32_t Scup; // HT cleanup segment suffix length
uint32_t Pcup; // HT cleanup segment prefix length
uint8_t S_blk; // Number of skipped magnitude bitplanes
uint8_t pLSB;
uint8_t *Dcup; // Byte of an HT cleanup segment
uint8_t *Dref; // Byte of an HT refinement segment
int z_blk; // Number of ht coding pass
uint8_t empty_passes;
StateVars mag_sgn; // Magnitude and Sign
StateVars mel; // Adaptive run-length coding
StateVars vlc; // Variable Length coding
StateVars sig_prop; // Significance propagation
MelDecoderState mel_state;
int ret;
/* Temporary buffers */
int32_t *sample_buf = NULL;
uint8_t *block_states = NULL;
int32_t n, val; // Post-processing
int32_t M_b = magp;
/* codeblock size as constrained by Rec. ITU-T T.800, Table A.18 */
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)
p0 = 0;
else if (cblk->length == 0)
p0 = 1;
empty_passes = p0 * 3;
z_blk = cblk->npasses - empty_passes;
if (z_blk <= 0)
return 0; // No passes within this set, continue
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 = cblk->data + Lcup; // Dref comes after the refinement segment
S_blk = p0 + cblk->zbp;
pLSB = 30 - S_blk;
Scup = (Dcup[Lcup - 1] << 4) + (Dcup[Lcup - 2] & 0x0F);
if (Scup < 2 || Scup > Lcup || Scup > 4079) {
av_log(s->avctx, AV_LOG_ERROR, "Cleanup pass suffix length is invalid %d\n",
Scup);
ret = AVERROR_INVALIDDATA;
goto free;
}
Pcup = Lcup - Scup;
/* modDcup shall be done before the creation of vlc instance. */
Dcup[Lcup - 1] = 0xFF;
Dcup[Lcup - 2] |= 0x0F;
/* Magnitude and refinement */
jpeg2000_init_zero(&mag_sgn);
jpeg2000_bitbuf_refill_forward(&mag_sgn, Dcup, Pcup);
/* Significance propagation */
jpeg2000_init_zero(&sig_prop);
/* Adaptive run length */
jpeg2000_init_mel(&mel, Pcup);
/* Variable Length coding */
jpeg2000_init_vlc(&vlc, Lcup, Pcup, Dcup);
jpeg2000_init_mel_decoder(&mel_state);
sample_buf = av_calloc((width + 4) * (height + 4), sizeof(int32_t));
block_states = av_calloc((width + 4) * (height + 4), sizeof(uint8_t));
if (!sample_buf || !block_states) {
ret = AVERROR(ENOMEM);
goto free;
}
if ((ret = jpeg2000_decode_ht_cleanup_segment(s, cblk, t1, &mel_state, &mel, &vlc,
&mag_sgn, Dcup, Lcup, Pcup, pLSB, width,
height, sample_buf, block_states)) < 0) {
av_log(s->avctx, AV_LOG_ERROR, "Bad HT cleanup segment\n");
goto free;
}
if (cblk->npasses > 1)
jpeg2000_decode_sigprop_segment(cblk, width, height, Dref, Lref,
pLSB - 1, sample_buf, block_states);
if (cblk->npasses > 2) {
if (Lref < 2){
av_log(s->avctx,AV_LOG_ERROR,"Invalid magnitude refinement length\n");
ret = AVERROR_INVALIDDATA;
goto free;
}
if ((ret = jpeg2000_decode_magref_segment(width, height, Dref, Lref,
pLSB - 1, sample_buf, block_states)) < 0)
goto free;
}
pLSB = 31 - M_b;
/* Reconstruct the sample values */
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
n = x + (y * t1->stride);
val = sample_buf[x + (y * width)];
/* Convert sign-magnitude to two's complement. */
val = val >> 31 ? 0x80000000 - val : val;
val >>= (pLSB - 1);
t1->data[n] = val;
}
}
free:
av_freep(&sample_buf);
av_freep(&block_states);
return ret;
}
/**
* CtxVLC tables (see Rec. ITU-T T.800, Annex C) as found at
* https://github.com/osamu620/OpenHTJ2K (author: Osamu Watanabe)
*/
static const uint16_t dec_cxt_vlc_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_cxt_vlc_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};