📄 dst_arith_decoder.c
字号:
/* ------------------------- External Functions ---------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* EXTERN dst_arith_coder__initialize */
/*****************************************************************************/
void
dst_arith_coder__initialize(dst_arith_state_ptr state, int num_contexts,
dst_context_state_ptr contexts,
dst_heap_unit_ptr heap, int total_bytes,
int error_resilient_termination)
{
state->word = state->save_word = 0;
state->current_lsb = 0; /* `word' unloaded. */
state->bytes_in_word = 0;
state->num_contexts = num_contexts;
assert(num_contexts <= DST_ARITH_MAX_CTXTS); /* Fast implementation
depends on this. */
state->contexts = contexts;
state->total_bytes_available = total_bytes;
state->total_bytes_consumed = 0;
state->final_segment_word_consumed = 0;
state->current_segment_bytes = 0;
state->bytes_left_in_segment =
state->total_bytes_available - state->total_bytes_consumed;
/* When the coder is not activated, we assume that all bytes in the
code stream are available, since we have no way of knowing anything
different. Of course, this means that erroneous consumption of raw
bits, say in the lazy mode, may eat into the portion of the
code-stream belonging to the next arithmetically coded segment, which
will cause a lot of errors. Some error resilience might be offered
by providing all the information which is known about segment lengths
including the lengths of raw bit-stream segments, but we do not
complicate the implementation with this for the moment, especially
since in many cases only the lengths of arithmetically coded segments
will actually be known. */
state->heap_head = state->heap_ptr = heap;
state->next_heap_pos = 0;
state->error_resilient_termination = error_resilient_termination;
init_dec(&(state->mqd));
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__model_init */
/*****************************************************************************/
void
dst_arith_coder__model_init(dst_arith_state_ptr state,
dst_context_state_ptr init)
{
dst_context_state_ptr csp1, csp2;
int n;
csp1 = state->contexts;
csp2 = csp1 + DST_ARITH_MAX_CTXTS;
for (n=state->num_contexts; n > 0; n--, csp1++, csp2++, init++)
{
*csp1 = *init;
*csp2 = dst_arith_state_to_delta[*csp1];
}
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__input_word */
/*****************************************************************************/
std_int
dst_arith_coder__input_word(dst_arith_state_ptr state)
{
std_int result;
if (!state->final_segment_word_consumed)
{
int bytes_in_word;
bytes_in_word = state->bytes_in_word;
if (bytes_in_word > state->bytes_left_in_segment)
bytes_in_word = state->bytes_left_in_segment;
state->total_bytes_consumed += bytes_in_word;
state->bytes_left_in_segment -= bytes_in_word;
}
if (state->bytes_left_in_segment == 0)
{ /* Do not consume anything. Just pad with a full word of FF's. */
state->total_bytes_consumed += state->bytes_left_in_segment;
state->bytes_left_in_segment = 0;
state->final_segment_word_consumed = 1;
state->bytes_in_word = 0;
return((std_int)(-1));
}
result = state->save_word =
state->heap_ptr->words[state->next_heap_pos++];
if (state->next_heap_pos == DST_HEAP_WORDS)
{
state->heap_ptr = state->heap_ptr->next;
state->next_heap_pos = 0;
}
state->bytes_in_word = 4;
if (state->bytes_left_in_segment < state->bytes_in_word)
{
std_int trailing_ffs;
trailing_ffs = state->bytes_in_word - state->bytes_left_in_segment;
trailing_ffs <<= 3;
trailing_ffs = ~(((std_int)(-1)) << trailing_ffs);
result |= trailing_ffs;
}
return(result);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__set_segment_size */
/*****************************************************************************/
void
dst_arith_coder__set_segment_size(dst_arith_state_ptr state,
int terminating_byte_count)
{
assert((!state->mqd.active) && ((state->current_lsb & 7) == 0));
assert(state->total_bytes_consumed <= terminating_byte_count);
assert(terminating_byte_count <= state->total_bytes_available);
/* Now set the new segment size and load the various state variables
accordingly. */
state->bytes_left_in_segment = state->current_segment_bytes =
terminating_byte_count - state->total_bytes_consumed;
if (state->bytes_left_in_segment < state->bytes_in_word)
{
std_int trailing_ffs;
trailing_ffs = state->bytes_in_word - state->bytes_left_in_segment;
trailing_ffs <<= 3;
trailing_ffs = ~(((std_int)(-1)) << trailing_ffs);
state->word |= trailing_ffs;
}
state->final_segment_word_consumed = 0;
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__activate */
/*****************************************************************************/
void
dst_arith_coder__activate(dst_arith_state_ptr state)
{
state->current_lsb &= ~7; /* Byte align code stream. */
state->mqd.active = 1;
dec_preload(state,&(state->mqd));
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__deactivate */
/*****************************************************************************/
int
dst_arith_coder__deactivate(dst_arith_state_ptr state)
{
int num_er_bits;
num_er_bits = 0;
if (!state->mqd.active)
{
if (state->error_resilient_termination)
num_er_bits = check_raw_erterm_bits(state);
state->current_lsb &= ~7;
}
while (state->bytes_left_in_segment > 0)
dst_arith_coder__input_word(state);
/* Correct `total_bytes_consumed' and `bytes_left_in_segment' values and
also restore the `word' state variable in preparation for further
consumption. */
assert((state->current_lsb & 7) == 0);
if (!state->final_segment_word_consumed)
{
int bytes_in_word;
bytes_in_word = state->bytes_in_word;
bytes_in_word -= state->current_lsb >> 3;
if (bytes_in_word > state->bytes_left_in_segment)
bytes_in_word = state->bytes_left_in_segment;
state->total_bytes_consumed += bytes_in_word;
state->bytes_left_in_segment -= bytes_in_word;
}
assert(state->bytes_left_in_segment == 0);
state->word = state->save_word;
state->bytes_in_word = (4-state->total_bytes_consumed) & 3;
state->current_lsb = state->bytes_in_word << 3;
/* Reset the arithmetic coder state and set a default segment length
for further raw or arithmetic decoding operations in which the segment
length is not explicitly signalled. */
if (state->mqd.active)
{
if (state->error_resilient_termination)
{
std_int last_byte;
last_byte = (state->word >> (state->bytes_in_word<<3)) & 0x00FF;
num_er_bits = check_mq_erterm_bits(state,last_byte);
}
state->mqd.active = 0;
init_dec(&(state->mqd));
}
dst_arith_coder__set_segment_size(state,state->total_bytes_available);
if (num_er_bits < 0)
num_er_bits = -1000;
return(num_er_bits);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__bytein */
/*****************************************************************************/
unsigned long
dst_arith_coder__bytein(unsigned long creg, int *ct,
dst_arith_state_ptr state)
{
assert(state->mqd.active);
if(state->mqd.buffer != (LONG_FF << S_DR_B_NML))
{
creg += state->mqd.buffer;
get_byte(state);
*ct = state->mqd.nextct;
state->mqd.nextct = NEXTBITS_NML;
state->mqd.buffer <<= S_DR_B_NML;
}
else
{ /* FF */
get_byte(state);
creg += LONG_FF << S_DR_B_NML;
*ct = state->mqd.nextct; /*NEXTBITS_NML*/
state->mqd.nextct = NEXTBITS_BS;
if (state->mqd.buffer == 0x00FF)
{
state->mqd.converted_doublets++;
state->mqd.buffer = 0x007F; /* General marker detection method will
have same effect in practice. */
}
state->mqd.buffer <<= S_DR_B_BS;
}
return(creg);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__terminate (Mitsubishi) */
/*****************************************************************************/
void
dst_arith_coder__terminate(dst_arith_state_ptr state)
{
state->mqd.active = 0;
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__check_logged_symbol */
/*****************************************************************************/
#ifdef DST_LOG_SYMBOLS
void
dst_arith_coder__check_logged_symbol(dst_arith_state_ptr state,
dst_context_state_ptr ctxt,
std_int symbol) /* David T mod */
{
int val, check_val;
if(state->symbol_log == NULL)
return;
if (ctxt == NULL)
val = 255;
else
val = ctxt - state->contexts;
check_val = getc(state->symbol_log);
if (val != check_val)
assert(val == check_val);
val = (symbol)?1:0;
check_val = getc(state->symbol_log);
if (val != check_val)
assert(val == check_val);
}
#endif /* DST_LOG_SYMBOLS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -