Skip to content

Blu-ray SUP export: fix invalid PTS/DTS on exported segments#12074

Merged
niksedk merged 1 commit into
mainfrom
fix/bluray-sup-pts-dts
Jul 2, 2026
Merged

Blu-ray SUP export: fix invalid PTS/DTS on exported segments#12074
niksedk merged 1 commit into
mainfrom
fix/bluray-sup-pts-dts

Conversation

@niksedk

@niksedk niksedk commented Jul 2, 2026

Copy link
Copy Markdown
Member

Fixes #10219.

What was wrong

BluRaySupPicture.CreateSupFrame (a port of BDSup2Sub's writer) mixed up the timestamp fields:

  • The ODS segment got PTS=0 with the decode-model value in DTS — the exact PTS 0, DTS 13097155 segment from the issue, violating "decoding must finish before presentation" (DTS ≤ PTS).
  • The first END segment inherited the ODS's PTS=0.
  • dts = (uint)(pts - decodeTimes) underflowed to a huge value for captions starting in the first ~150 ms.
  • WDS/PDS carried assorted offset PTS values; the original BDSup2Sub code writes DTS=0 on every segment.

Tools like SupMover shift the PTS of every segment when applying a delay, so the zeroed/garbled fields made every caption trigger "starts before the full delay amount" on negative delays (MonoS/SupMover#30).

The fix

Every segment of a display set now carries the display set's presentation time as PTS, and DTS stays 0 ("unset"). Rationale, checked against the ecosystem:

  • This is how .sup files extracted from retail discs look (per the segment traces in the SupMover issue) — uniform PTS per display set, empty DTS.
  • ffmpeg's sup demuxer has an explicit code path: "Many files have DTS set to 0 for all packets, so assume 0 means unset".
  • SupMover shifts each segment's PTS uniformly, which now works.
  • Muxers (tsMuxeR etc.) re-derive PES decode timing from the PCS when authoring an m2ts; the standalone .sup DTS field is informational.
  • Uniform PTS within a display set also keeps packets monotonic, so ffmpeg -c copy remuxing produces no "non-monotonous DTS" warnings (staggered per-segment PTS would).

Verification

Generated test sups via libse (caption at t=0, small gaps, and a 900×300 noisy bitmap forcing a 5-packet ODS chain):

  • Segment validator (python, parses every PG header): DTS=0 everywhere, DTS ≤ PTS, uniform PTS per display set, monotonic across sets, clean PCS…END structure. ✔
  • ffmpeg 4.4 remux to mkv: all 44 segments copied, zero warnings, timestamps intact. ✔
  • ffmpeg PGS decode (overlay onto black + per-frame signalstats): captions appear and clear at exactly the authored times, including the multi-packet ODS. ✔
  • SupMover (built from source): --delay -335 on a shifted file → zero warnings, all display sets moved exactly 335 ms, output still passes the validator. The only warnings left are for a caption genuinely starting at t=0, which is correct clamping. ✔
  • SE roundtrip: BluRaySupParser re-imports all captions with correct times, sizes, and forced flags. ✔
  • All 997 unit tests pass.

🤖 Generated with Claude Code

The writer put decode-model values into the DTS field and zeroed the
PTS of ODS/END segments, producing segments with DTS > PTS (e.g.
PTS=0, DTS=13097155), violating the rule that decoding must finish
before presentation. The DTS also underflowed to a huge uint for
captions starting within the first ~150 ms. This broke tools that
shift every segment's PTS, like SupMover with a negative delay.

Write timestamps the way .sup files extracted from retail discs look
and the common consumers expect: every segment of a display set
carries the display set's presentation time as PTS, and DTS stays 0
(ffmpeg's sup demuxer explicitly treats 0 as unset; muxers like
tsMuxeR re-derive decode timing from the PCS when authoring m2ts).

Verified: segment-level invariants (DTS=0, uniform PTS per display
set, monotonic), ffmpeg remux to mkv without warnings, ffmpeg PGS
decode renders/clears captions at the exact times, SupMover negative
delay with no spurious warnings, and SE roundtrip re-import.

Fixes #10219

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@niksedk niksedk merged commit 3d3e32d into main Jul 2, 2026
1 of 3 checks passed
@niksedk niksedk deleted the fix/bluray-sup-pts-dts branch July 2, 2026 13:50
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.

Export to Blu-ray SUP produces an incorrect file

1 participant