From 4a014f6a3c08b32694a4cebd01a4bcae9c3a0abd Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 30 Sep 2026 07:31:33 -0700 Subject: [PATCH 1/3] quest: address the 2026-09-30 audit review Time the egress cache refresh instead of counting its allocations, keep the V4L2 set_bitrate and 1088-row crop checks, drop the settled mobile ownership blockers, and gate the CAT and C# lines on their first leaf quest so quest ready reports them blocked. Co-Authored-By: Claude Opus 5.5 --- quest/m1/cli-packaging.md | 5 ++++- quest/m1/mobile-ownership.md | 6 +++--- quest/m1/perf/group-cost.md | 12 +++++++----- quest/m2/audio-decode-mediacodec.md | 1 - quest/m2/audio-encode-mediacodec.md | 1 - quest/m2/mobile-capture-android.md | 6 +----- quest/m2/mobile-capture-ios.md | 6 +----- quest/m2/mobile-completion.md | 17 +++++++---------- quest/m3/cat/README.md | 1 - quest/m3/cat/verify.md | 4 ++++ quest/m3/cs/generator.md | 4 ++++ 11 files changed, 31 insertions(+), 32 deletions(-) diff --git a/quest/m1/cli-packaging.md b/quest/m1/cli-packaging.md index 33a48b9b30..4cb9136bb0 100644 --- a/quest/m1/cli-packaging.md +++ b/quest/m1/cli-packaging.md @@ -33,7 +33,10 @@ then fails to open a device is the same gap one layer down. Also enable `v4l2` in the Linux ARM release build, so a released binary on a Raspberry Pi 4 publishes from `moq import capture` through the V4L2 M2M hardware encoder (`rs/moq-video/src/v4l2.rs`, already run on a Pi 4's -`bcm2835-codec`) with no GStreamer detour. Verify that once on a Pi 4. +`bcm2835-codec`) with no GStreamer detour. That Pi 4 run covered only +640x360 once, so the Pi 4 check also covers `set_bitrate` on a running +encoder (congestion control retunes through it) and 1080p, which codes as +1088 rows and relies on the compose rectangle to crop back. Add a board hardware note to `doc/bin/cli.md` next to the capture build instructions: Raspberry Pi 5 has no video encoder and Jetson Orin Nano ships diff --git a/quest/m1/mobile-ownership.md b/quest/m1/mobile-ownership.md index abfee2ab29..d16beae6f1 100644 --- a/quest/m1/mobile-ownership.md +++ b/quest/m1/mobile-ownership.md @@ -17,6 +17,6 @@ carry the Rust codecs, and #4094 added the `CVPixelBuffer` bridge stack beside one that exists. What remains is recording the verdict in `rs/moq-ffi/AGENTS.md` (a maintainer -edit) and in [Android capture](/quest/m2/mobile-capture-android.md) and -[iOS capture](/quest/m2/mobile-capture-ios.md), which target `moq-video` as -written and no longer wait on this. +edit). [Android capture](/quest/m2/mobile-capture-android.md), +[iOS capture](/quest/m2/mobile-capture-ios.md), and the MediaCodec audio +quests already record it and no longer wait on this. diff --git a/quest/m1/perf/group-cost.md b/quest/m1/perf/group-cost.md index 9dea750f03..1bf3bdeccf 100644 --- a/quest/m1/perf/group-cost.md +++ b/quest/m1/perf/group-cost.md @@ -26,14 +26,16 @@ the next largest source from there. A measured no-win abandons the quest, per this line's rules. Decided in the 2026-09-30 audit: two suspected per-group costs merged here -as candidates to measure with `SESSION_ALLOCS`, not separate quests. +as candidates to measure, not separate quests. - Egress cache refresh: `group::Consumer::keep_alive` takes a state read guard and calls `Charge::refresh` between completed frame writes on both - the lite and IETF publishers. It protects a drain longer than - `latency_max`, so keep per-frame liveness and - `slow_prefetch_reader_survives_expiry` (rs/moq-net/src/model/track.rs); - fewer refresh calls alone are not a win. + the lite and IETF publishers. That is lock, clock, and atomic work that may + allocate nothing, so time it rather than count allocations: CPU per + viewer-group for fast fanout and flow-controlled readers, over SUBSCRIBE + and FETCH. It protects a drain longer than `latency_max`, so keep + per-frame liveness and `slow_prefetch_reader_survives_expiry` + (rs/moq-net/src/model/track.rs); fewer refresh calls alone are not a win. - Owned decode copies: `rs/moq-net/src/coding/decode.rs` decodes `Vec` through `Buf::copy_to_bytes` then `to_vec`, and `String` consumes that vector. Measure on the real reader input types (contiguous and chained) diff --git a/quest/m2/audio-decode-mediacodec.md b/quest/m2/audio-decode-mediacodec.md index 3549847226..936bc13a32 100644 --- a/quest/m2/audio-decode-mediacodec.md +++ b/quest/m2/audio-decode-mediacodec.md @@ -25,7 +25,6 @@ behind a new optional audio `mediacodec` feature and the decode seam, on `target ## Required -- [Mobile ownership](/quest/m1/mobile-ownership.md) - if Kotlin owns platform codecs, this backend is moot - [Decode seam](/quest/m1/audio-codecs/decode-backend.md) - the candidate order this backend joins - [Layout](/quest/m1/audio-codecs/layout.md) - what a multichannel frame is delivered as diff --git a/quest/m2/audio-encode-mediacodec.md b/quest/m2/audio-encode-mediacodec.md index 5adc169241..7bb26674ea 100644 --- a/quest/m2/audio-encode-mediacodec.md +++ b/quest/m2/audio-encode-mediacodec.md @@ -20,7 +20,6 @@ behind the `mediacodec` feature and the encode seam. ## Required -- [Mobile ownership](/quest/m1/mobile-ownership.md) - if Kotlin owns platform codecs, this backend is moot - [Encode seam](/quest/m1/audio-codecs/encode-backend.md) - the candidate order this backend joins - [Layout](/quest/m1/audio-codecs/layout.md) - the input layout the encoder accepts - [MediaCodec decode](/quest/m2/audio-decode-mediacodec.md) - the round-trip regression decodes through it diff --git a/quest/m2/mobile-capture-android.md b/quest/m2/mobile-capture-android.md index 7482917a80..3b3478a5f1 100644 --- a/quest/m2/mobile-capture-android.md +++ b/quest/m2/mobile-capture-android.md @@ -7,7 +7,7 @@ camera, MediaProjection for the screen, and MediaCodec for encode and decode. ## Plan -MediaCodec encode/decode already exist in moq-video. Reuse them rather than +Rust owns capture and codecs on mobile, settled in the 2026-09-30 audit ([Mobile ownership](/quest/m1/mobile-ownership.md)). MediaCodec encode/decode already exist in moq-video. Reuse them rather than planning a second backend family. The remaining capture and native Surface integration needs NDK/JNI lifecycle, synchronization, and actual device proof. @@ -21,10 +21,6 @@ decides whether XL is worth spending. `moq-tokio` already reaches into Android through JNI for `tls::init_android`, so the mechanism exists. -## Required - -- [Ownership boundary](/quest/m1/mobile-ownership.md) - decides whether an NDK/JNI backend family is worth building - ## Related - [iOS capture](/quest/m2/mobile-capture-ios.md) - the other half of mobile, which diff --git a/quest/m2/mobile-capture-ios.md b/quest/m2/mobile-capture-ios.md index b24bcb8e0b..30c5b35de0 100644 --- a/quest/m2/mobile-capture-ios.md +++ b/quest/m2/mobile-capture-ios.md @@ -7,7 +7,7 @@ through ReplayKit. ## Plan -Not a new codec backend. VideoToolbox already encodes and decodes as the macOS +Rust owns capture and codecs on mobile, settled in the 2026-09-30 audit ([Mobile ownership](/quest/m1/mobile-ownership.md)). Not a new codec backend. VideoToolbox already encodes and decodes as the macOS backend. Reuse its native PixelBuffer surface and verify the iOS build and runtime path rather than assuming desktop behavior. The new work is capture wiring plus the lifecycle iOS imposes and macOS does not. @@ -22,10 +22,6 @@ Reuse the `capture::Source` shape the other platforms use rather than growing an iOS-specific entry point, so device enumeration and selection behave the same everywhere. -## Required - -- [Ownership boundary](/quest/m1/mobile-ownership.md) - decides whether Rust owns capture on mobile at all - ## Related - [Android capture and encode](/quest/m2/mobile-capture-android.md) - the other half of diff --git a/quest/m2/mobile-completion.md b/quest/m2/mobile-completion.md index 8490656ed7..ed7f100b60 100644 --- a/quest/m2/mobile-completion.md +++ b/quest/m2/mobile-completion.md @@ -9,15 +9,13 @@ work and deferred mobile phases are complete before #700 closes. ## Plan This quest owns the cross-phase completion proof, not another implementation. -Use the chosen Rust or platform-owned capture path and the existing binding -APIs. Record the supported path, limitations, and reproducible device results; -wire repeatable coverage into CI and identify the hardware evidence separately. -Update the native/mobile getting-started docs with the working path. - -The ownership decision may replace the Rust capture quests with platform-owned -work. In that case, update this quest's Required links to the replacement -implementation and proof quests before removing the abandoned blockers. -Abandoning a backend is not evidence that native/mobile support is complete. +Use the Rust capture path and the existing binding APIs: Rust owns capture +and codecs on mobile, settled in the 2026-09-30 audit +([Mobile ownership](/quest/m1/mobile-ownership.md)). Record the supported +path, limitations, and reproducible device results; wire repeatable coverage +into CI and identify the hardware evidence separately. Update the +native/mobile getting-started docs with the working path. + Do not close #700 merely because its next subset or a design decision finished. ## Required @@ -26,7 +24,6 @@ Do not close #700 merely because its next subset or a design decision finished. - [Dart codec parity](/quest/m1/dart-codecs.md) - codec-enabled artifacts and Dart video consumer integration - [iOS capture](/quest/m2/mobile-capture-ios.md) - deliver the selected iOS capture path - [Android capture](/quest/m2/mobile-capture-android.md) - deliver the selected Android capture and codec path -- [Mobile ownership](/quest/m1/mobile-ownership.md) - select and scope the mobile media architecture ## Closes diff --git a/quest/m3/cat/README.md b/quest/m3/cat/README.md index 4087147953..3f9876bc16 100644 --- a/quest/m3/cat/README.md +++ b/quest/m3/cat/README.md @@ -53,7 +53,6 @@ one. Everything rides `moq_auth::Request` and ## Required -- draft-ietf-moq-c4m registers the moqt claim keys - [Verify](/quest/m3/cat/verify.md) - `moq_auth::cat` turns a CAT into a grant and `moq auth serve` admits one; `moq auth sign|verify` mint and check the format diff --git a/quest/m3/cat/verify.md b/quest/m3/cat/verify.md index e606294f04..086b557424 100644 --- a/quest/m3/cat/verify.md +++ b/quest/m3/cat/verify.md @@ -87,3 +87,7 @@ in the 2026-09-28 quest audit. `@moq/auth` stays flat. Public API: `moq_auth::cat` new, `moq auth serve` and `moq auth sign|verify` gain flags. Wire: none. + +## Required + +- A consumer asks for CAT, or draft-ietf-moq-c4m registers the moqt claim keys diff --git a/quest/m3/cs/generator.md b/quest/m3/cs/generator.md index 0966cbebb8..2a181cc0ee 100644 --- a/quest/m3/cs/generator.md +++ b/quest/m3/cs/generator.md @@ -21,6 +21,10 @@ catches a typed `MoqException`, on the host runtime. handle cancels its pending calls. If upstream lacks the mapping, it lands in the fork here, never in the wrapper; the probe above is the acceptance test. +## Required + +- A .NET or Unity consumer asks for C# bindings + ## Related - [C++ generator](/quest/m1/cpp/generator.md) - the same port against the C++ generator From b0dbcd3627c153b801ba637aa50f584c68609ee5 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 30 Sep 2026 08:33:27 -0700 Subject: [PATCH 2/3] quest(m2): record the mobile ownership verdict in the MediaCodec audio quests Co-Authored-By: Claude Opus 5.5 --- quest/m2/audio-decode-mediacodec.md | 4 ++++ quest/m2/audio-encode-mediacodec.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/quest/m2/audio-decode-mediacodec.md b/quest/m2/audio-decode-mediacodec.md index 936bc13a32..bdf5613d33 100644 --- a/quest/m2/audio-decode-mediacodec.md +++ b/quest/m2/audio-decode-mediacodec.md @@ -8,6 +8,10 @@ device's codec list opens. ## Plan +Rust owns capture and codecs on mobile, settled in the 2026-09-30 audit +([Mobile ownership](/quest/m1/mobile-ownership.md)), so this backend is +the Android audio codec path. + The audio counterpart of `rs/moq-video/src/decode/backend/mediacodec.rs`, behind a new optional audio `mediacodec` feature and the decode seam, on `target_os = "android"`. diff --git a/quest/m2/audio-encode-mediacodec.md b/quest/m2/audio-encode-mediacodec.md index 7bb26674ea..9b792c91ae 100644 --- a/quest/m2/audio-encode-mediacodec.md +++ b/quest/m2/audio-encode-mediacodec.md @@ -7,6 +7,10 @@ where the device's encoder supports it. ## Plan +Rust owns capture and codecs on mobile, settled in the 2026-09-30 audit +([Mobile ownership](/quest/m1/mobile-ownership.md)), so this backend is +the Android audio codec path. + The audio counterpart of `rs/moq-video/src/encode/backend/mediacodec.rs`, behind the `mediacodec` feature and the encode seam. From 918c6e7d3a7848fb2b271eb3f8a770e47920c645 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 30 Sep 2026 08:55:22 -0700 Subject: [PATCH 3/3] quest(m2): drop the ownership condition from the mobile capture index entries Co-Authored-By: Claude Opus 5.5 --- quest/m2/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quest/m2/README.md b/quest/m2/README.md index f79539a25f..8d23de211c 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -67,8 +67,8 @@ waiting on an upstream release waits in [m4](/quest/m4/README.md). - [Catalog colour model](/quest/m2/color-catalog.md) - the catalog describes a rendition's colour and HDR properties once a renderer consumes them - [Archive recovery listing](/quest/m2/archive-recovery-listing.md) - a resumed DVR lists what changed since its checkpoint, not every stored group - [Relay io_uring packages](/quest/m2/relay-io-uring-package.md) - Linux relay packages ship io_uring once the ring is on par with tokio -- [iOS capture](/quest/m2/mobile-capture-ios.md) - camera and screen capture if the mobile ownership decision selects Rust -- [Android capture](/quest/m2/mobile-capture-android.md) - NDK/JNI capture using the existing codecs if mobile ownership selects Rust +- [iOS capture](/quest/m2/mobile-capture-ios.md) - Rust captures the camera and screen on iOS +- [Android capture](/quest/m2/mobile-capture-android.md) - Rust captures through NDK/JNI on Android, reusing the existing codecs - [Mobile completion](/quest/m2/mobile-completion.md) - verify the selected native/mobile path before closing #700 - [Opus implementation](/quest/m2/audio-opus-backend.md) - compare Opus codec quality, CPU, build cost, and the loss recovery each backend offers - [Latency ledger](/quest/m2/latency-ledger.md) - a session reports where its end-to-end audio delay went, stage by stage