#[cfg(all(test, feature = "std"))]
use super::*;
#[cfg(all(test, feature = "std"))]
pub(super) fn solid_v410_frame(width: u32, height: u32, u: u32, y: u32, v: u32) -> Vec<u32> {
let word = (v << 20) | (y << 10) | u;
std::vec![word; (width as usize) * (height as usize)]
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_luma_only_extracts_y_bytes_downshifted() {
let buf = solid_v410_frame(6, 8, 512, 256, 512);
let src = V410Frame::new(&buf, 6, 8, 6);
let mut luma = std::vec![0u8; 6 * 8];
let mut sink = MixedSinker::<V410>::new(6, 8).with_luma(&mut luma).unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
assert!(luma.iter().all(|&y| y == 64), "luma {luma:?}");
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_with_luma_u16_extracts_y_native_depth() {
let buf = solid_v410_frame(6, 8, 512, 0x3FC, 512);
let src = V410Frame::new(&buf, 6, 8, 6);
let mut luma = std::vec![0u16; 6 * 8];
let mut sink = MixedSinker::<V410>::new(6, 8)
.with_luma_u16(&mut luma)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
assert!(
luma.iter().all(|&y| y == 0x3FC),
"luma_u16 expected 0x3FC, got {:?}",
&luma[..8]
);
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_rgb_only_converts_gray_to_gray() {
let buf = solid_v410_frame(12, 4, 512, 512, 512);
let src = V410Frame::new(&buf, 12, 4, 12);
let mut rgb = std::vec![0u8; 12 * 4 * 3];
let mut sink = MixedSinker::<V410>::new(12, 4).with_rgb(&mut rgb).unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for px in rgb.chunks(3) {
assert!(px[0].abs_diff(128) <= 4);
assert_eq!(px[0], px[1]);
assert_eq!(px[1], px[2]);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_rgba_only_converts_gray_to_gray_with_opaque_alpha() {
let buf = solid_v410_frame(12, 4, 512, 512, 512);
let src = V410Frame::new(&buf, 12, 4, 12);
let mut rgba = std::vec![0u8; 12 * 4 * 4];
let mut sink = MixedSinker::<V410>::new(12, 4)
.with_rgba(&mut rgba)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for px in rgba.chunks(4) {
assert_eq!(px[3], 0xFF);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_rgb_u16_only_converts_gray_to_gray_native_depth() {
let buf = solid_v410_frame(12, 4, 512, 512, 512);
let src = V410Frame::new(&buf, 12, 4, 12);
let mut rgb = std::vec![0u16; 12 * 4 * 3];
let mut sink = MixedSinker::<V410>::new(12, 4)
.with_rgb_u16(&mut rgb)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for px in rgb.chunks(3) {
assert!(px[0].abs_diff(512) <= 16, "expected ~512, got {}", px[0]);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_rgba_u16_alpha_is_max() {
let buf = solid_v410_frame(12, 4, 512, 512, 512);
let src = V410Frame::new(&buf, 12, 4, 12);
let mut rgba = std::vec![0u16; 12 * 4 * 4];
let mut sink = MixedSinker::<V410>::new(12, 4)
.with_rgba_u16(&mut rgba)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for px in rgba.chunks(4) {
assert_eq!(px[3], 0x3FF);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_hsv_only_produces_valid_hue_range() {
let buf = solid_v410_frame(12, 4, 512, 512, 512);
let src = V410Frame::new(&buf, 12, 4, 12);
let n = 12 * 4;
let mut h = std::vec![0u8; n];
let mut s = std::vec![0u8; n];
let mut v_plane = std::vec![0u8; n];
let mut sink = MixedSinker::<V410>::new(12, 4)
.with_hsv(&mut h, &mut s, &mut v_plane)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
assert!(h.iter().all(|&x| x == 0), "H {h:?}");
assert!(s.iter().all(|&x| x == 0), "S {s:?}");
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_with_rgb_and_with_rgba_byte_identical_u8() {
let w = 12u32;
let h = 4u32;
let buf = solid_v410_frame(w, h, 200, 700, 400);
let src = V410Frame::new(&buf, w, h, w);
let mut rgb = std::vec![0u8; (w * h) as usize * 3];
let mut rgba = std::vec![0u8; (w * h) as usize * 4];
let mut sink = MixedSinker::<V410>::new(w as usize, h as usize)
.with_rgb(&mut rgb)
.unwrap()
.with_rgba(&mut rgba)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for i in 0..(w * h) as usize {
assert_eq!(rgba[i * 4], rgb[i * 3]);
assert_eq!(rgba[i * 4 + 1], rgb[i * 3 + 1]);
assert_eq!(rgba[i * 4 + 2], rgb[i * 3 + 2]);
assert_eq!(rgba[i * 4 + 3], 0xFF);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_with_rgb_u16_and_with_rgba_u16_byte_identical() {
let w = 12u32;
let h = 4u32;
let buf = solid_v410_frame(w, h, 200, 700, 400);
let src = V410Frame::new(&buf, w, h, w);
let mut rgb = std::vec![0u16; (w * h) as usize * 3];
let mut rgba = std::vec![0u16; (w * h) as usize * 4];
let mut sink = MixedSinker::<V410>::new(w as usize, h as usize)
.with_rgb_u16(&mut rgb)
.unwrap()
.with_rgba_u16(&mut rgba)
.unwrap();
v410_to(&src, true, ColorMatrix::Bt601, &mut sink).unwrap();
for i in 0..(w * h) as usize {
assert_eq!(rgba[i * 4], rgb[i * 3]);
assert_eq!(rgba[i * 4 + 1], rgb[i * 3 + 1]);
assert_eq!(rgba[i * 4 + 2], rgb[i * 3 + 2]);
assert_eq!(rgba[i * 4 + 3], 0x3FF);
}
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_with_simd_false_matches_with_simd_true() {
for w in [1usize, 2, 4, 7, 8, 15, 16, 17, 31, 32, 33, 1920, 1921] {
let h = 2usize;
let mut buf = std::vec![0u32; w * h];
let mut state = 0xC0FFEE_u32;
for word in &mut buf {
state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
let u = (state >> 2) & 0x3FF;
state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
let y = (state >> 2) & 0x3FF;
state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
let v = (state >> 2) & 0x3FF;
*word = (v << 20) | (y << 10) | u;
}
let src = V410Frame::new(&buf, w as u32, h as u32, w as u32);
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut sink_simd = MixedSinker::<V410>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap();
let mut sink_scalar = MixedSinker::<V410>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_simd(false);
v410_to(&src, false, ColorMatrix::Bt709, &mut sink_simd).unwrap();
v410_to(&src, false, ColorMatrix::Bt709, &mut sink_scalar).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "V410 SIMD≠scalar at width {w}");
}
}
fn pack_yuv444p10_to_v410(
y_plane: &[u16],
u_plane: &[u16],
v_plane: &[u16],
width: usize,
height: usize,
) -> Vec<u32> {
let mut packed = Vec::with_capacity(width * height);
for r in 0..height {
for c in 0..width {
let y = (y_plane[r * width + c] & 0x3FF) as u32;
let u = (u_plane[r * width + c] & 0x3FF) as u32;
let v = (v_plane[r * width + c] & 0x3FF) as u32;
packed.push((v << 20) | (y << 10) | u);
}
}
packed
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_planar_parity_with_yuv444p10() {
let width = 16usize;
let height = 4usize;
let mut yp = std::vec![0u16; width * height];
let mut up = std::vec![0u16; width * height];
let mut vp = std::vec![0u16; width * height];
pseudo_random_u16_low_n_bits(&mut yp, 0xC0FFEE, 10);
pseudo_random_u16_low_n_bits(&mut up, 0xBADF00D, 10);
pseudo_random_u16_low_n_bits(&mut vp, 0xFEEDFACE, 10);
let planar = Yuv444p10Frame::new(
&yp,
&up,
&vp,
width as u32,
height as u32,
width as u32,
width as u32,
width as u32,
);
let packed = pack_yuv444p10_to_v410(&yp, &up, &vp, width, height);
let v410 = V410Frame::new(&packed, width as u32, height as u32, width as u32);
let mut p_rgb = std::vec![0u8; width * height * 3];
let mut v_rgb = std::vec![0u8; width * height * 3];
let mut p_sink = MixedSinker::<Yuv444p10>::new(width, height)
.with_rgb(&mut p_rgb)
.unwrap();
let mut v_sink = MixedSinker::<V410>::new(width, height)
.with_rgb(&mut v_rgb)
.unwrap();
yuv444p10_to(&planar, false, ColorMatrix::Bt709, &mut p_sink).unwrap();
v410_to(&v410, false, ColorMatrix::Bt709, &mut v_sink).unwrap();
assert_eq!(p_rgb, v_rgb, "V410 ↔ Yuv444p10 u8 RGB diverges");
let mut p_rgb_u16 = std::vec![0u16; width * height * 3];
let mut v_rgb_u16 = std::vec![0u16; width * height * 3];
let mut p_sink2 = MixedSinker::<Yuv444p10>::new(width, height)
.with_rgb_u16(&mut p_rgb_u16)
.unwrap();
let mut v_sink2 = MixedSinker::<V410>::new(width, height)
.with_rgb_u16(&mut v_rgb_u16)
.unwrap();
yuv444p10_to(&planar, false, ColorMatrix::Bt709, &mut p_sink2).unwrap();
v410_to(&v410, false, ColorMatrix::Bt709, &mut v_sink2).unwrap();
assert_eq!(p_rgb_u16, v_rgb_u16, "V410 ↔ Yuv444p10 u16 RGB diverges");
}
#[test]
#[cfg(all(test, feature = "std"))]
fn v410_rgba_u16_buffer_too_short_returns_err() {
let mut rgba = std::vec![0u16; 6 * 7 * 4];
let result = MixedSinker::<V410>::new(6, 8).with_rgba_u16(&mut rgba);
let Err(err) = result else {
panic!("expected InsufficientRgbaU16Buffer");
};
assert_eq!(
err,
MixedSinkerError::InsufficientRgbaU16Buffer(InsufficientBuffer::new(192, 168))
);
}
#[test]
#[cfg(all(test, feature = "std"))]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn v410_le_be_roundtrip_byte_identical() {
let pack = |u: u32, y: u32, v: u32| -> u32 { (v << 20) | (y << 10) | u };
let logical: std::vec::Vec<u32> = (0..8 * 4)
.map(|i| match i % 4 {
0 => pack(512, 512, 512),
1 => pack(100, 700, 300),
2 => pack(900, 64, 64),
_ => pack(64, 940, 960),
})
.collect();
let pix_le: std::vec::Vec<u32> = logical.iter().map(|&w| as_le_u32(w)).collect();
let pix_be: std::vec::Vec<u32> = logical.iter().map(|&w| as_be_u32(w)).collect();
let frame_le = V410LeFrame::try_new(&pix_le, 8, 4, 8).unwrap();
let mut out_le = std::vec![0u8; 8 * 4 * 4];
let mut sink_le = MixedSinker::<V410>::new(8, 4)
.with_simd(false)
.with_rgba(&mut out_le)
.unwrap();
v410_to(&frame_le, true, ColorMatrix::Bt709, &mut sink_le).unwrap();
let frame_be = V410BeFrame::try_new(&pix_be, 8, 4, 8).unwrap();
let mut out_be = std::vec![0u8; 8 * 4 * 4];
let mut sink_be = MixedSinker::<V410<true>>::new(8, 4)
.with_simd(false)
.with_rgba(&mut out_be)
.unwrap();
v410_to_endian(&frame_be, true, ColorMatrix::Bt709, &mut sink_be).unwrap();
assert_eq!(
out_le, out_be,
"V410 LE/BE outputs diverge — `<const BE>` propagation broken"
);
}