Files
libfreemkv/docs/reorder.md
T
Matthew Jackson 6e14fc0c0c libfreemkv: 1.7.0 groundwork — sector-recycle soundness + CI hardening
Security
- Remove the unsafe Vec::set_len over recycled sector buffers — UB reachable
  from safe code (GHSA-j8ww-f5fg-9pmh, low). Uses Vec::resize; pooling unchanged.

CI / tooling
- clippy on stable with the MSRV single-sourced from Cargo.toml; cargo-deny
  dependency-audit gate with first-party git sources allowed (#15); audience-based
  comment-guard (#17).

Docs
- README (keydb ownership, BD-J parser count), drive-access transport/reset
  notes, mux timeline module-doc links.
2026-09-02 12:40:55 -07:00

60 lines
3.1 KiB
Markdown

# Display-order PTS reconstruction for sparse-PTS program-stream video
MPEG program streams (DVD VOB, HD-DVD EVO) timestamp video at GOP
granularity: only one access unit per GOP carries a PES PTS, and the rest
arrive with none. The H.264 / HEVC / VC-1 parsers collapse a missing PTS to
`0` (`pes.pts.or(dts).unwrap_or(0)`), so on such a source every non-anchor
frame lands on the same block timestamp. A decoder then cannot order them and
reports "non monotonically increasing dts". (The MPEG-2 parser already avoids
this by reconstructing per-picture PTS from `temporal_reference`; these three
codecs carry no such field.)
`SparsePtsReorder` reconstructs a display-order PTS for every frame from two
signals the parsers already provide — the coded picture type (I/P/B) and the
sparse anchor PTS — plus a per-frame duration self-calibrated from the spacing
between consecutive GOP anchors (no external frame-rate needed). It mirrors
the MPEG-2 parser's GOP-buffered origin-locking, but derives display order via
the classic single-anchor-delay rule instead of `temporal_reference`:
- In DECODE order an anchor (I/P) is stored before the B-frames that
reference it forward, so decode `I P B P B` displays as `I B P B P`.
- The rule that produces that mapping: an anchor is displayed only after the
previously-held anchor; a B-frame displays immediately. This is exact for
the classic (non-hierarchical) GOP structures HD-DVD H.264/VC-1 use.
This reconstruction is applied ONLY on the program-stream path
(`ContentFormat::MpegPs`). BD/UHD transport streams carry a per-frame PTS and
are never routed through it, so the primary decode path is untouched.
## `FALLBACK_FRAME_DUR_NS`
Fallback per-frame duration (ns) when the anchor spacing cannot calibrate one
(a stream with a single GOP, or no anchor PTS at all): 24000/1001 fps film,
the dominant HD-DVD cadence. Only affects intra-GOP spacing — each GOP's
origin is re-locked to its own anchor PTS, so a wrong fallback cannot drift
the timeline across GOPs.
## `MAX_GOP_FRAMES`
Force-complete the current GOP once it reaches this many buffered pictures
even without a keyframe. A GOP is normally a few dozen frames; a stream that
never signals a keyframe (open-GOP recovery-point coding, or crafted/corrupt
disc bytes) would otherwise buffer every access unit — the whole title — in
RAM. Mirrors the MPEG-2 parser's `MAX_PENDING_FRAMES` backstop so no
reassembly buffer grows unbounded on disc-controlled input.
## `MAX_GOP_BYTES`
Byte cap on the buffered GOP, complementing `MAX_GOP_FRAMES`. A GOP holds a
couple hundred MB at most in practice; this force-completes a run of
few-but-huge access units so a crafted/corrupt stream cannot over-allocate
(the AU assembler caps each frame at 8 MiB, so 600 frames alone could reach
~5 GiB without this).
## `display_indices`
Display index (0-based, decode order in → decode order out) for a GOP's coded
picture types via the classic single-anchor-delay reorder: an anchor (I/P) is
displayed only after the previously-held anchor; a B displays immediately.
Decode `I P B P B` → display indices `[0, 2, 1, 4, 3]` (display `I B P B P`).