Files
punktfunk/include
enricobuehler 7e97e600c7 feat(wire): the audio plane could not say what format it was carrying, so lossless had no way to be negotiated
The `0xC9` plane's header has no rate, depth or codec field, and `Hello`/`Welcome`
carried only a channel count. A second, lossless plane therefore needs its own tag and
its own negotiation rather than a wider header.

`0xD3` carries interleaved LE PCM behind DELIBERATELY the same 13-byte header as
`0xC9`, so `AudioGapTracker` and the pts/A-V-sync plumbing work unchanged and the only
new logic is the payload and its concealment. One frame per datagram, never
fragmented; the frame duration is chosen at session start from the raw frame size so
it cannot exceed the path MTU. Redundancy is not defined for this plane and is never
sent with it.

`Hello` gains `audio_rate_hz`/`audio_bits` — what the client is asking for. `Welcome`
gains `audio_codec`/`audio_rate_hz`/`audio_bits`/`audio_frame_us` — what the host
actually resolved, which may be lower, and which the client must open its device from
rather than from what it requested.

Two wire traps, both now covered:

`Welcome`'s tail is conditional — `cipher` at 68 and the 32-byte ChaCha key at 69..101
are emitted only for ChaCha — so an appended field lands at 79 under AES and 111 under
ChaCha. Getting that wrong breaks soft-AES clients (webOS) and nothing else, which is
exactly the kind of bug that ships. A test pins both offsets and both total lengths.

`Hello`'s post-HDR tail is capped at 27 bytes, because with no HDR block present the
decoder disambiguates by remaining length and a 28-byte tail would be misread AS an
HDR block. That budget goes from 3 spent to 8; a test pins it.

A default Opus session stays byte-identical on both messages: `Welcome` is still
exactly 68 bytes, `Hello` still 26.

`HOST_CAP_AUDIO_HIRES` takes the LAST free `host_caps` bit. The next host capability
needs a second byte and an ABI bump; the constant says so where someone will read it.
2026-08-16 01:37:19 +02:00
..