use std::num::NonZeroUsize;
use crate::{fake::block_data::FakeBlockData, mv::MotionVector, params::Subpel};
use semisafe::slice::get as semisafe_get;
use semisafe::slice::get_mut as semisafe_get_mut;
pub(crate) struct FakePlaneOfBlocks {
pub(crate) blk_x: NonZeroUsize,
pub(crate) blk_y: NonZeroUsize,
pub(crate) blk_size_x: NonZeroUsize,
pub(crate) blk_size_y: NonZeroUsize,
pub(crate) blk_count: NonZeroUsize,
pub(crate) pel: Subpel,
pub(crate) overlap_x: usize,
pub(crate) overlap_y: usize,
pub(crate) blocks: Vec<FakeBlockData>,
}
impl FakePlaneOfBlocks {
#[must_use]
#[inline]
pub fn new(
blk_size_x: NonZeroUsize,
blk_size_y: NonZeroUsize,
pel: Subpel,
overlap_x: usize,
overlap_y: usize,
blk_x: NonZeroUsize,
blk_y: NonZeroUsize,
) -> Self {
let blk_count = blk_x.saturating_mul(blk_y);
let mut blocks = Vec::with_capacity(blk_count.get());
for j in 0..blk_y.get() {
for i in 0..blk_x.get() {
let block = FakeBlockData {
x: (i * (blk_size_x.get() - overlap_x)) as _,
y: (j * (blk_size_y.get() - overlap_y)) as _,
vector: MotionVector::zero(),
};
blocks.push(block);
}
}
FakePlaneOfBlocks {
blk_x,
blk_y,
blk_size_x,
blk_size_y,
blk_count,
pel,
overlap_x,
overlap_y,
blocks,
}
}
pub(crate) fn update(&mut self, data: &[u8]) {
let blocks: &[MotionVector] = unsafe {
core::ptr::slice_from_raw_parts(
data as *const [u8] as *const MotionVector,
self.blk_count.get(),
)
.as_ref()
}
.expect("reference should be valid");
for i in 0..self.blk_count.get() {
semisafe_get_mut(&mut self.blocks, i).update(*semisafe_get(blocks, i));
}
}
pub(crate) fn get_block(&self, blk: usize) -> &FakeBlockData {
semisafe_get(&self.blocks, blk)
}
pub(crate) fn is_scenechange(&self, thscd1: u64, thscd2: u64) -> bool {
let sum = self
.blocks
.iter()
.filter(|blk| blk.vector.sad > thscd1 as i64)
.count();
sum > thscd2 as usize
}
}