Repository navigation
Conversation
The schedule charged video whole 188-byte packets at the lesser of Rx and Rbx, plus the clock packet, so a source filling its level's leak, as a full-rate feed with no HRD does, fell behind and missed a decode deadline. The transport buffer now drains whole packets at Rx, the clock packet among them, while MB passes only elementary bytes on into EB at Rbx. Unpadded, a slot carries the lesser of the two, fractions carried from slot to slot, without the one-packet slack. `just test ts --leak` round-trips 1080p video with no HRD at level 4.0's 24 Mb/s leak. Before, its export stopped 12.7 s into the 30 s clip. Retires quest/m1/tstd/video-leak.md. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Held to a transport buffer's worth ahead of the leak, MB emptied whenever audio due sooner took a position or two between video packets, and the leak idled. On a feed whose video fills Rbx, the export carried about 1 % less video than the source and stopped 105 s in. H.222.0 2.14.3.1 gives MB BSmux for this, 4 ms of the larger of Rbx and 2 Mb/s, and BSoh for PES headers. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The T-STD discards a video PES header in MB, before EB, but an audio or system PID's transport buffer feeds B directly: B holds the PES header until the access unit after it is removed (ISO 13818-1 2.4.2.3). The schedule counted only elementary bytes in every decoder buffer, so an audio PES could fill B with its frame and then overflow it by its header. Count the whole payload for PIDs without a leak, and keep video's EB elementary-only. The admission check now rejects a frame that fills B with no room for its header. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A padded export spent a whole clock packet on every 25 ms slot and a PES on every audio frame. A source multiplex with no null packets has no room for either, so an export at the source's own rate fell behind it until its lead ran out and it missed a deadline (moq-dev#5362). - Each slot's PCR rides the adaptation field of the clock PID's first packet in the slot when one goes out there, reflowing that PES's payload, and falls back to a clock packet of its own otherwise. - Consecutive frames of every audio codec (AAC, MP2, AC-3, E-AC-3 and AC-3 carried in a private stream) share a PES while they run on without a gap and fit B whole with their header. Each frame leaves B at its own decode time. PESs start on a grid of the media timeline, so exporters that joined at different frames cut the same PESs. - Frames and grid slots follow each other in decode order however often the exporter is polled, and tables muxed while frames are still packed go out with the next unit, in the order they were written. `just test ts --full` exports a generated 30 s clip at its own rate with no nulls: an x264 video at its level's leak beside MP2 and DVB AC-3, with the PCR in the video PID and several audio frames per PES. The new `overhead.py` fails the export if it spends more packets than the source on clocks and audio framing; CI runs it in the interop workflow. Retires quest/m1/tstd/mux-overhead.md. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #5306, which it targets until that lands.
Problem
A padded
export tscould not carry a CBR contribution feed at the feed's own multiplex rate whenthe feed fills that rate with no null packets (#5362). The export spent packets the source does not:
packets at the lesser of Rx and Rbx, plus the clock packet, and MB held only a transport buffer's
worth ahead of the leak.
video's adaptation field.
At the source's rate the export fell behind until its lead ran out, and it stopped on missed a
decode deadline on the video PID.
Approach
One commit per step, each retiring its quest:
fix(ts): admit leak-bound video at its full Rbx(quest/m1/tstd/video-leak.md). TB drainswhole packets at Rx, the clock packet among them, and MB passes elementary bytes on into EB at
Rbx. An unpadded slot carries the lesser of the two, with fractions carried from slot to slot and
no one-packet slack.
fix(ts): let video's MB run BSmux ahead of its leak. MB may hold BSmux ahead of the leak(2.14.3.1), so audio taking a position between video packets no longer idles it.
fix(ts): count audio PES headers in their decoder buffer. Only video's MB discards the PESheader before EB. For audio and system PIDs, B holds it until the access unit after it is removed
(ISO 13818-1 2.4.2.3). This reverses
a5640abee's accounting for PIDs without a leak and keepsvideo's. A 2,592-byte frame no longer fits a 2,592-byte B, so that test now pushes the largest
frame that fits with its 14-byte header.
feat(ts): carry the PCR in the clock PID and pack audio frames per PES(
quest/m1/tstd/mux-overhead.md).that PES's payload. A slot without one keeps its clock packet.
--delay, consecutive frames of every audio codec share a PES while they run on withouta gap and fit B with their header. The codecs are AAC, MP2, AC-3, E-AC-3, and AC-3 in a private
stream. Each frame leaves B at its own decode time.
holds, so exporters that joined at different frames cut the same PESs.
Tested with:
just test ts --leak: 1080p with no HRD at level 4.0's 24 Mb/s leak round-trips the whole 30 sclip. Before, the export stopped 12.7 s in.
just test ts --full, new, run in the interop workflow. The--leakvideo beside MP2 and DVBAC-3, muxed with its PCR in the video PID and several audio frames per PES, with the nulls
dropped, exports at its own 24.75 Mb/s. It covers the whole 30 s and the strict T-STD check
passes. The new
overhead.pycounts 8,026 packets spent on clocks and audio framing, againstthe source's 8,165.
just test ts,--hrd, and--headroompass.mainatb581c27ed, theexport stops 31 s in on the video PID. With the first two commits it runs through at 26 Mb/s,
but stops 185 s in at 25 Mb/s. With all four it runs through at the source's own 25 Mb/s. The
strict T-STD check,
compliance.pyand PCR accuracy all pass, and every frame of every trackis the source's.
just checkon macOS with host tools passes, apart from themoq-tokioflake below and the stepswhose tools are missing here: the js module (no
wasm-bindgen),nix flake check, and the Swiftstep (no Xcode).
Impact
Scheduleis private tomoq-mux.export tsoutput carries each slot's PCR in the PCR PID's adaptation fieldwhenever that PID has a packet in the slot.
--delay, an exported audio PES carries several frames, up to its B. With nodelay, it carries one frame, as before.
just test ts --fulland its CI step, andtest/ts/overhead.py.Alternatives
a5640abeedoes. Then PESs packed up to B overflow it bytheir header, which
compliance.py's strict check reports on--full.packet. Reflowing a PES the slot already carries costs at most one more packet, and only when its
last packet has no room left.
so the PES size follows B instead.
Follow-ups
--delay, plus a slot and its drain ahead of its decode.So at
--delay 1sor more, the first audio PES after startup can sit in B for longer than theT-STD's 1 s.
--fullruns at 900 ms for this reason. This belongs with the send-ahead quest.arrive. On the 25 Mb/s feed above, the source packs about 9.3 AC-3 frames per PES, while B caps
the export at seven. So the export spends 2.5 % more packets than the source on AC-3, and 1.0 %
more on MP2. It still fits, since it repeats PAT and PMT less often than the source.
moq-tokio'sa_refused_tcp_dial_keeps_retryingflakes under load. Within its 200 ms budget itsometimes sees timed out connecting instead of Connection refused. It is unrelated to this PR.
(Written by Claude Opus 5.5)
Need help on this PR? Tag
@codesmith-botwith what you need.