pub mod chunked;
pub mod scalar;
#[cfg(feature = "nightly")]
pub mod portable;
use crate::inter_pred::InterPredResult;
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn interpolate_luma(
src: &[i32],
src_stride: usize,
src_width: usize,
src_height: usize,
int_x: i32,
int_y: i32,
x_frac: u8,
y_frac: u8,
w: u32,
h: u32,
bit_depth: u32,
dst: &mut [i32],
dst_stride: usize,
) -> InterPredResult<()> {
#[cfg(feature = "nightly")]
{
portable::interpolate_luma(
src, src_stride, src_width, src_height, int_x, int_y, x_frac, y_frac, w, h, bit_depth,
dst, dst_stride,
)
}
#[cfg(not(feature = "nightly"))]
{
chunked::interpolate_luma(
src, src_stride, src_width, src_height, int_x, int_y, x_frac, y_frac, w, h, bit_depth,
dst, dst_stride,
)
}
}
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn interpolate_chroma(
src: &[i32],
src_stride: usize,
src_width: usize,
src_height: usize,
int_x: i32,
int_y: i32,
x_frac: u8,
y_frac: u8,
w: u32,
h: u32,
bit_depth: u32,
dst: &mut [i32],
dst_stride: usize,
) -> InterPredResult<()> {
#[cfg(feature = "nightly")]
{
portable::interpolate_chroma(
src, src_stride, src_width, src_height, int_x, int_y, x_frac, y_frac, w, h, bit_depth,
dst, dst_stride,
)
}
#[cfg(not(feature = "nightly"))]
{
chunked::interpolate_chroma(
src, src_stride, src_width, src_height, int_x, int_y, x_frac, y_frac, w, h, bit_depth,
dst, dst_stride,
)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_plane<F: FnMut(i32, i32) -> i32>(w: usize, h: usize, mut f: F) -> Vec<i32> {
let mut v = vec![0i32; w * h];
for y in 0..h {
for x in 0..w {
v[y * w + x] = f(x as i32, y as i32);
}
}
v
}
#[test]
fn luma_chunked_matches_scalar() {
let src = make_plane(64, 64, |x, y| ((x * 7 + y * 13) ^ (x * y)) & 0xff);
let sizes: &[(u32, u32)] = &[(4, 4), (4, 8), (8, 4), (8, 8), (8, 16), (16, 8), (16, 16)];
for &(w, h) in sizes {
for x_frac in 0..=3u8 {
for y_frac in 0..=3u8 {
let mut s = vec![0i32; (w * h) as usize];
let mut c = vec![0i32; (w * h) as usize];
scalar::interpolate_luma(
&src, 64, 64, 64, 20, 16, x_frac, y_frac, w, h, 8, &mut s, w as usize,
)
.unwrap();
chunked::interpolate_luma(
&src, 64, 64, 64, 20, 16, x_frac, y_frac, w, h, 8, &mut c, w as usize,
)
.unwrap();
assert_eq!(s, c, "luma w={w} h={h} xf={x_frac} yf={y_frac}");
}
}
}
}
#[test]
fn luma_chunked_matches_scalar_edges() {
let src = make_plane(16, 16, |x, y| (x * 5 + y * 11) & 0xff);
for &(int_x, int_y) in &[(-3i32, -3i32), (12, 12), (-3, 8), (10, -4)] {
for x_frac in 0..=3u8 {
for y_frac in 0..=3u8 {
let mut s = vec![0i32; 8 * 8];
let mut c = vec![0i32; 8 * 8];
scalar::interpolate_luma(
&src, 16, 16, 16, int_x, int_y, x_frac, y_frac, 8, 8, 8, &mut s, 8,
)
.unwrap();
chunked::interpolate_luma(
&src, 16, 16, 16, int_x, int_y, x_frac, y_frac, 8, 8, 8, &mut c, 8,
)
.unwrap();
assert_eq!(s, c, "luma edge ({int_x},{int_y}) xf={x_frac} yf={y_frac}");
}
}
}
}
#[test]
fn chroma_chunked_matches_scalar() {
let src = make_plane(32, 32, |x, y| (x * 3 + y * 5) & 0xff);
let sizes: &[(u32, u32)] = &[(2, 2), (2, 4), (4, 2), (4, 4), (4, 8), (8, 8)];
for &(w, h) in sizes {
for x_frac in 0..=7u8 {
for y_frac in 0..=7u8 {
let mut s = vec![0i32; (w * h) as usize];
let mut c = vec![0i32; (w * h) as usize];
scalar::interpolate_chroma(
&src, 32, 32, 32, 4, 5, x_frac, y_frac, w, h, 8, &mut s, w as usize,
)
.unwrap();
chunked::interpolate_chroma(
&src, 32, 32, 32, 4, 5, x_frac, y_frac, w, h, 8, &mut c, w as usize,
)
.unwrap();
assert_eq!(s, c, "chroma w={w} h={h} xf={x_frac} yf={y_frac}");
}
}
}
}
#[cfg(feature = "nightly")]
#[test]
fn luma_portable_matches_scalar() {
let src = make_plane(64, 64, |x, y| ((x * 7 + y * 13) ^ (x * y)) & 0xff);
let sizes: &[(u32, u32)] = &[(4, 4), (8, 8), (16, 16)];
for &(w, h) in sizes {
for x_frac in 0..=3u8 {
for y_frac in 0..=3u8 {
let mut s = vec![0i32; (w * h) as usize];
let mut p = vec![0i32; (w * h) as usize];
scalar::interpolate_luma(
&src, 64, 64, 64, 20, 16, x_frac, y_frac, w, h, 8, &mut s, w as usize,
)
.unwrap();
portable::interpolate_luma(
&src, 64, 64, 64, 20, 16, x_frac, y_frac, w, h, 8, &mut p, w as usize,
)
.unwrap();
assert_eq!(s, p, "luma w={w} h={h} xf={x_frac} yf={y_frac}");
}
}
}
}
}