Skip to content

fix(ts): schedule padded output at exact decoder times - #5306

Draft
kixelated wants to merge 2 commits into
mainfrom
quest/m1/ts-atsc-ac3
Draft

kixelated wants to merge 2 commits into
mainfrom
quest/m1/ts-atsc-ac3

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

The TS scheduler holds decoder bytes and transport deadlines on a 25 ms grid. At 48 kHz, ATSC AC-3 frames are 32 ms apart; 384 kb/s and higher can miss deadlines even though each frame fits the 2,592-byte main buffer.

Approach

Preserve exact transport deadlines and decode instants. For constant-rate output, plan packet positions and nulls together against each PID's transport buffer and decoder occupancy, freeing bytes at the actual decode instant. Per-PID head queues and ready/deferred heaps avoid scanning every future unit at each packet. The 25 ms PCR grid and constant-rate packet budget remain fixed. Oversized access units fail when queued with both the elementary/PES size and decoder capacity; ended tails still drain.

The regression fails before the fix at 384 kb/s. The candidate passes 64-frame receiver/deadline tests at 384/448/512/640 kb/s, exact in-slot removal, oversized refusal, and transport-buffer checks. Distinct PSI tune-in runs are paced, without importing adjacent-copy suppression. All TS tests, including the additional 18-scenario PSI regression, pass in the 6,982-test workspace run. Capture (459), playback (166), minimal (97), and VP (10) feature tests pass too. Full Nix just check passes. just test interop --all passes, including all language pairs, refusals, browser close and finite tails. quest check passes (454 documents). The separate strict headroom failure below remains reproducible and unresolved.

A CI-wired benchmark sweeps PID count and units per PID. The first implementation was 2.6–3.6 times slower at 64 PIDs; the heap implementation reduces the measured overhead to roughly 1–17% on this shared host. This is a correctness fix, not a claimed speedup.

PIDs Units/PID Before µs After µs
1 1 104.44 107.37
1 16 396.23 400.83
1 64 1395.19 1422.97
4 1 107.31 114.52
4 16 455.01 483.56
4 64 1753.65 1896.75
16 1 119.03 131.83
16 16 685.52 799.86
16 64 3461.80 3990.95
64 1 192.48 209.04
64 16 2030.62 2317.59
64 64 12339.43 13246.29

Impact

  • Public API: no exported symbol or signature changes. The new timing/packet-position state is private.
  • MoQ wire and catalogs: unchanged.
  • MPEG-TS: constant-rate packet placement now obeys exact receiver windows; unsupported oversized units fail earlier with specific sizes. No carriage change to DVB and no smaller PCR grid.
  • The existing CI headroom fixture now exercises 640 kb/s AC-3. It currently exposes the remaining startup defect described below, so this PR stays draft.
  • No dependency or version changes.

Alternatives

Only releasing bytes earlier is insufficient because flooring the delivery deadline loses up to 25 ms. Finer PCR slots change the selected timing contract. Post-layout padding cannot safely preserve a full slot's rate/deadline budget. Exact admission and layout share one packet clock instead.

Follow-ups

Retain this quest and keep the PR draft. Strict 640 kb/s headroom preserves 20.5 seconds from a 20.06-second source, with other streams passing, but reports 124 AC-3 decoder-buffer overflows (peak 170.2%). Instrumenting that same capture localizes every overflow to PCR times 1.528–2.403 seconds, with none afterward. Packet inspection of the same capture places the first padded interval at PCR 2.424956 seconds, after the final overflow; the startup intervals contain no null packets. Import only publishes its measured mux rate after a two-second window; until then, export uses the unchanged unpadded scheduler. A deterministic unknown-rate probe independently reaches 2,654/2,910/3,534/4,230 bytes against 2,592 at 384/448/512/640 kb/s.

Recommend adaptive padding for unknown-rate startup while retaining exact decoder windows and the 25 ms PCR grid. Alternatively require a known mux rate and explicitly refuse this unsupported mode, which changes the export contract. These consequential behavior/scope choices remain unresolved. Holding the initial catalog is separately tracked by #5287 and still has a finite-source withdrawal problem; no unpublished fix was imported to clear this failure. No compliance assertion or bitrate was weakened.

(Written by GPT-6 Astra)

kixelated and others added 2 commits October 10, 2026 22:12
Co-Authored-By: GPT-6 Astra <noreply@openai.com>
Co-Authored-By: GPT-6 Astra <noreply@openai.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant