open-standards/wai/wai-rs/tests/platform_encode.rs
Transaction Science 19b8efbd99 An encode record states null when nothing was measured, and run keeps its record then
The brief's form: quality is the figures, or null when not measured, and record::body writes null
until with_quality sets them. A record with no such member reads as before and states no figures
either, so every earlier record stands; a quality of any other form is record_malformed. The
corpus case that refused null is now accepted with pictures held and no verdict, and an empty
object takes its place among the malformed spellings. QualityBasis::Absent is NotMeasured.

wai_encode_measure run no longer fails after encoding when a decode gives nothing to measure. It
writes the record with null and says why in quality_not_measured, and --no-decode asks for that.
An Apple-gated test now drives run itself for each codec: a verifier's own decode recomputes
what it signed, with the verdict decoded, and the not-measured path keeps its record.

record::sign writes quality at its section 6.1 place, as its comment says, and the change note no
longer states a count of cases.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 03:01:50 -05:00

333 lines
22 KiB
Rust

//! `wai.video.encode` (extensions/platform-encode.md): the committed corpus
//! `encode-conformance/` regenerates byte for byte from its pinned fixture streams and decoded
//! pictures, every case gets the outcome it states, every record reason of §12 is in it, and
//! §12 lists exactly the reasons the reference reports. Where the platform's media framework is built in (macOS), an
//! encode through it of each codec holds to §4.3, signs a record that verifies, and decodes in
//! the platform's decoder to one picture per frame, and `wai_encode_measure run` signs the
//! quality of that decode; a host with no hardware engine fails those tests rather than
//! skipping them.
#![cfg(feature = "platform_encode")]
use std::collections::{BTreeMap, BTreeSet};
use std::path::PathBuf;
use wai::platform_encode::{corpus, record::Reason, sha256_hex};
fn dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../encode-conformance")
}
fn streams() -> BTreeMap<String, Vec<u8>> {
corpus::FIXTURES.iter().map(|f| (f.file.to_string(), std::fs::read(dir().join("streams").join(f.file)).expect("a fixture stream"))).collect()
}
fn decoded() -> BTreeMap<String, Vec<u8>> {
corpus::DECODED.iter().map(|d| (d.file.to_string(), std::fs::read(dir().join("decoded").join(d.file)).expect("decoded pictures"))).collect()
}
#[test]
fn the_fixture_streams_are_the_pinned_bytes() {
let pins: serde_json::Value = serde_json::from_slice(&std::fs::read(dir().join("streams.json")).expect("streams.json")).expect("JSON");
let s = streams();
assert_eq!(pins.as_object().expect("an object").len(), s.len(), "streams.json pins every fixture and nothing else");
for (k, v) in &s {
assert_eq!(pins[k].as_str(), Some(sha256_hex(v).as_str()), "{k} is not the bytes streams.json pins");
}
let pins: serde_json::Value = serde_json::from_slice(&std::fs::read(dir().join("decoded.json")).expect("decoded.json")).expect("JSON");
let d = decoded();
assert_eq!(pins.as_object().expect("an object").len(), d.len(), "decoded.json pins every decoded fixture and nothing else");
for (k, v) in &d {
assert_eq!(pins[k].as_str(), Some(sha256_hex(v).as_str()), "{k} is not the bytes decoded.json pins");
}
let held: BTreeSet<String> = std::fs::read_dir(dir().join("decoded")).expect("decoded/").flatten().map(|e| e.file_name().to_string_lossy().into_owned()).collect();
assert_eq!(held, d.keys().cloned().collect::<BTreeSet<_>>(), "decoded/ holds the decoded fixtures and nothing else");
}
#[test]
fn the_committed_corpus_regenerates_byte_for_byte() {
let generated = corpus::generate(&streams(), &decoded());
for (p, b) in &generated {
assert_eq!(std::fs::read(dir().join(p)).ok().as_ref(), Some(b), "{p} does not regenerate: run `wai_encode_vectors gen`");
}
for sub in ["records", "mutated", "handed"] {
for e in std::fs::read_dir(dir().join(sub)).expect("the corpus").flatten() {
let rel = format!("{sub}/{}", e.file_name().to_string_lossy());
assert!(generated.contains_key(&rel), "{rel} is not generated");
}
}
}
#[test]
fn every_case_gets_its_outcome_and_every_reason_appears() {
assert!(corpus::check(&dir()).is_ok(), "{:?}", corpus::check(&dir()));
let cases = corpus::cases(&streams(), &decoded());
let seen: BTreeSet<&str> = cases.iter().filter_map(|c| c.expect.map(Reason::code)).collect();
// The rendition's reason is the packager's corpus's (wai-pack tests/encode_rung.rs).
let want: BTreeSet<&str> = Reason::ALL.iter().map(|r| r.code()).filter(|c| *c != "encode-package-mismatch").collect();
assert_eq!(seen, want, "every record reason but the rendition's has a case");
assert!(cases.iter().filter(|c| c.expect.is_none()).count() >= corpus::FIXTURES.len(), "every fixture is accepted");
// The quality figures are checked: an accepted record states them over held pictures, and
// its verdict says what they rest on, each of the three words reached.
assert!(cases.iter().any(|c| c.expect.is_none() && c.decoded.is_some() && c.record.contains("\"quality\":{")), "a record with quality is accepted with its pictures held");
let words: BTreeSet<&str> = cases.iter().filter_map(|c| c.quality).collect();
assert_eq!(words, BTreeSet::from(["decoded", "handed", "stated"]), "a verdict reaches each of §7's words");
// `null` is not measured: accepted with pictures held, which have no figures to hold to.
assert!(cases.iter().any(|c| c.expect.is_none() && c.decoded.is_some() && c.quality.is_none() && c.record.contains("\"quality\":null")), "a record stating null is accepted, and its verdict names nothing");
}
/// Pictures handed over prove nothing of the stream (§7): a record stating a perfect score its
/// stream does not give holds against the encoder's own input, is `handed` and not `decoded`,
/// and is refused the moment the pictures are what the stream decodes to.
#[test]
fn only_a_decode_of_the_held_stream_makes_the_figures_the_streams() {
use wai::platform_encode::record::{self, Held, Pictures, QualityBasis};
let d = dir();
let read = |p: &str| std::fs::read(d.join(p)).expect("a corpus file");
let text = String::from_utf8(read("records/accept-quality-own-pictures-software-avc-128x72.json")).expect("a record");
let v: serde_json::Value = serde_json::from_str(&text).expect("JSON");
assert_eq!((v["quality"]["sse_y"].as_str(), v["quality"]["ssim_y_q32"].as_str()), (Some("0"), Some("4294967296")), "the figures of the encoder's own input");
let stream = read("streams/software-avc-128x72.h264");
let (hd, frames) = wai::platform_encode::y4m::read_all(&read("source.y4m")).expect("the source");
let planes = frames.concat();
let held = Held { stream: Some(&stream), source: Some((&hd, &planes)) };
let own = read("handed/software-avc-128x72.yuv");
let real = read("decoded/software-avc-128x72.yuv");
assert_eq!(record::verify_with(&text, &held, Some(Pictures::Handed(&own))).expect("the figures are the pictures'").quality, QualityBasis::Handed);
assert_eq!(record::verify_with(&text, &held, Some(Pictures::Handed(&real))).map(|v| v.quality), Err(Reason::QualityMismatch));
assert_eq!(record::verify_with(&text, &held, Some(Pictures::Decoded(&real))).map(|v| v.quality), Err(Reason::QualityMismatch));
assert_eq!(record::verify_with(&text, &held, None).expect("step 11 not made").quality, QualityBasis::Stated);
// No stream held: a decode of what? The pictures tie to nothing, whatever the caller says.
let no_stream = Held { stream: None, source: held.source };
assert_eq!(record::verify_with(&text, &no_stream, Some(Pictures::Decoded(&own))).expect("the figures are the pictures'").quality, QualityBasis::Handed);
// A record stating no figures says so in its verdict, whatever pictures are held, whether
// its `quality` is `null` or it has none: a reader takes the verdict, and never tells the two
// apart.
for name in ["records/accept-software-avc-128x72.json", "records/accept-quality-null-software-avc-128x72.json"] {
let none = String::from_utf8(read(name)).expect("a record");
assert_eq!(record::verify_with(&none, &held, Some(Pictures::Decoded(&real))).expect("nothing to check").quality, QualityBasis::NotMeasured, "{name}");
}
}
/// A record says `null` until its signer measures (§6.1, §8.3.2): what `record::body` builds
/// states it, verifies with stream, source and pictures all held, and rests on nothing; its
/// signer's figures then take its place.
#[test]
fn a_record_states_null_until_its_signer_measures() {
use wai::platform_encode::{self as pe, Codec, Encoded, Identity, record::{self, Held, Pictures, QualityBasis}};
let d = dir();
let read = |p: &str| std::fs::read(d.join(p)).expect("a corpus file");
let src = read("source.y4m");
let stream = read("streams/software-avc-128x72.h264");
let pictures = read("decoded/software-avc-128x72.yuv");
let p = pe::prepare(&src, Codec::Avc, Some((128, 72)), corpus::KBPS).expect("the corpus source");
let c = pe::annexb::check_stream(Codec::Avc, &stream, corpus::FRAMES, &corpus::PLAN).expect("a fixture stream holds to §4.3");
let identity = Identity { api: "software", encoder: "corpus".into(), version: "1".into(), hardware: false, device: "corpus".into(), driver: "corpus".into(), library_sha256: Some(sha256_hex(b"a library")) };
let e = Encoded { identity, stream: stream.clone(), units: c.units, sps: c.sps, wall_us: 1000 };
let body = record::body(&e, &p.cfg, &p.source, &corpus::PLAN, None, None, corpus::ISSUED_AT);
assert!(body.get("quality").is_some_and(serde_json::Value::is_null), "a body states null: {body}");
let key = ed25519_dalek::SigningKey::from_bytes(&corpus::SEED);
let (hd, frames) = pe::y4m::read_all(&src).expect("the source");
let planes = frames.concat();
let held = Held { stream: Some(&stream), source: Some((&hd, &planes)) };
let signed = record::sign(body, &key);
let text = record::to_text(&signed);
assert!(text.contains("\"quality\":null"), "the record's text states it");
assert_eq!(record::verify_with(&text, &held, Some(Pictures::Decoded(&pictures))).expect("a record of no figures").quality, QualityBasis::NotMeasured);
let q = record::Quality::measure(p.frames.iter().map(Vec::as_slice), &pictures, 128, 72).expect("a picture per frame");
let measured = record::to_text(&record::add_quality(&signed, &q, &key, "2026-11-06T09:30:00Z").expect("its own signer"));
assert_eq!(record::verify_with(&measured, &held, Some(Pictures::Decoded(&pictures))).expect("its figures hold").quality, QualityBasis::Decoded);
}
/// `wai_encode_measure quality --record`, end to end through the tool: the record gains its
/// figures, its own signer signs it again, and `issued_at` is when; a record is not signed
/// again without its signer's key, nor by another's. A record of `null` gains them as one with
/// no such member does. A sum of 0 prints as `exact`.
#[test]
fn the_measure_tool_signs_quality_into_a_record_as_its_signer() {
use std::process::Command;
use wai::platform_encode::record::{self, Held, Pictures, QualityBasis};
let d = dir();
let tmp = std::env::temp_dir().join(format!("wai-encode-measure-{}", std::process::id()));
std::fs::create_dir_all(&tmp).expect("a directory");
let out = tmp.join("out.json");
let path = |p: &str| d.join(p).to_string_lossy().into_owned();
let run_on = |rec: &str, pictures: &str, key: Option<&str>| {
let mut c = Command::new(env!("CARGO_BIN_EXE_wai_encode_measure"));
c.args(["quality", "--codec", "avc", "--stream", &path("streams/software-avc-128x72.h264"), "--source", &path("source.y4m"), "--size", "128x72"]);
c.args(["--decoded", &path(pictures), "--record", &path(rec), "--record-out", &out.to_string_lossy()]);
if let Some(k) = key {
let seed = tmp.join("seed");
std::fs::write(&seed, k).expect("a seed");
c.args(["--key", &seed.to_string_lossy()]);
}
c.output().expect("the tool runs")
};
let run = |pictures: &str, key: Option<&str>| run_on("records/accept-software-avc-128x72.json", pictures, key);
let corpus_key = "45".repeat(32);
let _ = std::fs::remove_file(&out);
let no_key = run("decoded/software-avc-128x72.yuv", None);
assert!(!no_key.status.success() && !out.exists(), "--record with no --key signs nothing: {no_key:?}");
let other_key = run("decoded/software-avc-128x72.yuv", Some(&"46".repeat(32)));
assert!(!other_key.status.success() && !out.exists(), "another's key signs nothing: {other_key:?}");
let good = run("decoded/software-avc-128x72.yuv", Some(&corpus_key));
assert!(good.status.success(), "{good:?}");
let line: serde_json::Value = serde_json::from_slice(&good.stdout).expect("one JSON line");
assert_eq!(line["pictures_read"], "handed", "--decoded hands the pictures over");
assert!(line["psnr_y"].is_number());
let text = std::fs::read_to_string(&out).expect("the record");
let stream = std::fs::read(d.join("streams/software-avc-128x72.h264")).expect("the stream");
let pictures = std::fs::read(d.join("decoded/software-avc-128x72.yuv")).expect("the pictures");
let src = std::fs::read(d.join("source.y4m")).expect("the source");
let (hd, frames) = wai::platform_encode::y4m::read_all(&src).expect("the source");
let planes = frames.concat();
let held = Held { stream: Some(&stream), source: Some((&hd, &planes)) };
let v = record::verify_with(&text, &held, Some(Pictures::Handed(&pictures))).expect("the record verifies");
assert_eq!(v.quality, QualityBasis::Handed);
let before: serde_json::Value = serde_json::from_slice(&std::fs::read(d.join("records/accept-software-avc-128x72.json")).expect("the record")).expect("JSON");
assert_eq!(v.record["signer_pubkey"], before["signer_pubkey"], "the record keeps its signer");
assert_ne!(v.record["issued_at"], before["issued_at"], "issued_at is when it was signed again");
assert_eq!(v.record["stream"], before["stream"]);
let of_null = run_on("records/accept-quality-null-software-avc-128x72.json", "decoded/software-avc-128x72.yuv", Some(&corpus_key));
assert!(of_null.status.success(), "{of_null:?}");
let text = std::fs::read_to_string(&out).expect("the record");
assert_eq!(record::verify_with(&text, &held, Some(Pictures::Handed(&pictures))).expect("the record verifies").quality, QualityBasis::Handed, "a record of null takes its figures");
let perfect = run("handed/software-avc-128x72.yuv", Some(&corpus_key));
assert!(perfect.status.success(), "{perfect:?}");
let line: serde_json::Value = serde_json::from_slice(&perfect.stdout).expect("one JSON line");
for k in ["psnr_y", "psnr_u", "psnr_v", "psnr_yuv_611"] {
assert_eq!(line[k], "exact", "{k}: a sum of 0 has no finite PSNR (staged-measurement §4.7)");
}
let _ = std::fs::remove_dir_all(&tmp);
}
#[test]
fn the_reasons_table_is_the_references() {
let text = std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../extensions/platform-encode.md")).expect("the extension");
let at = text.find("## 12. Reasons").expect("§12");
let end = text[at + 1..].find("\n## ").map_or(text.len(), |e| at + 1 + e);
let table: BTreeSet<String> = text[at..end]
.lines()
.filter(|l| l.starts_with("| `") && !l.contains("| producer |"))
.filter_map(|l| l.split('`').nth(1).map(String::from))
.collect();
let code: BTreeSet<String> = Reason::ALL.iter().map(|r| r.code().to_string()).collect();
assert_eq!(table, code, "§12's record reasons are exactly Reason::ALL");
}
/// The pictures the corpus pins under `decoded/` are what the platform's decoder makes of their
/// stream, byte for byte, so a `decoded` verdict in the corpus stands for a verifier's own decode
/// (§10.1).
#[cfg(target_vendor = "apple")]
#[test]
fn the_pinned_pictures_are_what_the_platform_decodes_their_stream_to() {
use wai::platform_encode::{self as pe, Codec};
let (s, d) = (streams(), decoded());
for f in corpus::DECODED {
let stream = &s[f.stream];
let units = pe::annexb::check_stream(Codec::Avc, stream, corpus::FRAMES, &corpus::PLAN).expect("a fixture stream holds to §4.3").units;
let mut pictures = Vec::new();
let n = pe::platform_decode(Codec::Avc, stream, &units, |p| {
pictures.extend_from_slice(p);
Ok(())
})
.expect("the platform decodes it");
assert_eq!(n, corpus::FRAMES, "{}: one picture per frame", f.file);
assert!(pictures == d[f.file], "{}: not what the platform decodes {} to", f.file, f.stream);
}
}
/// `wai_encode_measure run`, end to end through the tool, each codec on this host's encoder: the
/// record it writes states the quality of what its stream decodes to, a verifier's own decode
/// of that stream recomputes every figure, and the verdict is `decoded`. With nothing measured
/// the encode stands: the record states `null`, and the tool's line says why.
#[cfg(target_vendor = "apple")]
#[test]
fn the_measure_tools_run_signs_the_quality_of_its_stream() {
use std::process::Command;
use wai::platform_encode::{self as pe, Codec, record::{self, Held, Pictures, QualityBasis}};
let tmp = std::env::temp_dir().join(format!("wai-encode-measure-run-{}", std::process::id()));
let source = dir().join("source.y4m");
let src = std::fs::read(&source).expect("the source");
let (hd, frames) = pe::y4m::read_all(&src).expect("the source");
let planes = frames.concat();
for (codec, flag) in [(Codec::Avc, "avc"), (Codec::Hevc, "hevc")] {
let run = |name: &str, more: &[&str]| -> (serde_json::Value, String, Vec<u8>) {
let out = Command::new(env!("CARGO_BIN_EXE_wai_encode_measure"))
.args(["run", "--api", "platform", "--codec", flag, "--kbps", "400", "--idr-every", "5", "--name", name])
.arg("--source")
.arg(&source)
.arg("--out")
.arg(&tmp)
.args(more)
.output()
.expect("the tool runs");
assert!(out.status.success(), "{name}: {out:?}");
let line = serde_json::from_slice(&out.stdout).expect("one JSON line");
let text = std::fs::read_to_string(tmp.join(format!("{name}.record.json"))).expect("the record");
let stream = std::fs::read(tmp.join(format!("{name}.{}", codec.extension()))).expect("the stream");
(line, text, stream)
};
let (line, text, stream) = run(flag, &[]);
let plan: Vec<u64> = serde_json::from_str::<serde_json::Value>(&text).expect("JSON")["idr"].as_array().expect("a plan").iter().filter_map(serde_json::Value::as_u64).collect();
let units = pe::annexb::check_stream(codec, &stream, corpus::FRAMES, &plan).expect("the stream holds to §4.3").units;
let mut pictures = Vec::new();
let n = pe::platform_decode(codec, &stream, &units, |f| {
pictures.extend_from_slice(f);
Ok(())
})
.expect("the platform decodes it");
assert_eq!(n, corpus::FRAMES, "{flag}: one picture per frame");
let held = Held { stream: Some(&stream), source: Some((&hd, &planes)) };
let v = record::verify_with(&text, &held, Some(Pictures::Decoded(&pictures))).unwrap_or_else(|r| panic!("{flag}: {r}"));
assert_eq!(v.quality, QualityBasis::Decoded, "{flag}");
assert_eq!(line["quality"], v.record["quality"], "{flag}: the line prints what the record signs");
assert!(line["quality_not_measured"].is_null(), "{flag}: {line}");
let (line, text, stream) = run(&format!("{flag}-not-measured"), &["--no-decode"]);
assert!(text.contains("\"quality\":null"), "{flag}: the record states null");
let held = Held { stream: Some(&stream), source: Some((&hd, &planes)) };
assert_eq!(record::verify_with(&text, &held, None).unwrap_or_else(|r| panic!("{flag}: {r}")).quality, QualityBasis::NotMeasured, "{flag}");
assert!(line["quality"].is_null() && line["quality_not_measured"].is_string(), "{flag}: {line}");
}
let _ = std::fs::remove_dir_all(&tmp);
}
/// The media framework's encoders, each codec, on this host: §4.3 holds, a signed record
/// verifies with the stream and the source held, and the platform's decoder gives one
/// picture per frame.
#[cfg(target_vendor = "apple")]
#[test]
fn the_platform_encoder_makes_a_stream_that_holds_and_decodes() {
use wai::platform_encode::{self as pe, Api, Codec, Options, record};
let src = corpus::source();
for codec in [Codec::Avc, Codec::Hevc] {
let p = pe::prepare(&src, codec, None, 400).expect("the corpus source");
let e = pe::encode(Api::Platform, &p.cfg, &Options::default(), p.frames.iter().map(Vec::as_slice), &corpus::PLAN).unwrap_or_else(|e| panic!("{}: {e}", codec.name()));
assert!(e.identity.hardware, "{}: the framework chose its software encoder: {:?}", codec.name(), e.identity);
let body = record::body(&e, &p.cfg, &p.source, &corpus::PLAN, None, None, corpus::ISSUED_AT);
let text = record::to_text(&record::sign(body, &ed25519_dalek::SigningKey::from_bytes(&corpus::SEED)));
let (hd, frames) = pe::y4m::read_all(&src).expect("the source");
let planes = frames.concat();
record::verify(&text, &record::Held { stream: Some(&e.stream), source: Some((&hd, &planes)) }).unwrap_or_else(|r| panic!("{}: {r}", codec.name()));
let mut pictures = Vec::new();
let n = pe::platform_decode(codec, &e.stream, &e.units, |f| {
if f.len() != p.cfg.picture_len() {
return Err("a picture of another size".into());
}
pictures.extend_from_slice(f);
Ok(())
})
.expect("the platform decodes it");
assert_eq!(n, corpus::FRAMES, "{}: one picture per frame", codec.name());
// The figures of what the platform decoded, signed and recomputed from that decode:
// the one verdict that makes them the stream's (§7).
let q = record::Quality::measure(p.frames.iter().map(Vec::as_slice), &pictures, p.cfg.width, p.cfg.height).expect("a picture per frame");
let body = record::with_quality(record::body(&e, &p.cfg, &p.source, &corpus::PLAN, None, None, corpus::ISSUED_AT), &q);
let text = record::to_text(&record::sign(body, &ed25519_dalek::SigningKey::from_bytes(&corpus::SEED)));
let held = record::Held { stream: Some(&e.stream), source: Some((&hd, &planes)) };
let v = record::verify_with(&text, &held, Some(record::Pictures::Decoded(&pictures))).unwrap_or_else(|r| panic!("{}: {r}", codec.name()));
assert_eq!(v.quality, record::QualityBasis::Decoded, "{}", codec.name());
}
}