Skip to content
Closed
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
1 change: 1 addition & 0 deletions quest/m1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ bench all require its crate.
- [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
- [ATSC AC-3](/quest/m1/ts-atsc-ac3.md) - `export ts` carries 48 kHz ATSC AC-3 at every A/52 rate up to 640 kb/s instead of aborting from 384 kb/s up
- [TS table bursts](/quest/m1/ts-psi-repeat.md) - `export ts` lays a repeated PAT and PMT once where aligned keyframes would bunch them past their transport buffer
- [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
Expand Down
44 changes: 44 additions & 0 deletions quest/m1/ts-psi-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# [M] TS export never bunches repeated program tables

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Merge this with the existing PSI-runs quest

The parent commit already added quest/m1/tstd/psi-runs.md and linked it from quest/m1/tstd/README.md for this exact #5207 defect: it has the same aligned-keyframe scenario, review-thread/null-padding fix, and system-buffer regression test. Creating a second M1 quest leaves one fix with two statuses ([S] versus [M]), so completing either quest leaves the other falsely open; fold the extra detail into the existing quest instead.

AGENTS.md reference: AGENTS.md:L46-L46

Useful? React with 👍 / 👎.


## Goal

`moq export ts` never lays copies of the program tables back to back where
they would overrun the PAT's or a PMT's 512-byte transport buffer, drained at
Rxsys = 1 Mb/s (ISO 13818-1 2.4.2.3). Every copy that marks its own tune-in
point still goes out, and changed tables still go out in order. Export carries
every video rendition and writes the tables ahead of each video keyframe, so an
ABR ladder of three or more renditions with aligned keyframes overruns the
PAT's buffer today. At 25 Mb/s, three PAT and PMT pairs back to back deliver
564 B of PAT in about 301 µs, of which about 38 B drains, peaking near 526 B.
Two renditions' 376 B fit.
`compliance.py` grades the program tables' buffers too, so every TS Interop arm
catches a regression.

## Plan

Decided (2026-10-10), from Codex's review of #5207 and kixelated's reply
there. `Slot::layout` (`rs/moq-mux/src/container/ts/schedule.rs`) lays the
tables just ahead of the first packet muxed after them, so when a heavier lane
goes first, every table group in the slot flushes at once. `main` bunched them
the same way at high fill before #5207.

- Start from the diff in
[the review thread](https://github.com/moq-dev/moq/pull/5207#discussion_r4239051134):
a run of tables that the same flush would lay right behind an identical run
is dropped and padded back with nulls at the end of a padded slot, and
`Slot::nulls` becomes `Option<usize>` so an unpadded slot gains none. A slot
still opens with its clock packet and keeps its length, so no PCR moves.
Carrying each table once per slot was tried and reverted in #5207: it dropped
the copies that lead each send-ahead unit, breaking the tune-in points
`aac_program_config_follows_each_table` checks.
- A new table version that bunches with the old one stays as rare as it is;
spacing it out is not in scope.
- `compliance.py` gains a hard system-buffer check for the PAT and every PMT
PID: TBsys of 512 B drained at Rxsys, then Bsys, per ISO 13818-1 2.4.2.3. Its
strict T-STD check models only elementary streams today. DVB SI (SDT, EIT)
and SCTE-35 stay out, since ISO defines those buffers for program-specific
information. Every existing TS arm still passes.
- Test: a unit test runs laid slots' PAT and each PMT PID through its own
512-byte buffer drained at 1 Mb/s, with keyframes aligned at 25 Mb/s on three
video PIDs, which fails without the fix, and on two, which passes either way;
plus the diff's `a_repeated_table_run_is_laid_once`.
Loading