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/README.md b/quest/m2/README.md index e9c6f6e9f1..ce74dd43fd 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 diff --git a/quest/m2/audio-decode-mediacodec.md b/quest/m2/audio-decode-mediacodec.md index 5158823f91..ed9e496e96 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"`. @@ -23,10 +27,6 @@ behind a new optional audio `mediacodec` feature and the decode seam, on `target - The binding ships in the moq-ffi Android slice, which is how Kotlin and Dart reach it. -## Required - -- [Mobile ownership](/quest/m1/mobile-ownership.md) - if Kotlin owns platform codecs, this backend is moot - ## Related - [Android capture](/quest/m2/mobile-capture-android.md) - the video MediaCodec family this sits beside diff --git a/quest/m2/audio-encode-mediacodec.md b/quest/m2/audio-encode-mediacodec.md index 52ead7973e..c5d5d3a9e6 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. @@ -23,5 +27,4 @@ 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 - [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..b408e7b8bd 100644 --- a/quest/m2/mobile-capture-android.md +++ b/quest/m2/mobile-capture-android.md @@ -7,24 +7,19 @@ 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. -Weigh the cost honestly before starting. `moq-kit` already does this in Kotlin -over `moq-ffi`, and raw frames cannot cross the FFI boundary zero-copy, so a -Rust Android media path pays off for Rust-native consumers and not for the -mobile SDK. That is a real audience (this is the same gap that made -`iroh-live` reimplement the native layer) but it is worth naming, since it -decides whether XL is worth spending. +This is the Android SDK's media path, not a Rust-only extra. `moq-kit`'s +Kotlin capture is the parallel stack the verdict retires once this lands. +Frames cross `moq-ffi` as opaque `HardwareBuffer`/`Surface` handles rather than +copies. Rust-native consumers benefit too (the same gap that made `iroh-live` +reimplement the native layer). `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