Some checks failed
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 5s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 1m3s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 2m13s
joule-code conformance gate / joule-moq-relay, every target (pull_request) Has been cancelled
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Has been cancelled
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
WAI energy receipts / does this change touch it (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Has been cancelled
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Has been cancelled
WAI neural sink gates / does this change touch it (pull_request) Has been cancelled
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
wai-quantum WebGPU member / does this change touch it (pull_request) Has been cancelled
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Has been cancelled
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Has been cancelled
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Has been cancelled
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Has been cancelled
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Has been cancelled
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 1m29s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 1m55s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 3m15s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 4m59s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 5m44s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 3m49s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 13s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Has been skipped
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Has been skipped
wai-quantum CUDA member / does this change touch it (pull_request) Successful in 15s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Has been skipped
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Has been skipped
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Has been skipped
wai-quantum signal processor / does this change touch it (pull_request) Successful in 13s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Has been skipped
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 10s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Has been skipped
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Has been skipped
wai-quantum HIP member / does this change touch it (pull_request) Successful in 9s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Has been skipped
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Has been skipped
wai-quantum Metal member / does this change touch it (pull_request) Successful in 9s
wai-quantum Metal member / member · Metal (macos) (pull_request) Has been skipped
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Has been skipped
wai-quantum npu-cores member / does this change touch it (pull_request) Successful in 10s
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Has been skipped
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Has been skipped
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 9s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Has been skipped
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Has been skipped
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 9s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Has been skipped
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Has been skipped
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Has been skipped
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Has been skipped
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 3m52s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 10s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Has been skipped
wai-quantum service / does this change touch it (pull_request) Successful in 10s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 9s
wai-quantum service / service · linux (pull_request) Has been skipped
wai-quantum service / service · macos (pull_request) Has been skipped
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Has been skipped
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Has been skipped
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 8s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Has been skipped
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Has been skipped
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 9s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 7s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Has been skipped
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Has been skipped
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Has been skipped
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 6m4s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 3m59s
The gateway's README and both CHANGELOGs say the same. Co-Authored-By: Claude Opus 5.5 <[email protected]>
184 lines
12 KiB
Markdown
184 lines
12 KiB
Markdown
# joule-moq-ingest
|
||
|
||
A gateway between WebRTC and the MoQ tracks of a WAI room. A standard WebRTC encoder
|
||
publishes into a room over **WHIP** (RFC 9725); the gateway becomes its tracks' MoQ
|
||
publisher at the relay and signs every group's receipts as the first hop. A standard
|
||
WebRTC player watches a room's tracks over **WHEP** (`draft-ietf-wish-whep-05`); the
|
||
gateway subscribes at the relay and verifies every object's receipt before it hands the
|
||
frame on. The mapping it implements is WAI's `extensions/live-ingest.md`, which also maps
|
||
Enhanced RTMP v2 multitrack and SRT (specified, not implemented here).
|
||
|
||
It is a library (`GatewayServer`, `Gateway`) and a binary, `joule-moq-ingest`. The relay
|
||
is `joule-moq-relay`; the MOQT codec is `joule-moq`'s, `draft-ietf-moq-transport-22`.
|
||
|
||
## Resources
|
||
|
||
| resource | methods |
|
||
|---|---|
|
||
| `/whip` | `POST` an `application/sdp` offer: `201`, the answer, `Location`, `ETag`. `OPTIONS` (CORS, `Accept-Post`), `GET`, `HEAD` |
|
||
| `/whip/s/<id>` | `PATCH` an `application/trickle-ice-sdpfrag`: trickle ICE (`204`) or an ICE restart (`200`, a fragment, a new `ETag`); `DELETE` (`200`) ends the session and its tracks |
|
||
| `/whep/<room>/<owner>[?layer=<n>]` | `POST` an offer for the owner's tracks: `201`, or `409` with `Retry-After` while the owner is not live. `HEAD` answers with `Link: <urn:ietf:params:whep>; rel="profile"` (WHEP §4.2) |
|
||
| `/whep/s/<id>` | `PATCH`, `DELETE`, as for WHIP |
|
||
|
||
Every request but `OPTIONS` carries `Authorization: Bearer <token>`. **The token is a room
|
||
grant**: a WAI `WRG1` record (`live-rooms.md` §4), base64url without padding. A grant is
|
||
public, so every request that carries one also carries a proof of possession of its key,
|
||
`WAI-Room-Proof` (`live-rooms.md` §10.5.3), over a single-use challenge the gateway gave in
|
||
`WAI-Room-Challenge`: on a `401` and on each response to a request with a grant. Refusals are
|
||
RFC 9457 problem details whose `reason` member is `live-ingest.md` §14's code.
|
||
|
||
## Admission
|
||
|
||
The gateway holds each room's signed descriptor (`WRD1`) and checks a token against the
|
||
room it names, as the relay checks a token against its grants, here by the room's own
|
||
signed records: the grant reads and its signature verifies under the room's authority
|
||
(`live-rooms.md` §4.3, its field rules, its fourteen-day bound, its role and the room's
|
||
ceiling), it is good now, it is not among the room's revocations, its origins include the
|
||
gateway's, a single-use grant has opened no session here, and the request's proof passes
|
||
`live-rooms.md` §10.5.4 over a challenge held for its endpoint or session
|
||
(`joule_moq::grant_proof::check_proof`, through `gateway::check_http_proof`). What fails is `401` with
|
||
`WWW-Authenticate: Bearer error="invalid_token"`. A good grant without the power the
|
||
request needs is **`403`** with `error="insufficient_scope"` (RFC 6750 §3.1): the publish
|
||
power for each media kind a WHIP offer carries, the subscribe power up to the layer a WHEP
|
||
request asks for. A session's resource answers only the token that opened it.
|
||
|
||
`room.rs` reads descriptors and grants from the extension's text; `tests/room_corpus.rs`
|
||
holds it to WAI's corpus `wai/live-conformance/rooms/`: every room id and grant digest,
|
||
the registered profiles' records, and every refusal of a descriptor or a grant there, but
|
||
an exchanged grant's link and the key log, which a bearer token does not bring. It also
|
||
runs the corpus's six HTTP proofs through `check_http_proof`, each with its stated
|
||
outcome, and presents each accepted proof again as a replay.
|
||
|
||
## WHIP into the room
|
||
|
||
- **Tracks.** Per media kind of the offer, `(room, owner, audio|video)` / `0` and its
|
||
receipts track `0_receipts`; and the owner's catalog, `(room, owner)` / `catalog`, with
|
||
`catalog_receipts`. All are published (PUBLISH) before the answer goes back. Audio and
|
||
the catalog at publisher priority 0, video at 1.
|
||
- **Frames.** str0m depacketises RTP into frames: H.264 (RFC 6184), VP8 (RFC 7741), VP9
|
||
(RFC 9628), AV1 (its RTP payload format v1.0.0) and Opus (RFC 7587). Each frame is one
|
||
object, one `WAI1` envelope:
|
||
|
||
| codec | capability | payload |
|
||
|---|---|---|
|
||
| H.264 | `wai.video.avc` | one access unit, Annex B |
|
||
| VP8 | `wai.video.vp8` | one frame in IVF (`VP80`), its size from the keyframe header |
|
||
| VP9 | `wai.video.vp9` | one frame in IVF (`VP90`), its size from the uncompressed header |
|
||
| AV1 | `wai.video.av1` | one temporal unit in SPEC §5's AV1 framing, the temporal delimiter restored, the size from the sequence header |
|
||
| Opus | `wai.audio.opus.packet` | one packet |
|
||
|
||
- **Groups.** Video: one group per keyframe (a PLI goes to the publisher before the first
|
||
one, and when a group passes `max_video_group_ms`). Audio: one group per fixed window of
|
||
`audio_group_ms` on the room clock. One subgroup stream per group, written as the frames
|
||
arrive. A track's first group ID is its first frame's room-clock time in microseconds.
|
||
- **Time.** The manifest's `live` member carries the frame's room-clock time `t`, its RTP
|
||
time and clock rate, whether it is a keyframe, and on a group's first object the grant
|
||
reference (`live-rooms.md` §4.5). The mapping is anchored at a track's first frame's
|
||
arrival, `t = A + (R − R0) · 10^6 / rate`, and re-anchored at any frame it would place
|
||
more than `max_skew_ms` from its arrival: so **every frame's `t` lies within
|
||
`max_skew_ms` of its arrival at the gateway**.
|
||
- **Receipts.** When a group ends, the gateway signs its group receipt over every object
|
||
and publishes it with the object receipts on the receipts track, chained to the group
|
||
before. Every figure is the unmetered marker: no meter backs the gateway. The chain's
|
||
alias is derived per session, so a publisher that reconnects starts a new chain.
|
||
- **The catalog** is MSF JSON with WAI's `wai_*` fields, published once every track has
|
||
begun (or a second after the first did) and again whenever a codec or picture size
|
||
changes, and signed like the media, so a relay that checks every track of the room at its
|
||
door forwards it.
|
||
- **The end.** DELETE (or ICE lost, idle, a bound passed) ends each open group, publishes
|
||
its receipts, waits for the relay to acknowledge every stream, and sends PUBLISH_DONE
|
||
`TRACK_ENDED` on every track: the relay's subscribers see the tracks end.
|
||
|
||
## WHEP out of the room
|
||
|
||
The gateway reads the owner's latest catalog once its receipt verifies, answers the
|
||
player's offer with the codecs the tracks carry, and subscribes to each accepted track and
|
||
its receipts track from the start of the latest group (the live part from the Next Object,
|
||
the rest of that group by a fill), so the player starts at a keyframe. Before a frame
|
||
reaches the player, its group's receipts must name its MOQT group and Object ID and the
|
||
track's chain, verify under a trusted first hop's key (`whep.trust`; this gateway's own
|
||
key by default), chain to the group before, and prove the object's inclusion; the object
|
||
must open as an envelope of the track's codec. What fails is dropped and counted in the
|
||
session's record; a group whose receipts never come is dropped after `hold_ms`.
|
||
|
||
**What a WHEP player cannot see:** the receipts. WebRTC carries media only. The gateway
|
||
verifies on the player's behalf and records what it dropped and why; a WAI-aware player
|
||
subscribes to the same tracks and their receipts tracks over MoQ, through the relay's
|
||
WebTransport or WebSocket paths, and verifies every object itself.
|
||
|
||
A verified group is released when its receipts arrive, at the group's end, so a WHEP
|
||
player is up to a video group behind the publisher.
|
||
|
||
## Bounds
|
||
|
||
Each is a field of `[limits]`, `[groups]`, `[timeline]` or `[whep]` in the configuration:
|
||
|
||
| field | default | past it |
|
||
|---|---|---|
|
||
| `max_whip_sessions`, `max_whep_sessions` | 64, 256 | `503` with `Retry-After` |
|
||
| `max_tracks_per_session` | 2 | `422`; and one track of each kind at most |
|
||
| `max_bitrate_kbps` over `bitrate_window_ms` | 8 000 over 2 000 ms | stated per section as `b=AS` in the answer (a grant's publish profile lowers it); a session past it is ended |
|
||
| `max_frame_bytes` | 4 MiB | the frame is dropped and counted |
|
||
| `max_queue_bytes` | 32 MiB | the session is ended (`relay_backpressure`) |
|
||
| `audio_group_ms`, `max_video_group_ms` | 200, 2 000 | — |
|
||
| `max_skew_ms` | 250 | the track is re-anchored |
|
||
| `whep.hold_ms` | 5 000 | the group is dropped (`receipt_missing`) |
|
||
|
||
`gateway.example.toml` shows every field. It holds no secret: the relay token and the
|
||
signing key are files, and a room is its public, signed descriptor.
|
||
|
||
```text
|
||
joule-moq-ingest --config gateway.toml # JOULE_MOQ_INGEST_LOG sets the log level
|
||
```
|
||
|
||
Every listener is loopback by default: put a TLS front before the HTTP resources (RFC 9725
|
||
§5) and set `media.bind_ip` to an address clients reach.
|
||
|
||
## The WebRTC stack
|
||
|
||
[str0m](https://crates.io/crates/str0m) 0.24.1, pinned, MIT OR Apache-2.0, with
|
||
`default-features = false` and its `rust-crypto` backend: DTLS by str0m's own `dimpl`,
|
||
SRTP and the rest on RustCrypto, so no C library is linked. It is sans-IO: each session
|
||
here owns a UDP socket and drives its `Rtc` from a tokio task, feeding it datagrams and the
|
||
time and draining its output after every change. It depacketises and packetises H.264,
|
||
VP8, VP9, AV1 and Opus at the frame level (AV1 is a hidden codec in its public API; this
|
||
crate's tests take AV1 through it end to end), supports ICE lite and full ICE, ICE
|
||
restarts, NACK and keyframe requests. Every crate new to the lockfile is MIT, Apache-2.0
|
||
or ISC.
|
||
|
||
## The session record, and live metering
|
||
|
||
Each session ends with a record of what it carried, signed by the gateway's key
|
||
(`record.rs`, format `joule-moq-ingest/session/1`): per track and direction the objects and
|
||
bytes, the drops by reason, subscriber sessions and their time by layer class, the grant
|
||
with its ceilings and the bytes under it, and the gateway's energy as the unmetered marker.
|
||
`Gateway::records` keeps them and `summary.out_path` appends them as JSON lines.
|
||
|
||
These are the counts of the per-hop session record `WMH1` of WAI's live metering, kept in
|
||
its shape, role 3 (ingest gateway). Once that record lands, a `record::HopSink` that writes
|
||
`WMH1` turns each record into its track entries, subscriber time and ledger entry and signs
|
||
it with the same key, which the room's key log lists under `live/ingest`; nothing else in
|
||
the gateway changes.
|
||
|
||
## Tests
|
||
|
||
All on loopback, every wait bounded, the relay checking every receipt at its door:
|
||
|
||
| test | what it shows |
|
||
|---|---|
|
||
| `whip_publish` | A WHIP publisher (str0m as the client) sends three seconds of H.264 and Opus. A subscriber at the relay receives every group of both tracks, verifies every receipt under the gateway's key and every chain link, and gets the frames' bytes as sent; one group per keyframe, every audio group within its window; DELETE ends the tracks with PUBLISH_DONE; the session's record verifies. |
|
||
| `whep_play` | Before the publisher is live a WHEP POST is `409` with `Retry-After`. Then a WHEP player (str0m) gets the publisher's frames, byte for byte, from the keyframe of the group it joined to the last group closed; the WHEP session ends with the tracks, nothing refused. |
|
||
| `auth_and_ice` | No token `401`; a token that is not a grant `401 invalid_token`; a viewer's grant `403 insufficient_scope`; a grant past its window, one of another room; `415`; `422`; WHEP without subscribe or above `max_layer` `403`; discovery and CORS. `PATCH` without `If-Match` `428`, stale `412`, trickle `204`, another principal's grant, its own key proved, `403`; a `PATCH` or `DELETE` presenting the grant without a proof `401 pop_missing`; an ICE restart (`If-Match: *`) `200` with new credentials and a new `ETag`, ICE connecting again, and every frame before and after it at the relay. |
|
||
| `codecs` | VP8, VP9 and AV1 each through WHIP: every frame whole, one group per keyframe, the size each framing states. |
|
||
| `room_corpus` | The room reader against `wai/live-conformance/rooms/`, and its six HTTP proofs of possession through the gateway's proof step, each accepted proof also refused as a replay. |
|
||
|
||
## Not implemented
|
||
|
||
E-RTMP v2 and SRT ingest (`live-ingest.md` §12, §13: mapped only); a WHEP counter-offer;
|
||
a player's keyframe request carried upstream; publishing into a slot; simulcast within one
|
||
WHIP session; STUN and TURN in `Link` headers; reading the key log itself (revocations are
|
||
the list a deployment configures).
|
||
|
||
## Licence
|
||
|
||
Apache-2.0.
|