Repository navigation
fix(mux): give every TS PID a declared route - #6252
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Carry MPEG-1/2 video whole while it still paces the program, read the DSM-CC types as sections, count every stream the import does not carry in refused (0x86 without CUEI, base catalogs, TS-scrambled packets), and count packets on PIDs no table claims once every listed PMT is in. Programs owns that count for --program all. Export lists the NIT's network PID in the PAT whenever it carries the NIT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A refused stream with no track now reports an empty track, and a retired section keeps its row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A placed PES with a decode time is due by it rather than by its placement, so a whole picture shares the multiplex. test/ts gains an --mpeg2 arm decoding the round trip, and the T-STD model H.262 video. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Status: draft until moq-dev/moq#6208 lands. Remaining: the quest's PID lifecycle test (unlisted, added by a PMT revision, removed while its packets continue, added again, counters checked at each step, under both one Checks: Open decisions (recommendation first):
(Written by Claude Opus 5.5) |
Picks up #6208's PMT route retirement; section_framed now takes the DSM-CC types. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Unlisted, added by a PMT revision, removed while its packets continue, and added again, checked under one Import and under Programs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The epic's profile rows for MPEG-1/2 video, DSM-CC, uncarried PIDs and the PAT network entry are landed. A program a later PAT adds is left to pat-lifecycle, which now notes its PIDs count nowhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 2 minutes. View limit details
WalkthroughThe change updates MPEG-TS import routing, packet accounting, export tables, and scheduling. MPEG-1/2 video, LATM AAC, and DSM-CC streams receive updated handling. The importer reports refused packets for unclaimed PIDs and scrambled carried streams. The exporter updates PAT contents for carried NIT data and uses DTS when available. The TS test tools add MPEG-2 generation, compliance modeling, and capture grading. Priority: Merge Risk:
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db75614f77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A PMT section only claims PIDs, or names the multiplex clock, when the PAT lists its program on the PID that carried it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc80562b8e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Maintainer decision: group MPEG-1/2 video by sequence header. A PES carrying 0x000001B3 opens a group and the rest join it; amend the draft's pesPacket section to match. This still waits for moq-dev/moq#6371 to land first. (Written by Claude Opus 5.5) |
…hared parser Programs counts a PID no program reads through its readers table, and each Import tests its own routes, replacing the second PAT/PMT parse and the refcounted claims. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A PES carrying a sequence_header_code opens a group and the pictures after it join it, so a joiner or a dropped group never lands on a dependent picture. Pictures before the first sequence header, or after a loss until the next, are dropped. The mpegts draft's pesPacket section says so, and ts_programs sweeps stray PIDs against null stuffing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Program tables ride one lane in push order, and took the deadline of the unit they lead. A placed PES is due by its decode time, so tables leading an MPEG-2 picture that decodes well after its placement held the lane past the deadline of later tables leading audio, failing the export. They now go out by the PES's placement, ahead of its first byte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A video PES whose payload ends in part of a start code waits for the next PES on its stream, or the end of the stream, before its group is decided, so a sequence header straddling the boundary opens a group at the PES it begins in. The T-STD harness also refuses the vbv_delay method and a zero VBV buffer, takes Rbx from the stream rate at High-1440 and High level, and aligns repeated decoded pictures by suffix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c60315cf9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 8c60315
Confirmed the independent P2 clock-discontinuity finding: #6252 (comment) . The new last-PES lookahead filter at rs/moq-mux/src/container/ts/import.rs:2454–2458 remains active when timebase_break settles/releases the old timeline. A complete MPEG-1/2 PES ending in a partial start-code prefix remains held despite a valid timestamp, failing Stream::placed and aborting import. Resolve lookahead before draining the old clock, as EOF/route retirement do; cover a flagged PCR discontinuity, including a dedicated PCR PID.
The bounded one-PES lookahead addresses the earlier split-header finding, but needs this lifecycle boundary handled. The scrambled-section reset remains fixed; harness updates address the earlier VBV-model, zero-buffer, rate and repeated-picture findings.
Verification: static update/surrounding-code review, accounting for merged base changes since the last published review. No tests, builds or FFmpeg checks run.
A whole video PES ending in part of a start code waited for the next PES, which a clock break never delivers on the old timeline, so the break refused the import. The break now ends that lookahead, as end of input and a PMT revision already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: 89e9976
The clock-discontinuity finding #6252 (comment) is fixed. timebase_break ends pending start-code lookahead before settling/releasing the old timeline, letting complete held PES drain before discontinuity. Regression covers dedicated PCR PID, partial-prefix tail and new-clock restart.
No new actionable bugs found. Reusing end-of-lookahead is narrow and avoids extra buffering complexity.
Verification: static delta and surrounding code, accounting for base merge. No tests or builds run.
|
Landing summary for 89e9976:
(Written by Claude Opus 5.5) |
# Conflicts: # rs/moq-mux/src/container/ts/import.rs # rs/moq-mux/src/container/ts/import_test.rs # rs/moq-mux/src/container/ts/stats.rs
# Conflicts: # quest/m1/ts-reliability/README.md
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fae6c81588
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…te drop Export judged every pesPacket frame decodable on its own, so after dropping a late MPEG-2 picture the jitter buffer resumed at the next picture, which references the dropped one. A frame of either video class now resumes only at a keyframe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit: aa1fc67
The independent MPEG-video recovery finding #6252 (comment) is fixed: export.rs now uses the existing video classification for Arrival::sync, so whole-PES MPEG-1/2 video waits for a keyframe after a late drop while audio/data retain their behavior. The new regression checks dependent pictures are omitted until the next sequence header. The previously reviewed clock-discontinuity fix remains unchanged.
No new actionable bugs found. Reusing Kind::class is a suitably narrow solution without adding another recovery mechanism.
Verification: static delta, classification and jitter-recovery inspection, accounting for intervening base merges. No tests or builds run.
|
Landing summary for aa1fc67, after the merge queue dropped 89e9976 for a conflict with main:
(Written by Claude Opus 5.5) |
Unify the PMT deadline with moq-dev#6252's: each waiting program's wait is timed on one shared clock and checked on every packet, not only at a PAT, and a lapse refuses the multiplex, as decided on this PR, rather than releasing the unclaimed-PID count. Also fixes round 3's open findings: a retired program keeps the picture its finish flushes unless a running program still carries that PID, a retired row is not quiet, a PMT section a moved or retired program leaves unfinished counts its bad CRC once, and the ts_programs bench's idle programs send a PMT listing no stream so they never reach the deadline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every PID of an imported program, other than the null PID, now takes one declared route: decoded, whole-PES
pesPacket,verbatimsection, captured PSI/SI, or not carried and counted ints::stats. Finishes the questquest/m1/ts-reliability/stream-routes.mdand deletes it. Builds on moq-dev/moq#6208's route retirement and moq-dev/moq#6371's shared parser.What changed
pesPackettrack instead of being discarded, and keeps its clock role (its PTS still paces the program; stats classvideo). A Hang player still sees no rendition it cannot decode. A PES carrying asequence_header_codeopens a group and the pictures after it join it, so a joiner or a dropped group never lands on a dependent picture. Pictures before the first sequence header, or after a lost one until the next, are dropped. A header split across two PES opens the group at the PES it begins in: a video PES ending in part of a start code waits for the next PES on its stream before its group is decided; a clock break, a PMT revision, or the end of input ends the wait (one PES of extra latency, only then).verbatim, instead of failing every PES start code asdamaged.mpegtssection, no PCR, bad Opus config), counts onerefusedwith a warning, its row'strackempty.Class::Datarow with an emptytrack,refusedcounting packets, and one warning.ts/unclaimed.rsholds the counts; each owner decides what is claimed and when counting starts:Importcounts a packet on a PID its own routes do not claim (PMT, streams, clock, sections, PAT, captured SI, null), once a PMT is in and the PAT lists only this program.--program Nof an MPTS counts none, since it cannot tell another program's PIDs from strays.--program all:Programscounts a packet on a PID no program reads (Programs::readers, from the shared parser), the PAT's PMT PIDs, the SI PIDs and the null PID aside, once for the multiplex. Counting waits until every program the PAT lists has started, or 0.5 s of the first program's clock has passed without its PMT (TR 101 290PMT_error_2).refusedand lose the unit in progress (a PES or a partial section), rather than parse damage. The route stays, so the stream resumes when clear.missed a decode deadline on PID 4096injust test ts --mpeg2after merging main).ImportorPrograms.pesPacket; theImportdocs now say so.doc/bin/cli.mdanddoc/concept/stats.mddescribe the routes and the counts.ts-reliabilityprofile rows this covers are landed;pat-lifecyclenotes what a program a later PAT adds does to the count.Public API and wire impact
ts::stats::Snapshot::streams: rows now exist for PIDs that publish no track (emptytrack), andrefusedalso counts unclaimed packets and TS-scrambled ones. MPEG-1/2 video rows arepesPacketwith classvideoand units counted as delivered PES. To migrate, filter on a non-emptytrackwhere you read the rows as published tracks.mpegtssection where they were missing before. draft-lcurley-moq-mpegts (-01, in progress) lists them among thepesPacketand section-framed examples, groups MPEG-1/2 videopesPacketframes from one sequence header to the next instead of one PES per group (the PES a header begins in opens the group, even when the next PES completes it), and requires the PAT network entry when a NIT is carried.Tests
ts/routes_test.rs: MPEG-2 whole-PES carriage, its groups (a mid-GOP join and a scrambled loss each wait for the next sequence header) and an export round trip, each DSM-CC type, 0x86 without CUEI, LATM, CAT + PSIP + unlisted PID (field by field) + nulls + scrambled ES, 16 scrambled packets wrapping a section PID's counter, media before the PMT, a two-program MPTS underProgramswith program 2 media ahead of its PMT, the same MPTS under--program 1, a PMT that never arrives, a PMT on another program's PID, and one PID's lifecycle (unlisted, listed, dropped while flowing, listed again) under both owners.routes_test::mpeg2_sequence_header_split_across_pes_opens_a_group: a sequence header split at each of its three inner boundaries opens its group at the PES it begins in, a split picture start code opens none, and a whole PES ending in part of a start code still goes out at a flagged clock break (on a dedicated PCR PID) and at end of input.export_test::service_layer_survives_roundtripchecks the PAT's network entry and that the re-import counts no row for the NIT PID.schedule: a placed PES yields to units due before it decodes, and the tables leading one go out by its placement (without the fix it fails with the harness's error).test/ts --mpeg2: Main Profile at Main Level MPEG-2 video round trip, FFmpeg decode compared picture by picture (aligned by suffix, so a repeated picture is fine),holes.py, and the T-STD model, which gains H.262 parameters (Tables 8-13/8-14, leak method with Rbx = min(1.05 Res, Rmax) at High-1440 and High; the vbv_delay method and a zero VBV buffer are refused, covered incompliance.test.py). Wired into.github/workflows/ts.yml.benches/ts_programs.rs(from moq-dev/moq#6371) also sweeps 16 and 256 stray PIDs per frame against the same packets as null stuffing, which skips the accounting. Locally, on a loaded machine: 1 program 1.41 GiB/s stray against 1.70 GiB/s null at 256 strays, and no slope with program count (16 programs: 720 against 626 MiB/s).Decisions
Recorded from the open questions on this PR, each taking the recommendation:
StreamTypeIsSection).refusedunits: one per refused listed stream, one per packet for unclaimed and scrambled PIDs ✅, over one unit for both.pesPacketsection for 0x01/0x02 ✅, over keeping per-PES groups and documenting resync at the next sequence header.Revisited after moq-dev/moq#6371, per moq-dev/moq#6334; agent choices, confirmed by the maintainer on 2026-10-25:
Programsclassifies throughPrograms::readersinstead of re-reading the PAT and every PMT, and the refcountedclaims.rsis gone ✅. The earlier Codex finding on a PMT arriving on another program's PID is now covered by perf(mux): parse an MPTS once for every program #6371'sPrograms, which starts a program only from a PMT on the PID its PAT entry names; the test stays.Programsdoes not start yet, holds the count back for 0.5 s like any missing PMT, then its elementary PIDs count as unclaimed, since nothing reads them ✅. This replaces the earlier choice that its PIDs stay claimed, which needed a second PMT parse;pat-lifecyclenotes it.Importcounts once its PMT is in, with no 0.5 s lapse: before a PMT it has no clock to time one ✅.Checks
just checkpasses (rs, js, drafts, markdown, gh, quest, shell) after merging main,cargo test -p moq-mux --all-features --lib container::tspasses (653; the whole moq-mux lib, 1754, after the second merge of main),cargo clippy -p moq-mux --all-features --all-targetsis clean,python3 test/ts/compliance.test.pypasses, andjust test ts --mpeg2passes (473 of 500 pictures decoded as the source's, 0 joined pictures skipped, T-STD clean). Not rerun locally:just test ts --klv --strict(CI runs it).Follow-ups
(Written by Claude Opus 5.5)
🤖 Generated with Claude Code