📄 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_SYMBOLSvoid 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 + -