fix(core): let CODEC_PYROWAVE survive the Welcome decode whitelist
ci / web (push) Successful in 1m8s
ci / docs-site (push) Successful in 1m12s
decky / build-publish (push) Successful in 32s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 37s
apple / swift (push) Successful in 2m34s
ci / bench (push) Successful in 6m53s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10m4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9m10s
arch / build-publish (push) Successful in 13m42s
docker / deploy-docs (push) Successful in 21s
android / android (push) Successful in 14m48s
deb / build-publish (push) Successful in 14m53s
windows-host / package (push) Successful in 15m18s
flatpak / build-publish (push) Failing after 8m14s
ci / rust (push) Successful in 18m28s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m27s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m16s
release / apple (push) Successful in 24m45s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m21s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m4s
apple / screenshots (push) Successful in 19m29s
ci / web (push) Successful in 1m8s
ci / docs-site (push) Successful in 1m12s
decky / build-publish (push) Successful in 32s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 37s
apple / swift (push) Successful in 2m34s
ci / bench (push) Successful in 6m53s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 10s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10m4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9m10s
arch / build-publish (push) Successful in 13m42s
docker / deploy-docs (push) Successful in 21s
android / android (push) Successful in 14m48s
deb / build-publish (push) Successful in 14m53s
windows-host / package (push) Successful in 15m18s
flatpak / build-publish (push) Failing after 8m14s
ci / rust (push) Successful in 18m28s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m27s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m55s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 13m20s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m16s
release / apple (push) Successful in 24m45s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m21s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m4s
apple / screenshots (push) Successful in 19m29s
Found by the first live session on .21: the host negotiated PyroWave and put codec=8 on the wire, but Welcome::decode's codec whitelist (H264/AV1, else HEVC — the corrupt-byte guard) folded it to HEVC, so the client opened an FFmpeg HEVC decoder against wavelet AUs. Roundtrip test now pins the pyrowave byte (and that a genuinely unknown future bit still folds to the HEVC default). With the fix the Phase-2 exit session runs END TO END on .21 (host + session client on one box, host capturing the GNOME virtual display, client presenting into a headless weston): negotiated codec=PyroWave (adv 0x0f) → PyroWave encoder (CPU-capture path — this box's Mutter+NVIDIA rejects the LINEAR-dmabuf offer) → wire → PyroWave decoder on the presenter's device → planar CSC. Static desktop: stable 60 fps, e2e 2.1-4.1 ms p50 (p95 <= 6 ms), decode 0.2-0.6 ms, vs HEVC/NVENC-direct baseline 2.1 ms — parity at idle. Full-window motion: 60 fps at ~80 Mb/s all-intra (HEVC ~7), decode still sub-ms, zero decode errors or keyframe-request chatter across every run. Deeper motion/loss characterization needs a dmabuf-accepting host box (this one is capped by the CPU capture path). Also retires the stale "no shipping client decodes this" wording in the host encoder/dispatch logs — the negotiation exists now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -955,6 +955,7 @@ impl Welcome {
|
|||||||
codec: match b.get(66).copied() {
|
codec: match b.get(66).copied() {
|
||||||
Some(CODEC_H264) => CODEC_H264,
|
Some(CODEC_H264) => CODEC_H264,
|
||||||
Some(CODEC_AV1) => CODEC_AV1,
|
Some(CODEC_AV1) => CODEC_AV1,
|
||||||
|
Some(CODEC_PYROWAVE) => CODEC_PYROWAVE,
|
||||||
_ => CODEC_HEVC,
|
_ => CODEC_HEVC,
|
||||||
},
|
},
|
||||||
// Optional trailing host-caps byte — absent on an older host → 0 (no gamepad-state
|
// Optional trailing host-caps byte — absent on an older host → 0 (no gamepad-state
|
||||||
|
|||||||
@@ -124,6 +124,45 @@ fn codec_negotiation_and_back_compat() {
|
|||||||
resolve_codec(CODEC_HEVC | CODEC_PYROWAVE, CODEC_HEVC, CODEC_PYROWAVE),
|
resolve_codec(CODEC_HEVC | CODEC_PYROWAVE, CODEC_HEVC, CODEC_PYROWAVE),
|
||||||
Some(CODEC_HEVC)
|
Some(CODEC_HEVC)
|
||||||
);
|
);
|
||||||
|
// And the negotiated bit SURVIVES the Welcome wire roundtrip — the decode whitelist
|
||||||
|
// once folded unknown codec bytes (incl. PyroWave) to HEVC, which sent wavelet AUs
|
||||||
|
// into an FFmpeg HEVC decoder on the first on-glass run.
|
||||||
|
let mut pw_w = Welcome::decode(
|
||||||
|
&Welcome {
|
||||||
|
abi_version: 2,
|
||||||
|
udp_port: 1,
|
||||||
|
mode: Mode {
|
||||||
|
width: 1280,
|
||||||
|
height: 720,
|
||||||
|
refresh_hz: 60,
|
||||||
|
},
|
||||||
|
fec: FecConfig {
|
||||||
|
scheme: FecScheme::Gf16,
|
||||||
|
fec_percent: 0,
|
||||||
|
max_data_per_block: 1024,
|
||||||
|
},
|
||||||
|
shard_payload: 1024,
|
||||||
|
encrypt: false,
|
||||||
|
key: [0; 16],
|
||||||
|
salt: [0; 4],
|
||||||
|
frames: 0,
|
||||||
|
compositor: CompositorPref::Auto,
|
||||||
|
gamepad: GamepadPref::Auto,
|
||||||
|
bitrate_kbps: 0,
|
||||||
|
bit_depth: 8,
|
||||||
|
color: ColorInfo::SDR_BT709,
|
||||||
|
chroma_format: CHROMA_IDC_420,
|
||||||
|
audio_channels: 2,
|
||||||
|
codec: CODEC_PYROWAVE,
|
||||||
|
host_caps: 0,
|
||||||
|
}
|
||||||
|
.encode(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(pw_w.codec, CODEC_PYROWAVE);
|
||||||
|
// A genuinely unknown future bit still folds to the HEVC default.
|
||||||
|
pw_w.codec = 0x40;
|
||||||
|
assert_eq!(Welcome::decode(&pw_w.encode()).unwrap().codec, CODEC_HEVC);
|
||||||
|
|
||||||
// A Hello advertising codecs roundtrips, and the wire form of a codec-only Hello decodes on
|
// A Hello advertising codecs roundtrips, and the wire form of a codec-only Hello decodes on
|
||||||
// a build that ignores the trailing byte (back-compat: extra bytes are skipped).
|
// a build that ignores the trailing byte (back-compat: extra bytes are skipped).
|
||||||
|
|||||||
@@ -674,9 +674,10 @@ fn open_video_backend(
|
|||||||
{
|
{
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
?codec,
|
?codec,
|
||||||
"PUNKTFUNK_ENCODER=pyrowave: EXPERIMENTAL all-intra wavelet stream — \
|
"PUNKTFUNK_ENCODER=pyrowave forces the all-intra wavelet stream \
|
||||||
clients without a PyroWave decoder (all of them until CODEC_PYROWAVE \
|
regardless of the negotiated codec — only a pyrowave-feature client \
|
||||||
lands) cannot display it"
|
that ALSO preferred CODEC_PYROWAVE can display it (lab override; \
|
||||||
|
normal sessions negotiate it instead)"
|
||||||
);
|
);
|
||||||
pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps)
|
pyrowave::PyroWaveEncoder::open(width, height, fps, bitrate_bps)
|
||||||
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"))
|
.map(|e| (Box::new(e) as Box<dyn Encoder>, "pyrowave"))
|
||||||
|
|||||||
@@ -430,8 +430,7 @@ impl PyroWaveEncoder {
|
|||||||
gpu = %props.device_name_as_c_str().unwrap_or(c"?").to_string_lossy(),
|
gpu = %props.device_name_as_c_str().unwrap_or(c"?").to_string_lossy(),
|
||||||
mode = %format!("{w}x{h}@{fps}"),
|
mode = %format!("{w}x{h}@{fps}"),
|
||||||
budget_kib = frame_budget / 1024,
|
budget_kib = frame_budget / 1024,
|
||||||
"PyroWave encoder open (intra-only wavelet, BT.709 limited 4:2:0) — \
|
"PyroWave encoder open (intra-only wavelet, BT.709 limited 4:2:0)"
|
||||||
EXPERIMENTAL: no shipping client decodes this until CODEC_PYROWAVE lands"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user