feat(pyrowave): Windows host HDR + 4:4:4, Rust client HDR present
Phase 3 of design/pyrowave-444-hdr.md. A PyroWave session now negotiates HDR
(10-bit) and 4:4:4 on a Windows host exactly like HEVC/AV1, and the Linux
client presents it through the real HDR10 path.
Host (Windows): BgraToYuvPlanes becomes mode-aware — SDR/BGRA and HDR/scRGB
variants at half- or full-res chroma. The HDR passes reuse HdrP010Converter's
exact colour math (scRGB -> PQ BT.2020 limited studio codes, verified by
hdr_p010_selftest) but write P010-style MSB-packed codes into two separate
shareable R16_UNORM/R16G16_UNORM textures; chroma keeps the pyrowave family's
centre-sited 2x2 box. idd_push pins the composition to the NEGOTIATED depth
(SDR sessions force advanced color off as before; 10-bit sessions enable it
and ride the FP16 ring), and the descriptor poller re-asserts that state
instead of following display flips the fixed-format encoder can't. The
encoder imports 8/16-bit planes per session and stamps the sequence header's
BT.2020/PQ/matrix bits on HDR (stamp_color_bits, extending 574e3e4e's range
stamp); supports_10bit/can_encode_10bit/can_encode_444 gates open (HDR
Windows-only — Linux capture has no HDR source).
Client: the plane ring becomes R16_UNORM for 10-bit sessions (with a
STORAGE_IMAGE format probe), the planar CSC pass joins the HDR10 swapchain
rebuild (set_hdr_mode previously destroyed it without rebuilding — latent),
st.hdr follows frame.color.is_pq(), and the planar push constants carry
depth-10 MSB-packed rows + the PQ tonemap mode, identical to the NV12 arm.
Verified: .173 (RTX 4090) deploy-config clippy + fmt + wire tests + the
extended pyrowave_win_smoke (10-case {SDR,HDR}x{420,444} matrix incl. R16
imports and header stamps); .21 (RTX 5070 Ti) clippy across 4 crates, host
186 tests, client/presenter/encode tests, both Linux GPU smokes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1134,9 +1134,10 @@ impl PyroWaveEncoder {
|
||||
)?;
|
||||
packets.truncate(out_n.max(1));
|
||||
// Correct pyrowave's zeroed sequence-header VUI: it signals ycbcr_range=FULL, but our CSC
|
||||
// emits BT.709 LIMITED — patch the bit HONEST so VUI-honoring clients don't wash out blacks.
|
||||
// emits BT.709 LIMITED — patch the bits HONEST so VUI-honoring clients don't wash out
|
||||
// blacks. (Linux capture has no HDR path, so this side never stamps BT.2020/PQ.)
|
||||
if let Some(p) = packets.first() {
|
||||
crate::pyrowave_wire::mark_limited_range(&mut self.bitstream, p.offset);
|
||||
crate::pyrowave_wire::stamp_color_bits(&mut self.bitstream, p.offset, false);
|
||||
}
|
||||
// Frame into the wire AU via the shared helper (byte-identical on Linux + Windows): the dense
|
||||
// single packet, or the datagram-aligned windowed AU (§4.4).
|
||||
@@ -1678,5 +1679,19 @@ mod tests {
|
||||
dump("ref-chunked-y.bin", &y);
|
||||
dump("ref-chunked-cb.bin", &cb);
|
||||
dump("ref-chunked-cr.bin", &cr);
|
||||
|
||||
// 4:4:4 dense AU + its reference (full-res chroma planes) — the Apple 4:4:4 layout's
|
||||
// golden (design/pyrowave-444-hdr.md Phase 4). Same odd-block geometry.
|
||||
let mut enc =
|
||||
PyroWaveEncoder::open(w, h, 60, 6_500_000, crate::ChromaFormat::Yuv444).expect("open");
|
||||
enc.submit(&test_card(w, h, 13)).expect("444 submit");
|
||||
let au = enc.poll().expect("poll").expect("444 AU");
|
||||
assert!(!au.chunk_aligned);
|
||||
dump("au-dense444.bin", &au.data);
|
||||
// SAFETY: test-only FFI with locally-owned buffers.
|
||||
let (y, cb, cr) = unsafe { decode_planes_chroma(w, h, &au.data, true) };
|
||||
dump("ref-dense444-y.bin", &y);
|
||||
dump("ref-dense444-cb.bin", &cb);
|
||||
dump("ref-dense444-cr.bin", &cr);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user