-
-
Notifications
You must be signed in to change notification settings - Fork 248
docs(quest): plan follow-ups from the next-16 quest run #4105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # [M] moq-lite-07 counts group streams instead of dropping groups | ||
|
|
||
| ## Goal | ||
|
|
||
| On moq-lite-07, a subscriber knows a subscription has delivered everything | ||
| once it has seen as many group streams as the publisher opened, the way | ||
| moq-transport's PUBLISH_DONE Stream Count works. SUBSCRIBE_DROP is gone from | ||
| lite-07: a group the publisher skipped or never opened is simply not counted, | ||
| so nothing has to name it. Published versions (lite-01 to -06) keep decoding | ||
| SUBSCRIBE_DROP unchanged. | ||
|
|
||
| Where reliable reset is negotiated, the count is exact and the subscriber | ||
| waits for nothing else. Where it is not (browsers today), a stream reset | ||
| before its header arrived is still invisible, so the track-tail grace stays. | ||
|
|
||
| ## Plan | ||
|
|
||
| - Wire: SUBSCRIBE_END gains `Stream Count`, the number of group streams the | ||
| publisher opened for this subscription. The publisher sends it once every | ||
| group stream below the end has been opened (not finished), like | ||
| PUBLISH_DONE, so the boundary arrives slightly later than today. Remove | ||
| SUBSCRIBE_DROP and its type from lite-07 and reword the Subscribe Stream | ||
| section: the FIN follows once every counted stream has finished or been | ||
| reset. lite-07 is unpublished, so this changes it in place; update | ||
| `drafts/draft-lcurley-moq-lite.md` and its changelog. | ||
| - Rust and JS publishers count the streams they open per subscription and | ||
| send the count; a relay counts its own downstream streams, never forwarding | ||
| the upstream count. | ||
| - Subscribers on lite-07 stop waiting once the count is reached, accepting a | ||
| late stream below the end within the grace. On lite-05 and -06, the | ||
| DROP accounting from JS track tail (#4086) stays as it is. | ||
| - Tests in both languages: a late stream after SUBSCRIBE_END, a skipped group | ||
| that is never counted, a reset stream, and a count of zero. Add a Rust-JS | ||
| interop case. | ||
|
|
||
| This lands before lite-07 is published. Rust has never sent or acted on | ||
| SUBSCRIBE_DROP, so [Rust track tail](/quest/m1/rust-track-tail.md) builds its | ||
| lite accounting on the count rather than on drops. | ||
|
|
||
| ## Related | ||
|
|
||
| - [Rust track tail](/quest/m1/rust-track-tail.md) - builds on this count for moq-lite | ||
| - [Reliable stream reset](/quest/m1/quic/reliable-reset.md) - makes the count exact by keeping a reset stream's header | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # [S] A failed NVENC encode does not hang shutdown | ||
|
|
||
| ## Goal | ||
|
|
||
| After NVENC rejects an encode (P7 with high-quality tuning returns | ||
| `InvalidParam`), the process shuts down promptly. Today it hangs on exit. | ||
|
|
||
| ## Plan | ||
|
|
||
| Reproduce it first with the `encode-presets` example from #4099. Suspects, | ||
| from reading the code: `encode::Sink` runs NVENC on the `moq-video-encode` | ||
| thread, and `Worker::drop` joins it. That thread then drops the encoder, and | ||
| `Session::drop` calls a synchronous end-of-stream `encode_picture`. A | ||
| `Pending` that did not finish runs a blocking `lock_bitstream`. Either one can | ||
| wedge on a session the driver already refused, and the join then waits | ||
| forever. | ||
|
|
||
| Fix the cause, for example by skipping end-of-stream on a session whose | ||
| encode failed. A timeout on the join doesn't count as a fix. Add a regression | ||
| test that forces the failing configuration on hardware where NVENC exists and | ||
| asserts teardown returns. Wire it into the nightly GPU lane if there is one; | ||
| otherwise say where it runs. | ||
|
Comment on lines
+21
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When no nightly GPU lane exists, the AGENTS.md reference: AGENTS.md:L18-L23 Useful? React with 馃憤聽/ 馃憥. |
||
|
|
||
| ## Related | ||
|
|
||
| - [NVENC recovery](/quest/m1/nvenc-recovery.md) - the other NVENC failure path, rate changes and partial init | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # [S] Signal.race releases its listeners when it loses a race | ||
|
|
||
| ## Goal | ||
|
|
||
| `Signal.race` from `@moq/signals` no longer leaves a `changed` listener on | ||
| each signal when its own promise is raced and loses. Today it disposes them | ||
| only when one of the signals changes, so `js/net/src/origin.ts`'s | ||
| `#changed()`, raced against `closed` in `connection/forward.ts`, keeps | ||
| listeners for as long as the table stays quiet. Awaiting it directly still | ||
| works, with the same signature. | ||
|
|
||
| ## Plan | ||
|
|
||
| Make it consistent with the free `race()` and `effect.race` from | ||
| [JS retention](https://github.com/moq-dev/moq/pull/4085), which already | ||
| subscribe to `Once`/`GetPromise` values and dispose them when the race | ||
| settles. `Signal.race` returns that same kind of awaitable instead of a | ||
| native promise: it attaches its signal listeners when first awaited or | ||
| subscribed, and releases them when it settles or when its last subscriber | ||
| detaches. Racing it through `race()` or `effect.race` then cleans up both | ||
| sides. Settle the exact return type at PR time, keeping `await` source | ||
| compatible; if the change is a published type break, stop and bring it back. | ||
|
|
||
| Audit the callers in `js/net` (`announced`, `broadcast`, `group`, `origin`, | ||
| `track`, both subscribers) for the ones that race the result, and add a | ||
| listener-count test for the `origin.ts` case that fails today. | ||
|
|
||
| ## Required | ||
|
|
||
| - JS retention (#4085) merged, which adds the free `race()` this builds on |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # [S] moq-tokio reconnect and worker tests bind their own ports | ||
|
|
||
| ## Goal | ||
|
|
||
| The moq-tokio integration tests stop picking a free port, releasing it, and | ||
| binding it again, a race another process can win. `reconnect.rs`'s | ||
| `spawn_server` loses its retry loop, and the worker tests that do not need a | ||
| known port bind `:0`. | ||
|
|
||
| ## Plan | ||
|
|
||
| - Add `Server::tcp_local_addr()` and `Listener::tcp_local_addr()`, mirroring | ||
| `websocket_local_addr()`, reporting the bound address of the plain TCP | ||
| (qmux) listener. Today `StreamListeners` keeps only the configured bind and | ||
| moves the bound listener into its accept task. `spawn_server` binds `:0` and | ||
| reads the address back. This is an additive public API. | ||
| - In `worker.rs`, the tests that only need some port bind `:0` through the | ||
| group and use `Group::local_addr()`. The tests that rebind the same port | ||
| after a drop, or probe it while the group holds it, keep a known port, which | ||
| is the behavior under test. | ||
| - No retries or sleeps. | ||
|
|
||
| ## Related | ||
|
|
||
| - [Test ports](https://github.com/moq-dev/moq/pull/4084) - the same fix for `websocket_forbidden_does_not_end_a_quic_connect` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # [S] AAC encode refuses a channel count it cannot name | ||
|
|
||
| ## Goal | ||
|
|
||
| Writing an AudioSpecificConfig for a channel count that no AAC | ||
| channelConfiguration names is an error, not a stereo config with a warning, | ||
| in `moq_mux::codec::aac::Config::encode` and `@moq/hang`'s | ||
| `audioSpecificConfig`. This mirrors the parse side, which since #4093 refuses | ||
| reserved values instead of guessing stereo. | ||
|
|
||
| ## Plan | ||
|
|
||
| Both functions become fallible, a published API break in each language, so | ||
| this targets `dev`. Counts with a PCE-free configuration map as today. For | ||
| the others, either write channelConfiguration 0 with a PCE derived from the | ||
| layout, or refuse. Pick one at PR time and apply it in both languages. Test | ||
| every count from 1 to 8 and one beyond. | ||
|
|
||
| ## Related | ||
|
|
||
| - [AAC PCE](https://github.com/moq-dev/moq/pull/4093) - the parse half | ||
| - [Layout](/quest/m1/audio-codecs/layout.md) - the layout a PCE would be derived from |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| # [M] noq releases an endpoint's socket on close | ||
|
|
||
| ## Goal | ||
|
|
||
| A noq endpoint can close its UDP socket, and report when it has, without | ||
| waiting for every connection handle to drop. moq-tokio then deletes the | ||
| closable socket wrapper that #4087 added to make `Listener::close` release the | ||
| port. | ||
|
|
||
| ## Plan | ||
|
|
||
| In moq-dev/noq, add an endpoint operation that closes the endpoint, waits | ||
| until each connection has sent its close, and then releases the socket. Later | ||
| sends are dropped and receives end. Test it there. Cut a noq release, bump the | ||
| pin, and replace moq-tokio's wrapper with the upstream call. The Go | ||
| `TestReconnectAcrossRelayRestart` and moq-tokio's | ||
| `close_releases_quic_socket` stay green. | ||
|
|
||
| ## Related | ||
|
|
||
| - [Listener close](https://github.com/moq-dev/moq/pull/4087) - the local wrapper this replaces |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # [M] NVENC reuses its input and output buffers | ||
|
|
||
| ## Goal | ||
|
|
||
| The NVENC backend stops allocating per frame. At 1080p, creating the output | ||
| bitstream and input buffer (or registering the CUDA resource) is about half | ||
| of frame-to-packet time. A benchmark shows the pooled path is faster at | ||
| 720p and 1080p, with the numbers in the PR. If it doesn't win, abandon the | ||
| quest and report the numbers. | ||
|
|
||
| ## Plan | ||
|
|
||
| `rs/moq-video/src/encode/backend/nvenc.rs` calls `create_output_bitstream`, | ||
| `create_input_buffer` (CPU frames) or `register_generic_resource` (CUDA | ||
| frames) on every `encode`, and frees them all at the end of the call. Keep a | ||
| small pool sized by the frames in flight, which is one today since B-frames | ||
| are off. Re-register a CUDA resource only when its pointer changes. Measure | ||
| with the `encode-presets` example from #4099. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This quest changes the
rs/moq-netwire format but only schedules the draft update, so it can be completed while leaving the user-facingdoc/conceptdescription out of sync. Include the applicable concept documentation in the quest scope alongside the Rust, JavaScript, and draft changes.AGENTS.md reference: AGENTS.md:L94-L98
Useful? React with 馃憤聽/ 馃憥.