Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ bench all require its crate.
- [Encoder colour](/quest/m1/color-model.md) - every moq-video encode path signals the colour its output actually has, or refuses instead of mislabelling
- [T-STD TS export](/quest/m1/tstd/README.md) - `moq export ts` is a proper remux that passes the T-STD buffer model, starting with a fixed `--delay`
- [Multi-packet PMT](/quest/m1/ts-pmt-split.md) - `export ts` splits a PMT longer than one packet instead of exiting before its first packet
- [TS damage log](/quest/m1/ts-damage-log.md) - a burst of damaged TS units logs a first warning and a periodic summary per PID, not one warning per unit
- [TS adaptation field length](/quest/m1/ts-adaptation-only.md) - a TS adaptation field with the wrong length for its packet (183 adaptation-only, at most 182 with a payload) is refused as damage
- [Rust non-continuous signal](/quest/m1/rust-continuous.md) - the Rust container consumer reports a frame after a subscribe or discontinuity as non-continuous, like JS, for the tune-in and warmup trims
- [Open-GOP leading pictures](/quest/m1/open-gop-leading-pictures.md) - a viewer joining at a recovery point drops the leading pictures it cannot decode; continuous viewers keep them
- [Watch decode errors](/quest/m1/watch-decode-error.md) - a WebCodecs error ends the subscription and the element reports it
Expand All @@ -195,7 +197,10 @@ bench all require its crate.
- [#709](/quest/m1/709-automatic-letsencrypt-support.md) - the relay provisions and renews its own ACME certificate through rustls-acme over TLS-ALPN-01, persisted on disk
- [Draft 14-16 updates](/quest/m1/ietf-legacy-updates.md) - Rust and JS apply and answer moq-transport 14-16 request updates without ending or leaking the request
- [JS session caps](/quest/m1/js-session-parity.md) - @moq/net enforces moq-net's per-session announce and subscription caps
- [JS pending tail](/quest/m1/js-pending-tail.md) - a JS reader holds for a track's pending tail like Rust, once #4225 lands
- [Tail arrivals](/quest/m1/tail-arrivals.md) - a track judges its pending tail from recorded arrivals, not a cache scan, and errors a reader whose tail ends short
- [JS pending tail](/quest/m1/js-pending-tail.md) - a JS reader holds for a track's pending tail like Rust
- [Group demand after accept](/quest/m1/group-demand-accept.md) - an accepted group request's demand ends cleanly instead of failing with NotFound
- [Pool churn cursors](/quest/m1/pool-churn-cursors.md) - the origin pool churn benchmark sweeps announce cursors per prefix
- [In-band CMAF follow-ups](/quest/m1/cmaf-inline-followups.md) - MSF, h264/h265 export, and gst caps handle avc3/hev1 CMAF
- [Datagram replay bound](/quest/m1/datagram-replay-bound.md) - a new Rust datagram subscriber starts within its max delay of the newest datagram, not at a minutes-old buffer
- [Catalog colour](/quest/m1/color-catalog.md) - the catalog describes a rendition's colour and HDR properties, which the WebGPU HDR renderer reads
Expand Down
30 changes: 30 additions & 0 deletions quest/m1/group-demand-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# [S] An accepted group request's demand ends cleanly

## Goal

Once a group request is answered with `accept`, its `group::Demand` ends the
way a dropped request's does: `used()`, `unused()`, and `closed()` return
`Error::Dropped`, which moq-ffi's `MoqGroupDemand` reports as `Closed`. A rejected request's demand
still fails with the reject reason.

## Plan

Today `group::Request::accept` stores `rejected = NotFound` so a fetch that
joins the answered request fails, and `Demand::abort_reason`
(`rs/moq-net/src/model/group.rs`, `DemandSource::Fetch`) reads that same
field, so every binding sees `NotFound` after an accept. Keep the
joined-fetch refusal in its own field and let the demand read only an actual
reject.

Decided 2026-10-10 (found in #5139): clean close after accept, reject keeps
its error. Add a moq-net test that both outcomes hold for `used()`,
`unused()`, and `closed()`, flip moq-ffi's
`group_request_demand_fails_after_accept`, and update the `MoqGroupDemand`
docs in Rust, Go, Python, and Swift. Hand-written moq-c is frozen, so it gets
no change.

Public API: behavior only (the error a demand wait returns). Wire: none.

## Related

- [Track request demand](/quest/m1/ffi-shape/track-request-demand.md) - its demand should end the same way
8 changes: 8 additions & 0 deletions quest/m1/js-pending-tail.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@ Mirror the Rust pending-tail hold from #4225 (`rs/moq-net/src/model/track.rs`)
and test it against the Rust behavior with mocked time. Split from [JS session parity](/quest/m1/js-session-parity.md) on
2026-10-08 so the caps work stays ready.

Mirror the arrival record from [Tail arrivals](/quest/m1/tail-arrivals.md)
rather than #4225's cache scan (decided 2026-10-10), so JS ports the final
design once.

Public API: none. Wire: none.

## Required

- [Tail arrivals](/quest/m1/tail-arrivals.md) - Rust judges tail holes from recorded arrivals and errors a short tail

## Related

- [JS session parity](/quest/m1/js-session-parity.md) - per-session caps, the other half
15 changes: 15 additions & 0 deletions quest/m1/pool-churn-cursors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# [XS] Origin pool churn benchmark sweeps cursors

## Goal

`bench_pool_churn` in `rs/moq-net/benches/origin.rs` sweeps the number of
announce cursors on a prefix, alongside members and paths, so a renewal cost
that grows with cursors shows up as a slope.

## Plan

PR #5182 made a front's renewal check read each cursor presenting the prefix, and
a renewal restarts every cursor, so both scale with cursors. Add the axis, and
include a scoped cursor so the per-cursor scope filter is measured.

Public API: none. Wire: none.
26 changes: 26 additions & 0 deletions quest/m1/tail-arrivals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# [M] A track's pending tail counts arrivals, not its cache

## Goal

A received track decides which groups are still missing below a declared end
from a per-track record of live groups that arrived, which eviction never
touches. An end check stops scanning the cache, and a reader whose track
ends short because a never-arrived group was aborted gets the abort error
instead of a clean end. A reader that got every group still ends cleanly.

## Plan

PR #4225 judges holes from the cached range (`finish_at_pending` /
`set_tail_pending` in `rs/moq-net/src/model/track.rs`), so each end check is
O(groups), and an evicted group, a datagram, or an abort over a group that
never arrived all look alike. Decided 2026-10-10: record live arrivals per
track (fetched copies never count, as in #4225), bounded by the subscription's
grace like `tail::Tail`, and error the reader on an aborted hole.
Open: whether an arrival that ages past grace before the end is declared still
counts as arrived or becomes a hole.

Add a benchmark swept over tracks and groups held at the tail, per AGENTS.md's
fan-out rule. Mirror the record in JS through
[JS pending tail](/quest/m1/js-pending-tail.md), which waits for this.

Public API: behavior only (a short tail errors). Wire: none.
17 changes: 17 additions & 0 deletions quest/m1/ts-adaptation-only.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# [XS] A TS adaptation field must fit its packet

## Goal

`adaptation_valid` (`rs/moq-mux/src/container/ts/import.rs`) refuses an
adaptation-only packet (`adaptation_field_control == 0b10`) whose adaptation
field length is not 183, and a packet with both (`0b11`) whose field is longer
than 182, as ISO 13818-1 requires, so either is treated as damage like any
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
other malformed adaptation field. Lands on `main` first, then is
cherry-picked to `release`.

## Plan

Found reviewing #5124. Add a regression test covering both boundaries,
on a media PID and on the PCR PID.

Public API: none. Wire: none.
18 changes: 18 additions & 0 deletions quest/m1/ts-damage-log.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# [XS] A burst of damaged TS units logs a summary, not a flood

## Goal

When MPEG-TS ingest refuses damaged units, it warns on the first damaged unit
of a burst per PID, then logs one summary with the count per interval, instead
of one warning per unit for the whole session. Lands on `main` first, then is
cherry-picked to `release`.

## Plan

`Import::damage` (`rs/moq-mux/src/container/ts/import.rs`) already counts per
PID in `damaged`, but warns on every unit. Since #4733 (and #5124 on
`release`) a sender streaming garbage no longer ends the session, so the
warning repeats for its lifetime. Decided 2026-10-10: first warning plus a
periodic summary per PID, no new dependency; test it with mocked time.

Public API: none. Wire: none.
Loading