use std::{num::NonZeroUsize, sync::Arc};
use v_frame::{frame::Frame, pixel::Pixel};
use super::intra::BLOCK_TO_PLANE_SHIFT;
use crate::data::plane::{Area, AsRegion, PlaneRegion, Rect};
pub const IMPORTANCE_BLOCK_SIZE: usize =
1 << (IMPORTANCE_BLOCK_TO_BLOCK_SHIFT + BLOCK_TO_PLANE_SHIFT);
pub const IMPORTANCE_BLOCK_TO_BLOCK_SHIFT: usize = 1;
pub const IMP_BLOCK_MV_UNITS_PER_PIXEL: i64 = 8;
pub const IMP_BLOCK_SIZE_IN_MV_UNITS: i64 =
IMPORTANCE_BLOCK_SIZE as i64 * IMP_BLOCK_MV_UNITS_PER_PIXEL;
pub(crate) fn estimate_importance_block_difference<T: Pixel>(
frame: &Arc<Frame<T>>,
ref_frame: &Arc<Frame<T>>,
) -> f64 {
let plane_org = &frame.y_plane;
let plane_ref = &ref_frame.y_plane;
let h_in_imp_b = plane_org.height().get() / IMPORTANCE_BLOCK_SIZE;
let w_in_imp_b = plane_org.width().get() / IMPORTANCE_BLOCK_SIZE;
let mut imp_block_costs = 0;
(0..h_in_imp_b).for_each(|y| {
(0..w_in_imp_b).for_each(|x| {
let region_org = plane_org.region(Area::Rect(Rect {
x: (x * IMPORTANCE_BLOCK_SIZE) as isize,
y: (y * IMPORTANCE_BLOCK_SIZE) as isize,
width: NonZeroUsize::new(IMPORTANCE_BLOCK_SIZE).expect("non-zero const"),
height: NonZeroUsize::new(IMPORTANCE_BLOCK_SIZE).expect("non-zero const"),
}));
let region_ref = plane_ref.region(Area::Rect(Rect {
x: (x * IMPORTANCE_BLOCK_SIZE) as isize,
y: (y * IMPORTANCE_BLOCK_SIZE) as isize,
width: NonZeroUsize::new(IMPORTANCE_BLOCK_SIZE).expect("non-zero const"),
height: NonZeroUsize::new(IMPORTANCE_BLOCK_SIZE).expect("non-zero const"),
}));
let sum_8x8_block = |region: &PlaneRegion<T>| {
region
.rows_iter()
.map(|row| {
row.iter()
.map(|pixel| pixel.to_u16().expect("value should fit in u16"))
.sum::<u16>() as i64
})
.sum::<i64>()
};
let histogram_org_sum = sum_8x8_block(®ion_org);
let histogram_ref_sum = sum_8x8_block(®ion_ref);
let count = (IMPORTANCE_BLOCK_SIZE * IMPORTANCE_BLOCK_SIZE) as i64;
let mean = (((histogram_org_sum + count / 2) / count)
- ((histogram_ref_sum + count / 2) / count))
.abs();
imp_block_costs += mean as u64;
});
});
imp_block_costs as f64 / (w_in_imp_b * h_in_imp_b) as f64
}