📄 dst_arith_encoder.c
字号:
state->word = 0;
dst_arith_coder__output_word(state,state->word);
}
state->mqe.num_preceding_bytes =
(state->saved_words << 2) + ((32-state->current_lsb)>>3);
/* Set active flags. */
assert(!state->mqe.active);
state->mqe.active = 1;
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__output_word */
/*****************************************************************************/
void
dst_arith_coder__output_word(dst_arith_state_ptr state, std_int word)
/* Outputs a word to the code word heap. */
{
int pos;
pos = state->next_heap_pos;
state->heap->words[pos++] = word;
state->saved_words++;
if (pos == DST_HEAP_WORDS)
{
dst_heap_unit_ptr elt;
pos = 0;
elt = state->code_heap_mgr->get_unit(state->code_heap_mgr);
elt->next = NULL;
state->heap = state->heap->next = elt;
}
state->next_heap_pos = pos;
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__byteout */
/*****************************************************************************/
std_int
dst_arith_coder__byteout(std_int creg, std_short *ct,
dst_arith_state_ptr state)
{
assert(state->mqe.active);
if (state->mqe.have_unsent_ff)
{
put_byte(state,LONG_FF);
state->mqe.have_unsent_ff = 0;
}
if(state->mqe.buffer != LONG_FF)
{
if( !(creg & M_CR_C) )
{ /* No Carry */
put_byte(state,state->mqe.buffer);
state->mqe.buffer = (creg >> S_CR_B_NML);
creg &= M_CR_SX_NML;
*ct = NEXTBITS_NML;
}
else
{ /* Carry */
state->mqe.buffer++; /* Carry propagation */
if(state->mqe.buffer != LONG_FF)
{
put_byte(state,state->mqe.buffer);
state->mqe.buffer = ((creg >> S_CR_B_NML) & M_CR_BUF8);
creg &= M_CR_SX_NML;
*ct = NEXTBITS_NML;
}
else
{
state->mqe.have_unsent_ff = 1;
state->mqe.buffer = ((creg >> S_CR_B_BS) & M_CR_BUF7);
creg &= M_CR_SX_BS;
*ct = NEXTBITS_BS;
}
}
}
else
{ /* buffer == BYTE_FF */
state->mqe.have_unsent_ff = 1;
state->mqe.buffer = (creg >> S_CR_B_BS);
creg &= M_CR_SX_BS;
*ct = NEXTBITS_BS;
}
return(creg);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__deactivate */
/*****************************************************************************/
int
dst_arith_coder__deactivate(dst_arith_state_ptr state,
int easy)
{
int num_bytes;
if (!state->mqe.active)
num_bytes = perform_raw_terminating_flush(state);
else
{
assert((state->current_lsb & 7) == 0);
if (state->error_resilient_termination)
num_bytes = perform_error_resilient_flush(state);
else if (easy)
num_bytes = perform_easy_terminating_flush(state);
else
num_bytes = perform_best_terminating_flush(state);
init_enc(&(state->mqe));
}
return(num_bytes);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__flush */
/*****************************************************************************/
void
dst_arith_coder__flush(dst_arith_state_ptr state)
{
assert(!state->mqe.active); /* Encoder must already have been deactivated */
if (state->current_lsb < 32)
dst_arith_coder__output_word(state,state->word);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__get_minimum_bytes */
/*****************************************************************************/
int
dst_arith_coder__get_minimum_bytes(dst_arith_state_ptr state,
dst_heap_unit_ptr heap, int heap_pos,
int min_bytes, int max_bytes)
/* Determines the minimum number of whole bytes which are required to
correctly decode all coded symbols up to and including the last symbol
whose coding resulted in the state recorded in the supplied `state'
structure. The `heap' and `heap_pos' arguments identify the heap unit
structure and the word index within this structure, of the first word
saved by the arithmetic coding engine. The function indexes into the
saved bit-stream to determine the effect of premature termination on
successful decoding up to the point associated with `state'. The
function depends intimately on the assumption that the decoder will
stuff 1's onto the end of the bit-stream as necessary and then
replace consecutive FF's by the pattern FF,7F,FF,... Consequently,
the `dst_arith_coder__input_word' function and the `bytein' function
in "dst_arith_decoder.c" must not be carelessly modified.
The original version of this function (for the original EBCOT arithmetic
coder) was bit oriented and never overestimated the required code length;
however, the bit-stuffing policy in the MQ coder is byte oriented, which
makes estimation of the minimum number of whole bytes directly somewhat
simpler; this is sufficient, since the block coder represents truncation
points in bytes, not bits.
The `min_bytes' and `max_bytes' fields are provided to account for the
fact that there may be multiple arithmetic code-word segments in the
code stream where we are wanting to compute a termination point inside
one of those segments. The `min_bytes' field identifies the number of
bytes in the code stream preceding the relevant segment, whereas the
`max_bytes' field identifies the number of bytes in the code stream up
until the end of the segment. */
{
std_int upper_C, upper_buf, lower_C, lower_buf;
std_int word, last_byte_is_ff, next_byte;
std_short ct;
std_int n, in_word_idx, tmp;
int num_bytes;
word = 0; /* Suppress compiler warnings. */
next_byte = 0; /* Suppress compiler warnings. */
if (!state->mqe.active)
{ /* Computing the length of a raw bit-stream segment -> easy! */
int current_lsb;
current_lsb = state->current_lsb & ~7;
num_bytes = (state->saved_words << 2) + ((32-current_lsb)>>3);
return(num_bytes);
}
assert((state->current_lsb & 7) == 0);
num_bytes = (state->saved_words << 2) + ((32-state->current_lsb)>>3);
if (state->mqe.io_enable)
num_bytes++;
num_bytes--;
if (state->mqe.have_unsent_ff)
num_bytes++;
if (num_bytes > max_bytes)
return(max_bytes);
assert(num_bytes >= (min_bytes-1));
/* `num_bytes' represents the number of bytes which have been pushed
out to the heap by this stage, not including any value sent to
the byte buffer in the `state->mqe' structure. This value might
be less than `min_bytes'. For example, if no symbols have been coded
at all, this value will be equal to `min_bytes'-1. The interpretation
of a value of `min_bytes'-1 is that the byte buffer in the `state->mqe'
structure is itself empty. */
ct = state->mqe.ct;
lower_C = state->mqe.creg;
upper_C = lower_C + state->mqe.areg;
lower_C <<= ct;
upper_C <<= ct;
upper_buf = lower_buf = state->mqe.buffer;
if (upper_C & M_CR_C)
{
upper_C -= M_CR_C;
upper_buf++;
}
if (lower_C & M_CR_C)
{
lower_C -= M_CR_C;
lower_buf++;
}
/* At this point, `upper_buf' holds the buffer value and
`upper_C' the C-register value corresponding to an upper bound;
Similarly, `lower_C' and `lower_buf' represent the lower bound on
the arithmetic code-word. After padding (due to truncation), the
code-word must be strictly less than the upper bound and no less than
the lower bound in order to ensure correct decoding. We would normally
only need to consider the upper bound, but the bit-stuffing policy used
by the MQ coder renders this insufficient. */
/* Now for the loop to find the minimum number of bytes required.
We start by checking whether or not we need any more than the
`num_bytes' value, i.e. whether or not we need the byte whose
position corresponds to that of the byte in `state->mqe.buffer'. */
in_word_idx = -1; /* Illegal value. */
last_byte_is_ff = state->mqe.have_unsent_ff;
while (1)
{
if (last_byte_is_ff)
{ /* If we stop immediately before here, the decoder will pad
with 0x7F, 0xFF, 0x7F, 0xFF, ..., which is equivalent to a
number strictly less than 128, but larger than any number less
than 128. */
if ((upper_buf >= 128) && (lower_buf < 128))
{
num_bytes--; /* Do not need the preceding byte either since
the decoder will substitute the 0xFF
automatically as the first byte after the
end of the string. */
break;
}
}
else
{ /* If we stop immediately before here, the decoder will pad
with 0xFF, 0x7F, 0xFF, 0x7F, ..., which is equivalent to a
number strictly less than 256, but larger than any number less
than 256. */
if ((upper_buf >= 256) && (lower_buf < 256))
{
break; /* We are done. */
}
}
/* Retrieve next actual byte in codeword segment. */
if (in_word_idx < 0)
{ /* First access to heap. */
word = 0; in_word_idx = 3;
if (num_bytes >= 0)
{
n = num_bytes>>2; /* Number of whole words in heap to skip. */
in_word_idx = num_bytes - (n<<2); /* Index of byte in word. */
while (n)
{
tmp = DST_HEAP_WORDS - heap_pos;
if (tmp > n)
{
heap_pos += n;
n = 0;
}
else
{
n -= tmp;
heap_pos = 0;
heap = heap->next;
}
}
word = heap->words[heap_pos++];
word <<= (in_word_idx << 3);
next_byte = (word>>24) & 0x00FF;
}
}
else if (num_bytes >= 0)
{
in_word_idx++; word <<= 8;
if (in_word_idx == 4)
{
if (heap_pos >= DST_HEAP_WORDS)
{ heap = heap->next; heap_pos = 0; }
word = heap->words[heap_pos++];
in_word_idx = 0;
}
next_byte = (word >> 24) & 0x00FF;
}
if (num_bytes < min_bytes)
next_byte = 0;
/* Advance to the next byte position. */
upper_buf -= next_byte;
lower_buf -= next_byte;
num_bytes++;
assert(num_bytes <= max_bytes);
if (next_byte != 0x00FF)
{ /* move left-most 8 bits of C into buffer. */
upper_buf <<= 8; lower_buf <<= 8;
upper_buf |= (upper_C >> (16+SPACER)) & 0x00FF;
lower_buf |= (lower_C >> (16+SPACER)) & 0x00FF;
upper_C <<= 8; lower_C <<= 8;
last_byte_is_ff = 0;
}
else
{ /* move left-most 7 bits of C into buffer. */
upper_buf <<= 7; lower_buf <<= 7;
upper_buf |= (upper_C >> (16+SPACER+1)) & 0x007F;
lower_buf |= (lower_C >> (16+SPACER+1)) & 0x007F;
upper_C <<= 7; lower_C <<= 7;
last_byte_is_ff = 1;
}
upper_C &= M_CR_BSX;
lower_C &= M_CR_BSX;
}
if (num_bytes < min_bytes)
num_bytes = min_bytes;
return(num_bytes);
}
/*****************************************************************************/
/* EXTERN dst_arith_coder__log_symbol */
/*****************************************************************************/
#ifdef DST_LOG_SYMBOLS
void
dst_arith_coder__log_symbol(dst_arith_state_ptr state,
dst_context_state_ptr ctxt,
std_int symbol) /* David T mod */
{
int val;
if(state->symbol_log == NULL)
return;
if (ctxt == NULL)
val = 255;
else
val = ctxt - state->contexts;
putc(val,state->symbol_log);
val = (symbol)?1:0;
putc(val,state->symbol_log);
}
#endif /* DST_LOG_SYMBOLS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -