739a5f76bf
ci / web (push) Successful in 1m3s
ci / docs-site (push) Successful in 58s
decky / build-publish (push) Successful in 16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 8s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 7s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 7s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 43s
ci / bench (push) Successful in 5m21s
arch / build-publish (push) Successful in 10m58s
docker / deploy-docs (push) Successful in 28s
android / android (push) Successful in 13m23s
deb / build-publish (push) Successful in 12m58s
ci / rust (push) Successful in 18m5s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 12m31s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 12m56s
flatpak / build-publish (push) Successful in 5m53s
windows-host / package (push) Successful in 14m37s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m9s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m15s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m12s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m6s
apple / swift (push) Has been cancelled
apple / screenshots (push) Has been cancelled
release / apple (push) Has been cancelled
The Apple client now decodes PyroWave natively on the presenter's own MTLDevice —
no MoltenVK, no upstream C++ in the app. Completes and wires up the decoder whose
early working-tree snapshot rode along in 9127c346:
- MetalWaveletShaders.swift: wavelet_dequant + idwt hand-ported from the vendored
GLSL (STORAGE_MODE 0 only; subgroup scans → 32-wide simdgroups; DCShift spec
constant → function constant; precision-1 split: fp16 levels 0-1 / fp32 2-4).
- MetalWaveletDecoder.swift: Swift reimplementation of push_packet/decode_packet
incl. the Phase-4 chunk-aligned window walk (FRAG chains, zeroed missing shards,
the >half-blocks partial rule), init_block_meta's block-index space, and the
42-dequant + 13-idwt dispatch structure with encoder-boundary barriers. SOF-dims
changes rebuild the size-dependent resources, which is also the mid-stream
resize path. Ring of 4 output plane sets on the presenter's queue.
- Presenter: pf_frag_planar (3xR8, the planar_csc.frag twin) + renderPlanar with
a shared present tail; ReadyFrame carries an image enum (.video | .planar).
- Stage2Pipeline: a dedicated PyroWave pump — no VideoToolbox machinery, no
keyframe/re-anchor recovery (all-intra; partials render as localized blur by
design), newest-frame-index staleness guard for late partials.
- Opt-in: "PyroWave (wired LAN)" codec entry (probe-gated, ≈A13 floor via a real
kernel-compile probe), selecting it advertises + prefers the codec and forces
the session SDR (HDR/10-bit/4:4:4 caps dropped, plan contract).
- Core ABI: punktfunk_connection_shard_payload() — the Welcome's negotiated shard
payload, needed by native decoders to walk chunk-aligned AUs.
- Validation: golden fixtures generated by the host encoder + upstream's own
decoder (pyrowave_dump_golden, RTX 5070 Ti); the Metal decode PSNR-matches at
77-88 dB across all planes for dense AND chunk-aligned AUs, and a hole-punched
partial still decodes. Parser unit tests cover the window walk, FRAG chains,
broken chains, the half-blocks gate, and the block-index layout.
Tests: apple 134 green (mac; iOS/tvOS build), host 312 w/ pyrowave on .21,
core 148 w/ quic; clippy/fmt clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
73 lines
3.7 KiB
Markdown
73 lines
3.7 KiB
Markdown
---
|
||
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, 60 fps):
|
||
|
||
| Mode | Bitrate |
|
||
|---|---|
|
||
| 1280×800 @ 60 (Deck) | ≈ 100 Mbps |
|
||
| 1920×1080 @ 60 | ≈ 200 Mbps |
|
||
| 2560×1440 @ 60 | ≈ 355 Mbps |
|
||
| 3840×2160 @ 60 | ≈ 800 Mbps |
|
||
|
||
120 Hz doubles these. Gigabit Ethernet tops out around 940 Mbps of payload, so 4K60 wants
|
||
2.5GbE (or a lower rate). **Do not run this over Wi-Fi** — that's what HEVC/AV1 are for.
|
||
|
||
Also: PyroWave is **8-bit SDR only**. An HDR session stays on HEVC/AV1 regardless of this
|
||
setting.
|
||
|
||
## Turning it on
|
||
|
||
1. **Host** (Linux): build/install a host with the `pyrowave` feature. On an NVIDIA host the
|
||
capture path additionally needs `PUNKTFUNK_ENCODER=pyrowave` in `host.env` for the codec to
|
||
be advertised; AMD/Intel hosts advertise it automatically when the feature is present.
|
||
2. **Client**:
|
||
- Linux session client (with the `pyrowave` feature): 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); picking it forces
|
||
the session SDR.
|
||
3. Leave the bitrate on Automatic: a PyroWave session pins itself to the ~1.6 bpp rate for
|
||
your mode (≈200 Mbps at 1080p60). 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 host + Linux client (including docked Deck) and Apple clients (native Metal decode
|
||
on Mac / Apple TV 4K / iPad) today; the Windows host is tracked on the
|
||
[roadmap](/docs/roadmap).
|
||
- 8-bit SDR, 4:2:0 only.
|