Skip to content

feat(moq-mux): carry B-frame reorder depth as catalog jitter (exact DTS reserve)#1857

Open
kixelated wants to merge 1 commit into
claude/nice-chandrasekhar-3a58a6from
claude/bframe-jitter-reserve
Open

feat(moq-mux): carry B-frame reorder depth as catalog jitter (exact DTS reserve)#1857
kixelated wants to merge 1 commit into
claude/nice-chandrasekhar-3a58a6from
claude/bframe-jitter-reserve

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Stacked on #1843. Makes the exporter's decode-clock reserve exact instead of a fixed guess, so DTS ≤ PTS holds for real B-frame feeds — by carrying the reorder depth the source already knows through the catalog.

What

  • TS import now reads the PES DTS (previously discarded), computes the reorder delay (max(PTS − DTS)), and folds it into the video rendition's catalog jitter. The jitter field already documents this exact case ("up to 3 b-frames in a row → 3 × 1000/fps") — this finally populates it. The jitter estimator now reports max(min frame duration, max reorder), and a freshly created rendition is seeded from it so a dirty start (frames before the first SPS, as in the kyrion capture) doesn't lose the value.
  • TS export sizes its decode-clock reserve from the catalog jitter, falling back to the small monotonic-only nudge (fix(moq-mux): author DTS for B-frame MPEG-TS export #1843) when none is declared. With the reorder depth known, the authored DTS is both strictly increasing and ≤ PTS.

This rides through the relay via the catalog, so it survives pub | relay | sub with no per-frame wire change, and no catalog format change (jitter already existed — only its population and consumption change).

Why this over the fixed reserve

#1843 keeps DTS monotonic (fixes +igndts) but can't guarantee DTS ≤ PTS without either over-buffering (large fixed reserve = latency) or guessing. The source TS states the exact reorder (PTS − DTS); this carries it, so the reserve equals the actual reorder depth — minimal latency, exact, and B-frame-free streams are unaffected (reserve ≈ one frame).

Notes / decisions for the reviewer

  • Final branch: I based this on the fix(moq-mux): author DTS for B-frame MPEG-TS export #1843 branch (not dev) only to keep the diff to one commit — dev is currently ~35 commits behind main, so a direct dev PR would show all of that. It's not a catalog format change, so it can land on main together with fix(moq-mux): author DTS for B-frame MPEG-TS export #1843, or be retargeted to dev if you'd rather batch it there. Your call at merge time.
  • Behavior change: B-frame streams now report a larger jitter (the reorder delay, e.g. ~167 ms for kyrion) instead of just the frame interval — which is the field's documented meaning, and correctly sizes the browser player's buffer too.
  • Re-import unaffected: the importer still delivers frames in decode order with PTS; the DTS is only used to derive the reserve.

Test plan

  • author_dts: monotonic across reorder with the fallback; DTS ≤ PTS once the reserve covers the reorder span.
  • Import: import_kyrion_video_jitter_captures_reorder asserts the video jitter reflects the ~5-frame reorder (~167 ms), not the ~33 ms frame interval.
  • End-to-end: the kyrion export test now asserts the video PES carry a strictly increasing DTS ≤ PTS timeline (the whole import → jitter → export chain).
  • Full moq-mux suite (249 tests), cargo clippy, cargo fmt clean (via nix).

(Written by Claude)

…S reserve from it

The TS exporter authors a decode timeline (DTS) for reordered video, but with only
a fixed fallback reserve it could not guarantee DTS <= PTS for deep reorders. The
source TS already states the reorder depth (PTS - DTS per PES); carry it through the
catalog so the exporter reserves exactly enough.

- The TS importer now reads the PES DTS (previously discarded), computes the reorder
  delay (max PTS - DTS), and folds it into the catalog `jitter` for the video
  rendition. `jitter` already documents this case ("3 b-frames in a row -> 3 *
  1000/fps"); this finally populates it. Generalize the jitter estimator to report
  max(min frame duration, max reorder), and seed a freshly created rendition from it
  so a dirty start (frames before the first SPS) doesn't lose the value.
- The TS exporter sizes its decode-clock reserve from the catalog `jitter`, falling
  back to the small monotonic-only nudge when none is declared. With the reorder
  depth known, DTS <= PTS holds (verified on the real kyrion 1080i feed).

This rides through the relay via the catalog, so it survives pub | relay | sub with
no per-frame wire change. No catalog format change (jitter already existed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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