5.9.4
Fixed
- An MKV track carrying
TrackTimestampScale != 1now demuxes on the coherent, unscaled segment axis (cluster + rel) instead of a silently wrong hybrid axis (cluster + rel x scale). (#145, reported by @cmcpherson274)
Details
Inherited FFmpeg behavior, present in n8.1.2 and current master: matroskadec bakes the track's TrackTimestampScale (TTS) into the stream time base (segment scale x TTS) but divides only the CLUSTER component of each block timestamp by it (cluster_time / track->time_scale + block_time). In seconds that lands every packet on cluster + rel x TTS: neither the unscaled nor the fully scaled axis.
On the reporter's TTS=2.0 fixture this reproduced every measured number: cue starts shifted by relTs x (TTS - 1) per cluster (12->14 s, 24.5->29 s), packets arrived non-monotonic in storage order (the 29 s cue before the 25 s clear, since a late-rel block in cluster N overtakes an early-rel block in cluster N+1), and a stale fade outlived its authored clear. Packet durations were additionally off by a factor of TTS. All silent: right pixels, wrong times, no warning.
Fix, at the FFmpeg layer (FFmpegBuild 2.1.2, patch_ffmpeg_matroska_tts): any TrackTimestampScale != 1.0 is clamped to 1.0 with an AV_LOG_WARNING carrying the ignored value, extending upstream's own < 0.01 clamp in the same spot. Rationale for clamping over full spec scaling: RFC 9559 deprecates the element (maxver 3), matroska.org documents that most readers ignore it (a non-1.0 value in the wild is almost always muxer damage, not intent), and full scaling would desync the track from its sibling tracks. The clamp keeps every track on the coherent, monotonic storage axis and is a strict no-op for TTS = 1.0, i.e. effectively all real-world Matroska. The silence is gone too: the warning flows into host log taps.
Verification
Issue145MatroskaTrackTimestampScaleTests: a minimal in-memory Matroska writer (BlockGroup + BlockDuration, 5 s clusters mirroring the reporter's fixture shape) demuxed through the engine. RED on FFmpegBuild 2.1.1 with exactly the reported shifts; GREEN on 2.1.2, with the TTS=2.0 file demuxing identically to the TTS-less control.- Full suite: 747 Swift Testing + 311 XCTest tests pass; strict-concurrency clean; iOS/tvOS Simulator CI green.
Thanks @cmcpherson274 for another precision report: the hybrid-axis formula, the storage-order observation, and the per-cluster error bound were all verbatim correct.