use crate::vp9::common::bool_coder::BoolReader;
use crate::vp9::common::generated::{
NMV_BITS_PROBS, NMV_CLASS0_FP_PROBS, NMV_CLASS0_PROBS, NMV_CLASS_PROBS, NMV_FP_PROBS,
NMV_JOINT_PROBS, NMV_SIGN_PROBS,
};
use crate::vp9::common::mvref::Mv;
use crate::vp9::common::trees::{read_tree, MV_CLASS_TREE, MV_FP_TREE, MV_JOINT_TREE};
const CLASS0_BITS: i32 = 1;
#[inline]
fn mv_joint_vertical(j: usize) -> bool {
j == 2 || j == 3
}
#[inline]
fn mv_joint_horizontal(j: usize) -> bool {
j == 1 || j == 3
}
pub fn read_mv(r: &mut BoolReader, ref_mv: Mv) -> Mv {
let j = read_tree(r, &MV_JOINT_TREE, &NMV_JOINT_PROBS);
let mut mv = ref_mv;
if mv_joint_vertical(j) {
mv.row = ref_mv.row.wrapping_add(read_component(r, 0) as i16);
}
if mv_joint_horizontal(j) {
mv.col = ref_mv.col.wrapping_add(read_component(r, 1) as i16);
}
mv
}
fn read_component(r: &mut BoolReader, idx: usize) -> i32 {
let sign = r.read(NMV_SIGN_PROBS[idx]);
let mv_class = read_tree(r, &MV_CLASS_TREE, &NMV_CLASS_PROBS[idx]);
let (d, mag) = if mv_class == 0 {
(r.read(NMV_CLASS0_PROBS[idx][0]) as i32, 0)
} else {
let n = mv_class as i32 + CLASS0_BITS - 1;
let mut d = 0i32;
for i in 0..n {
d |= (r.read(NMV_BITS_PROBS[idx][i as usize]) as i32) << i;
}
(d, 2 << (mv_class as i32 + 2))
};
let fp_probs: &[u8] = if mv_class == 0 {
&NMV_CLASS0_FP_PROBS[idx][d as usize]
} else {
&NMV_FP_PROBS[idx]
};
let fr = read_tree(r, &MV_FP_TREE, fp_probs) as i32;
let hp = 1;
let mag = mag + ((d << 3) | (fr << 1) | hp) + 1;
if sign != 0 {
-mag
} else {
mag
}
}