mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-04-22 22:00:15 +08:00
228 lines
6.1 KiB
Markdown
228 lines
6.1 KiB
Markdown
|
|
## Rans Decoding
|
|
|
|
### DecodeSymbols()
|
|
|
|
~~~~~
|
|
void DecodeSymbols(num_symbols, num_components, out_values) {
|
|
scheme UI8
|
|
if (scheme == 0) {
|
|
DecodeTaggedSymbols(num_symbols, num_components, out_values);
|
|
} else if (scheme == 1) {
|
|
DecodeRawSymbols(num_symbols, out_values);
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### ComputeRAnsUnclampedPrecision
|
|
|
|
~~~~~
|
|
int ComputeRAnsUnclampedPrecision(max_bit_length) {
|
|
return (3 * max_bit_length) / 2;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### ComputeRAnsPrecisionFromMaxSymbolBitLength
|
|
|
|
~~~~~
|
|
int ComputeRAnsPrecisionFromMaxSymbolBitLength(max_bit_length) {
|
|
return ComputeRAnsUnclampedPrecision(max_bit_length) < 12
|
|
? 12
|
|
: ComputeRAnsUnclampedPrecision(max_bit_length) > 20
|
|
? 20
|
|
: ComputeRAnsUnclampedPrecision(max_bit_length);
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### DecodeTaggedSymbols
|
|
|
|
~~~~~
|
|
void DecodeTaggedSymbols(num_values, num_components, out_values) {
|
|
max_symbol_bit_length_t = 5;
|
|
rans_precision_bits_t =
|
|
ComputeRAnsPrecisionFromMaxSymbolBitLength(max_symbol_bit_length_t);
|
|
rans_precision = 1 << rans_precision_bits_t;
|
|
l_rans_base = rans_precision * 4;
|
|
num_symbols_ varUI32
|
|
BuildSymbolTables(num_symbols_, lut_table_, probability_table_);
|
|
bytes_encoded varUI64
|
|
encoded_data UI8[size]
|
|
|
|
RansInitDecoder(ans_, &encoded_data[0], bytes_encoded, l_rans_base);
|
|
for (i = 0; i < num_values; i += num_components) {
|
|
RansRead(ans_, l_rans_base, rans_precision,
|
|
lut_table_, probability_table_, &bit_length);
|
|
for (j = 0; j < num_components; ++j) {
|
|
val f[bit_length]
|
|
out_values.push_back(val);
|
|
}
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### DecodeRawSymbols
|
|
|
|
~~~~~
|
|
void DecodeRawSymbols(num_values, out_values) {
|
|
max_bit_length UI8
|
|
num_symbols_ varUI32
|
|
rans_precision_bits = (3 * max_bit_length) / 2;
|
|
if (rans_precision_bits > 20)
|
|
rans_precision_bits = 20;
|
|
if (rans_precision_bits < 12)
|
|
rans_precision_bits = 12;
|
|
rans_precision = 1 << rans_precision_bits;
|
|
l_rans_base = rans_precision * 4;
|
|
BuildSymbolTables(num_symbols_, lut_table_, probability_table_);
|
|
bytes_encoded UI64
|
|
buffer UI8[size]
|
|
RansInitDecoder(ans_, &buffer[0], bytes_encoded, l_rans_base);
|
|
for (i = 0; i < num_values; ++i) {
|
|
RansRead(ans_, l_rans_base, rans_precision,
|
|
lut_table_, probability_table_, &val);
|
|
out_values.push_back(val);
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### BuildSymbolTables
|
|
|
|
~~~~~
|
|
void BuildSymbolTables(num_symbols_, lut_table_, probability_table_) {
|
|
for (i = 0; i < num_symbols_; ++i) {
|
|
// Decode the first byte and extract the number of extra bytes we need to
|
|
// get, or the offset to the next symbol with non-zero probability.
|
|
prob_data UI8
|
|
token = prob_data & 3;
|
|
if (token == 3) {
|
|
offset = prob_data >> 2;
|
|
for (j = 0; j < offset + 1; ++j) {
|
|
token_probs[i + j] = 0;
|
|
}
|
|
i += offset;
|
|
} else {
|
|
prob = prob_data >> 2;
|
|
for (j = 0; j < token; ++j) {
|
|
eb UI8
|
|
prob = prob | (eb << (8 * (j + 1) - 2));
|
|
}
|
|
token_probs[i] = prob;
|
|
}
|
|
}
|
|
rans_build_look_up_table(&token_probs[0], num_symbols_, lut_table_,
|
|
probability_table_);
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### rans_build_look_up_table
|
|
|
|
~~~~~
|
|
void rans_build_look_up_table(
|
|
token_probs[], num_symbols, lut_table_, probability_table_) {
|
|
cum_prob = 0;
|
|
act_prob = 0;
|
|
for (i = 0; i < num_symbols; ++i) {
|
|
probability_table_[i].prob = token_probs[i];
|
|
probability_table_[i].cum_prob = cum_prob;
|
|
cum_prob += token_probs[i];
|
|
for (j = act_prob; j < cum_prob; ++j) {
|
|
lut_table_[j] = i;
|
|
}
|
|
act_prob = cum_prob;
|
|
}
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### RansInitDecoder
|
|
|
|
~~~~~
|
|
void RansInitDecoder(ans, buf, offset, l_rans_base) {
|
|
ans.buf = buf;
|
|
x = buf[offset - 1] >> 6;
|
|
if (x == 0) {
|
|
ans.buf_offset = offset - 1;
|
|
ans.state = buf[offset - 1] & 0x3F;
|
|
} else if (x == 1) {
|
|
ans.buf_offset = offset - 2;
|
|
ans.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
|
|
} else if (x == 2) {
|
|
ans.buf_offset = offset - 3;
|
|
ans.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
|
|
} else if (x == 3) {
|
|
ans.buf_offset = offset - 4;
|
|
ans.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
|
|
}
|
|
ans.state += l_rans_base;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### RansRead
|
|
|
|
~~~~~
|
|
void RansRead(ans, l_rans_base, rans_precision,
|
|
lut_table_, probability_table_, val) {
|
|
while (ans.state < l_rans_base && ans.buf_offset > 0) {
|
|
ans.state = ans.state * IO_BASE + ans.buf[--ans.buf_offset];
|
|
}
|
|
quo = ans.state / rans_precision;
|
|
rem = ans.state % rans_precision;
|
|
fetch_sym(&sym, rem, lut_table_, probability_table_);
|
|
ans.state = quo * sym.prob + rem - sym.cum_prob;
|
|
val = sym.val;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### fetch_sym
|
|
|
|
~~~~~
|
|
void fetch_sym(sym, rem, lut_table_, probability_table_) {
|
|
symbol = lut_table_[rem];
|
|
sym.val = symbol;
|
|
sym.prob = probability_table_[symbol].prob;
|
|
sym.cum_prob = probability_table_[symbol].cum_prob;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|
|
|
|
|
|
### RabsDescRead
|
|
|
|
~~~~~
|
|
void RabsDescRead(ans, p0, out_val) {
|
|
p = rabs_ans_p8_precision - p0;
|
|
if (ans.state < rabs_l_base) {
|
|
ans.state = ans.state * IO_BASE + ans.buf[--ans.buf_offset];
|
|
}
|
|
x = ans.state;
|
|
quot = x / rabs_ans_p8_precision;
|
|
rem = x % rabs_ans_p8_precision;
|
|
xn = quot * p;
|
|
val = rem < p;
|
|
if (val) {
|
|
ans.state = xn + rem;
|
|
} else {
|
|
ans.state = x - xn - p;
|
|
}
|
|
out_val = val;
|
|
}
|
|
~~~~~
|
|
{:.draco-syntax }
|