xenia-canary/third_party/crunch/crnlib/crn_symbol_codec.cpp

1902 lines
49 KiB
C++
Raw Normal View History

2014-01-21 07:02:34 +00:00
// 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<prefix_coding::decoder_tables>(*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<uint8>(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<prefix_coding::decoder_tables>();
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<uint16>(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<prefix_coding::decoder_tables>(*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<prefix_coding::decoder_tables>();
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<uint16> 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<uint16>(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<uint16>(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<uint8>(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<prefix_coding::decoder_tables>();
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<prefix_coding::decoder_tables>();
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<uint8>(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<uint16>(math::clamp<uint>((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<uint16>& codes)
{
if (!size)
return;
if (size < cMinSmallZeroRunSize)
{
while (size--)
codes.push_back(0);
}
else if (size <= cMaxSmallZeroRunSize)
codes.push_back( static_cast<uint16>(cSmallZeroRunCode | ((size - cMinSmallZeroRunSize) << 8)) );
else
{
CRNLIB_ASSERT((size >= cMinLargeZeroRunSize) && (size <= cMaxLargeZeroRunSize));
codes.push_back( static_cast<uint16>(cLargeZeroRunCode | ((size - cMinLargeZeroRunSize) << 8)) );
}
size = 0;
}
static inline void end_nonzero_run(uint& size, uint len, crnlib::vector<uint16>& codes)
{
if (!size)
return;
if (size < cSmallMinNonZeroRunSize)
{
while (size--)
codes.push_back(static_cast<uint16>(len));
}
else if (size <= cSmallMaxNonZeroRunSize)
{
codes.push_back(static_cast<uint16>(cSmallRepeatCode | ((size - cSmallMinNonZeroRunSize) << 8)));
}
else
{
CRNLIB_ASSERT((size >= cLargeMinNonZeroRunSize) && (size <= cLargeMaxNonZeroRunSize));
codes.push_back(static_cast<uint16>(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<uint16> 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<uint8> 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<uint8>(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<uint16>(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<uint16>(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<uint16>(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<bit_buf_t>(bits) << m_bit_count);
m_total_bits_written += num_bits;
while (m_bit_count <= (cBitBufSize - 8))
{
m_output_buf.push_back(static_cast<uint8>(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<bit_buf_t>(c) << (cBitBufSize - m_bit_count));
}
return static_cast<uint>(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<bit_buf_t>(c) << (cBitBufSize - m_bit_count));
}
uint k = static_cast<uint>((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<int>((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<uint16>(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<uint8>(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<uint8>(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<uint8>(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<uint8>(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<bit_buf_t>(c) << (cBitBufSize - m_bit_count));
}
uint k = static_cast<uint>((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<int>((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<bit_buf_t>(c) << (cBitBufSize - m_bit_count));
}
uint result = static_cast<uint>(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<bit_buf_t>(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<int>(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