Files
punktfunk/clients/probe
enricobuehler ffc0b07b46 feat(protocol,host): negotiate video codec + add a GPU-less software (openh264) encode path
Phase 1 of codec negotiation, and the Linux software H.264 encode path it unblocks.

**Codec negotiation (core `quic`):**
- `Hello.video_codecs` (bitfield: CODEC_H264/HEVC/AV1) — the client advertises what it can
  decode; appended as a trailing byte (older client → 0 = HEVC-only, back-compat).
- `Welcome.codec` — the single codec the host resolved and will emit; trailing byte (older
  host → HEVC).
- `resolve_codec(client, host_capable)` picks the shared codec (precedence HEVC > AV1 > H.264)
  or `None` → the host refuses honestly rather than sending an undecodable stream.
- Roundtrip + back-compat tests; cbindgen exports the CODEC_* constants.

**Software encoder (host):**
- The openh264 `OpenH264Encoder` (was Windows-only) is now built on Linux too — it's
  platform-agnostic (consumes CPU RGB `CapturedFrame`s, statically-bundled openh264). `openh264`
  moved to the shared linux+windows Cargo target.
- `PUNKTFUNK_ENCODER=software` selects it: `open_video` gains a `software` branch (H.264 only),
  and `session_plan::resolve_encoder` / `capture::gpu_encode` resolve `EncoderBackend::Software`
  → `output_format().gpu = false`, so the portal capturer delivers CPU RGB. Explicit-only (auto
  never picks it — a box with a dead driver still has /dev/nvidiactl and would mis-resolve NVENC).

**Host codec resolution (`punktfunk1`):**
- The native path no longer hardcodes HEVC: it resolves the codec from the client's advertised
  set ∩ the host's capability (`Codec::host_wire_caps`: software→H.264, else HEVC), threads it
  through `SessionPlan.codec`, and opens the encoder + validates reconfigures at that codec. A
  software host + HEVC-only client is refused with a clear error.
- 4:4:4 is gated on HEVC (it's HEVC-only).

**Probe:** advertises H264|HEVC|AV1 and logs the resolved codec.

Validated on the GPU-less dev box: negotiation is live end-to-end (probe advertises 0x07 → host
resolves H.264 → Welcome reports it → plan = Software/H264), and the openh264 unit test (CPU RGB →
AnnexB IDR) now runs on Linux. Full capture→encode still needs a GPU on this box — every
compositor screencast path (KWin GL, gamescope VK_EXT_physical_device_drm, wlroots EGL) requires
one; software render (llvmpipe/pixman) can't be captured — so this box exercises negotiation +
encoder, not live capture. The software path unblocks GPU-less-*encode* boxes that still have a
display GPU. Phase 2 (clients advertising real codecs + decoding per Welcome.codec) is a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 23:13:39 +00:00
..

punktfunk — probe (reference client)

punktfunk-probe is the headless reference client for the punktfunk/1 protocol — a command-line tool for testing, latency measurement, and validating host behavior. It's not a streaming app you'd watch on; it connects, exercises a plane, and reports numbers. If you want to actually stream, use the Linux, Windows, Apple, or Android clients.

Because it links the same punktfunk-core as every other client, it's also the canonical example of driving the protocol end to end: QUIC control plane, UDP data plane, and the side planes (input, audio, rumble) over QUIC datagrams.

What it does

  • Receives a real stream, writes a playable .h265, and reports per-frame capture→…→reassembled latency percentiles (the host stamps each frame with its capture clock).
  • Verification mode against a synthetic host — byte-checks deterministic test frames.
  • Exercises every plane with scripted test traffic: --input-test (mouse/keyboard), --mic-test (a 440 Hz Opus tone up to the host mic), --touch-test (a synthetic finger), --rich-input-test (DualSense touchpad + motion, logging the HID-output feedback that comes back).
  • Trust--pin <64-hex> pins the host fingerprint; --pair <PIN> runs the SPAKE2 pairing ceremony and prints the verified fingerprint to pin from then on. Without a pin it trusts on first use.
  • Discovery--discover [secs] browses the LAN for _punktfunk._udp hosts and prints each (name, addr:port, pairing requirement, cert fingerprint), then exits.
  • Negotiation knobs--mode WxHxFPS, --remode (mid-stream mode change), --bitrate, --audio-channels (stereo / 5.1 / 7.1), --compositor, --gamepad, --launch, --speed-test.

Usage

# stream 720p120 from a host, save the video, and print latency percentiles:
cargo run -p punktfunk-probe -- --mode 1280x720x120 --connect HOST:PORT --out /tmp/a.h265

# list hosts on the LAN:
cargo run -p punktfunk-probe -- --discover

# pair with a host that requires it (read the PIN off the host), then stream:
cargo run -p punktfunk-probe -- --connect HOST:PORT --pair 1234
cargo run -p punktfunk-probe -- --connect HOST:PORT --pin <64-hex> --input-test

Full flag reference is in the module doc-comment at the top of src/main.rs.

  • Project README — the host, the streaming clients, and the protocol
  • punktfunk-host punktfunk1-host — the persistent native-protocol listener to probe against (see the "Running on this box" section of the repo README / CLAUDE.md)