Skip to content

pmp4: support tracks longer than 2^32 ticks - #377

Merged
aler9 merged 1 commit into
bluenviron:mainfrom
hsdfat:pmp4-long-track-duration
Sep 20, 2026
Merged

aler9 merged 1 commit into
bluenviron:mainfrom
hsdfat:pmp4-long-track-duration

Conversation

@hsdfat

@hsdfat hsdfat commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Presentation.Marshal summed sample durations into a uint32 and always wrote mdhd with version 0. The duration of tracks longer than 2^32 ticks (13.25h at 90kHz, 24.8h at 48kHz) therefore wrapped around in mdhd, tkhd and elst. For example, a 14h 25fps H264 track is reported by ffprobe as 2678s instead of 50400s, and players that honour edit lists stop playback at 44:38. MediaMTX builds these files in playback /get?format=mp4, so this hits exports longer than about 13h.

Durations are now summed with 64 bits, and mdhd is written with version 1 only when the duration does not fit into 32 bits (ISO/IEC 14496-12, 8.4.2), so existing output is unchanged. tkhd, mvhd and elst stay at version 0 because they use the 1000Hz movie timescale. This means that presentations longer than 49.7 days (2^32 ms) still wrap in those three boxes.

The reader now reads the version 1 duration too. Before, a version 1 mdhd was read as a duration of 0, so the time offset came out wrong (1294967296 instead of 0 for an FFmpeg file with -video_track_timescale 1500000000). Version 1 durations are range-checked: invalid duration is returned when the time offset (mdhd duration minus the sum of the sample durations) does not fit into an int32, instead of wrapping silently. Version 0 durations keep their current behaviour, so files that were written by the current version of Marshal with a wrapped duration still read with the right time offset.

Add a round-trip test case with a 14h track (two samples of 7h at 90kHz, plus a 1s time offset) that covers the version 1 write and read, a test case with the same track as written by the current Marshal (wrapped version 0 mdhd), and a fuzz seed with a version 1 mdhd duration inconsistent with the samples. The existing test bytes are unchanged.

Sample durations were summed into a 32-bit integer and mdhd was always
written with version 0, therefore the duration of tracks longer than
2^32 ticks (13.25h at 90kHz) wrapped around in mdhd, tkhd and elst: a
14h presentation was reported as 44m38s, and players that honour edit
lists stopped there.

Sum durations with 64 bits and write mdhd with version 1 when the
duration does not fit into 32 bits (ISO/IEC 14496-12, 8.4.2). Read the
version 1 duration too, and return an error when it is not consistent
with the sample durations. Version 0 durations are still read as
before, so that files written by previous versions of Marshal, whose
duration may have wrapped around, keep working.
@codecov

codecov Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.35%. Comparing base (8937889) to head (e8ada6c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #377      +/-   ##
==========================================
+ Coverage   91.02%   91.35%   +0.32%     
==========================================
  Files          98       98              
  Lines        5472     5482      +10     
==========================================
+ Hits         4981     5008      +27     
+ Misses        491      474      -17     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aler9
aler9 merged commit c123814 into bluenviron:main Sep 20, 2026
8 checks passed
@aler9

aler9 commented Sep 20, 2026

Copy link
Copy Markdown
Member

merged, thanks

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.

2 participants