1
0
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:
Mark Thompson
2025-05-05 21:04:54 +01:00
parent 9980a0b9b1
commit a3c8fba5da
3 changed files with 536 additions and 130 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}
} }