[Matroska-devel] New Matroska field: Timescale

wm4 nfxjfg at googlemail.com
Thu Sep 24 13:38:30 CEST 2015

On Thu, 24 Sep 2015 11:09:48 +0200
Jerome Martinez <jerome at mediaarea.net> wrote:

> Le 23/09/2015 17:43, Steve Lhomme a écrit :
> > Following this week-end's VDD15 (Videolan Dev Days) we have some
> > productive talks with Dave Rice (working on the IETF specifications)
> > and a guy from YouTube on how we could improve Matroska for long term
> > storage/archival and also new features in video.
> >
> > There are a few fields that would need to be added to reach this goal.
> > I'll send an email for each (family of) field so the discussions are
> > easy to follow.
> >
> > One of the most common drawback mentioned when Matroska comes to mind
> > is the inaccurate approach for timestamps (that should not be called
> > timecodes which is something different in the video world).
> It would be great to replace "timecode" by "timestamp" everywhere in the 
> documentation.
> >   The proper
> > way to do it, at least for clock accurate digital sources should be
> > using a fraction format (numerator/denominator).
> >
> > See this page for own the basic math works:
> > http://matroska.org/technical/specs/notes.html#TimecodeScale
> >
> > (1233 + 564264) * 1000000 = 565497000000
> >       = 565497 ms
> >       = 565.497s
> >
> > With a numerator/denominator approach this example would become:
> > (1233 + 564264) * 1 / 1000 = 565.497s
> >
> > A NSTC movie (29.76fps) could have a better accuracy using 30000/1001
> > (or 30/1001 if you want a large range of values in your block).
> >
> > One of the drawback (and why it was not adopted in the first place) is
> > that when you mix heterogeneous sources you need to find a common
> > fraction that works for all tracks and still get enough range within
> > the 16 bits possible for a Block timecode. It was less of a problem
> > when we had TrackTimecodeScale to account for each track specifics,
> > but that element is deprecated.
> Why is TrackTimecodeScale deprecated? This is actually the right method 
> from my point of view (but it is now too late for having it without 
> breaking compatibility) because a scale is per track.
> >
> > If we decide to use fractions, it should be possible to keep backward
> > compatibility. The current TimecodeScale would be an approximation of
> > the fraction in nanoseconds. New players would take advantage of the
> > new fields as they are upgraded.
> Nanoseconds would not resolve the main issue: it is not accurate.
> It would be more accurate than today with a timescale of 1000000:
> - at 29700/1000, first frame is at 33366700 nanoseconds
> - at 30000/1001, first frame is at 33366667 nanoseconds
> so we can detect this difference, but FFmpeg will still not put 
> 29700/1000 or 30000/1001 because Matroska does not say that this is the 
> real frame rate.
> So we may need to provide the time scale with a fraction, per track, 
> without changing something else.
> With it, I think it is not necessary to use nanoseconds, and:
> - players not supporting frame rate info per track with a fraction would 
> use TimeCode field as today (33ms will stay 33ms)
> - players supporting frame rate info per track with a fraction would 
> "convert" TimeCode field to the nearest real frame rate (33ms with a 
> time scale of 1001/30000 will be converted to 33.366667ms because it is 
> the nearest "valid" value, 21ms with a timescale of 1024/48000 will be 
> converted to 21.333333ms because it is the nearest "valid" value)

It's very hard to design this in a backwards compatible and robust way.

If you define a per-track framerate to which timestamps should be
fixed, you won't support VFR. (Yes, such files exist.) Also, doesn't
default-duration already define such a per-track framerate? It works
badly, because OF COURSE some muxers  write broken framerates. In one
case, the framerate was based on a single _rounded_ frame duration,
even though the actual framerate was different (other frames had a
different frame duration).

We could store 2 timestamps per packet. But you bet there will be at
least 1 muxer which writes two completely different timestamps (one of
them broken), so users will consider a player broken, depending whether
it interprets the broken timestamp.

We could somehow store the difference between the rounded timestamp and
the real timestamp per packet - this might be somewhat more robust, as
even with broken timestamps, the difference will be at most +/- 1 ms,
but it sounds complex and messy.

And last but not least, we have to store other timestamp fields
correctly, like in the seek index, chapter index, etc.

More information about the Matroska-devel mailing list