You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-04 22:03:09 +02:00
apv_decode: Multisymbol entropy decode
This commit is contained in:
@ -160,6 +160,7 @@ static int apv_decode_block(AVCodecContext *avctx,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
LOCAL_ALIGNED_32(int16_t, coeff, [64]);
|
LOCAL_ALIGNED_32(int16_t, coeff, [64]);
|
||||||
|
memset(coeff, 0, 64 * sizeof(int16_t));
|
||||||
|
|
||||||
err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);
|
err = ff_apv_entropy_decode_block(coeff, gbc, entropy_state);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@ -216,8 +217,8 @@ static int apv_decode_tile_component(AVCodecContext *avctx, void *data,
|
|||||||
.log_ctx = avctx,
|
.log_ctx = avctx,
|
||||||
.decode_lut = &decode_lut,
|
.decode_lut = &decode_lut,
|
||||||
.prev_dc = 0,
|
.prev_dc = 0,
|
||||||
.prev_dc_diff = 20,
|
.prev_k_dc = 5,
|
||||||
.prev_1st_ac_level = 0,
|
.prev_k_level = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
@ -33,14 +33,39 @@
|
|||||||
#define APV_VLC_LUT_BITS 9
|
#define APV_VLC_LUT_BITS 9
|
||||||
#define APV_VLC_LUT_SIZE (1 << APV_VLC_LUT_BITS)
|
#define APV_VLC_LUT_SIZE (1 << APV_VLC_LUT_BITS)
|
||||||
|
|
||||||
typedef struct APVVLCLUTEntry {
|
typedef struct APVSingleVLCLUTEntry {
|
||||||
uint16_t result; // Return value if not reading more.
|
uint16_t result; // Return value if not reading more.
|
||||||
uint8_t consume; // Number of bits to consume.
|
uint8_t consume; // Number of bits to consume.
|
||||||
uint8_t more; // Whether to read additional bits.
|
uint8_t more; // Whether to read additional bits.
|
||||||
} APVVLCLUTEntry;
|
} APVSingleVLCLUTEntry;
|
||||||
|
|
||||||
|
typedef struct APVMultiVLCLUTEntry {
|
||||||
|
// Number of symbols this bit stream resolves to.
|
||||||
|
uint8_t count;
|
||||||
|
// k_run after decoding all symbols.
|
||||||
|
uint8_t k_run : 2;
|
||||||
|
// k_level after decoding the first level symbol.
|
||||||
|
uint8_t k_level_0 : 3;
|
||||||
|
// k_level after decoding all symbols.
|
||||||
|
uint8_t k_level_1 : 3;
|
||||||
|
// Run output values.
|
||||||
|
uint8_t run[2];
|
||||||
|
// Level output values.
|
||||||
|
int16_t level[2];
|
||||||
|
// Bit index of the end of each code.
|
||||||
|
uint8_t offset[4];
|
||||||
|
} APVMultiVLCLUTEntry;
|
||||||
|
|
||||||
typedef struct APVVLCLUT {
|
typedef struct APVVLCLUT {
|
||||||
APVVLCLUTEntry lut[6][APV_VLC_LUT_SIZE];
|
// Single-symbol LUT for VLCs.
|
||||||
|
// Applies to all coefficients, but used only for DC coefficients
|
||||||
|
// in the decoder.
|
||||||
|
APVSingleVLCLUTEntry single_lut[6][APV_VLC_LUT_SIZE];
|
||||||
|
// Multi-symbol LUT for run/level combinations, decoding up to four
|
||||||
|
// symbols per step. Comes in two versions, which to use depends on
|
||||||
|
// whether the next symbol is a run or a level.
|
||||||
|
APVMultiVLCLUTEntry run_first_lut[3][5][APV_VLC_LUT_SIZE];
|
||||||
|
APVMultiVLCLUTEntry level_first_lut[3][5][APV_VLC_LUT_SIZE];
|
||||||
} APVVLCLUT;
|
} APVVLCLUT;
|
||||||
|
|
||||||
typedef struct APVEntropyState {
|
typedef struct APVEntropyState {
|
||||||
@ -48,33 +73,29 @@ typedef struct APVEntropyState {
|
|||||||
|
|
||||||
const APVVLCLUT *decode_lut;
|
const APVVLCLUT *decode_lut;
|
||||||
|
|
||||||
|
// Previous DC level value.
|
||||||
int16_t prev_dc;
|
int16_t prev_dc;
|
||||||
int16_t prev_dc_diff;
|
// k parameter implied by the previous DC level value.
|
||||||
int16_t prev_1st_ac_level;
|
uint8_t prev_k_dc;
|
||||||
|
// k parameter implied by the previous first AC level value.
|
||||||
|
uint8_t prev_k_level;
|
||||||
} APVEntropyState;
|
} APVEntropyState;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the decoder VLC look-up table.
|
* Build the decoder VLC look-up tables.
|
||||||
*/
|
*/
|
||||||
void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut);
|
void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entropy decode a single 8x8 block to coefficients.
|
* Entropy decode a single 8x8 block to coefficients.
|
||||||
*
|
*
|
||||||
* Outputs in block order (dezigzag already applied).
|
* Outputs nonzero coefficients only to the block row-major order
|
||||||
|
* (dezigzag is applied within the function). The output block
|
||||||
|
* must have been filled with zeroes before calling this function.
|
||||||
*/
|
*/
|
||||||
int ff_apv_entropy_decode_block(int16_t *coeff,
|
int ff_apv_entropy_decode_block(int16_t *restrict coeff,
|
||||||
GetBitContext *gbc,
|
GetBitContext *restrict gbc,
|
||||||
APVEntropyState *state);
|
APVEntropyState *restrict state);
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a single APV VLC code.
|
|
||||||
*
|
|
||||||
* This entrypoint is exposed for testing.
|
|
||||||
*/
|
|
||||||
unsigned int ff_apv_read_vlc(GetBitContext *gbc, int k_param,
|
|
||||||
const APVVLCLUT *lut);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* AVCODEC_APV_DECODE_H */
|
#endif /* AVCODEC_APV_DECODE_H */
|
||||||
|
@ -19,15 +19,55 @@
|
|||||||
#include "apv.h"
|
#include "apv.h"
|
||||||
#include "apv_decode.h"
|
#include "apv_decode.h"
|
||||||
|
|
||||||
|
#include "put_bits.h"
|
||||||
|
|
||||||
|
|
||||||
|
av_always_inline
|
||||||
|
static unsigned int apv_read_vlc(GetBitContext *restrict gbc, int k_param,
|
||||||
|
const APVVLCLUT *restrict lut)
|
||||||
|
{
|
||||||
|
unsigned int next_bits;
|
||||||
|
const APVSingleVLCLUTEntry *ent;
|
||||||
|
|
||||||
|
next_bits = show_bits(gbc, APV_VLC_LUT_BITS);
|
||||||
|
ent = &lut->single_lut[k_param][next_bits];
|
||||||
|
|
||||||
|
if (ent->more) {
|
||||||
|
unsigned int leading_zeroes;
|
||||||
|
|
||||||
|
skip_bits(gbc, ent->consume);
|
||||||
|
|
||||||
|
next_bits = show_bits(gbc, 16);
|
||||||
|
leading_zeroes = 15 - av_log2(next_bits);
|
||||||
|
|
||||||
|
if (leading_zeroes == 0) {
|
||||||
|
// This can't happen mid-stream because the lookup would
|
||||||
|
// have resolved a leading one into a shorter code, but it
|
||||||
|
// can happen if we are hitting the end of the buffer.
|
||||||
|
// Return an invalid code to propagate as an error.
|
||||||
|
return APV_MAX_TRANS_COEFF + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_bits(gbc, leading_zeroes + 1);
|
||||||
|
|
||||||
|
return (2 << k_param) +
|
||||||
|
((1 << leading_zeroes) - 1) * (1 << k_param) +
|
||||||
|
get_bits(gbc, leading_zeroes + k_param);
|
||||||
|
} else {
|
||||||
|
skip_bits(gbc, ent->consume);
|
||||||
|
return ent->result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut)
|
void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut)
|
||||||
{
|
{
|
||||||
const int code_len = APV_VLC_LUT_BITS;
|
const int code_len = APV_VLC_LUT_BITS;
|
||||||
const int lut_size = APV_VLC_LUT_SIZE;
|
const int lut_size = APV_VLC_LUT_SIZE;
|
||||||
|
|
||||||
|
// Build the single-symbol VLC table.
|
||||||
for (int k = 0; k <= 5; k++) {
|
for (int k = 0; k <= 5; k++) {
|
||||||
for (unsigned int code = 0; code < lut_size; code++) {
|
for (unsigned int code = 0; code < lut_size; code++) {
|
||||||
APVVLCLUTEntry *ent = &decode_lut->lut[k][code];
|
APVSingleVLCLUTEntry *ent = &decode_lut->single_lut[k][code];
|
||||||
unsigned int first_bit = code & (1 << code_len - 1);
|
unsigned int first_bit = code & (1 << code_len - 1);
|
||||||
unsigned int remaining_bits = code ^ first_bit;
|
unsigned int remaining_bits = code ^ first_bit;
|
||||||
|
|
||||||
@ -64,153 +104,497 @@ void ff_apv_entropy_build_decode_lut(APVVLCLUT *decode_lut)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
av_always_inline
|
// Build the multi-symbol VLC table.
|
||||||
static unsigned int apv_read_vlc(GetBitContext *gbc, int k_param,
|
for (int start_run = 0; start_run <= 2; start_run++) {
|
||||||
const APVVLCLUT *lut)
|
for (int start_level = 0; start_level <= 4; start_level++) {
|
||||||
{
|
for (unsigned int code = 0; code < lut_size; code++) {
|
||||||
unsigned int next_bits;
|
APVMultiVLCLUTEntry *ent;
|
||||||
const APVVLCLUTEntry *ent;
|
int k_run, k_level;
|
||||||
|
GetBitContext gbc;
|
||||||
|
PutBitContext pbc;
|
||||||
|
uint8_t buffer[16];
|
||||||
|
uint8_t run_first_buffer[16];
|
||||||
|
uint8_t level_first_buffer[16];
|
||||||
|
|
||||||
next_bits = show_bits(gbc, APV_VLC_LUT_BITS);
|
memset(buffer, 0, sizeof(buffer));
|
||||||
ent = &lut->lut[k_param][next_bits];
|
init_put_bits(&pbc, buffer, sizeof(buffer));
|
||||||
|
put_bits(&pbc, APV_VLC_LUT_BITS, code);
|
||||||
|
flush_put_bits(&pbc);
|
||||||
|
|
||||||
if (ent->more) {
|
memcpy(run_first_buffer, buffer, sizeof(buffer));
|
||||||
unsigned int leading_zeroes;
|
memcpy(level_first_buffer, buffer, sizeof(buffer));
|
||||||
|
|
||||||
skip_bits(gbc, ent->consume);
|
k_run = start_run;
|
||||||
|
k_level = start_level;
|
||||||
|
|
||||||
next_bits = show_bits(gbc, 16);
|
ent = &decode_lut->run_first_lut[k_run][k_level][code];
|
||||||
leading_zeroes = 15 - av_log2(next_bits);
|
memset(ent, 0, sizeof(*ent));
|
||||||
|
init_get_bits8(&gbc, run_first_buffer, sizeof(run_first_buffer));
|
||||||
|
|
||||||
if (leading_zeroes == 0) {
|
ent->count = 0;
|
||||||
// This can't happen mid-stream because the lookup would
|
for (int i = 0; i <= 1; i++) {
|
||||||
// have resolved a leading one into a shorter code, but it
|
int value, sign, pos;
|
||||||
// can happen if we are hitting the end of the buffer.
|
|
||||||
// Return an invalid code to propagate as an error.
|
value = apv_read_vlc(&gbc, k_run, decode_lut);
|
||||||
return APV_MAX_TRANS_COEFF + 1;
|
pos = get_bits_count(&gbc);
|
||||||
|
if (pos > APV_VLC_LUT_BITS)
|
||||||
|
break;
|
||||||
|
ent->run[i] = value;
|
||||||
|
ent->offset[ent->count] = pos;
|
||||||
|
++ent->count;
|
||||||
|
k_run = FFMIN(value >> 2, 2);
|
||||||
|
|
||||||
|
value = apv_read_vlc(&gbc, k_level, decode_lut);
|
||||||
|
sign = get_bits1(&gbc);
|
||||||
|
pos = get_bits_count(&gbc);
|
||||||
|
if (pos > APV_VLC_LUT_BITS)
|
||||||
|
break;
|
||||||
|
++value;
|
||||||
|
ent->level[i] = sign ? -value : value;
|
||||||
|
ent->offset[ent->count] = pos;
|
||||||
|
++ent->count;
|
||||||
|
k_level = FFMIN(value >> 2, 4);
|
||||||
|
if (i == 0)
|
||||||
|
ent->k_level_0 = k_level;
|
||||||
|
}
|
||||||
|
if (ent->count > 0 && ent->count < 4)
|
||||||
|
ent->offset[3] = ent->offset[ent->count - 1];
|
||||||
|
ent->k_run = k_run;
|
||||||
|
ent->k_level_1 = k_level;
|
||||||
|
|
||||||
|
k_run = start_run;
|
||||||
|
k_level = start_level;
|
||||||
|
|
||||||
|
ent = &decode_lut->level_first_lut[k_run][k_level][code];
|
||||||
|
memset(ent, 0, sizeof(*ent));
|
||||||
|
init_get_bits8(&gbc, level_first_buffer, sizeof(level_first_buffer));
|
||||||
|
|
||||||
|
ent->count = 0;
|
||||||
|
for (int i = 0; i <= 1; i++) {
|
||||||
|
int value, sign, pos;
|
||||||
|
|
||||||
|
value = apv_read_vlc(&gbc, k_level, decode_lut);
|
||||||
|
sign = get_bits1(&gbc);
|
||||||
|
pos = get_bits_count(&gbc);
|
||||||
|
if (pos > APV_VLC_LUT_BITS)
|
||||||
|
break;
|
||||||
|
++value;
|
||||||
|
ent->level[i] = sign ? -value : value;
|
||||||
|
ent->offset[ent->count] = pos;
|
||||||
|
++ent->count;
|
||||||
|
k_level = FFMIN(value >> 2, 4);
|
||||||
|
if (i == 0)
|
||||||
|
ent->k_level_0 = k_level;
|
||||||
|
|
||||||
|
value = apv_read_vlc(&gbc, k_run, decode_lut);
|
||||||
|
pos = get_bits_count(&gbc);
|
||||||
|
if (pos > APV_VLC_LUT_BITS)
|
||||||
|
break;
|
||||||
|
ent->run[i] = value;
|
||||||
|
ent->offset[ent->count] = pos;
|
||||||
|
++ent->count;
|
||||||
|
k_run = FFMIN(value >> 2, 2);
|
||||||
|
}
|
||||||
|
if (ent->count > 0 && ent->count < 4)
|
||||||
|
ent->offset[3] = ent->offset[ent->count - 1];
|
||||||
|
ent->k_run = k_run;
|
||||||
|
ent->k_level_1 = k_level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_bits(gbc, leading_zeroes + 1);
|
|
||||||
|
|
||||||
return (2 << k_param) +
|
|
||||||
((1 << leading_zeroes) - 1) * (1 << k_param) +
|
|
||||||
get_bits(gbc, leading_zeroes + k_param);
|
|
||||||
} else {
|
|
||||||
skip_bits(gbc, ent->consume);
|
|
||||||
return ent->result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ff_apv_read_vlc(GetBitContext *gbc, int k_param,
|
int ff_apv_entropy_decode_block(int16_t *restrict coeff,
|
||||||
const APVVLCLUT *lut)
|
GetBitContext *restrict gbc,
|
||||||
{
|
APVEntropyState *restrict state)
|
||||||
return apv_read_vlc(gbc, k_param, lut);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ff_apv_entropy_decode_block(int16_t *coeff,
|
|
||||||
GetBitContext *gbc,
|
|
||||||
APVEntropyState *state)
|
|
||||||
{
|
{
|
||||||
const APVVLCLUT *lut = state->decode_lut;
|
const APVVLCLUT *lut = state->decode_lut;
|
||||||
int k_param;
|
int scan_pos;
|
||||||
|
int k_dc = state->prev_k_dc;
|
||||||
|
int k_run, k_level;
|
||||||
|
uint32_t next_bits, lut_bits;
|
||||||
|
const APVMultiVLCLUTEntry *ent;
|
||||||
|
|
||||||
// DC coefficient.
|
// DC coefficient is likely to be large and cannot be usefully
|
||||||
|
// combined with other read steps, so extract it separately.
|
||||||
{
|
{
|
||||||
int abs_dc_coeff_diff;
|
int dc_coeff, abs_diff, sign;
|
||||||
int sign_dc_coeff_diff;
|
|
||||||
int dc_coeff;
|
|
||||||
|
|
||||||
k_param = av_clip(state->prev_dc_diff >> 1, 0, 5);
|
abs_diff = apv_read_vlc(gbc, k_dc, lut);
|
||||||
abs_dc_coeff_diff = apv_read_vlc(gbc, k_param, lut);
|
|
||||||
|
|
||||||
if (abs_dc_coeff_diff > 0)
|
if (abs_diff) {
|
||||||
sign_dc_coeff_diff = get_bits1(gbc);
|
sign = get_bits1(gbc);
|
||||||
else
|
if (sign)
|
||||||
sign_dc_coeff_diff = 0;
|
dc_coeff = state->prev_dc - abs_diff;
|
||||||
|
else
|
||||||
|
dc_coeff = state->prev_dc + abs_diff;
|
||||||
|
} else {
|
||||||
|
dc_coeff = state->prev_dc;
|
||||||
|
}
|
||||||
|
|
||||||
if (sign_dc_coeff_diff)
|
|
||||||
dc_coeff = state->prev_dc - abs_dc_coeff_diff;
|
|
||||||
else
|
|
||||||
dc_coeff = state->prev_dc + abs_dc_coeff_diff;
|
|
||||||
|
|
||||||
if (dc_coeff < APV_MIN_TRANS_COEFF ||
|
if (dc_coeff < APV_MIN_TRANS_COEFF ||
|
||||||
dc_coeff > APV_MAX_TRANS_COEFF) {
|
dc_coeff > APV_MAX_TRANS_COEFF) {
|
||||||
av_log(state->log_ctx, AV_LOG_ERROR,
|
av_log(state->log_ctx, AV_LOG_ERROR,
|
||||||
"Out-of-range DC coefficient value: %d "
|
"Out-of-range DC coefficient value: %d.\n",
|
||||||
"(from prev_dc %d abs_dc_coeff_diff %d sign_dc_coeff_diff %d)\n",
|
dc_coeff);
|
||||||
dc_coeff, state->prev_dc, abs_dc_coeff_diff, sign_dc_coeff_diff);
|
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
coeff[0] = dc_coeff;
|
coeff[0] = dc_coeff;
|
||||||
|
|
||||||
state->prev_dc = dc_coeff;
|
state->prev_dc = dc_coeff;
|
||||||
state->prev_dc_diff = abs_dc_coeff_diff;
|
state->prev_k_dc = FFMIN(abs_diff >> 1, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AC coefficients.
|
// Repeatedly read 18 bits, look up the first half of them in either
|
||||||
|
// the run-first or the level-first table. If the next code is too
|
||||||
|
// long the 18 bits will allow resolving a run code (up to 63)
|
||||||
|
// without reading any more bits, and will allow the exact length
|
||||||
|
// of a level code to be determined. (Note that reusing the
|
||||||
|
// single-symbol LUT is never useful here as the multisymbol lookup
|
||||||
|
// has already determined that the code is too long.)
|
||||||
|
|
||||||
|
// Run a single iteration of the run-first LUT to start, then a
|
||||||
|
// single iteration of the level-first LUT if that only read a
|
||||||
|
// single code. This avoids dealing with the first-AC logic inside
|
||||||
|
// the normal code lookup sequence.
|
||||||
|
|
||||||
|
k_level = state->prev_k_level;
|
||||||
{
|
{
|
||||||
int scan_pos = 1;
|
next_bits = show_bits(gbc, 18);
|
||||||
int first_ac = 1;
|
lut_bits = next_bits >> (18 - APV_VLC_LUT_BITS);
|
||||||
int prev_level = state->prev_1st_ac_level;
|
|
||||||
int prev_run = 0;
|
|
||||||
|
|
||||||
do {
|
ent = &lut->run_first_lut[0][k_level][lut_bits];
|
||||||
int coeff_zero_run;
|
|
||||||
|
|
||||||
k_param = av_clip(prev_run >> 2, 0, 2);
|
if (ent->count == 0) {
|
||||||
coeff_zero_run = apv_read_vlc(gbc, k_param, lut);
|
// One long code.
|
||||||
|
uint32_t bits, low_bits;
|
||||||
|
unsigned int leading_zeroes, low_bit_count, low_bit_shift;
|
||||||
|
int run;
|
||||||
|
|
||||||
if (coeff_zero_run > APV_BLK_COEFFS - scan_pos) {
|
// Remove the prefix bits.
|
||||||
|
bits = next_bits & 0xffff;
|
||||||
|
// Determine code length.
|
||||||
|
leading_zeroes = 15 - av_log2(bits);
|
||||||
|
// Extract the low bits.
|
||||||
|
low_bit_count = leading_zeroes;
|
||||||
|
low_bit_shift = 16 - (1 + 2 * leading_zeroes);
|
||||||
|
low_bits = (bits >> low_bit_shift) & ((1 << low_bit_count) - 1);
|
||||||
|
// Construct run code.
|
||||||
|
run = 2 + ((1 << leading_zeroes) - 1) + low_bits;
|
||||||
|
// Skip over the bits just used.
|
||||||
|
skip_bits(gbc, 2 + leading_zeroes + 1 + low_bit_count);
|
||||||
|
|
||||||
|
scan_pos = run + 1;
|
||||||
|
if (scan_pos >= 64)
|
||||||
|
goto end_of_block;
|
||||||
|
k_run = FFMIN(run >> 2, 2);
|
||||||
|
goto first_level;
|
||||||
|
} else {
|
||||||
|
// One or more short codes starting with a run; if there is
|
||||||
|
// a level code then the length needs to be saved for the
|
||||||
|
// next block.
|
||||||
|
|
||||||
|
scan_pos = ent->run[0] + 1;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[0]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
if (ent->count > 1) {
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[0];
|
||||||
|
++scan_pos;
|
||||||
|
state->prev_k_level = ent->k_level_0;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[1]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 2) {
|
||||||
|
scan_pos += ent->run[1];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[2]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 3) {
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[1];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
k_run = ent->k_run;
|
||||||
|
k_level = ent->k_level_1;
|
||||||
|
if (ent->count == 1)
|
||||||
|
goto first_level;
|
||||||
|
else if (ent->count & 1)
|
||||||
|
goto next_is_level;
|
||||||
|
else
|
||||||
|
goto next_is_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first_level: {
|
||||||
|
next_bits = show_bits(gbc, 18);
|
||||||
|
lut_bits = next_bits >> (18 - APV_VLC_LUT_BITS);
|
||||||
|
|
||||||
|
ent = &lut->level_first_lut[k_run][k_level][lut_bits];
|
||||||
|
|
||||||
|
if (ent->count == 0) {
|
||||||
|
// One long code.
|
||||||
|
uint32_t bits;
|
||||||
|
unsigned int leading_zeroes;
|
||||||
|
int level, abs_level, sign;
|
||||||
|
|
||||||
|
// Remove the prefix bits.
|
||||||
|
bits = next_bits & 0xffff;
|
||||||
|
// Determine code length.
|
||||||
|
leading_zeroes = 15 - av_log2(bits);
|
||||||
|
// Skip the prefix and length bits.
|
||||||
|
skip_bits(gbc, 2 + leading_zeroes + 1);
|
||||||
|
// Read the rest of the code and construct the level.
|
||||||
|
// Include the + 1 offset for nonzero value here.
|
||||||
|
abs_level = (2 << k_level) +
|
||||||
|
((1 << leading_zeroes) - 1) * (1 << k_level) +
|
||||||
|
get_bits(gbc, leading_zeroes + k_level) + 1;
|
||||||
|
|
||||||
|
sign = get_bits(gbc, 1);
|
||||||
|
if (sign)
|
||||||
|
level = -abs_level;
|
||||||
|
else
|
||||||
|
level = abs_level;
|
||||||
|
|
||||||
|
// Check range (not checked in any other case, only a long
|
||||||
|
// code can be out of range).
|
||||||
|
if (level < APV_MIN_TRANS_COEFF ||
|
||||||
|
level > APV_MAX_TRANS_COEFF) {
|
||||||
av_log(state->log_ctx, AV_LOG_ERROR,
|
av_log(state->log_ctx, AV_LOG_ERROR,
|
||||||
"Out-of-range zero-run value: %d (at scan pos %d)\n",
|
"Out-of-range AC coefficient value at %d: %d.\n",
|
||||||
coeff_zero_run, scan_pos);
|
scan_pos, level);
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = level;
|
||||||
|
++scan_pos;
|
||||||
|
k_level = FFMIN(abs_level >> 2, 4);
|
||||||
|
state->prev_k_level = k_level;
|
||||||
|
if (scan_pos >= 64)
|
||||||
|
goto end_of_block;
|
||||||
|
goto next_is_run;
|
||||||
|
|
||||||
for (int i = 0; i < coeff_zero_run; i++) {
|
} else {
|
||||||
coeff[ff_zigzag_direct[scan_pos]] = 0;
|
// One or more short codes.
|
||||||
++scan_pos;
|
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[0];
|
||||||
|
++scan_pos;
|
||||||
|
state->prev_k_level = ent->k_level_0;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[0]);
|
||||||
|
goto end_of_block;
|
||||||
}
|
}
|
||||||
prev_run = coeff_zero_run;
|
if (ent->count > 1) {
|
||||||
|
scan_pos += ent->run[0];
|
||||||
if (scan_pos < APV_BLK_COEFFS) {
|
if (scan_pos >= 64) {
|
||||||
int abs_ac_coeff_minus1;
|
skip_bits(gbc, ent->offset[1]);
|
||||||
int sign_ac_coeff;
|
goto end_of_block;
|
||||||
int level;
|
|
||||||
|
|
||||||
k_param = av_clip(prev_level >> 2, 0, 4);
|
|
||||||
abs_ac_coeff_minus1 = apv_read_vlc(gbc, k_param, lut);
|
|
||||||
sign_ac_coeff = get_bits(gbc, 1);
|
|
||||||
|
|
||||||
if (sign_ac_coeff)
|
|
||||||
level = -abs_ac_coeff_minus1 - 1;
|
|
||||||
else
|
|
||||||
level = abs_ac_coeff_minus1 + 1;
|
|
||||||
|
|
||||||
if (level < APV_MIN_TRANS_COEFF ||
|
|
||||||
level > APV_MAX_TRANS_COEFF) {
|
|
||||||
av_log(state->log_ctx, AV_LOG_ERROR,
|
|
||||||
"Out-of-range AC coefficient value: %d "
|
|
||||||
"(from prev_level %d abs_ac_coeff_minus1 %d sign_ac_coeff %d)\n",
|
|
||||||
level, prev_level, abs_ac_coeff_minus1, sign_ac_coeff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coeff[ff_zigzag_direct[scan_pos]] = level;
|
|
||||||
|
|
||||||
prev_level = abs_ac_coeff_minus1 + 1;
|
|
||||||
if (first_ac) {
|
|
||||||
state->prev_1st_ac_level = prev_level;
|
|
||||||
first_ac = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
++scan_pos;
|
|
||||||
}
|
}
|
||||||
|
if (ent->count > 2) {
|
||||||
} while (scan_pos < APV_BLK_COEFFS);
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[1];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[2]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 3) {
|
||||||
|
scan_pos += ent->run[1];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
k_run = ent->k_run;
|
||||||
|
k_level = ent->k_level_1;
|
||||||
|
if (ent->count & 1)
|
||||||
|
goto next_is_run;
|
||||||
|
else
|
||||||
|
goto next_is_level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
next_is_run: {
|
||||||
|
next_bits = show_bits(gbc, 18);
|
||||||
|
lut_bits = next_bits >> (18 - APV_VLC_LUT_BITS);
|
||||||
|
|
||||||
|
ent = &lut->run_first_lut[k_run][k_level][lut_bits];
|
||||||
|
|
||||||
|
if (ent->count == 0) {
|
||||||
|
// One long code.
|
||||||
|
uint32_t bits, low_bits;
|
||||||
|
unsigned int leading_zeroes, low_bit_count, low_bit_shift;
|
||||||
|
int run;
|
||||||
|
|
||||||
|
// Remove the prefix bits.
|
||||||
|
bits = next_bits & 0xffff;
|
||||||
|
// Determine code length.
|
||||||
|
leading_zeroes = 15 - av_log2(bits);
|
||||||
|
// Extract the low bits.
|
||||||
|
low_bit_count = leading_zeroes + k_run;
|
||||||
|
low_bit_shift = 16 - (1 + 2 * leading_zeroes + k_run);
|
||||||
|
low_bits = (bits >> low_bit_shift) & ((1 << low_bit_count) - 1);
|
||||||
|
// Construct run code.
|
||||||
|
run = (2 << k_run) +
|
||||||
|
((1 << leading_zeroes) - 1) * (1 << k_run) +
|
||||||
|
low_bits;
|
||||||
|
// Skip over the bits just used.
|
||||||
|
skip_bits(gbc, 2 + leading_zeroes + 1 + low_bit_count);
|
||||||
|
|
||||||
|
scan_pos += run;
|
||||||
|
if (scan_pos >= 64)
|
||||||
|
goto end_of_block;
|
||||||
|
k_run = FFMIN(run >> 2, 2);
|
||||||
|
goto next_is_level;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// One or more short codes.
|
||||||
|
|
||||||
|
scan_pos += ent->run[0];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[0]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
if (ent->count > 1) {
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[0];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[1]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 2) {
|
||||||
|
scan_pos += ent->run[1];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[2]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 3) {
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[1];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
k_run = ent->k_run;
|
||||||
|
k_level = ent->k_level_1;
|
||||||
|
if (ent->count & 1)
|
||||||
|
goto next_is_level;
|
||||||
|
else
|
||||||
|
goto next_is_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_is_level: {
|
||||||
|
next_bits = show_bits(gbc, 18);
|
||||||
|
lut_bits = next_bits >> (18 - APV_VLC_LUT_BITS);
|
||||||
|
|
||||||
|
ent = &lut->level_first_lut[k_run][k_level][lut_bits];
|
||||||
|
|
||||||
|
if (ent->count == 0) {
|
||||||
|
// One long code.
|
||||||
|
uint32_t bits;
|
||||||
|
unsigned int leading_zeroes;
|
||||||
|
int level, abs_level, sign;
|
||||||
|
|
||||||
|
// Remove the prefix bits.
|
||||||
|
bits = next_bits & 0xffff;
|
||||||
|
// Determine code length.
|
||||||
|
leading_zeroes = 15 - av_log2(bits);
|
||||||
|
// Skip the prefix and length bits.
|
||||||
|
skip_bits(gbc, 2 + leading_zeroes + 1);
|
||||||
|
// Read the rest of the code and construct the level.
|
||||||
|
// Include the + 1 offset for nonzero value here.
|
||||||
|
abs_level = (2 << k_level) +
|
||||||
|
((1 << leading_zeroes) - 1) * (1 << k_level) +
|
||||||
|
get_bits(gbc, leading_zeroes + k_level) + 1;
|
||||||
|
|
||||||
|
sign = get_bits(gbc, 1);
|
||||||
|
if (sign)
|
||||||
|
level = -abs_level;
|
||||||
|
else
|
||||||
|
level = abs_level;
|
||||||
|
|
||||||
|
// Check range (not checked in any other case, only a long
|
||||||
|
// code can be out of range).
|
||||||
|
if (level < APV_MIN_TRANS_COEFF ||
|
||||||
|
level > APV_MAX_TRANS_COEFF) {
|
||||||
|
av_log(state->log_ctx, AV_LOG_ERROR,
|
||||||
|
"Out-of-range AC coefficient value at %d: %d.\n",
|
||||||
|
scan_pos, level);
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = level;
|
||||||
|
++scan_pos;
|
||||||
|
k_level = FFMIN(abs_level >> 2, 4);
|
||||||
|
if (scan_pos >= 64)
|
||||||
|
goto end_of_block;
|
||||||
|
goto next_is_run;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// One or more short codes.
|
||||||
|
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[0];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[0]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
if (ent->count > 1) {
|
||||||
|
scan_pos += ent->run[0];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[1]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 2) {
|
||||||
|
coeff[ff_zigzag_direct[scan_pos]] = ent->level[1];
|
||||||
|
++scan_pos;
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[2]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->count > 3) {
|
||||||
|
scan_pos += ent->run[1];
|
||||||
|
if (scan_pos >= 64) {
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
goto end_of_block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_bits(gbc, ent->offset[3]);
|
||||||
|
k_run = ent->k_run;
|
||||||
|
k_level = ent->k_level_1;
|
||||||
|
if (ent->count & 1)
|
||||||
|
goto next_is_run;
|
||||||
|
else
|
||||||
|
goto next_is_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end_of_block: {
|
||||||
|
if (scan_pos > 64) {
|
||||||
|
av_log(state->log_ctx, AV_LOG_ERROR,
|
||||||
|
"Block decode reached invalid scan position %d.\n",
|
||||||
|
scan_pos);
|
||||||
|
return AVERROR_INVALIDDATA;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user