-use nihav_core::io::byteio::*;
use nihav_core::codecs::{EncoderResult, EncoderError};
use nihav_codec_support::codecs::MV;
+use crate::codecs::vpenc::coder::*;
+use crate::codecs::vpenc::models::*;
use super::super::vpcommon::*;
use super::super::vp6data::*;
use super::models::*;
-struct EncSeq {
- bit: bool,
- idx: u8,
-}
-
-pub struct TokenSeq<T: PartialEq> {
- val: T,
- seq: &'static [EncSeq],
-}
-
-macro_rules! bit_entry {
- (T; $idx:expr) => {EncSeq {bit: true, idx: $idx }};
- (F; $idx:expr) => {EncSeq {bit: false, idx: $idx }};
-}
-
-macro_rules! bit_seq {
- ($val: expr; $( $bit:tt),* ; $( $idx:expr),* ) => {
- TokenSeq {
- val: $val,
- seq:
- &[
- $(
- bit_entry!($bit; $idx),
- )*
- ]
- }
- };
-}
+pub use crate::codecs::vpenc::coder::{BoolEncoder, Estimator};
pub const MODE_TREE: &[TokenSeq<VPMBType>] = &[
bit_seq!(VPMBType::Intra; T, F, F; 0, 2, 5),
bit_seq!(9; T, T; 0, 4),
];
-pub struct BoolEncoder<'a, 'b> {
- bw: &'a mut ByteWriter<'b>,
- val: u32,
- range: u32,
- bits: u8,
- saved: u8,
- run: usize,
+pub trait EncoderTrait {
+ fn write_cat(&mut self, cat: i8, tree: &[TokenSeq<i8>], tok_probs: &[u8], val_probs: &[u8; 11]) -> EncoderResult<()>;
+ fn write_large_coef(&mut self, val: i16, cat: usize) -> EncoderResult<()>;
+ fn write_dc(&mut self, val: i16, tok_probs: &[u8; 5], val_probs: &[u8; 11]) -> EncoderResult<()>;
+ fn write_ac(&mut self, val: i16, tree: &[TokenSeq<i8>], probs: &[u8; 11]) -> EncoderResult<()>;
+ fn write_zero_run(&mut self, val: usize, probs: &[u8; 14]) -> EncoderResult<()>;
}
-impl<'a, 'b> BoolEncoder<'a, 'b> {
- pub fn new(bw: &'a mut ByteWriter<'b>) -> Self {
- Self {
- bw,
- val: 0,
- range: 255,
- bits: 0,
- saved: 0,
- run: 0,
- }
- }
- pub fn put_bool(&mut self, bit: bool, prob: u8) -> EncoderResult<()> {
- let split = 1 + (((self.range - 1) * u32::from(prob)) >> 8);
- if bit {
- self.range -= split;
- self.val += split;
- } else {
- self.range = split;
- }
-
- if self.range < 128 {
- self.renorm()?;
- }
- Ok(())
- }
- fn flush_run(&mut self, overflow: bool) -> EncoderResult<()> {
- if self.run > 0 {
- self.bw.write_byte(self.saved + (overflow as u8))?;
- if !overflow {
- for _ in 1..self.run {
- self.bw.write_byte(0xFF)?;
- }
- } else {
- for _ in 1..self.run {
- self.bw.write_byte(0)?;
- }
- }
- self.run = 0;
- }
- Ok(())
- }
- fn renorm(&mut self) -> EncoderResult<()> {
- let bits = (self.range.leading_zeros() & 7) as u8;
- self.range <<= bits;
- if self.bits + bits < 23 {
- self.bits += bits;
- self.val <<= bits;
- } else {
- for _ in 0..bits {
- if (self.bits == 23) && ((self.val >> 31) != 0) {
- self.flush_run(true)?;
- }
- self.val <<= 1;
- self.bits += 1;
- if self.bits == 24 {
- let tbyte = (self.val >> 24) as u8;
- let nbyte = (self.val >> 16) as u8;
- if tbyte < 0xFF {
- self.flush_run(false)?;
- if nbyte < 0xFE {
- self.bw.write_byte(tbyte)?;
- } else {
- self.saved = tbyte;
- self.run = 1;
- }
- } else {
- self.run += 1;
- }
- self.val &= 0xFFFFFF;
- self.bits -= 8;
- }
- }
- }
- Ok(())
- }
- pub fn flush(mut self) -> EncoderResult<()> {
- self.flush_run(false)?;
- self.val <<= 24 - self.bits;
- self.bw.write_u32be(self.val)?;
- Ok(())
- }
-
- pub fn put_bits(&mut self, val: u32, len: u8) -> EncoderResult<()> {
- let mut mask = 1 << (len - 1);
- while mask != 0 {
- self.put_bool((val & mask) != 0, 128)?;
- mask >>= 1;
- }
- Ok(())
- }
- fn put_probability(&mut self, prob: u8) -> EncoderResult<()> {
- self.put_bits(u32::from(prob >> 1), 7)
- }
- fn encode_probability(&mut self, new: u8, old: u8, prob: u8) -> EncoderResult<()> {
- self.put_bool(new != old, prob)?;
- if new != old {
- self.put_probability(new)?;
- }
- Ok(())
- }
- pub fn write_el<T: PartialEq>(&mut self, el: T, tree: &[TokenSeq<T>], probs: &[u8]) -> EncoderResult<()> {
- for entry in tree.iter() {
- if entry.val == el {
- for seq in entry.seq.iter() {
- self.put_bool(seq.bit, probs[seq.idx as usize])?;
- }
- return Ok(());
- }
- }
- Err(EncoderError::Bug)
- }
+impl<'a, 'b> EncoderTrait for BoolEncoder<'a, 'b> {
fn write_cat(&mut self, cat: i8, tree: &[TokenSeq<i8>], tok_probs: &[u8], val_probs: &[u8; 11]) -> EncoderResult<()> {
for entry in tree.iter() {
if entry.val == cat {
let sum = u32::from(prob_xmitted[mode * 2]) + u32::from(prob_xmitted[mode * 2 + 1]);
mdl.probs[9] = 255 - rescale_mb_mode_prob(u32::from(prob_xmitted[mode * 2 + 1]), sum);
- let inter_mv0_weight = (cnt[0] as u32) + (cnt[2] as u32);
- let inter_mv1_weight = (cnt[3] as u32) + (cnt[4] as u32);
- let gold_mv0_weight = (cnt[5] as u32) + (cnt[6] as u32);
- let gold_mv1_weight = (cnt[8] as u32) + (cnt[9] as u32);
- let mix_weight = (cnt[1] as u32) + (cnt[7] as u32);
+ let inter_mv0_weight = cnt[0] + cnt[2];
+ let inter_mv1_weight = cnt[3] + cnt[4];
+ let gold_mv0_weight = cnt[5] + cnt[6];
+ let gold_mv1_weight = cnt[8] + cnt[9];
+ let mix_weight = cnt[1] + cnt[7];
mdl.probs[0] = 1 + rescale_mb_mode_prob(inter_mv0_weight + inter_mv1_weight, total);
mdl.probs[1] = 1 + rescale_mb_mode_prob(inter_mv0_weight, inter_mv0_weight + inter_mv1_weight);
mdl.probs[2] = 1 + rescale_mb_mode_prob(mix_weight, mix_weight + gold_mv0_weight + gold_mv1_weight);
- mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0] as u32, inter_mv0_weight);
- mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3] as u32, inter_mv1_weight);
+ mdl.probs[3] = 1 + rescale_mb_mode_prob(cnt[0], inter_mv0_weight);
+ mdl.probs[4] = 1 + rescale_mb_mode_prob(cnt[3], inter_mv1_weight);
mdl.probs[5] = 1 + rescale_mb_mode_prob(cnt[1], mix_weight);
mdl.probs[6] = 1 + rescale_mb_mode_prob(gold_mv0_weight, gold_mv0_weight + gold_mv1_weight);
mdl.probs[7] = 1 + rescale_mb_mode_prob(cnt[5], gold_mv0_weight);
bc.put_bool(diff < 0, 128)?;
bc.write_el(d0, MODE_TREE_DIFF, MODE_TREE_DIFF_PROBS)?;
if d0 == 7 {
- bc.put_bits(diff.abs() as u32, 7)?;
+ bc.put_bits(u32::from(diff.unsigned_abs()), 7)?;
}
tprob[i ^ 1] = (i16::from(tprob[i ^ 1]) + deltas[i ^ 1]) as u8;
}
Ok(())
}
-struct Estimator {}
+pub trait VP6EstimatorTrait {
+ fn write_cat(&self, cat: i8, tree: &[TokenSeq<i8>], probs: &mut [ProbCounter; 11]);
+ fn write_dc(&self, val: i16, probs: &mut [ProbCounter; 11]);
+ fn write_ac(&self, val: i16, tree: &[TokenSeq<i8>], probs: &mut [ProbCounter; 11]);
+ fn write_zero_run(&self, val: usize, probs: &mut [ProbCounter; 14]);
+}
-impl Estimator {
- fn new() -> Self { Self{} }
- fn write_el<T: PartialEq>(&self, el: T, tree: &[TokenSeq<T>], probs: &mut [ProbCounter]) {
- for entry in tree.iter() {
- if entry.val == el {
- for seq in entry.seq.iter() {
- probs[seq.idx as usize].add(seq.bit);
- }
- return;
- }
- }
- }
+impl VP6EstimatorTrait for Estimator {
fn write_cat(&self, cat: i8, tree: &[TokenSeq<i8>], probs: &mut [ProbCounter; 11]) {
for entry in tree.iter() {
if entry.val == cat {
}
}
}
- fn est_nits(bit: bool, prob: u8) -> u32 {
- if !bit {
- u32::from(PROB_BITS[prob as usize])
- } else {
- u32::from(PROB_BITS[256 - (prob as usize)])
- }
- }
- fn nits_to_bits(nits: u32) -> u32 { (nits + 7) >> 3 }
}
pub fn estimate_block(blk: &[i16; 64], _dc_mode: usize, model: &mut VP56CoeffModelStat, vp6model: &mut VP6ModelsStat, scan: &[usize; 64]) {