mirror of
https://github.com/exoticorn/upkr.git
synced 2026-01-20 11:36:42 +01:00
add bitstream variant, could be useful on 8bit platforms
This commit is contained in:
90
src/rans.rs
90
src/rans.rs
@@ -1,6 +1,5 @@
|
||||
use crate::context_state::Context;
|
||||
|
||||
const L_BITS: u32 = 12;
|
||||
pub const PROB_BITS: u32 = 8;
|
||||
pub const ONE_PROB: u32 = 1 << PROB_BITS;
|
||||
|
||||
@@ -13,43 +12,75 @@ pub trait EntropyCoder {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RansCoder(Vec<u16>);
|
||||
pub struct RansCoder {
|
||||
bits: Vec<u16>,
|
||||
use_bitstream: bool,
|
||||
}
|
||||
|
||||
impl EntropyCoder for RansCoder {
|
||||
fn encode_bit(&mut self, bit: bool, prob: u16) {
|
||||
assert!(prob < 32768);
|
||||
self.0.push(prob | ((bit as u16) << 15));
|
||||
self.bits.push(prob | ((bit as u16) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
impl RansCoder {
|
||||
pub fn new() -> RansCoder {
|
||||
RansCoder(Vec::new())
|
||||
pub fn new(use_bitstream: bool) -> RansCoder {
|
||||
RansCoder {
|
||||
bits: Vec::new(),
|
||||
use_bitstream,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(self) -> Vec<u8> {
|
||||
let mut buffer = vec![];
|
||||
let mut state = 1 << L_BITS;
|
||||
let l_bits: u32 = if self.use_bitstream { 15 } else { 12 };
|
||||
let mut state = 1 << l_bits;
|
||||
|
||||
const MAX_STATE_FACTOR: u32 = 1 << (L_BITS + 8 - PROB_BITS);
|
||||
for step in self.0.into_iter().rev() {
|
||||
let mut byte = 0u8;
|
||||
let mut bit = 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;
|
||||
})
|
||||
} else {
|
||||
Box::new(|state: &mut u32| {
|
||||
buffer.push(*state as u8);
|
||||
*state >>= 8;
|
||||
})
|
||||
};
|
||||
|
||||
let num_flush_bits = if self.use_bitstream { 1 } else { 8 };
|
||||
let max_state_factor: u32 = 1 << (l_bits + num_flush_bits - PROB_BITS);
|
||||
for step in self.bits.into_iter().rev() {
|
||||
let prob = step as u32 & 32767;
|
||||
let (start, prob) = if step & 32768 != 0 {
|
||||
(0, prob)
|
||||
} else {
|
||||
(prob, ONE_PROB - prob)
|
||||
};
|
||||
let max_state = MAX_STATE_FACTOR * prob;
|
||||
let max_state = max_state_factor * prob;
|
||||
while state >= max_state {
|
||||
buffer.push(state as u8);
|
||||
state >>= 8;
|
||||
flush_state(&mut state);
|
||||
}
|
||||
state = ((state / prob) << PROB_BITS) + (state % prob) + start;
|
||||
}
|
||||
|
||||
while state > 0 {
|
||||
buffer.push(state as u8);
|
||||
state >>= 8;
|
||||
flush_state(&mut state);
|
||||
}
|
||||
|
||||
drop(flush_state);
|
||||
|
||||
if self.use_bitstream && byte != 0 {
|
||||
buffer.push(byte);
|
||||
}
|
||||
|
||||
buffer.reverse();
|
||||
@@ -99,14 +130,22 @@ impl EntropyCoder for CostCounter {
|
||||
pub struct RansDecoder<'a> {
|
||||
data: &'a [u8],
|
||||
state: u32,
|
||||
use_bitstream: bool,
|
||||
byte: u8,
|
||||
bits_left: u8,
|
||||
}
|
||||
|
||||
const PROB_MASK: u32 = ONE_PROB - 1;
|
||||
const L: u32 = 1 << L_BITS;
|
||||
|
||||
impl<'a> RansDecoder<'a> {
|
||||
pub fn new(data: &'a [u8]) -> RansDecoder<'a> {
|
||||
RansDecoder { data, state: 0 }
|
||||
pub fn new(data: &'a [u8], use_bitstream: bool) -> RansDecoder<'a> {
|
||||
RansDecoder {
|
||||
data,
|
||||
state: 0,
|
||||
use_bitstream,
|
||||
byte: 0,
|
||||
bits_left: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_with_context(&mut self, context: &mut Context) -> bool {
|
||||
@@ -117,9 +156,22 @@ impl<'a> RansDecoder<'a> {
|
||||
|
||||
pub fn decode_bit(&mut self, prob: u16) -> bool {
|
||||
let prob = prob as u32;
|
||||
while self.state < L {
|
||||
self.state = (self.state << 8) | self.data[0] as u32;
|
||||
self.data = &self.data[1..];
|
||||
if self.use_bitstream {
|
||||
while self.state < 32768 {
|
||||
if self.bits_left == 0 {
|
||||
self.byte = self.data[0];
|
||||
self.data = &self.data[1..];
|
||||
self.bits_left = 8;
|
||||
}
|
||||
self.state = (self.state << 1) | (self.byte & 1) as u32;
|
||||
self.byte >>= 1;
|
||||
self.bits_left -= 1;
|
||||
}
|
||||
} else {
|
||||
while self.state < 4096 {
|
||||
self.state = (self.state << 8) | self.data[0] as u32;
|
||||
self.data = &self.data[1..];
|
||||
}
|
||||
}
|
||||
|
||||
let bit = (self.state & PROB_MASK) < prob;
|
||||
|
||||
Reference in New Issue
Block a user