use v_frame::{
pixel::Pixel,
plane::{Plane, PlaneConfig, PlaneOffset, PlaneSlice},
};
use crate::data::{
frame::{FrameInvariants, RefType},
mc::put_8tap,
motion::MotionVector,
plane::PlaneRegionMut,
tile::TileRect,
};
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Default)]
pub enum PredictionMode {
#[default]
DC_PRED, V_PRED, H_PRED, D45_PRED, D135_PRED, D113_PRED, D157_PRED, D203_PRED, D67_PRED, SMOOTH_PRED, SMOOTH_V_PRED,
SMOOTH_H_PRED,
PAETH_PRED,
UV_CFL_PRED,
NEARESTMV,
NEAR0MV,
NEAR1MV,
NEAR2MV,
GLOBALMV,
NEWMV,
NEAREST_NEARESTMV,
NEAR_NEAR0MV,
NEAR_NEAR1MV,
NEAR_NEAR2MV,
NEAREST_NEWMV,
NEW_NEARESTMV,
NEAR_NEW0MV,
NEAR_NEW1MV,
NEAR_NEW2MV,
NEW_NEAR0MV,
NEW_NEAR1MV,
NEW_NEAR2MV,
GLOBAL_GLOBALMV,
NEW_NEWMV,
}
impl PredictionMode {
pub fn is_intra(self) -> bool {
self < PredictionMode::NEARESTMV
}
#[allow(clippy::too_many_arguments)]
pub fn predict_inter_single<T: Pixel>(
self,
fi: &FrameInvariants<T>,
tile_rect: TileRect,
p: usize,
po: PlaneOffset,
dst: &mut PlaneRegionMut<'_, T>,
width: usize,
height: usize,
ref_frame: RefType,
mv: MotionVector,
bit_depth: usize,
) {
assert!(!self.is_intra());
let frame_po = tile_rect.to_frame_plane_offset(po);
if let Some(ref rec) = fi.rec_buffer.frames[fi.ref_frames[ref_frame.to_index()] as usize] {
let (row_frac, col_frac, src) =
PredictionMode::get_mv_params(&rec.frame.planes[p], frame_po, mv);
put_8tap(dst, src, width, height, col_frac, row_frac, bit_depth);
}
}
fn get_mv_params<T: Pixel>(
rec_plane: &Plane<T>,
po: PlaneOffset,
mv: MotionVector,
) -> (i32, i32, PlaneSlice<'_, T>) {
let &PlaneConfig { xdec, ydec, .. } = &rec_plane.cfg;
let row_offset = mv.row as i32 >> (3 + ydec);
let col_offset = mv.col as i32 >> (3 + xdec);
let row_frac = ((mv.row as i32) << (1 - ydec)) & 0xf;
let col_frac = ((mv.col as i32) << (1 - xdec)) & 0xf;
let qo = PlaneOffset {
x: po.x + col_offset as isize - 3,
y: po.y + row_offset as isize - 3,
};
(
row_frac,
col_frac,
rec_plane.slice(qo).clamp().subslice(3, 3),
)
}
}
#[derive(Copy, Clone, Debug)]
#[allow(clippy::upper_case_acronyms)]
pub enum PredictionVariant {
NONE,
LEFT,
TOP,
BOTH,
}
impl PredictionVariant {
pub const fn new(x: usize, y: usize) -> Self {
match (x, y) {
(0, 0) => PredictionVariant::NONE,
(_, 0) => PredictionVariant::LEFT,
(0, _) => PredictionVariant::TOP,
_ => PredictionVariant::BOTH,
}
}
}