Repository navigation
quest: plan T-STD follow-ups #4680
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c7e59e1
715ec12
c51535c
4bd40d1
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,38 @@ | ||
| # [S] FETCH_OK carries the track's properties | ||
|
|
||
| ## Goal | ||
|
|
||
| Our IETF publisher's FETCH_OK carries the same track properties its | ||
| SUBSCRIBE_OK does: max cache duration, timescale, priority, and group order. | ||
| A fetch-only reader then learns the track as a subscriber would, and a relay | ||
| meets draft 16+'s rule to include all of a track's properties. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found (2026-10-01) while merging main into dev (#4647): a group FETCH with no | ||
| prior SUBSCRIBE_OK now reads its max age from FETCH_OK, but our publisher | ||
| sends an empty block. | ||
|
|
||
| - `rs/moq-net/src/ietf/publisher.rs` sends FETCH_OK with | ||
| `properties: Default::default()`. SUBSCRIBE_OK fills them in the block near | ||
| `publisher.rs:655`. Share that code so the two can't diverge. | ||
| - Our group-fetch accept path reads only the max age from FETCH_OK and | ||
| hardcodes a microsecond timescale. Apply the same properties SUBSCRIBE_OK | ||
| does (timescale, priority, group order) there too. | ||
| - Drafts 14-15 allow the omission: MAX_CACHE_DURATION is a MAY there, and | ||
| FETCH_OK has no properties block. From draft 16, a relay MUST include all | ||
| Extension Headers / Properties associated with a track in FETCH_OK (d16 | ||
| §8.6, d22 §7.7). An empty block also misleads the reader: it infers | ||
| Ascending order and priority 128 where SUBSCRIBE_OK says Descending. | ||
| - Honour INCLUDE_PROPERTIES (0x35) on FETCH from draft 20. It defaults to | ||
| sending the properties; at 0 the block is present but empty. `fetch.rs` | ||
| decodes it on draft 20+ and drops it, so it is not honoured today. | ||
| - Test per draft range: FETCH_OK round-trips the properties SUBSCRIBE_OK would | ||
| carry, and INCLUDE_PROPERTIES = 0 empties the block. | ||
|
|
||
| Public API: none. Wire: FETCH_OK gains its properties on drafts that define | ||
| the block. Interop: run `just test interop --all`. | ||
|
|
||
| ## Related | ||
|
|
||
| - [Fetch without SUBSCRIBE](/quest/m1/ietf-fetch-only.md) - asks TRACK_STATUS for the same properties when a publisher omits them | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,11 @@ decode, and the JS test should drive the software decoder. | |
| Every continuous group is passed through untouched. | ||
| - The same rule in the Rust decode path (`moq-video` decode consumers), so | ||
| native playback and the transcoder tune in the same way. | ||
| - The same rule in `moq export ts`. Decided (2026-10-01): the fixed-delay | ||
| export (#4645) still sends a join's orphaned leading pictures, so 3 of 500 | ||
| frames on the open-GOP fixture decode after they present | ||
| (`dts-before-pts`). Trim them at tune-in from the same signal, and make | ||
| `just test ts --open-gop` pass under `--strict`. | ||
|
Comment on lines
+56
to
+57
Contributor
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. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '1,100p' quest/m1/open-gop-leading-pictures.md
sed -n '180,325p' test/ts/open-gop.py
sed -n '315,355p' test/ts/README.mdRepository: moq-dev/moq Length of output: 13410 Distinguish cold tune-in from continuous playback in the Open-GOP test plan. The planned tune-in trim conflicts with the current This is a documentation and test-contract inconsistency, not an implemented runtime failure. Update the plan so the existing preservation check applies to continuous playback, and add a separate cold-tune-in case that expects orphaned leading pictures to be trimmed. 🤖 Prompt for AI Agents |
||
| - This quest owns the Rust non-continuous signal, which audio warmup and | ||
| consumer warmup reuse rather than each adding one. Today | ||
| `moq_mux::container::Consumer::poll_read` returns a bare frame, and | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # [S] DVB E-AC-3 gets a buffer model in TS export | ||
|
|
||
| ## Goal | ||
|
|
||
| `moq export ts` splits DVB E-AC-3 private-data PES (`stream_type` 0x06 with | ||
| an `enhanced_AC3_descriptor`) one access unit per PES, schedules each against | ||
| the E-AC-3 buffer ETSI TS 101 154 gives DVB, and `test/ts/compliance.py` | ||
| grades it. That's the same treatment DVB AC-3 got in | ||
| the fixed-delay export (#4645). | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #4645: E-AC-3 carried as DVB private data still goes out unsplit, | ||
| with no buffer model, so a multi-frame PES can overflow B. | ||
|
|
||
| - Split it the way #4645 splits DVB AC-3, but per access unit: an | ||
| independent sync frame plus the dependent substreams that follow it share | ||
| one presentation interval (ETSI TS 102 366 Annex E), so they go out in one | ||
| PES on one decode time. Read sizes from each sync frame's `frmsiz`, and | ||
| drop a frame shorter than its header says. | ||
| - The buffer is the DVB one, not ATSC's: #4645's 12,896 B is A/52 Annex G's | ||
| for `stream_type` 0x87, and DVB AC-3 uses 5,696 B. Take the E-AC-3 value | ||
| from ETSI TS 101 154, cite the clause, and add it to the schedule's | ||
| per-PID admission and to the `tstd` model in `compliance.py`, which | ||
| refuses DVB E-AC-3 today. | ||
| - Test: a synthetic multi-frame E-AC-3 PES exports one access unit per PES; | ||
| an independent-plus-dependent fixture keeps both substreams on one | ||
| interval (32 ms for six 48 kHz blocks, not 64); and a control in | ||
| `tstd-controls.py` overflows B without the split. | ||
|
|
||
| ## Required | ||
|
|
||
| - [T-STD TS export](/quest/m1/tstd/README.md) - the per-PID schedule this joins |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # [L] Two TS export legs emit identical packets for ST 2022-7 | ||
|
|
||
| ## Goal | ||
|
|
||
| Two `moq export ts --sync` legs of one broadcast, joined at different | ||
| moments, emit packet-identical TS from their first common packet, across | ||
| skips and source drift, continuity counters included. A ST 2022-7 selector | ||
| can then switch between them hitlessly. | ||
|
|
||
| ## Plan | ||
|
|
||
| Decided (2026-10-01), from t0ms's review of the fixed-delay export (#4645). | ||
| They call 2022-7 a differentiator for primary distribution, not a | ||
| requirement, so this waits until the T-STD line settles. | ||
|
|
||
| - Measured acquisition stays the default. `--sync` opts in to anchoring on | ||
| the catalog clock: release at `clock.wall + pts + delay`, so every leg | ||
| anchors the same way however it joined. This needs NTP-synced hosts. If the | ||
| measured age is implausible (negative, or beyond the delay), the export | ||
| fails loud. | ||
| - Continuity counters restart at each group. Each media PID's first packet in | ||
| a group sets `discontinuity_indicator`, and its counter is numbered from | ||
| there, so it comes from the media and not from what a leg has sent. The PCR | ||
| moves to its own PID, because a discontinuity flag on the PCR PID would | ||
| declare a time-base break. Loss is still detected within a group. | ||
| - Once anchored identically, both legs must make the same skip decision and | ||
| lay out the same slots. t0ms's `two_legs_render_a_skip_the_same_way` stays | ||
| ignored in #4645 until this lands. With the audio late, it also showed a | ||
| PES header byte that differs at the skip; find and fix that. | ||
| - Test with mocked time: | ||
| - two legs, joined a second apart, give byte-identical output including | ||
| the counters; | ||
| - the same across a mid-run skip, and under ±30 ppm drift; | ||
| - `--sync` with an implausible age fails loud. | ||
|
|
||
| ## Required | ||
|
|
||
| - [T-STD TS export](/quest/m1/tstd/README.md) - the export, clock recovery, and schedule these legs share | ||
|
|
||
| ## Related | ||
|
|
||
| - [TS passthrough](/quest/m1/ts-passthrough.md) - byte-identical legs for free in its own lane; adopts `--sync` for alignment |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| # [S] The T-STD harness covers MB overflow and an AAC broadcast reference | ||
|
|
||
| ## Goal | ||
|
|
||
| `just test ts-tstd` has a negative control that overflows the video multiplex | ||
| buffer (MB), and a positive reference that carries AAC the way a broadcast | ||
| encoder does. Every buffer and codec the export emits then has a control on | ||
| each side. | ||
|
|
||
| ## Plan | ||
|
|
||
| Found in #4643. Grading against the declared HRD made MB about 3.6 MB on the | ||
| Kyrion capture, more than its 4 s holds, so no control reaches MB any more. | ||
| The only positive reference carries MPEG audio, but the export emits AAC. | ||
|
|
||
| - MB: a longer clip with no declared HRD (level defaults), restamped to a | ||
| burst, which overflows MB and passes as captured. | ||
| - AAC: a shareable broadcast-style reference whose AAC passes B. | ||
| - FFmpeg's default 0.7 s audio lead overflows the 3,584 B AAC buffer, so try | ||
| its mux delay options first. | ||
| - If no generated clip passes, ask t0ms whether a short AAC capture can be | ||
| shared. | ||
| - Each control fails or passes for the stated reason, and `interop.yml` | ||
| runs them. | ||
|
|
||
| ## Required | ||
|
|
||
| - [T-STD TS export](/quest/m1/tstd/README.md) - `just test ts-tstd` and `tstd-controls.py` land with it (#4645) |
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.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the stated FETCH_OK baseline.
ietf::FetchOkhas no Track Properties field inrs/moq-net/src/ietf/fetch.rs:293-298. The publisher constructs it without one inrs/moq-net/src/ietf/publisher.rs:1139-1370. Update this step to add and encode Track Properties before sharing property construction with SUBSCRIBE_OK.Proposed wording
📝 Committable suggestion
🤖 Prompt for AI Agents