// File: crn_symbol_codec.cpp // See Copyright Notice and license at the end of inc/crnlib.h #include "crn_core.h" #include "crn_symbol_codec.h" #include "crn_huffman_codes.h" namespace crnlib { static float gProbCost[cSymbolCodecArithProbScale]; //const uint cArithProbMulLenSigBits = 8; //const uint cArithProbMulLenSigScale = 1 << cArithProbMulLenSigBits; class arith_prob_cost_initializer { public: arith_prob_cost_initializer() { const float cInvLn2 = 1.0f / 0.69314718f; for (uint i = 0; i < cSymbolCodecArithProbScale; i++) gProbCost[i] = -logf(i * (1.0f / cSymbolCodecArithProbScale)) * cInvLn2; } }; static arith_prob_cost_initializer g_prob_cost_initializer; double symbol_histogram::calc_entropy() const { double total = 0.0f; for (uint i = 0; i < m_hist.size(); i++) total += m_hist[i]; if (total == 0.0f) return 0.0f; double entropy = 0.0f; double neg_inv_log2 = -1.0f / log(2.0f); double inv_total = 1.0f / total; for (uint i = 0; i < m_hist.size(); i++) { if (m_hist[i]) { double bits = log(m_hist[i] * inv_total) * neg_inv_log2; entropy += bits * m_hist[i]; } } return entropy; } uint64 symbol_histogram::get_total() const { uint64 total = 0; for (uint i = 0; i < m_hist.size(); i++) total += m_hist[i]; return total; } adaptive_huffman_data_model::adaptive_huffman_data_model(bool encoding, uint total_syms) : m_total_syms(0), m_update_cycle(0), m_symbols_until_update(0), m_total_count(0), m_pDecode_tables(NULL), m_decoder_table_bits(0), m_encoding(encoding) { if (total_syms) init(encoding, total_syms); } adaptive_huffman_data_model::adaptive_huffman_data_model(const adaptive_huffman_data_model& other) : m_total_syms(0), m_update_cycle(0), m_symbols_until_update(0), m_total_count(0), m_pDecode_tables(NULL), m_decoder_table_bits(0), m_encoding(false) { *this = other; } adaptive_huffman_data_model::~adaptive_huffman_data_model() { if (m_pDecode_tables) crnlib_delete(m_pDecode_tables); } adaptive_huffman_data_model& adaptive_huffman_data_model::operator= (const adaptive_huffman_data_model& rhs) { if (this == &rhs) return *this; m_total_syms = rhs.m_total_syms; m_update_cycle = rhs.m_update_cycle; m_symbols_until_update = rhs.m_symbols_until_update; m_total_count = rhs.m_total_count; m_sym_freq = rhs.m_sym_freq; m_codes = rhs.m_codes; m_code_sizes = rhs.m_code_sizes; if (rhs.m_pDecode_tables) { if (m_pDecode_tables) *m_pDecode_tables = *rhs.m_pDecode_tables; else m_pDecode_tables = crnlib_new(*rhs.m_pDecode_tables); } else { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } m_decoder_table_bits = rhs.m_decoder_table_bits; m_encoding = rhs.m_encoding; return *this; } void adaptive_huffman_data_model::clear() { m_sym_freq.clear(); m_codes.clear(); m_code_sizes.clear(); m_total_syms = 0; m_update_cycle = 0; m_symbols_until_update = 0; m_decoder_table_bits = 0; m_total_count = 0; if (m_pDecode_tables) { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } } void adaptive_huffman_data_model::init(bool encoding, uint total_syms) { clear(); m_encoding = encoding; m_sym_freq.resize(total_syms); m_code_sizes.resize(total_syms); m_total_syms = total_syms; if (m_total_syms <= 16) m_decoder_table_bits = 0; else m_decoder_table_bits = static_cast(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits)); if (m_encoding) m_codes.resize(total_syms); else m_pDecode_tables = crnlib_new(); reset(); } void adaptive_huffman_data_model::reset() { if (!m_total_syms) return; for (uint i = 0; i < m_total_syms; i++) m_sym_freq[i] = 1; m_total_count = 0; m_update_cycle = m_total_syms; update(); m_symbols_until_update = m_update_cycle = 8;//(m_total_syms + 6) >> 1; } void adaptive_huffman_data_model::rescale() { uint total_freq = 0; for (uint i = 0; i < m_total_syms; i++) { uint freq = (m_sym_freq[i] + 1) >> 1; total_freq += freq; m_sym_freq[i] = static_cast(freq); } m_total_count = total_freq; } void adaptive_huffman_data_model::update() { m_total_count += m_update_cycle; if (m_total_count >= 32768) rescale(); void* pTables = create_generate_huffman_codes_tables(); uint max_code_size, total_freq; bool status = generate_huffman_codes(pTables, m_total_syms, &m_sym_freq[0], &m_code_sizes[0], max_code_size, total_freq); CRNLIB_ASSERT(status); CRNLIB_ASSERT(total_freq == m_total_count); if (max_code_size > prefix_coding::cMaxExpectedCodeSize) prefix_coding::limit_max_code_size(m_total_syms, &m_code_sizes[0], prefix_coding::cMaxExpectedCodeSize); free_generate_huffman_codes_tables(pTables); if (m_encoding) status = prefix_coding::generate_codes(m_total_syms, &m_code_sizes[0], &m_codes[0]); else status = prefix_coding::generate_decoder_tables(m_total_syms, &m_code_sizes[0], m_pDecode_tables, m_decoder_table_bits); CRNLIB_ASSERT(status); status; m_update_cycle = (5 * m_update_cycle) >> 2; uint max_cycle = (m_total_syms + 6) << 3; // this was << 2 - which is ~12% slower but compresses around .5% better if (m_update_cycle > max_cycle) m_update_cycle = max_cycle; m_symbols_until_update = m_update_cycle; } static_huffman_data_model::static_huffman_data_model() : m_total_syms(0), m_pDecode_tables(NULL), m_encoding(false) { } static_huffman_data_model::static_huffman_data_model(const static_huffman_data_model& other) : m_total_syms(0), m_pDecode_tables(NULL), m_encoding(false) { *this = other; } static_huffman_data_model::~static_huffman_data_model() { if (m_pDecode_tables) crnlib_delete(m_pDecode_tables); } static_huffman_data_model& static_huffman_data_model::operator=(const static_huffman_data_model& rhs) { if (this == &rhs) return *this; m_total_syms = rhs.m_total_syms; m_codes = rhs.m_codes; m_code_sizes = rhs.m_code_sizes; if (rhs.m_pDecode_tables) { if (m_pDecode_tables) *m_pDecode_tables = *rhs.m_pDecode_tables; else m_pDecode_tables = crnlib_new(*rhs.m_pDecode_tables); } else { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } m_encoding = rhs.m_encoding; return *this; } void static_huffman_data_model::clear() { m_total_syms = 0; m_codes.clear(); m_code_sizes.clear(); if (m_pDecode_tables) { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } m_encoding = false; } bool static_huffman_data_model::init(bool encoding, uint total_syms, const uint16* pSym_freq, uint code_size_limit) { CRNLIB_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1)); m_encoding = encoding; m_total_syms = total_syms; code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize); m_code_sizes.resize(total_syms); void* pTables = create_generate_huffman_codes_tables(); uint max_code_size = 0, total_freq; bool status = generate_huffman_codes(pTables, m_total_syms, pSym_freq, &m_code_sizes[0], max_code_size, total_freq); free_generate_huffman_codes_tables(pTables); if (!status) return false; if (max_code_size > code_size_limit) { if (!prefix_coding::limit_max_code_size(m_total_syms, &m_code_sizes[0], code_size_limit)) return false; } if (m_encoding) { m_codes.resize(total_syms); if (m_pDecode_tables) { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } if (!prefix_coding::generate_codes(m_total_syms, &m_code_sizes[0], &m_codes[0])) return false; } else { m_codes.clear(); if (!m_pDecode_tables) m_pDecode_tables = crnlib_new(); if (!prefix_coding::generate_decoder_tables(m_total_syms, &m_code_sizes[0], m_pDecode_tables, compute_decoder_table_bits())) return false; } return true; } bool static_huffman_data_model::init(bool encoding, uint total_syms, const uint* pSym_freq, uint code_size_limit) { CRNLIB_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1)); crnlib::vector sym_freq16(total_syms); uint max_freq = 0; for (uint i = 0; i < total_syms; i++) max_freq = math::maximum(max_freq, pSym_freq[i]); if (!max_freq) return false; if (max_freq <= cUINT16_MAX) { for (uint i = 0; i < total_syms; i++) sym_freq16[i] = static_cast(pSym_freq[i]); } else { for (uint i = 0; i < total_syms; i++) { uint f = pSym_freq[i]; if (!f) continue; uint64 fl = f; fl = ((fl << 16) - fl) + (max_freq >> 1); fl /= max_freq; if (fl < 1) fl = 1; CRNLIB_ASSERT(fl <= cUINT16_MAX); sym_freq16[i] = static_cast(fl); } } return init(encoding, total_syms, &sym_freq16[0], code_size_limit); } bool static_huffman_data_model::init(bool encoding, uint total_syms, const uint8* pCode_sizes, uint code_size_limit) { CRNLIB_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms) && (code_size_limit >= 1)); m_encoding = encoding; code_size_limit = math::minimum(code_size_limit, prefix_coding::cMaxExpectedCodeSize); m_code_sizes.resize(total_syms); uint min_code_size = UINT_MAX; uint max_code_size = 0; for (uint i = 0; i < total_syms; i++) { uint s = pCode_sizes[i]; m_code_sizes[i] = static_cast(s); min_code_size = math::minimum(min_code_size, s); max_code_size = math::maximum(max_code_size, s); } if ((max_code_size < 1) || (max_code_size > 32) || (min_code_size > code_size_limit)) return false; if (max_code_size > code_size_limit) { if (!prefix_coding::limit_max_code_size(m_total_syms, &m_code_sizes[0], code_size_limit)) return false; } if (m_encoding) { m_codes.resize(total_syms); if (m_pDecode_tables) { crnlib_delete(m_pDecode_tables); m_pDecode_tables = NULL; } if (!prefix_coding::generate_codes(m_total_syms, &m_code_sizes[0], &m_codes[0])) return false; } else { m_codes.clear(); if (!m_pDecode_tables) m_pDecode_tables = crnlib_new(); if (!prefix_coding::generate_decoder_tables(m_total_syms, &m_code_sizes[0], m_pDecode_tables, compute_decoder_table_bits())) return false; } return true; } bool static_huffman_data_model::init(bool encoding, const symbol_histogram& hist, uint code_size_limit) { return init(encoding, hist.size(), hist.get_ptr(), code_size_limit); } bool static_huffman_data_model::prepare_decoder_tables() { uint total_syms = m_code_sizes.size(); CRNLIB_ASSERT((total_syms >= 1) && (total_syms <= prefix_coding::cMaxSupportedSyms)); m_encoding = false; m_total_syms = total_syms; m_codes.clear(); if (!m_pDecode_tables) m_pDecode_tables = crnlib_new(); return prefix_coding::generate_decoder_tables(m_total_syms, &m_code_sizes[0], m_pDecode_tables, compute_decoder_table_bits()); } uint static_huffman_data_model::compute_decoder_table_bits() const { uint decoder_table_bits = 0; if (m_total_syms > 16) decoder_table_bits = static_cast(math::minimum(1 + math::ceil_log2i(m_total_syms), prefix_coding::cMaxTableBits)); return decoder_table_bits; } adaptive_bit_model::adaptive_bit_model() { clear(); } adaptive_bit_model::adaptive_bit_model(float prob0) { set_probability_0(prob0); } adaptive_bit_model::adaptive_bit_model(const adaptive_bit_model& other) : m_bit_0_prob(other.m_bit_0_prob) { } adaptive_bit_model& adaptive_bit_model::operator= (const adaptive_bit_model& rhs) { m_bit_0_prob = rhs.m_bit_0_prob; return *this; } void adaptive_bit_model::clear() { m_bit_0_prob = 1U << (cSymbolCodecArithProbBits - 1); } void adaptive_bit_model::set_probability_0(float prob0) { m_bit_0_prob = static_cast(math::clamp((uint)(prob0 * cSymbolCodecArithProbScale), 1, cSymbolCodecArithProbScale - 1)); } float adaptive_bit_model::get_cost(uint bit) const { return gProbCost[bit ? (cSymbolCodecArithProbScale - m_bit_0_prob) : m_bit_0_prob]; } void adaptive_bit_model::update(uint bit) { if (!bit) m_bit_0_prob += ((cSymbolCodecArithProbScale - m_bit_0_prob) >> cSymbolCodecArithProbMoveBits); else m_bit_0_prob -= (m_bit_0_prob >> cSymbolCodecArithProbMoveBits); CRNLIB_ASSERT(m_bit_0_prob >= 1); CRNLIB_ASSERT(m_bit_0_prob < cSymbolCodecArithProbScale); } adaptive_arith_data_model::adaptive_arith_data_model(bool encoding, uint total_syms) { init(encoding, total_syms); } adaptive_arith_data_model::adaptive_arith_data_model(const adaptive_arith_data_model& other) { m_total_syms = other.m_total_syms; m_probs = other.m_probs; } adaptive_arith_data_model::~adaptive_arith_data_model() { } adaptive_arith_data_model& adaptive_arith_data_model::operator= (const adaptive_arith_data_model& rhs) { m_total_syms = rhs.m_total_syms; m_probs = rhs.m_probs; return *this; } void adaptive_arith_data_model::clear() { m_total_syms = 0; m_probs.clear(); } void adaptive_arith_data_model::init(bool encoding, uint total_syms) { encoding; if (!total_syms) { clear(); return; } if ((total_syms < 2) || (!math::is_power_of_2(total_syms))) total_syms = math::next_pow2(total_syms); m_total_syms = total_syms; m_probs.resize(m_total_syms); } void adaptive_arith_data_model::reset() { for (uint i = 0; i < m_probs.size(); i++) m_probs[i].clear(); } float adaptive_arith_data_model::get_cost(uint sym) const { uint node = 1; uint bitmask = m_total_syms; float cost = 0.0f; do { bitmask >>= 1; uint bit = (sym & bitmask) ? 1 : 0; cost += m_probs[node].get_cost(bit); node = (node << 1) + bit; } while (bitmask > 1); return cost; } symbol_codec::symbol_codec() { clear(); } void symbol_codec::clear() { m_pDecode_buf = NULL; m_pDecode_buf_next = NULL; m_pDecode_buf_end = NULL; m_decode_buf_size = 0; m_bit_buf = 0; m_bit_count = 0; m_total_model_updates = 0; m_mode = cNull; m_simulate_encoding = false; m_total_bits_written = 0; m_arith_base = 0; m_arith_value = 0; m_arith_length = 0; m_arith_total_bits = 0; m_output_buf.clear(); m_arith_output_buf.clear(); m_output_syms.clear(); } void symbol_codec::start_encoding(uint expected_file_size) { m_mode = cEncoding; m_total_model_updates = 0; m_total_bits_written = 0; put_bits_init(expected_file_size); m_output_syms.resize(0); arith_start_encoding(); } // Code length encoding symbols: // 0-16 - actual code lengths const uint cMaxCodelengthCodes = 21; const uint cSmallZeroRunCode = 17; const uint cLargeZeroRunCode = 18; const uint cSmallRepeatCode = 19; const uint cLargeRepeatCode = 20; const uint cMinSmallZeroRunSize = 3; const uint cMaxSmallZeroRunSize = 10; const uint cMinLargeZeroRunSize = 11; const uint cMaxLargeZeroRunSize = 138; const uint cSmallMinNonZeroRunSize = 3; const uint cSmallMaxNonZeroRunSize = 6; const uint cLargeMinNonZeroRunSize = 7; const uint cLargeMaxNonZeroRunSize = 70; const uint cSmallZeroRunExtraBits = 3; const uint cLargeZeroRunExtraBits = 7; const uint cSmallNonZeroRunExtraBits = 2; const uint cLargeNonZeroRunExtraBits = 6; static const uint8 g_most_probable_codelength_codes[] = { cSmallZeroRunCode, cLargeZeroRunCode, cSmallRepeatCode, cLargeRepeatCode, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 16 }; const uint cNumMostProbableCodelengthCodes = sizeof(g_most_probable_codelength_codes) / sizeof(g_most_probable_codelength_codes[0]); static inline void end_zero_run(uint& size, crnlib::vector& codes) { if (!size) return; if (size < cMinSmallZeroRunSize) { while (size--) codes.push_back(0); } else if (size <= cMaxSmallZeroRunSize) codes.push_back( static_cast(cSmallZeroRunCode | ((size - cMinSmallZeroRunSize) << 8)) ); else { CRNLIB_ASSERT((size >= cMinLargeZeroRunSize) && (size <= cMaxLargeZeroRunSize)); codes.push_back( static_cast(cLargeZeroRunCode | ((size - cMinLargeZeroRunSize) << 8)) ); } size = 0; } static inline void end_nonzero_run(uint& size, uint len, crnlib::vector& codes) { if (!size) return; if (size < cSmallMinNonZeroRunSize) { while (size--) codes.push_back(static_cast(len)); } else if (size <= cSmallMaxNonZeroRunSize) { codes.push_back(static_cast(cSmallRepeatCode | ((size - cSmallMinNonZeroRunSize) << 8))); } else { CRNLIB_ASSERT((size >= cLargeMinNonZeroRunSize) && (size <= cLargeMaxNonZeroRunSize)); codes.push_back(static_cast(cLargeRepeatCode | ((size - cLargeMinNonZeroRunSize) << 8))); } size = 0; } uint symbol_codec::encode_transmit_static_huffman_data_model(static_huffman_data_model& model, bool simulate = false, static_huffman_data_model* pDeltaModel ) { CRNLIB_ASSERT(m_mode == cEncoding); uint total_used_syms = 0; for (uint i = model.m_total_syms; i > 0; i--) { if (model.m_code_sizes[i - 1]) { total_used_syms = i; break; } } if (!total_used_syms) { if (!simulate) { encode_bits(0, math::total_bits(prefix_coding::cMaxSupportedSyms)); } return math::total_bits(prefix_coding::cMaxSupportedSyms); } crnlib::vector codes; codes.reserve(model.m_total_syms); uint prev_len = UINT_MAX; uint cur_zero_run_size = 0; uint cur_nonzero_run_size = 0; const uint8* pCodesizes = &model.m_code_sizes[0]; crnlib::vector delta_code_sizes; if ((pDeltaModel) && (pDeltaModel->get_total_syms())) { if (pDeltaModel->m_code_sizes.size() < total_used_syms) return 0; delta_code_sizes.resize(total_used_syms); for (uint i = 0; i < total_used_syms; i++) { int delta = (int)model.m_code_sizes[i] - (int)pDeltaModel->m_code_sizes[i]; if (delta < 0) delta += 17; delta_code_sizes[i] = static_cast(delta); } pCodesizes = delta_code_sizes.get_ptr(); } for (uint i = 0; i <= total_used_syms; i++) { const uint len = (i < total_used_syms) ? *pCodesizes++ : 0xFF; CRNLIB_ASSERT((len == 0xFF) || (len <= prefix_coding::cMaxExpectedCodeSize)); if (!len) { end_nonzero_run(cur_nonzero_run_size, prev_len, codes); if (++cur_zero_run_size == cMaxLargeZeroRunSize) end_zero_run(cur_zero_run_size, codes); } else { end_zero_run(cur_zero_run_size, codes); if (len != prev_len) { end_nonzero_run(cur_nonzero_run_size, prev_len, codes); if (len != 0xFF) codes.push_back(static_cast(len)); } else if (++cur_nonzero_run_size == cLargeMaxNonZeroRunSize) end_nonzero_run(cur_nonzero_run_size, prev_len, codes); } prev_len = len; } uint16 hist[cMaxCodelengthCodes]; utils::zero_object(hist); for (uint i = 0; i < codes.size(); i++) { uint code = codes[i] & 0xFF; CRNLIB_ASSERT(code < cMaxCodelengthCodes); hist[code] = static_cast(hist[code] + 1); } static_huffman_data_model dm; if (!dm.init(true, cMaxCodelengthCodes, hist, 7)) return 0; uint num_codelength_codes_to_send; for (num_codelength_codes_to_send = cNumMostProbableCodelengthCodes; num_codelength_codes_to_send > 0; num_codelength_codes_to_send--) if (dm.get_cost(g_most_probable_codelength_codes[num_codelength_codes_to_send - 1])) break; uint total_bits = math::total_bits(prefix_coding::cMaxSupportedSyms); total_bits += 5; total_bits += 3 * num_codelength_codes_to_send; if (!simulate) { encode_bits(total_used_syms, math::total_bits(prefix_coding::cMaxSupportedSyms)); encode_bits(num_codelength_codes_to_send, 5); for (uint i = 0; i < num_codelength_codes_to_send; i++) encode_bits(dm.get_cost(g_most_probable_codelength_codes[i]), 3); } for (uint i = 0; i < codes.size(); i++) { uint code = codes[i]; uint extra = code >> 8; code &= 0xFF; uint extra_bits = 0; if (code == cSmallZeroRunCode) extra_bits = cSmallZeroRunExtraBits; else if (code == cLargeZeroRunCode) extra_bits = cLargeZeroRunExtraBits; else if (code == cSmallRepeatCode) extra_bits = cSmallNonZeroRunExtraBits; else if (code == cLargeRepeatCode) extra_bits = cLargeNonZeroRunExtraBits; total_bits += dm.get_cost(code); if (!simulate) encode(code, dm); if (extra_bits) { if (!simulate) encode_bits(extra, extra_bits); total_bits += extra_bits; } } return total_bits; } void symbol_codec::encode_bits(uint bits, uint num_bits) { CRNLIB_ASSERT(m_mode == cEncoding); if (!num_bits) return; CRNLIB_ASSERT((num_bits == 32) || (bits <= ((1U << num_bits) - 1))); if (num_bits > 16) { record_put_bits(bits >> 16, num_bits - 16); record_put_bits(bits & 0xFFFF, 16); } else record_put_bits(bits, num_bits); } void symbol_codec::encode_align_to_byte() { CRNLIB_ASSERT(m_mode == cEncoding); if (!m_simulate_encoding) { output_symbol sym; sym.m_bits = 0; sym.m_num_bits = output_symbol::cAlignToByteSym; sym.m_arith_prob0 = 0; m_output_syms.push_back(sym); } else { // We really don't know how many we're going to write, so just be conservative. m_total_bits_written += 7; } } void symbol_codec::encode(uint sym, adaptive_huffman_data_model& model) { CRNLIB_ASSERT(m_mode == cEncoding); CRNLIB_ASSERT(model.m_encoding); record_put_bits(model.m_codes[sym], model.m_code_sizes[sym]); uint freq = model.m_sym_freq[sym]; freq++; model.m_sym_freq[sym] = static_cast(freq); if (freq == cUINT16_MAX) model.rescale(); if (--model.m_symbols_until_update == 0) { m_total_model_updates++; model.update(); } } void symbol_codec::encode(uint sym, static_huffman_data_model& model) { CRNLIB_ASSERT(m_mode == cEncoding); CRNLIB_ASSERT(model.m_encoding); CRNLIB_ASSERT(model.m_code_sizes[sym]); record_put_bits(model.m_codes[sym], model.m_code_sizes[sym]); } void symbol_codec::encode_truncated_binary(uint v, uint n) { CRNLIB_ASSERT((n >= 2) && (v < n)); uint k = math::floor_log2i(n); uint u = (1 << (k + 1)) - n; if (v < u) encode_bits(v, k); else encode_bits(v + u, k + 1); } uint symbol_codec::encode_truncated_binary_cost(uint v, uint n) { CRNLIB_ASSERT((n >= 2) && (v < n)); uint k = math::floor_log2i(n); uint u = (1 << (k + 1)) - n; if (v < u) return k; else return k + 1; } void symbol_codec::encode_golomb(uint v, uint m) { CRNLIB_ASSERT(m > 0); uint q = v / m; uint r = v % m; while (q > 16) { encode_bits(0xFFFF, 16); q -= 16; } if (q) encode_bits( (1 << q) - 1, q); encode_bits(0, 1); encode_truncated_binary(r, m); } void symbol_codec::encode_rice(uint v, uint m) { CRNLIB_ASSERT(m > 0); uint q = v >> m; uint r = v & ((1 << m) - 1); while (q > 16) { encode_bits(0xFFFF, 16); q -= 16; } if (q) encode_bits( (1 << q) - 1, q); encode_bits(0, 1); encode_bits(r, m); } uint symbol_codec::encode_rice_get_cost(uint v, uint m) { CRNLIB_ASSERT(m > 0); uint q = v >> m; //uint r = v & ((1 << m) - 1); return q + 1 + m; } void symbol_codec::arith_propagate_carry() { int index = m_arith_output_buf.size() - 1; while (index >= 0) { uint c = m_arith_output_buf[index]; if (c == 0xFF) m_arith_output_buf[index] = 0; else { m_arith_output_buf[index]++; break; } index--; } } void symbol_codec::arith_renorm_enc_interval() { do { m_arith_output_buf.push_back( (m_arith_base >> 24) & 0xFF ); m_total_bits_written += 8; m_arith_base <<= 8; } while ((m_arith_length <<= 8) < cSymbolCodecArithMinLen); } void symbol_codec::arith_start_encoding() { m_arith_output_buf.resize(0); m_arith_base = 0; m_arith_value = 0; m_arith_length = cSymbolCodecArithMaxLen; m_arith_total_bits = 0; } void symbol_codec::encode(uint bit, adaptive_bit_model& model, bool update_model) { CRNLIB_ASSERT(m_mode == cEncoding); m_arith_total_bits++; if (!m_simulate_encoding) { output_symbol sym; sym.m_bits = bit; sym.m_num_bits = -1; sym.m_arith_prob0 = model.m_bit_0_prob; m_output_syms.push_back(sym); } //uint x = gArithProbMulTab[model.m_bit_0_prob >> (cSymbolCodecArithProbBits - cSymbolCodecArithProbMulBits)][m_arith_length >> (32 - cSymbolCodecArithProbMulLenSigBits)] << 16; uint x = model.m_bit_0_prob * (m_arith_length >> cSymbolCodecArithProbBits); if (!bit) { if (update_model) model.m_bit_0_prob += ((cSymbolCodecArithProbScale - model.m_bit_0_prob) >> cSymbolCodecArithProbMoveBits); m_arith_length = x; } else { if (update_model) model.m_bit_0_prob -= (model.m_bit_0_prob >> cSymbolCodecArithProbMoveBits); uint orig_base = m_arith_base; m_arith_base += x; m_arith_length -= x; if (orig_base > m_arith_base) arith_propagate_carry(); } if (m_arith_length < cSymbolCodecArithMinLen) arith_renorm_enc_interval(); } void symbol_codec::encode(uint sym, adaptive_arith_data_model& model) { uint node = 1; uint bitmask = model.m_total_syms; do { bitmask >>= 1; uint bit = (sym & bitmask) ? 1 : 0; encode(bit, model.m_probs[node]); node = (node << 1) + bit; } while (bitmask > 1); } void symbol_codec::arith_stop_encoding() { if (!m_arith_total_bits) return; uint orig_base = m_arith_base; if (m_arith_length > 2 * cSymbolCodecArithMinLen) { m_arith_base += cSymbolCodecArithMinLen; m_arith_length = (cSymbolCodecArithMinLen >> 1); } else { m_arith_base += (cSymbolCodecArithMinLen >> 1); m_arith_length = (cSymbolCodecArithMinLen >> 9); } if (orig_base > m_arith_base) arith_propagate_carry(); arith_renorm_enc_interval(); while (m_arith_output_buf.size() < 4) { m_arith_output_buf.push_back(0); m_total_bits_written += 8; } } void symbol_codec::stop_encoding(bool support_arith) { CRNLIB_ASSERT(m_mode == cEncoding); arith_stop_encoding(); if (!m_simulate_encoding) assemble_output_buf(support_arith); m_mode = cNull; } void symbol_codec::record_put_bits(uint bits, uint num_bits) { CRNLIB_ASSERT(m_mode == cEncoding); CRNLIB_ASSERT(num_bits <= 25); CRNLIB_ASSERT(m_bit_count >= 25); if (!num_bits) return; m_total_bits_written += num_bits; if (!m_simulate_encoding) { output_symbol sym; sym.m_bits = bits; sym.m_num_bits = (uint16)num_bits; sym.m_arith_prob0 = 0; m_output_syms.push_back(sym); } } void symbol_codec::put_bits_init(uint expected_size) { m_bit_buf = 0; m_bit_count = cBitBufSize; m_output_buf.resize(0); m_output_buf.reserve(expected_size); } void symbol_codec::put_bits(uint bits, uint num_bits) { CRNLIB_ASSERT(num_bits <= 25); CRNLIB_ASSERT(m_bit_count >= 25); if (!num_bits) return; m_bit_count -= num_bits; m_bit_buf |= (static_cast(bits) << m_bit_count); m_total_bits_written += num_bits; while (m_bit_count <= (cBitBufSize - 8)) { m_output_buf.push_back(static_cast(m_bit_buf >> (cBitBufSize - 8))); m_bit_buf <<= 8; m_bit_count += 8; } } void symbol_codec::put_bits_align_to_byte() { uint num_bits_in = cBitBufSize - m_bit_count; if (num_bits_in & 7) { put_bits(0, 8 - (num_bits_in & 7)); } } void symbol_codec::flush_bits() { //put_bits(15, 4); // for table look-ahead //put_bits(3, 3); // for table look-ahead put_bits(0, 7); // to ensure the last bits are flushed } void symbol_codec::assemble_output_buf(bool support_arith) { m_total_bits_written = 0; uint arith_buf_ofs = 0; if (support_arith) { if (m_arith_output_buf.size()) { put_bits(1, 1); m_arith_length = cSymbolCodecArithMaxLen; m_arith_value = 0; for (uint i = 0; i < 4; i++) { const uint c = m_arith_output_buf[arith_buf_ofs++]; m_arith_value = (m_arith_value << 8) | c; put_bits(c, 8); } } else { put_bits(0, 1); } } for (uint sym_index = 0; sym_index < m_output_syms.size(); sym_index++) { const output_symbol& sym = m_output_syms[sym_index]; if (sym.m_num_bits == output_symbol::cAlignToByteSym) { put_bits_align_to_byte(); } else if (sym.m_num_bits == output_symbol::cArithSym) { if (m_arith_length < cSymbolCodecArithMinLen) { do { const uint c = (arith_buf_ofs < m_arith_output_buf.size()) ? m_arith_output_buf[arith_buf_ofs++] : 0; put_bits(c, 8); m_arith_value = (m_arith_value << 8) | c; } while ((m_arith_length <<= 8) < cSymbolCodecArithMinLen); } //uint x = gArithProbMulTab[sym.m_arith_prob0 >> (cSymbolCodecArithProbBits - cSymbolCodecArithProbMulBits)][m_arith_length >> (32 - cSymbolCodecArithProbMulLenSigBits)] << 16; uint x = sym.m_arith_prob0 * (m_arith_length >> cSymbolCodecArithProbBits); uint bit = (m_arith_value >= x); if (bit == 0) { m_arith_length = x; } else { m_arith_value -= x; m_arith_length -= x; } CRNLIB_VERIFY(bit == sym.m_bits); } else { put_bits(sym.m_bits, sym.m_num_bits); } } flush_bits(); } //------------------------------------------------------------------------------------------------------------------ // Decoding //------------------------------------------------------------------------------------------------------------------ bool symbol_codec::start_decoding(const uint8* pBuf, size_t buf_size, bool eof_flag, need_bytes_func_ptr pNeed_bytes_func, void *pPrivate_data) { if (!buf_size) return false; m_total_model_updates = 0; m_pDecode_buf = pBuf; m_pDecode_buf_next = pBuf; m_decode_buf_size = buf_size; m_pDecode_buf_end = pBuf + buf_size; m_pDecode_need_bytes_func = pNeed_bytes_func; m_pDecode_private_data = pPrivate_data; m_decode_buf_eof = eof_flag; if (!pNeed_bytes_func) { m_decode_buf_eof = true; } m_mode = cDecoding; get_bits_init(); return true; } uint symbol_codec::decode_bits(uint num_bits) { CRNLIB_ASSERT(m_mode == cDecoding); if (!num_bits) return 0; if (num_bits > 16) { uint a = get_bits(num_bits - 16); uint b = get_bits(16); return (a << 16) | b; } else return get_bits(num_bits); } void symbol_codec::decode_remove_bits(uint num_bits) { CRNLIB_ASSERT(m_mode == cDecoding); while (num_bits > 16) { remove_bits(16); num_bits -= 16; } remove_bits(num_bits); } uint symbol_codec::decode_peek_bits(uint num_bits) { CRNLIB_ASSERT(m_mode == cDecoding); CRNLIB_ASSERT(num_bits <= 25); if (!num_bits) return 0; while (m_bit_count < (int)num_bits) { uint c = 0; if (m_pDecode_buf_next == m_pDecode_buf_end) { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; if (m_pDecode_buf_next < m_pDecode_buf_end) c = *m_pDecode_buf_next++; } } else c = *m_pDecode_buf_next++; m_bit_count += 8; CRNLIB_ASSERT(m_bit_count <= cBitBufSize); m_bit_buf |= (static_cast(c) << (cBitBufSize - m_bit_count)); } return static_cast(m_bit_buf >> (cBitBufSize - num_bits)); } uint symbol_codec::decode(adaptive_huffman_data_model& model) { CRNLIB_ASSERT(m_mode == cDecoding); CRNLIB_ASSERT(!model.m_encoding); const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables; while (m_bit_count < (cBitBufSize - 8)) { uint c = 0; if (m_pDecode_buf_next == m_pDecode_buf_end) { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; if (m_pDecode_buf_next < m_pDecode_buf_end) c = *m_pDecode_buf_next++; } } else c = *m_pDecode_buf_next++; m_bit_count += 8; m_bit_buf |= (static_cast(c) << (cBitBufSize - m_bit_count)); } uint k = static_cast((m_bit_buf >> (cBitBufSize - 16)) + 1); uint sym, len; if (k <= pTables->m_table_max_code) { uint32 t = pTables->m_lookup[m_bit_buf >> (cBitBufSize - pTables->m_table_bits)]; CRNLIB_ASSERT(t != cUINT32_MAX); sym = t & cUINT16_MAX; len = t >> 16; CRNLIB_ASSERT(model.m_code_sizes[sym] == len); } else { len = pTables->m_decode_start_code_size; for ( ; ; ) { if (k <= pTables->m_max_codes[len - 1]) break; len++; } int val_ptr = pTables->m_val_ptrs[len - 1] + static_cast((m_bit_buf >> (cBitBufSize - len))); if (((uint)val_ptr >= model.m_total_syms)) { // corrupted stream, or a bug CRNLIB_ASSERT(0); return 0; } sym = pTables->m_sorted_symbol_order[val_ptr]; } m_bit_buf <<= len; m_bit_count -= len; uint freq = model.m_sym_freq[sym]; freq++; model.m_sym_freq[sym] = static_cast(freq); if (freq == cUINT16_MAX) model.rescale(); if (--model.m_symbols_until_update == 0) { m_total_model_updates++; model.update(); } return sym; } void symbol_codec::decode_set_input_buffer(const uint8* pBuf, size_t buf_size, const uint8* pBuf_next, bool eof_flag) { CRNLIB_ASSERT(m_mode == cDecoding); m_pDecode_buf = pBuf; m_pDecode_buf_next = pBuf_next; m_decode_buf_size = buf_size; m_pDecode_buf_end = pBuf + buf_size; if (!m_pDecode_need_bytes_func) m_decode_buf_eof = true; else m_decode_buf_eof = eof_flag; } bool symbol_codec::decode_receive_static_huffman_data_model(static_huffman_data_model& model, static_huffman_data_model* pDeltaModel) { CRNLIB_ASSERT(m_mode == cDecoding); const uint total_used_syms = decode_bits(math::total_bits(prefix_coding::cMaxSupportedSyms)); if (!total_used_syms) { model.clear(); return true; } model.m_code_sizes.resize(total_used_syms); memset(&model.m_code_sizes[0], 0, sizeof(model.m_code_sizes[0]) * total_used_syms); const uint num_codelength_codes_to_send = decode_bits(5); if ((num_codelength_codes_to_send < 1) || (num_codelength_codes_to_send > cMaxCodelengthCodes)) return false; static_huffman_data_model dm; dm.m_code_sizes.resize(cMaxCodelengthCodes); for (uint i = 0; i < num_codelength_codes_to_send; i++) dm.m_code_sizes[g_most_probable_codelength_codes[i]] = static_cast(decode_bits(3)); if (!dm.prepare_decoder_tables()) return false; uint ofs = 0; while (ofs < total_used_syms) { const uint num_remaining = total_used_syms - ofs; uint code = decode(dm); if (code <= 16) model.m_code_sizes[ofs++] = static_cast(code); else if (code == cSmallZeroRunCode) { uint len = decode_bits(cSmallZeroRunExtraBits) + cMinSmallZeroRunSize; if (len > num_remaining) return false; ofs += len; } else if (code == cLargeZeroRunCode) { uint len = decode_bits(cLargeZeroRunExtraBits) + cMinLargeZeroRunSize; if (len > num_remaining) return false; ofs += len; } else if ((code == cSmallRepeatCode) || (code == cLargeRepeatCode)) { uint len; if (code == cSmallRepeatCode) len = decode_bits(cSmallNonZeroRunExtraBits) + cSmallMinNonZeroRunSize; else len = decode_bits(cLargeNonZeroRunExtraBits) + cLargeMinNonZeroRunSize; if ((!ofs) || (len > num_remaining)) return false; const uint prev = model.m_code_sizes[ofs - 1]; if (!prev) return false; const uint end = ofs + len; while (ofs < end) model.m_code_sizes[ofs++] = static_cast(prev); } else { CRNLIB_ASSERT(0); return false; } } if (ofs != total_used_syms) return false; if ((pDeltaModel) && (pDeltaModel->get_total_syms())) { uint n = math::minimum(pDeltaModel->m_code_sizes.size(), total_used_syms); for (uint i = 0; i < n; i++) { int codesize = model.m_code_sizes[i] + pDeltaModel->m_code_sizes[i]; if (codesize > 16) codesize -= 17; model.m_code_sizes[i] = static_cast(codesize); } } return model.prepare_decoder_tables(); } uint symbol_codec::decode(static_huffman_data_model& model) { CRNLIB_ASSERT(m_mode == cDecoding); CRNLIB_ASSERT(!model.m_encoding); const prefix_coding::decoder_tables* pTables = model.m_pDecode_tables; while (m_bit_count < (cBitBufSize - 8)) { uint c = 0; if (m_pDecode_buf_next == m_pDecode_buf_end) { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; if (m_pDecode_buf_next < m_pDecode_buf_end) c = *m_pDecode_buf_next++; } } else c = *m_pDecode_buf_next++; m_bit_count += 8; m_bit_buf |= (static_cast(c) << (cBitBufSize - m_bit_count)); } uint k = static_cast((m_bit_buf >> (cBitBufSize - 16)) + 1); uint sym, len; if (k <= pTables->m_table_max_code) { uint32 t = pTables->m_lookup[m_bit_buf >> (cBitBufSize - pTables->m_table_bits)]; CRNLIB_ASSERT(t != cUINT32_MAX); sym = t & cUINT16_MAX; len = t >> 16; CRNLIB_ASSERT(model.m_code_sizes[sym] == len); } else { len = pTables->m_decode_start_code_size; for ( ; ; ) { if (k <= pTables->m_max_codes[len - 1]) break; len++; } int val_ptr = pTables->m_val_ptrs[len - 1] + static_cast((m_bit_buf >> (cBitBufSize - len))); if (((uint)val_ptr >= model.m_total_syms)) { // corrupted stream, or a bug CRNLIB_ASSERT(0); return 0; } sym = pTables->m_sorted_symbol_order[val_ptr]; } m_bit_buf <<= len; m_bit_count -= len; return sym; } uint symbol_codec::decode_truncated_binary(uint n) { CRNLIB_ASSERT(n >= 2); uint k = math::floor_log2i(n); uint u = (1 << (k + 1)) - n; uint i = decode_bits(k); if (i >= u) i = ((i << 1) | decode_bits(1)) - u; return i; } uint symbol_codec::decode_golomb(uint m) { CRNLIB_ASSERT(m > 1); uint q = 0; for ( ; ; ) { uint k = decode_peek_bits(16); uint l = utils::count_leading_zeros16((~k) & 0xFFFF); q += l; if (l < 16) break; } decode_remove_bits(q + 1); uint r = decode_truncated_binary(m); return (q * m) + r; } uint symbol_codec::decode_rice(uint m) { CRNLIB_ASSERT(m > 0); uint q = 0; for ( ; ; ) { uint k = decode_peek_bits(16); uint l = utils::count_leading_zeros16((~k) & 0xFFFF); q += l; decode_remove_bits(l); if (l < 16) break; } decode_remove_bits(1); uint r = decode_bits(m); return (q << m) + r; } uint64 symbol_codec::stop_decoding() { CRNLIB_ASSERT(m_mode == cDecoding); uint64 n = m_pDecode_buf_next - m_pDecode_buf; m_mode = cNull; return n; } void symbol_codec::get_bits_init() { m_bit_buf = 0; m_bit_count = 0; } uint symbol_codec::get_bits(uint num_bits) { CRNLIB_ASSERT(num_bits <= 25); if (!num_bits) return 0; while (m_bit_count < (int)num_bits) { uint c = 0; if (m_pDecode_buf_next == m_pDecode_buf_end) { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; if (m_pDecode_buf_next < m_pDecode_buf_end) c = *m_pDecode_buf_next++; } } else c = *m_pDecode_buf_next++; m_bit_count += 8; CRNLIB_ASSERT(m_bit_count <= cBitBufSize); m_bit_buf |= (static_cast(c) << (cBitBufSize - m_bit_count)); } uint result = static_cast(m_bit_buf >> (cBitBufSize - num_bits)); m_bit_buf <<= num_bits; m_bit_count -= num_bits; return result; } void symbol_codec::remove_bits(uint num_bits) { CRNLIB_ASSERT(num_bits <= 25); if (!num_bits) return; while (m_bit_count < (int)num_bits) { uint c = 0; if (m_pDecode_buf_next == m_pDecode_buf_end) { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; if (m_pDecode_buf_next < m_pDecode_buf_end) c = *m_pDecode_buf_next++; } } else c = *m_pDecode_buf_next++; m_bit_count += 8; CRNLIB_ASSERT(m_bit_count <= cBitBufSize); m_bit_buf |= (static_cast(c) << (cBitBufSize - m_bit_count)); } m_bit_buf <<= num_bits; m_bit_count -= num_bits; } void symbol_codec::decode_align_to_byte() { CRNLIB_ASSERT(m_mode == cDecoding); if (m_bit_count & 7) { remove_bits(m_bit_count & 7); } } int symbol_codec::decode_remove_byte_from_bit_buf() { if (m_bit_count < 8) return -1; int result = static_cast(m_bit_buf >> (cBitBufSize - 8)); m_bit_buf <<= 8; m_bit_count -= 8; return result; } uint symbol_codec::decode(adaptive_bit_model& model, bool update_model) { if (m_arith_length < cSymbolCodecArithMinLen) { uint c = get_bits(8); m_arith_value = (m_arith_value << 8) | c; m_arith_length <<= 8; CRNLIB_ASSERT(m_arith_length >= cSymbolCodecArithMinLen); } CRNLIB_ASSERT(m_arith_length >= cSymbolCodecArithMinLen); //uint x = gArithProbMulTab[model.m_bit_0_prob >> (cSymbolCodecArithProbBits - cSymbolCodecArithProbMulBits)][m_arith_length >> (32 - cSymbolCodecArithProbMulLenSigBits)] << 16; uint x = model.m_bit_0_prob * (m_arith_length >> cSymbolCodecArithProbBits); uint bit = (m_arith_value >= x); if (!bit) { if (update_model) model.m_bit_0_prob += ((cSymbolCodecArithProbScale - model.m_bit_0_prob) >> cSymbolCodecArithProbMoveBits); m_arith_length = x; } else { if (update_model) model.m_bit_0_prob -= (model.m_bit_0_prob >> cSymbolCodecArithProbMoveBits); m_arith_value -= x; m_arith_length -= x; } return bit; } uint symbol_codec::decode(adaptive_arith_data_model& model) { uint node = 1; do { uint bit = decode(model.m_probs[node]); node = (node << 1) + bit; } while (node < model.m_total_syms); return node - model.m_total_syms; } void symbol_codec::start_arith_decoding() { CRNLIB_ASSERT(m_mode == cDecoding); m_arith_length = cSymbolCodecArithMaxLen; m_arith_value = 0; if (get_bits(1)) { m_arith_value = (get_bits(8) << 24); m_arith_value |= (get_bits(8) << 16); m_arith_value |= (get_bits(8) << 8); m_arith_value |= get_bits(8); } } void symbol_codec::decode_need_bytes() { if (!m_decode_buf_eof) { m_pDecode_need_bytes_func(m_pDecode_buf_next - m_pDecode_buf, m_pDecode_private_data, m_pDecode_buf, m_decode_buf_size, m_decode_buf_eof); m_pDecode_buf_end = m_pDecode_buf + m_decode_buf_size; m_pDecode_buf_next = m_pDecode_buf; } } } // namespace crnlib