1902 lines
49 KiB
C++
1902 lines
49 KiB
C++
// 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
|