mirror of
https://github.com/exoticorn/upkr.git
synced 2026-01-20 19:46:42 +01:00
add remaining encoding config options + presets for x86 and z80
This commit is contained in:
73
src/rans.rs
73
src/rans.rs
@@ -1,4 +1,4 @@
|
||||
use crate::context_state::Context;
|
||||
use crate::{context_state::Context, Config};
|
||||
|
||||
pub const PROB_BITS: u32 = 8;
|
||||
pub const ONE_PROB: u32 = 1 << PROB_BITS;
|
||||
@@ -15,20 +15,25 @@ pub trait EntropyCoder {
|
||||
pub struct RansCoder {
|
||||
bits: Vec<u16>,
|
||||
use_bitstream: bool,
|
||||
bitstream_is_big_endian: bool,
|
||||
invert_bit_encoding: bool,
|
||||
}
|
||||
|
||||
impl EntropyCoder for RansCoder {
|
||||
fn encode_bit(&mut self, bit: bool, prob: u16) {
|
||||
assert!(prob < 32768);
|
||||
self.bits.push(prob | ((bit as u16) << 15));
|
||||
self.bits
|
||||
.push(prob | (((bit ^ self.invert_bit_encoding) as u16) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
impl RansCoder {
|
||||
pub fn new(use_bitstream: bool) -> RansCoder {
|
||||
pub fn new(config: &Config) -> RansCoder {
|
||||
RansCoder {
|
||||
bits: Vec::new(),
|
||||
use_bitstream,
|
||||
use_bitstream: config.use_bitstream,
|
||||
bitstream_is_big_endian: config.bitstream_is_big_endian,
|
||||
invert_bit_encoding: config.invert_bit_encoding,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,18 +43,31 @@ impl RansCoder {
|
||||
let mut state = 1 << l_bits;
|
||||
|
||||
let mut byte = 0u8;
|
||||
let mut bit = 8;
|
||||
let mut bit = if self.bitstream_is_big_endian { 0 } else { 8 };
|
||||
let mut flush_state: Box<dyn FnMut(&mut u32)> = if self.use_bitstream {
|
||||
Box::new(|state: &mut u32| {
|
||||
bit -= 1;
|
||||
byte |= ((*state & 1) as u8) << bit;
|
||||
if bit == 0 {
|
||||
buffer.push(byte);
|
||||
byte = 0;
|
||||
bit = 8;
|
||||
}
|
||||
*state >>= 1;
|
||||
})
|
||||
if self.bitstream_is_big_endian {
|
||||
Box::new(|state: &mut u32| {
|
||||
byte |= ((*state & 1) as u8) << bit;
|
||||
bit += 1;
|
||||
if bit == 8 {
|
||||
buffer.push(byte);
|
||||
byte = 0;
|
||||
bit = 0;
|
||||
}
|
||||
*state >>= 1;
|
||||
})
|
||||
} else {
|
||||
Box::new(|state: &mut u32| {
|
||||
bit -= 1;
|
||||
byte |= ((*state & 1) as u8) << bit;
|
||||
if bit == 0 {
|
||||
buffer.push(byte);
|
||||
byte = 0;
|
||||
bit = 8;
|
||||
}
|
||||
*state >>= 1;
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Box::new(|state: &mut u32| {
|
||||
buffer.push(*state as u8);
|
||||
@@ -91,10 +109,11 @@ impl RansCoder {
|
||||
pub struct CostCounter {
|
||||
cost: f64,
|
||||
log2_table: Vec<f64>,
|
||||
invert_bit_encoding: bool,
|
||||
}
|
||||
|
||||
impl CostCounter {
|
||||
pub fn new() -> CostCounter {
|
||||
pub fn new(config: &Config) -> CostCounter {
|
||||
let log2_table = (0..ONE_PROB)
|
||||
.map(|prob| {
|
||||
let inv_prob = ONE_PROB as f64 / prob as f64;
|
||||
@@ -104,6 +123,7 @@ impl CostCounter {
|
||||
CostCounter {
|
||||
cost: 0.0,
|
||||
log2_table,
|
||||
invert_bit_encoding: config.invert_bit_encoding,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +138,7 @@ impl CostCounter {
|
||||
|
||||
impl EntropyCoder for CostCounter {
|
||||
fn encode_bit(&mut self, bit: bool, prob: u16) {
|
||||
let prob = if bit {
|
||||
let prob = if bit ^ self.invert_bit_encoding {
|
||||
prob as u32
|
||||
} else {
|
||||
ONE_PROB - prob as u32
|
||||
@@ -133,18 +153,22 @@ pub struct RansDecoder<'a> {
|
||||
use_bitstream: bool,
|
||||
byte: u8,
|
||||
bits_left: u8,
|
||||
invert_bit_encoding: bool,
|
||||
bitstream_is_big_endian: bool,
|
||||
}
|
||||
|
||||
const PROB_MASK: u32 = ONE_PROB - 1;
|
||||
|
||||
impl<'a> RansDecoder<'a> {
|
||||
pub fn new(data: &'a [u8], use_bitstream: bool) -> RansDecoder<'a> {
|
||||
pub fn new(data: &'a [u8], config: &Config) -> RansDecoder<'a> {
|
||||
RansDecoder {
|
||||
data,
|
||||
state: 0,
|
||||
use_bitstream,
|
||||
use_bitstream: config.use_bitstream,
|
||||
byte: 0,
|
||||
bits_left: 0,
|
||||
invert_bit_encoding: config.invert_bit_encoding,
|
||||
bitstream_is_big_endian: config.bitstream_is_big_endian,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +187,13 @@ impl<'a> RansDecoder<'a> {
|
||||
self.data = &self.data[1..];
|
||||
self.bits_left = 8;
|
||||
}
|
||||
self.state = (self.state << 1) | (self.byte & 1) as u32;
|
||||
self.byte >>= 1;
|
||||
if self.bitstream_is_big_endian {
|
||||
self.state = (self.state << 1) | (self.byte >> 7) as u32;
|
||||
self.byte <<= 1;
|
||||
} else {
|
||||
self.state = (self.state << 1) | (self.byte & 1) as u32;
|
||||
self.byte >>= 1;
|
||||
}
|
||||
self.bits_left -= 1;
|
||||
}
|
||||
} else {
|
||||
@@ -183,6 +212,6 @@ impl<'a> RansDecoder<'a> {
|
||||
};
|
||||
self.state = prob * (self.state >> PROB_BITS) + (self.state & PROB_MASK) - start;
|
||||
|
||||
bit
|
||||
bit ^ self.invert_bit_encoding
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user