📄 ebcot_decoder.c
字号:
std_short *cp;
std_int *dcp, *dcpp, dbl_out_of_bounds;
rows = master->height;
cols = master->width;
dcpp = (std_int *)(master->interleaved_context_buffer);
assert((master->interleaved_row_gap & 3) == 0);
d_gap = master->interleaved_row_gap >> 1;
dbl_out_of_bounds = (1<<OUT_OF_BOUNDS_POS);
dbl_out_of_bounds <<= 16;
dbl_out_of_bounds |= (1<<OUT_OF_BOUNDS_POS);
for (; rows > 0; rows -= 4, dcpp+=d_gap)
{
for (dcp=dcpp, c=cols; c > 0; c--)
{ *(dcp++) = 0; *(dcp++) = 0; }
for (c=8; c > 0; c--)
{ *(dcp++) = dbl_out_of_bounds; *(dcp++) = dbl_out_of_bounds; }
}
if (rows < 0)
{ /* One or more rows in the final stripe is out of bounds. */
dcpp -= d_gap;
for (; rows < 0; rows++)
{
cp = ((std_short *) dcpp) + (4+rows);
for (c=cols; c > 0; c--, cp+=4)
*cp = OUT_OF_BOUNDS;
}
}
}
/*****************************************************************************/
/* STATIC prepare_speedup_buffer */
/*****************************************************************************/
static void
prepare_speedup_buffer(block_master_ptr master)
{
int whole_stripes, partial_stripe, r, gap;
int internal_words, extra_words, c;
std_int *sup, *supp, boundary_word;
whole_stripes = master->stripes;
partial_stripe = 0;
if (master->height & 3)
{ whole_stripes--; partial_stripe = 1; }
internal_words = master->width >> 3;
c = master->width - (internal_words<<3);
boundary_word = ((-1)<<(c+9)) & 0x0000FF00;
extra_words = 2; /* Beyond the boundary word. */
gap = master->speed_up_row_gap;
if ((internal_words+extra_words+1) > gap)
extra_words--;
assert((internal_words+extra_words+1) <= gap);
for (supp=master->speed_up_buffer, r=whole_stripes; r > 0; r--, supp+=gap)
{
for (sup=supp, c=internal_words; c > 0; c--)
*(sup++) = 0;
*(sup++) = boundary_word;
for (c=extra_words; c > 0; c--)
*(sup++) = 0x0000FF00;
}
if (partial_stripe)
for (sup=supp, c=internal_words+extra_words+1; c > 0; c--)
*(sup++) = 0x0000FF00;
}
/*****************************************************************************/
/* STATIC consume_segment_marker */
/*****************************************************************************/
static int
consume_segment_marker(block_master_ptr master)
/* Original function by Sarnoff, modified by David Taubman. Returns the
number of verified bits (i.e. 4) if successful, 0 if error resilient
decoding has not been requested, and a large negative number if
an error is detected. */
{
dst_arith_state_ptr state;
std_int areg, code, symbol, n;
unsigned long creg;
int ct;
dst_context_state_ptr csp;
state = &(master->coder_state);
assert(state->mqd.active);
areg = state->mqd.areg; creg = state->mqd.creg; ct = state->mqd.ct;
csp = state->contexts + UNI_OFFSET;
for (code=0, n=3; n >= 0; n--)
{
dst_get_symbol(areg,creg,ct,state,symbol,csp);
code |= (symbol << n);
}
state->mqd.areg = areg; state->mqd.creg = creg; state->mqd.ct = ct;
if (master->min_erkeep_bits > 0)
{
if (code != 0x000A)
return(-1000);
return(4);
}
return(0);
}
/*****************************************************************************/
/* STATIC convert_special_lengths */
/*****************************************************************************/
static void
convert_special_lengths(ebcot_block_info_ptr block)
/* This function processes the `ebcot_pass_info' array of the supplied
code-block to convert the `special_length' field's interpretation as
described in "ebcot_decoder.h" under the definition of `ebcot_pass_info'.
Only at this point will the member code-blocks be ready for decoding by
the `decode_block' function. The function must be called before the
block is actually decoded, but not before the relevant packet has been
recovered from the code-stream and reduced in length as required to
satisfy any simulated parsing constraint. */
{
int layer_bytes, last_layer_bytes, layer_idx;
int idx, scn, have_length, length;
ebcot_pass_info_ptr passes;
assert(!block->special_lengths_converted);
/* First convert the `special_length' fields associated with
terminated passes to refer to the length of the entire
code-stream, rather than the length relative to the last
layer boundary. */
passes = block->passes;
last_layer_bytes = 0;
layer_idx = passes[0].layer_idx;
layer_bytes = passes[0].layer_bytes;
for (idx=0; idx < block->num_passes; idx++)
{
if (layer_idx < (int) passes[idx].layer_idx)
{
last_layer_bytes = layer_bytes;
layer_idx = passes[idx].layer_idx;
layer_bytes += passes[idx].layer_bytes;
}
assert(layer_idx == (int) passes[idx].layer_idx);
if (passes[idx].terminated)
passes[idx].special_length += last_layer_bytes;
}
/* Now fill in the `special_length' fields of all entries in
the `ebcot_pass_info' array to identify the total number of
bytes from the start of the code-stream to the end of the
next termination point. */
length = have_length = 0;
for (idx=0; idx < block->num_passes; idx++)
{
if (!have_length)
{ /* Compute length of current segment. */
length = block->total_bytes;
for (scn=idx; scn < block->num_passes; scn++)
if (passes[scn].terminated)
{
length = passes[scn].special_length;
break;
}
have_length = 1;
}
block->passes[idx].special_length = (std_ushort) length;
if (block->passes[idx].terminated)
have_length = 0;
}
block->special_lengths_converted = 1;
}
/*****************************************************************************/
/* STATIC decode_block_once */
/*****************************************************************************/
static int
decode_block_once(block_master_ptr master, ebcot_band_info_ptr band,
ebcot_block_info_ptr info, int extra_lsbs)
/* This function performs most of the work of the block decoding process,
with the exception of preparatory phases for ROI decoding and
bit-stream byte-order reversal and with the exception of the final
writing of the decoded output buffer to the storage swath used to
serve calls to the `__pull_line' interface function. The reason for
isolating the actual decoding code in a separate function from these
pre- and post-processing stages is three-fold: 1) it should make the
implementation more readable; 2) it eases the construction of accurate
timing loops which measure the time taken to decode the same information
multiple times to decrease measurement jitter; and 3) it simplifies the
implementation of error resilient decoding. The function returns 1 if
successful and 0 if an error was detected during decoding. In the latter
event the function will be called a second time to decode everything up
until the last coding pass which is considered reliable. */
{
int bitplane_idx, last_bitplane, pass_idx, n;
int max_significant_bit_idx, significant;
master->bit_idx = IMPLEMENTATION_PRECISION-2;
max_significant_bit_idx = master->bit_idx - info->insignificant_msbs;
last_bitplane = master->bit_idx - extra_lsbs;
if (extra_lsbs < 1)
{ /* Cannot decode all bit-planes with current implementation precision.
Adjust `last_bitplane' and `info->num_passes'. */
last_bitplane = master->bit_idx-1;
pass_idx = last_bitplane * PASSES_PER_BITPLANE;
if (pass_idx < info->num_passes)
info->num_passes = pass_idx+1;
}
master->height = info->rows;
master->width = info->cols;
master->stripes = (master->height+3)>>2;
memset(master->interleaved_sample_buffer,0,sizeof(ifc_int) *
(size_t)(master->stripes*master->interleaved_row_gap));
/* Get ready for the decoding passes. */
dst_arith_coder__initialize(&(master->coder_state),EBCOT_TOTAL_CONTEXTS,
master->contexts,info->first_unit,
info->total_bytes,
master->error_resilient_termination &&
(master->min_erkeep_bits > 0));
dst_arith_coder__model_init(&(master->coder_state),initial_mq_contexts);
dst_arith_coder__set_segment_size(&(master->coder_state),
info->passes[0].special_length);
#ifdef DST_LOG_SYMBOLS
master->coder_state.symbol_log = start_symbol_log(band,info);
#endif /* DST_LOG_SYMBOLS */
reset_block_contexts(master);
if (master->speed_up_buffer != NULL)
prepare_speedup_buffer(master);
if (master->min_erkeep_bits > 0)
memset(master->incremental_er_bits,0,
sizeof(int)*(size_t) info->num_passes);
master->zc_lut = band->zc_lut;
/* Perform the decoding passes. */
master->first_bit_idx = -1;
for (significant=0, bitplane_idx=0, pass_idx=0;
bitplane_idx <= last_bitplane;
bitplane_idx++, master->bit_idx--)
{
if (pass_idx == info->num_passes)
break;
assert(master->bit_idx > 0);
if (!significant)
{
if (master->bit_idx <= max_significant_bit_idx)
{
significant = 1;
master->first_bit_idx = master->bit_idx;
}
}
for (n=0; n < PASSES_PER_BITPLANE; n++, pass_idx++)
{
block_coding_pass_func pass_function;
if (pass_idx == info->num_passes)
break;
if (significant)
{
int verified_bits;
pass_function = band->pass_funcs[n];
if (master->reset)
dst_arith_coder__model_init(&(master->coder_state),
initial_mq_contexts);
pass_function(master);
verified_bits = 0;
if (master->segmark && (n==0))
verified_bits = consume_segment_marker(master);
if (info->passes[pass_idx].terminated)
{
verified_bits +=
dst_arith_coder__deactivate(&(master->coder_state));
if (pass_idx < (info->num_passes-1))
dst_arith_coder__set_segment_size(&(master->coder_state),
info->passes[pass_idx+1].special_length);
}
if (verified_bits < 0)
{
assert(master->min_erkeep_bits > 0);
info->num_passes = pass_idx;
return(0); /* Error detected. */
}
master->incremental_er_bits[pass_idx] = verified_bits;
}
}
}
dst_arith_coder__terminate(&(master->coder_state));
#ifdef DST_LOG_SYMBOLS
fclose(master->coder_state.symbol_log);
master->coder_state.symbol_log = NULL;
#endif /* DST_LOG_SYMBOLS */
return(1);
}
/*****************************************************************************/
/* STATIC decode_block */
/*****************************************************************************/
static void
decode_block(ebcot_decoder_ref self, ebcot_tile_ptr tile,
ebcot_component_info_ptr comp_info, ifc_int *sample_buffer,
ebcot_band_info_ptr band, ebcot_block_info_ptr info)
/* Decodes a single block of sample values. The actual dimensions of the
block may be found in the `info' structure. The `sample_buffer' array
receives the samples organized in lexicographical fashion, with
consecutive rows of block samples separated by `self->master.row_gap'
samples, which is always larger than the block width. */
{
ebcot_precinct_info_ptr precinct;
block_master_ptr master = &(comp_info->master);
int extra_lsbs, roi_boost_delta, msb_first, n, success, cpu_iterations;
dst_heap_unit_ptr heap;
clock_t cpu_time = 0;
/* Begin DST POC mod */
precinct = info->precinct;
while (precinct->recovered_layers < precinct->max_recoverable_layers)
retrieve_next_packet(self);
/* End DST POC mod */
if (!info->special_lengths_converted)
convert_special_lengths(info);
/* Check ROI information and determine the actual number of extra LSB's. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -