From 06fe0055c92ea0a16f94c59cd0269df3a7b2a140 Mon Sep 17 00:00:00 2001 From: Steve Lhomme Date: Sun, 11 Oct 2020 10:05:36 +0200 Subject: [PATCH] add TimestampNumerator/TimestampDenominator to override the value of TimestampScale This allows sample precision of each timestamp is some cases, mostly single track files. Wherever TimestampScale was used, if this fraction is found, it should be used instead. --- ebml_matroska.xml | 14 +++++++++++--- notes.md | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ebml_matroska.xml b/ebml_matroska.xml index 6cb7a751..9993014e 100644 --- a/ebml_matroska.xml +++ b/ebml_matroska.xml @@ -88,8 +88,16 @@ The format depends on the ChapProcessCodecID used; see (#chapprocesscodecid-elem Timestamp scale in nanoseconds (1.000.000 means all timestamps in the Segment are expressed in milliseconds). + + Timestamp numerator to apply instead of the TimestampScale, when the TimestampDenominator is present as well. + + + + Timestamp denominator to apply instead of the TimestampScale, when the TimestampNumerator is present as well. + + - Duration of the Segment in nanoseconds based on TimestampScale. + Duration of the Segment in nanoseconds based on TimestampScale and TimestampNumerator/TimestampDenominator in v5. The date and time that the Segment was created by the muxing application or library. @@ -110,7 +118,7 @@ The format depends on the ChapProcessCodecID used; see (#chapprocesscodecid-elem The Top-Level Element containing the (monolithic) Block structure. - Absolute timestamp of the cluster (based on TimestampScale). + Absolute timestamp of the cluster (based on TimestampScale and TimestampNumerator/TimestampDenominator in v5). @@ -172,7 +180,7 @@ If BlockAddIDType of the corresponding block is 0, this value is also the value - The duration of the Block (based on TimestampScale). + The duration of the Block (based on TimestampScale and TimestampNumerator/TimestampDenominator in v5). The BlockDuration Element can be useful at the end of a Track to define the duration of the last frame (as there is no subsequent Block available), or when there is a break in a track like for subtitle tracks. BlockDuration **MUST** be set (minOccurs=1) if the associated TrackEntry stores a DefaultDuration value. diff --git a/notes.md b/notes.md index 536832d7..f9db3c74 100644 --- a/notes.md +++ b/notes.md @@ -577,6 +577,32 @@ Some general notes for a program: that it started with. Using a slightly lower timestamp scale factor can help here in that it removes the need for proper rounding in the conversion from sample number to `Raw Timestamp`. +## Rational Number and Nanoseconds + +Historically timestamps in Matroska were stored in nanoseconds precision. +The `TimestampScale` would reduce the size of each value stored in the file by dividing each real timestamps by a certain value. +For many sampling frequencies, that means rounding the values and losing precision. +There are `TimestampNumerator` and `TimestampDenominator` to fix this precision loss. +They override the value of `TimestampScale` in all places it is used. + +This formula remains but there is no rounding involved anymore: + + (a + b) * c + + a = `Block`'s Timestamp + b = `Cluster`'s Timestamp + c = `TimestampScale` + +For compatibility with older readers that don't understand these elements, the `TimestampScale` value *MUST* +be the rounded values of `TimestampNumerator` divided by `TimestampDenominator` in nanoseconds. + +This fraction may not be usable in most cases. It works well with files having a single Track. +It only works when Tracks have a sampling frequency which is highly divisible. +For example even a video track of 1/25000 (PAL) with audio of 1/48000 (DAT) doesn't work well. The reduced fraction gives 25/48. +A `TimestampNumerator` of 1 and `TimestampDenominator` of 25\*48000 would give ticks that hit on each clock. +But the amount of samples possible in a Block/SimpleBlock is stored on 16 bits or 65536 values. So the duration possible in a Cluster would be 65536 / (25\*48000) or 54.6 ms. Which is not enough to be efficient storage. +It would only work if audio samples were packed with a multiple of 25 samples, which is usually not the case. + ## TrackTimestampScale The `TrackTimestampScale Element` is used align tracks that would otherwise be played at