📄 mq_encoder.h
字号:
assert(active && (!checked_out) && !MQ_segment); checked_out = true; t = this->t; temp = this->temp; store = this->buf_next; } void check_in(kdu_int32 A, kdu_int32 C, kdu_int32 t, kdu_int32 temp, kdu_byte *store) { // Use this form for MQ codeword segments. assert(active && checked_out && MQ_segment); checked_out = false; this->A = A; this->C = C; this->t = t; this->temp = temp; this->buf_next = store; } void check_in(kdu_int32 t, kdu_int32 temp, kdu_byte *store) { // Use this form for raw codeword segments. assert(active && checked_out && !MQ_segment); checked_out = false; this->t = t; this->temp = temp; this->buf_next = store; } public: // Encoding functions. Note: use macros for the highest throughput void mq_encode(kdu_int32 symbol, mqe_state &state); /* Note that symbol must be 0 or KDU_INT32_MIN */ void mq_encode_run(kdu_int32 run); // Encodes a 2 bit run length, MSB first void raw_encode(kdu_int32 symbol); /* Note that symbol must be 0 or 1. */ private: void transfer_byte(); /* Used by the `mq_encode' member function. */ public: // Probability estimation state machine. static kdu_int32 p_bar_table[47]; // Normalized LPS probabilities static mqe_transition transition_table[94]; // See def'n of `mqe_transition' private: // Internal functions void find_truncation_point(kdu_byte *limit); /* This function is automatically invoked from within `terminate' to determine optimal truncation points for continued codeword segments (it may also be applied to non-continued segments to find the minimal segment length). The function may also be invoked from within the `get_final_length' member function. The `limit' argument points to the location in the byte buffer which immediately follows the last byte in the already terminated codeword segment. Legal access is permitted only to bytes preceding this location. */ private: // Data kdu_int32 A; // Only the least significant 16 bits of A are used kdu_int32 C; // Holds a 28 bit number (including the carry bit) kdu_int32 t; // This is "t_bar" in the book kdu_int32 temp; // This is "T_bar" in the book kdu_byte *buf_start, *buf_next; kdu_byte overwritten_byte; bool checked_out; bool MQ_segment; bool active; bool truncation_point_found; mq_encoder *prev; // Point from which coding continues in same segment mq_encoder *next; // Point to which coding continues in next segment };/*****************************************************************************//* INLINE mqe_state::init *//*****************************************************************************/inline void mqe_state::init(int Sigma, kdu_int32 s){ assert((Sigma >= 0) && (Sigma <= 46) && (s == (s&1))); mps_p_bar = mq_encoder::p_bar_table[Sigma] + (s<<31); transition = mq_encoder::transition_table + ((Sigma<<1) + s);}/* ========================================================================= *//* Fast Coding Macros *//* ========================================================================= *//* Note: although in-lining is preferable, most compilers fail to realize the full speed potential of macros. These are critical to the overall system throughput and also to the size of the code fragment which gets executed inside the coding pass loops. *//*****************************************************************************//* MACRO _mqe_transfer_byte_ *//*****************************************************************************/ /* The following macro implements the Transfer-Byte procedure from Section 12.1.2 of the book by Taubman and Marcellin. The implementation, however, is carefully optimized to pair down the number of test and the overall number of instructions. In particular, we test for the two conditions which can cause a bit-stuffing operation simultaneously. */#define _mqe_transfer_byte_(C,t,temp,store) \ { \ temp += C>>MQE_CARRY_POS; /* Saves comparisons to add the carry first */ \ if (temp >= 0xFF) \ { \ *(store++) = (kdu_byte) 0xFF; \ temp = (temp | 0xFF)>>1; /* Holds 0x7F unless had FF and a carry */ \ temp &= (C>>MQE_MSBS_POS); /* Clear carry if temp not initially FF */ \ C &= MQE_MSBS_CLEAR; \ t = 7; \ } \ else \ { \ *(store++) = (kdu_byte) temp; \ temp = (C>>MQE_PARTIAL_POS) & 0xFF; /* Still need to clear carry */ \ C &= MQE_PARTIAL_CLEAR; \ t = 8; \ } \ }/*****************************************************************************//* MACRO _mq_encode_ *//*****************************************************************************/ /* The following macro implements the MQ-Encode procedure described in Section 12.1.2 of the book by Taubman and Marcellin. The main optimization trick is that described in Section 17.1.1, whereby the test for renormalization appears first; this helps because conditional exchange can occur only during renormalization. Beyond the implementation tricks suggested in Section 17.1.1, we are able to combine the tests for an MPS symbol and a renormalization event into a single test by using a quantity which we shall call `lps_p_bar'. The most significant bit of this 32-bit word is 1 if the symbol being coded is an LPS. The 15 LSB's hold the normalized MPS probability, (`p_bar' in the book). This trick relies upon the fact that A-p_bar must be a strictly positive quantity at all times, since A >= 2^15 and p_bar < 2^15 are both guaranteed. To minimize the number of variables which are required, storage for `lps_p_bar' is shared with the incoming symbol. The user should take careful note that the value of the symbol variable has no well-defined value upon return from the function. This may cause problems if the caller intends to re-use the symbol value. If your compiler and architecture support the allocation of registers for critical variables, it is recommended that `lps_p_bar', `state', `A' and `C' be allocated registers, in that order. */#define _mq_encode_(lps_p_bar,state,A,C,t,temp,store) \ { /* Note: incoming symbol must be in `lps_p_bar' as 0 or KDU_INT32_MIN */ \ assert((lps_p_bar == 0) || (lps_p_bar == KDU_INT32_MIN)); \ lps_p_bar ^= (state).mps_p_bar; \ A -= lps_p_bar; \ if (A >= MQE_A_MIN) \ { /* Symbol is MPS and (A-p_bar) >= 2^15, meaning no renormalization */ \ C += lps_p_bar; \ } \ else \ { /* Renormalization is inevitable and conditional exchange possible */ \ if (lps_p_bar >= 0) \ { /* Symbol is MPS, but A-p_bar < 2^15. */ \ if (A < lps_p_bar) \ A = lps_p_bar; /* Conditional exchange */ \ else \ C = C + lps_p_bar; \ state = (state).transition->mps; \ } \ else \ { /* Symbol is LPS, so A-p_bar is necessarily less than 2^15 */ \ A &= KDU_INT32_MAX; \ lps_p_bar &= KDU_INT32_MAX; \ if (A < lps_p_bar) \ C = C + lps_p_bar; /* Conditional exchange */ \ else \ A = lps_p_bar; \ state = (state).transition->lps; \ } \ assert(A < MQE_A_MIN); \ do { \ A += A; C += C; \ if ((--t)==0) \ _mqe_transfer_byte_(C,t,temp,store); \ } while (A < MQE_A_MIN); \ } \ }/*****************************************************************************//* MACRO _mq_encode_run_ *//*****************************************************************************/ /* Specialization of _mq_encode_ to the case where the state is equal to the special non-adaptive MQ coder state (last state in transition table); encodes a 2-bit run length, starting from the motr significant bit. */#define _mq_encode_run_(run,A,C,t,temp,store) \ { \ assert(run == (run&3)); \ A -= 0x5601; \ if (((run & 2)==0) && (A >= MQE_A_MIN)) \ { /* Symbol is MPS and no renormalization is required. */ \ C += 0x5601; \ } \ else \ { /* Renormalization is required. */ \ if ((run & 2) == 0) \ { /* Symbol is an MPS */ \ if (A < 0x5601) \ A = 0x5601; /* Conditional exchange */ \ else \ C += 0x5601; \ } \ else \ { /* Symbol is an LPS */ \ if (A < 0x5601) \ C += 0x5601; /* Conditional exchange */ \ else \ A = 0x5601; \ } \ do { \ A += A; C += C; t--; \ if (t == 0) \ _mqe_transfer_byte_(C,t,temp,store); \ } while (A < MQE_A_MIN); \ } \ A -= 0x5601; \ if (((run & 1)==0) && (A >= MQE_A_MIN)) \ { /* Symbol is MPS and no renormalization is required. */ \ C += 0x5601; \ } \ else \ { /* Renormalization is required. */ \ if ((run & 1) == 0) \ { /* Symbol is an MPS */ \ if (A < 0x5601) \ A = 0x5601; /* Conditional exchange */ \ else \ C += 0x5601; \ } \ else \ { /* Symbol is an LPS */ \ if (A < 0x5601) \ C += 0x5601; /* Conditional exchange */ \ else \ A = 0x5601; \ } \ do { \ A += A; C += C; t--; \ if (t == 0) \ _mqe_transfer_byte_(C,t,temp,store); \ } while (A < MQE_A_MIN); \ } \ }/*****************************************************************************//* MACRO _raw_encode_ *//*****************************************************************************/ /* By contrast with MQ coding, symbols here must be either 0 or 1 (not 0 or KDU_INT32_MIN). */#define _raw_encode_(symbol,t,temp,store) \ { \ assert((symbol == 0) || (symbol == 1)); \ if (t==0) \ { \ *(store++) = (kdu_byte) temp; \ temp = (temp+1)>>8; /* Evaluates to 1 if `temp' was FF, else 0. */ \ t = 8-temp; \ temp = 0; \ } \ temp += temp + symbol; \ t--; \ }#endif // MQ_ENCODER_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -