// wai-conformance: int-kernels //! `wai.video.int_motion` — **frame-state-equivalence**: a deterministic integer //! inter-frame codec reconstructs every frame byte-identically on every machine, //! so each frame's hash (and the whole clip's) is portable. Committed vector under //! `tests/vectors/int_video/`; never skips. #![cfg(feature = "video_int")] use std::path::PathBuf; use wai::int_video::{decode, fnv1a}; fn dir() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/vectors/int_video") } fn jload(name: &str) -> serde_json::Value { serde_json::from_slice(&std::fs::read(dir().join(name)).unwrap()).unwrap() } #[test] fn decodes_the_clip_byte_for_byte_frame_by_frame() { // The committed integer bitstream (I-frame + integer-MC P-frames + quantized // residual) decodes — no float anywhere — to the SAME frames the encoder // produced, each verified by its own FNV-1a, plus the whole-clip hash. let bs = jload("int_video_bitstream.json"); let conf = jload("int_video.json"); let clip = decode(&bs).expect("decode"); let (h, w) = (conf["h"].as_u64().unwrap() as usize, conf["w"].as_u64().unwrap() as usize); let want_frames = conf["frame_hashes"].as_array().unwrap(); assert_eq!((clip.h, clip.w), (h, w)); assert_eq!(clip.frames.len(), want_frames.len(), "frame count"); let mut all = Vec::new(); for (i, frame) in clip.frames.iter().enumerate() { assert_eq!(frame.len(), h * w * 3, "frame {i} size"); let got = format!("{:016x}", fnv1a(frame)); assert_eq!(got, want_frames[i].as_str().unwrap(), "frame {i} must reproduce its committed hash"); all.extend_from_slice(&hex16(&got)); } // the whole-clip hash = FNV-1a over the concatenated frame-hash bytes let clip_hash = format!("{:016x}", fnv1a(&all)); assert_eq!(clip_hash, conf["clip_hash"].as_str().unwrap(), "clip hash"); println!( "int_video: {} frames {h}x{w} RGB -> per-frame byte-exact, clip {clip_hash}", clip.frames.len() ); } /// The 8 bytes of a 16-hex string (the encoder hashes the concatenated raw /// frame-hash bytes, not their hex text). fn hex16(s: &str) -> [u8; 8] { let mut o = [0u8; 8]; for (i, b) in o.iter_mut().enumerate() { *b = u8::from_str_radix(&s[i * 2..i * 2 + 2], 16).unwrap(); } o }