111 lines
7 KiB
Markdown
111 lines
7 KiB
Markdown
# live-conformance/compose — live composition
|
||
|
||
The corpus of [`extensions/live-compose.md`](../../extensions/live-compose.md) §11: the
|
||
layout function and the mixer on their own, `WCD1` composition descriptors, and rooms (a
|
||
signed `WRD1` descriptor, its `WRG1` grants and its principals' `WEV1` chains) composed at
|
||
a list of instants, with `WCR1` composition receipts checked against them.
|
||
|
||
**Composition equivalence.** A conforming implementation reaches, for every case, the
|
||
outcome the case states, rectangle for rectangle and sample for sample:
|
||
|
||
- a **layout** case's `params` (the descriptor's fields, §3.1) and `entrants` (each a
|
||
`principal`, its `join` order, its `video` as `[width, height]` or `null`, whether it has
|
||
`audio`, and its `attrs` as `[key, value]` pairs) give the `order`, the `tiles` and the
|
||
`voices` of §5 and §6, or the refusal `reason`. A tile is its `principal`, its `place`
|
||
(`grid`, `featured` or `pip`), its `z`, its `tile` rectangle and its `dst` and `src`
|
||
rectangles (`null` when its video is stopped), each `[x, y, w, h]`; a voice its
|
||
`principal`, `gain` and `pan`;
|
||
- a **mix** case's `channels`, `frames` and `inputs` (each its `channels`, `gain`, `pan` and
|
||
`pcm`, signed 16-bit little-endian samples in hexadecimal) give the mixed `pcm` (§6), or
|
||
the refusal;
|
||
- a **descriptor** case's `bytes` read (§3.3) to its `digest` and `fields`, or are refused;
|
||
- a **composition** case's `room`, `descriptor` and `instants` give the descriptor's
|
||
`digest` and a frame per instant (§9): its `participants` (each its `principal`, its
|
||
`grant`, its `join` order, its `attrs`, and its `video` and `audio` sources with their
|
||
slot, media kind, profile, layers, composed layer, layering, dimensions and `tracks`),
|
||
its `set_digest` (§4.5), and its `order`, `tiles` and `voices`; or a refusal and where,
|
||
`at`: `["room"]`, `["room", …]` with the room verifier's own place (live-rooms §9.1),
|
||
`["descriptor"]` or `["set", t]`;
|
||
- a **receipt** case's `room`, `descriptor` and `receipt` are accepted (§8.3) with the
|
||
receipt's `digest` and the `set_digest` it names, or refused, `at` as above or
|
||
`["receipt"]`.
|
||
|
||
A verifier that reaches another outcome, reason, place, rectangle, sample or digest does
|
||
not conform.
|
||
|
||
**Provenance.** Generated here: `wai_live_compose_vectors gen` writes every case, room,
|
||
descriptor, record and receipt from scenes authored in code, from fixed seeds. Each key is
|
||
SHA-256 of a fixed label and the principal's index, each pure layout case's participant a
|
||
SHA-256 of a fixed label and an index (a name, not a key), each block of PCM SHA-256 output
|
||
under a fixed label (it stands for decoded audio and is no recording), each object digest
|
||
of a receipt SHA-256 of a fixed label (it stands for an object and hashes none), every time
|
||
is a constant (the room's `t0` is 2026-10-17T00:00:00Z), and Ed25519 signing is
|
||
deterministic (RFC 8032), so the file is the same bytes on every machine. The generator
|
||
asserts that each case reaches the outcome it was written to have before it writes it. No
|
||
recorded data.
|
||
|
||
## Layout
|
||
|
||
One file, `vectors.json`:
|
||
|
||
- `principals`: the room's keys, by name (informative).
|
||
- `layouts`, `mixes`, `descriptors`: the cases above, each with `name` and `about`.
|
||
- `rooms`: by name, each a `descriptor` and `grants` (hexadecimal), `key_log_head` (`null`:
|
||
the room names no origin) and `chains` (lists of records in hexadecimal).
|
||
- `compositions`, `receipts`: the cases above, each naming its room.
|
||
|
||
The **studio** room has a director (its role has the direct and compose powers), a
|
||
performer (camera and music, featured, order 1, gain 5120), a guest (speech only at first,
|
||
order 3, then exchanged at 5 s for a grant of order 0, gain 2048 and pan −2048, then video
|
||
at 7 s), a screen-sharing device, an encoder live in the slot `main` under a staged
|
||
profile of the room's own, a mixer (the compose power; it publishes the composed tracks),
|
||
and a viewer. The director's video stops at 6 s and the performer leaves at 8 s. Its
|
||
variants: `studio_bad_order` (the guest's order is `third`), `studio_lifecycle_gap` (the
|
||
relay's record at 6 s not delivered), `studio_viewer_gap` (the viewer's first chat not
|
||
delivered) and `studio_refused` (the viewer sends a `control` it may not).
|
||
|
||
Cases:
|
||
|
||
- layouts: `grid_0` to `grid_12`; portrait, square and auto canvases; `fill_fill`,
|
||
`fill_cover`, `fill_contain`, `fill_default` and extreme aspects; the featured
|
||
participant alone, of four, on a portrait canvas, kept past the tile limit, first of two,
|
||
absent, and unread; order by attribute and ties broken by key; stopped video shown and
|
||
omitted; the tile limit and the voice limit; picture in picture in each corner, static
|
||
and dynamic, alone, with derived sizes, with stopped video, first of two, and over a
|
||
featured tile; and attributes that do not read;
|
||
- mixes: passing through, both widths into both, saturation, pans, gains, ties, silence and
|
||
five refusals;
|
||
- descriptors: the room's three and canvases at their limits, and each refusal a descriptor
|
||
alone can have;
|
||
- compositions: `grid_session` (every second from 1 s to 9 s), `pip_session`,
|
||
`participant_gap`, `signer_with_power`, and a refusal for a signer without the power, one
|
||
not in the room, another room, a bad signature, an instant before `effective`, an
|
||
attribute that does not read, a lifecycle gap and a refused room;
|
||
- receipts: `video`, `audio` and `pip_video` accepted, and one refused for each reason a
|
||
receipt can have.
|
||
|
||
## Running
|
||
|
||
```
|
||
cd ../../wai-rs
|
||
cargo run --no-default-features --features live_compose --bin wai_live_compose_vectors -- verify ../live-conformance/compose
|
||
cargo run --no-default-features --features live_compose --bin wai_live_compose_vectors -- gen ../live-conformance/compose # regenerate
|
||
cargo test --no-default-features --features live_compose --test live_compose
|
||
cd ../live-conformance
|
||
python3 live_compose_verify.py compose
|
||
```
|
||
|
||
`wai_live_compose_vectors verify` and `tests/live_compose.rs` require the file to regenerate
|
||
byte for byte and `wai-rs` to give every case its outcome; the test also requires every
|
||
reason of §10 to refuse a case, the cases above to be there, the grid session to change its
|
||
order at the guest's exchange, and §10 to list exactly the reasons the reference reports.
|
||
`live_compose_verify.py` is the second implementation, written from the extension's text
|
||
and sharing no code with `wai-rs`: it verifies each room with `live_rooms_verify.py` and
|
||
steps through its lifecycle replay to take the room at each instant, gives every case the
|
||
same outcome, requires the same coverage of reasons, and then mutates copies of the corpus,
|
||
one defect each (a tile moved, tiles swapped, the PiP window's z, a source or destination
|
||
rectangle, the order, an entrant's attribute, a parameter, a stated reason, a voice, a mixed
|
||
or input sample, a pan, a descriptor's byte or digest, a frame's tile, set digest, join
|
||
order or tracks, an instant, a lifecycle record not delivered, a grant's byte, a receipt's
|
||
byte or digest, and a stated outcome), each of which must fail. Pass = an exit status of 0
|
||
from each.
|