Key the seam-crossing rule on reorder, not on driving epochs

A Dolby Vision enhancement layer is a second video track: it does not
drive epochs, but it does carry B-frame reorder. The crossing rule was
keyed on driving epochs, so the EL took the branch whose premise is that
the track has no reorder — and its ordinary reorder dip near the end of a
clip, which during an overlap also lands inside the next clip's range,
was read as a join. The EL was then placed on the next clip's offset, out
of step with the base-layer frame it must be co-timed with by the width
of the overlap: the same desync the per-track cursor was added to remove,
reintroduced for one track.

The property the rule actually depends on is whether a backward step can
be reorder, so it is now keyed on that. Both sinks derive it from the
track kind rather than from the epoch driver.
This commit is contained in:
Matthew Jackson
2026-08-05 17:52:13 -07:00
parent c8fafec393
commit f4fb5c65e0
3 changed files with 83 additions and 21 deletions
+6 -1
View File
@@ -1414,7 +1414,12 @@ impl<W: Write + Seek> MkvMuxer<W> {
// outside every clip's IN/OUT marks, which only a seam-plan-driven
// title can report. Dropping it is the point: emitting it is what put
// duplicate content on the timeline at a join.
let Some(pts_ns) = self.continuity.map(pts_ns, drives_epoch, track_idx) else {
let Some(pts_ns) = self.continuity.map(
pts_ns,
drives_epoch,
track_idx,
self.track_is_video.get(track_idx).copied().unwrap_or(false),
) else {
return Ok(());
};
let raw_ticks = pts_ns / TIMESTAMP_SCALE_NS;