Files
punktfunk/crates/punktfunk-core
enricobuehler 56f9c8c4b4
windows-host / package (push) Successful in 2m7s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 34s
ci / web (push) Successful in 53s
ci / docs-site (push) Successful in 1m3s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 4m31s
ci / rust (push) Failing after 6m39s
decky / build-publish (push) Successful in 30s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 9s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 8s
ci / bench (push) Successful in 5m17s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 5m0s
arch / build-publish (push) Successful in 16m33s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 9s
apple / swift (push) Successful in 5m13s
android / android (push) Successful in 17m48s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 6m16s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10m5s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 9m0s
deb / build-publish (push) Successful in 12m2s
flatpak / build-publish (push) Failing after 8m6s
docker / deploy-docs (push) Successful in 23s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m18s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m22s
release / apple (push) Successful in 27m42s
apple / screenshots (push) Successful in 18m40s
feat(core,android): Automatic bitrate caps at the client decode limit, not the link ceiling
The Automatic bitrate controller only reacted to network signals (loss, capture→received
OWD, FEC-unrecoverable frames, jump-to-live flush), so on a fast LAN feeding a slower
mobile HW decoder it slow-started straight to the link-probe ceiling and parked there —
backlogging frames inside the decoder, where those signals never register, and choking it.
Reported on a Snapdragon 8 Gen 1: Automatic pinned ~500 Mbps with unusable latency.

Feed the client's decode-stage latency (received→decoded) into the controller as a
first-class signal, symmetric with the existing OWD one: a rise over its rolling-min
baseline ends the slow-start climb and, sustained over two windows, backs the rate ×0.7
down to the real decode limit — so Automatic settles where the decoder keeps up.

- core/abr: on_window gains decode_mean_us; a decode_means rolling-min baseline +
  DECODE_RISE_US (15 ms) fold a decode rise into the bad-window logic.
- core/client: per-frame report_decode_us accumulator, drained to a window mean by the
  data-plane pump; wants_decode_latency() gate (Automatic, non-PyroWave) lets embedders
  skip the measurement where it's ignored. Re-target log prints the driving signals.
- android/decode: report the decode stage on both the sync and async decode paths,
  HUD-independent, measured from the AU leaving next_frame (so codec-input backpressure
  is included) and excluding the vsync present wait.

Apple/Windows report_decode_us calls to follow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:28:11 +02:00
..

punktfunk-core

The shared protocol core — the one place where punktfunk's transport, forward error correction, and crypto live. It's linked into the host and every native client, so there's exactly one implementation of the wire format everywhere.

Written in Rust with no async on the per-frame path (native threads only). It exposes both a normal Rust API and a stable, versioned C ABI, so the Swift and Kotlin clients — and any C embedder — link the same code as the Rust ones.

What's in here

  • Transport & session (session.rs, transport/, packet.rs) — the punktfunk/1 data plane over raw UDP: packetization, reassembly (with attacker-bounded limits), pacing, and socket tuning.
  • FEC (fec/) — the wall-breaker. Two codes:
    • GF(2⁸) classic ReedSolomon with the Cauchy generator matrix — byte-identical to the nanors library Moonlight uses, so our parity is decodable by a stock Moonlight client.
    • GF(2¹⁶) Leopard-RS (SIMD, O(n log n)) — up to 65535 shards/block, which removes the ~1 Gbps FEC ceiling. punktfunk/1 negotiates this one.
  • Crypto (crypto.rs) — AES-128-GCM session encryption with per-direction nonce salts and sequence-as-AAD; SPAKE2 PIN pairing lives behind the quic feature.
  • QUIC control plane (quic.rs, client.rs, feature quic) — the Hello/Welcome/Start handshake, cert pinning/TOFU, reverse audio, and the embeddable NativeClient connector. This is the only place tokio/quinn are allowed; the feature is off by default so the core stays runtime-free.
  • C ABI (abi.rs) — the versioned surface (punktfunk_abi_version(), PunktfunkConfig carrying its own struct_size) that generates include/punktfunk_core.h via cbindgen at build time.

Build outputs

The crate builds three ways at once (crate-type = ["lib", "cdylib", "staticlib"]):

Output Used by
lib (rlib) the host, probe, and tools link it as a normal Rust crate
cdylib (.so/.dylib) the Swift / Kotlin clients via the C ABI
staticlib (.a) the C test harness and static embedding

Test

cargo test -p punktfunk-core                 # unit + proptest + loopback
cargo run  -p loss-harness                   # FEC loss-resilience sweep (no network needed)
bash crates/punktfunk-core/tests/c/run.sh    # standalone C-ABI link + round-trip proof

Design invariants (do not regress)

  • One core, linked everywhere — protocol/FEC/crypto live only here, behind the stable C ABI.
  • No async on the hot path — the per-frame pipeline is native threads only; quic (tokio/quinn) is control-plane only, feature-gated, off by default.
  • Security hardening stays intact — the reassembler bounds attacker-controlled fields before allocating; AES-GCM keeps per-direction nonce salts + seq-as-AAD; the ABI checks struct_size. Regression tests exist — keep them green.
  • punktfunk-host — the streaming host built on this core
  • Clients — the apps that link this core over the C ABI (or directly, in Rust)
  • punktfunk-planning: implementation-plan.md (internal planning repo) — why GF(2¹⁶) FEC, the latency budget, and the architecture thesis