Skip to content

Commit

Permalink
add TimestampNumerator/TimestampDenominator to override the value of …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
robUx4 committed Apr 4, 2021
1 parent 882738e commit 06fe005
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
14 changes: 11 additions & 3 deletions ebml_matroska.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,16 @@ The format depends on the ChapProcessCodecID used; see (#chapprocesscodecid-elem
<documentation lang="en" purpose="definition">Timestamp scale in nanoseconds (1.000.000 means all timestamps in the Segment are expressed in milliseconds).</documentation>
<extension type="libmatroska" cppname="TimecodeScale"/>
</element>
<element name="TimestampNumerator" path="\Segment\Tracks\TrackEntry\TimestampNumerator" id="0x2AF6A9" type="uinteger" range="not 0" maxOccurs="1" minver="5">
<documentation lang="en" purpose="definition">Timestamp numerator to apply instead of the TimestampScale, when the TimestampDenominator is present as well.</documentation>
<extension webm="0"/>
</element>
<element name="TimestampDenominator" path="\Segment\Tracks\TrackEntry\TimestampDenominator" id="0x2AF6AA" type="uinteger" range="not 0" maxOccurs="1" minver="5">
<documentation lang="en" purpose="definition">Timestamp denominator to apply instead of the TimestampScale, when the TimestampNumerator is present as well.</documentation>
<extension webm="0"/>
</element>
<element name="Duration" path="\Segment\Info\Duration" id="0x4489" type="float" range="&gt; 0x0p+0" maxOccurs="1">
<documentation lang="en" purpose="definition">Duration of the Segment in nanoseconds based on TimestampScale.</documentation>
<documentation lang="en" purpose="definition">Duration of the Segment in nanoseconds based on TimestampScale and TimestampNumerator/TimestampDenominator in v5.</documentation>
</element>
<element name="DateUTC" path="\Segment\Info\DateUTC" id="0x4461" type="date" maxOccurs="1">
<documentation lang="en" purpose="definition">The date and time that the Segment was created by the muxing application or library.</documentation>
Expand All @@ -110,7 +118,7 @@ The format depends on the ChapProcessCodecID used; see (#chapprocesscodecid-elem
<documentation lang="en" purpose="definition">The Top-Level Element containing the (monolithic) Block structure.</documentation>
</element>
<element name="Timestamp" path="\Segment\Cluster\Timestamp" id="0xE7" type="uinteger" minOccurs="1" maxOccurs="1">
<documentation lang="en" purpose="definition">Absolute timestamp of the cluster (based on TimestampScale).</documentation>
<documentation lang="en" purpose="definition">Absolute timestamp of the cluster (based on TimestampScale and TimestampNumerator/TimestampDenominator in v5).</documentation>
<extension type="libmatroska" cppname="ClusterTimecode"/>
</element>
<element name="SilentTracks" path="\Segment\Cluster\SilentTracks" id="0x5854" type="master" maxOccurs="1">
Expand Down Expand Up @@ -172,7 +180,7 @@ If BlockAddIDType of the corresponding block is 0, this value is also the value
<extension type="webmproject.org" webm="1"/>
</element>
<element name="BlockDuration" path="\Segment\Cluster\BlockGroup\BlockDuration" id="0x9B" type="uinteger" maxOccurs="1">
<documentation lang="en" purpose="definition">The duration of the Block (based on TimestampScale).
<documentation lang="en" purpose="definition">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.</documentation>
<implementation_note note_attribute="minOccurs">BlockDuration **MUST** be set (minOccurs=1) if the associated TrackEntry stores a DefaultDuration value.</implementation_note>
Expand Down
26 changes: 26 additions & 0 deletions notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 06fe005

Please sign in to comment.