docs(pyrowave): document 4:4:4 + HDR and add an interactive bitrate calculator
decky / build-publish (push) Successful in 20s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 38s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 14s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 56s
arch / build-publish (push) Successful in 12m17s
deb / build-publish (push) Successful in 9m20s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 5m18s
docker / deploy-docs (push) Successful in 26s
android / android (push) Successful in 16m30s
deb / build-publish-host (push) Successful in 12m43s
ci / rust (push) Successful in 24m28s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m38s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m39s
ci / web (push) Successful in 48s
apple / swift (push) Successful in 1m22s
ci / docs-site (push) Successful in 54s
ci / bench (push) Successful in 5m55s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
apple / screenshots (push) Successful in 6m31s
decky / build-publish (push) Successful in 20s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 38s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 14s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 56s
arch / build-publish (push) Successful in 12m17s
deb / build-publish (push) Successful in 9m20s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 5m18s
docker / deploy-docs (push) Successful in 26s
android / android (push) Successful in 16m30s
deb / build-publish-host (push) Successful in 12m43s
ci / rust (push) Successful in 24m28s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 13m38s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m39s
ci / web (push) Successful in 48s
apple / swift (push) Successful in 1m22s
ci / docs-site (push) Successful in 54s
ci / bench (push) Successful in 5m55s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
apple / screenshots (push) Successful in 6m31s
- New "4:4:4 and HDR" section: what each mode buys, the ~1.6× / +15% bitrate cost, that HDR needs a Windows host today (Linux capture has no HDR source), and that the two combine (~1.9× the 4:2:0 SDR rate). - Interactive <BitrateCalculator> (registered in the MDX components map): resolution (presets or custom), frame rate, 4:2:0/4:4:4, SDR/HDR -> the estimated Automatic pin, bits/pixel, per-frame size, and which link tier it needs. Formula mirrors the host's resolve_bitrate_kbps_for exactly. - Expanded the bandwidth table with 120 Hz rows; note the big modes want 5/10 GbE. - Document PUNKTFUNK_PYROWAVE_MAX_MBPS (cap the open-loop pin on a constrained link) in configuration.md. - pyrowave.md -> .mdx so the page can host the component. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: PyroWave (wired-LAN codec)
|
||||
description: The opt-in ultra-low-latency wavelet codec for wired links — what it is, the bandwidth it needs, and how to turn it on.
|
||||
---
|
||||
|
||||
PyroWave is an **opt-in** video codec mode for links that can afford real bandwidth: wired
|
||||
Ethernet, a docked Steam Deck, a 2.5GbE LAN. It trades bitrate for latency — instead of
|
||||
H.264/HEVC/AV1 on the GPU's video engine, frames are compressed with
|
||||
[PyroWave](https://github.com/Themaister/pyrowave), an intra-only wavelet codec running as plain
|
||||
Vulkan compute. Punktfunk vendors a pinned copy and runs it on both ends.
|
||||
|
||||
**It is never selected automatically.** HEVC/AV1 remain the codecs for Wi-Fi and everything
|
||||
else; PyroWave engages only when *you* pick it on the client **and** the host supports it. If
|
||||
either side can't, the session silently falls back to the normal codec ladder.
|
||||
|
||||
## Why you'd want it
|
||||
|
||||
- **Codec latency drops by an order of magnitude.** Encode and decode each take a fraction of a
|
||||
millisecond of GPU compute (measured ~0.15 ms encode / ~0.07 ms decode at 1080p on an
|
||||
RTX 5070 Ti), versus one-to-several milliseconds per side for the hardware H.26x pipelines.
|
||||
- **Every frame is a keyframe.** There is no GOP, no reference chain, no keyframe round-trip
|
||||
after packet loss — a lost frame costs exactly that frame, and the next one is already a
|
||||
complete picture. The whole IDR/recovery apparatus that produces loss-time stutter simply
|
||||
doesn't exist in this mode.
|
||||
- **Uniform frame sizes.** The rate control hits its per-frame byte budget exactly, so the
|
||||
pacer sees a flat load instead of 20–40× keyframe spikes.
|
||||
|
||||
## What it costs
|
||||
|
||||
Bandwidth. At the codec's ~1.6 bits-per-pixel operating point (4:2:0, SDR):
|
||||
|
||||
| Mode | Bitrate |
|
||||
|---|---|
|
||||
| 1280×800 @ 60 (Deck) | ≈ 100 Mbps |
|
||||
| 1920×1080 @ 60 | ≈ 200 Mbps |
|
||||
| 1920×1080 @ 120 | ≈ 400 Mbps |
|
||||
| 2560×1440 @ 60 | ≈ 355 Mbps |
|
||||
| 2560×1440 @ 120 | ≈ 710 Mbps |
|
||||
| 3840×2160 @ 60 | ≈ 800 Mbps |
|
||||
| 3840×2160 @ 120 | ≈ 1.6 Gbps |
|
||||
|
||||
Frame rate scales the rate linearly, [4:4:4](#444-and-hdr) multiplies it by ~1.6, and an
|
||||
[HDR](#444-and-hdr) (10-bit) session adds ~15 %. Estimate any combination:
|
||||
|
||||
<BitrateCalculator />
|
||||
|
||||
Gigabit Ethernet tops out around 940 Mbps of payload, so 4K60 wants 2.5GbE and the big
|
||||
4:4:4 / HDR / high-refresh modes want 5GbE or 10GbE. **Do not run this over Wi-Fi** — that's
|
||||
what HEVC/AV1 are for.
|
||||
|
||||
## 4:4:4 and HDR
|
||||
|
||||
PyroWave carries **full-chroma 4:4:4** and **HDR** the same way it carries everything else —
|
||||
intra-only, every frame a keyframe — so the low-latency and clean-loss properties above hold
|
||||
in these modes too. Both are negotiated per session from your client's settings, exactly like
|
||||
HEVC/AV1; nothing PyroWave-specific to turn on beyond picking the codec.
|
||||
|
||||
- **4:4:4 (full chroma).** With your client's **4:4:4** setting on, the session encodes chroma
|
||||
at full resolution instead of subsampled 4:2:0 — sharp coloured text, thin UI lines, and
|
||||
red/blue edges that 4:2:0 softens. It costs ~1.6× the bitrate (chroma compresses better than
|
||||
luma, so it is less than the 2× the extra samples imply). Available on Linux and Windows
|
||||
hosts.
|
||||
- **HDR (10-bit, BT.2020 PQ).** With HDR on and an HDR host display pipeline, the session
|
||||
carries a 10-bit BT.2020 PQ signal in 16-bit planes and adds ~15 % to the bitrate. **HDR
|
||||
needs a Windows host today** — the Linux host's capture path has no HDR source yet, so
|
||||
Linux-hosted sessions are SDR (4:4:4 still works).
|
||||
- The two combine: a 4:4:4 **and** HDR session applies both factors (~1.6 × 1.15 ≈ 1.9× the
|
||||
4:2:0 SDR rate). The Apple and Rust clients decode whatever the session negotiated — 4:2:0
|
||||
or 4:4:4, SDR or HDR — with no extra setup.
|
||||
|
||||
At the top end this gets demanding: 4:4:4 + HDR at a super-ultrawide 5120×1440@240 pins around
|
||||
5.3 Gbps, which is more than a 5GbE link carries. On a link that can't keep up, either set an
|
||||
explicit lower bitrate on the client or cap the host's Automatic pin with
|
||||
[`PUNKTFUNK_PYROWAVE_MAX_MBPS`](/docs/configuration) — otherwise the overshoot just becomes
|
||||
dropped packets.
|
||||
|
||||
## Turning it on
|
||||
|
||||
1. **Host** (Linux): nothing to do — default builds ship the codec and every Linux GPU host
|
||||
advertises it. AMD/Intel hosts encode from the capture dmabuf zero-copy; on an NVIDIA host
|
||||
a PyroWave session currently captures via CPU RGB (a modest host-side cost that only
|
||||
affects sessions that picked this codec — everything else keeps its zero-copy path).
|
||||
2. **Client**:
|
||||
- Linux session client: set **Settings → Video codec → PyroWave (wired LAN)** in the
|
||||
gamepad console, or launch with `PUNKTFUNK_PREFER_PYROWAVE=1`.
|
||||
- Apple (Mac, Apple TV 4K, iPad — wired networking strongly recommended): set
|
||||
**Settings → Codec → PyroWave (wired LAN)**. The option appears only on devices whose
|
||||
GPU passes the decode probe (Apple Silicon and A13-class or newer). The decoder follows
|
||||
the stream: 4:2:0 or 4:4:4, SDR or HDR, per what the session negotiated.
|
||||
3. Leave the bitrate on Automatic: a PyroWave session pins itself to the ~1.6 bpp rate for
|
||||
your mode (≈200 Mbps at 1080p60; ~2.6 bpp for 4:4:4, +15 % for HDR). An explicit bitrate is honored if you set one, but the
|
||||
adaptive-bitrate controller stays off either way — this codec has no useful low-rate
|
||||
regime, so under sustained loss the right move is switching back to HEVC, not degrading.
|
||||
The pin follows the resolution: a mid-stream resize (e.g. Match window) re-pins the rate
|
||||
for the new mode, so resizing a window down also cuts the bandwidth.
|
||||
|
||||
The stats overlay shows `pyrowave` as the decode path when the mode is active.
|
||||
|
||||
## Current limits
|
||||
|
||||
- Linux and Windows hosts; Linux clients (including docked Deck) and Apple clients (native
|
||||
Metal decode on Mac / Apple TV 4K / iPad) today.
|
||||
- HDR needs a Windows host (the Linux host's capture path has no HDR source yet).
|
||||
Reference in New Issue
Block a user