committed by
Thomas Guillem
1 changed files with 109 additions and 0 deletions
@ -0,0 +1,109 @@ |
|||||
|
# Clock Architecture |
||||
|
|
||||
|
## Introduction |
||||
|
|
||||
|
This document presents the new clock archictecture for **VLC**, starting from |
||||
|
VLC 4.0. |
||||
|
|
||||
|
The clock is the element that manages the synchronisation of all [ES][ES], |
||||
|
notably audio and video (+subtitles) synchronization. |
||||
|
|
||||
|
While it can seem simple, at first glance, this part is not trivial, because |
||||
|
one must take care of numerous clocks in parallel, and they can be out-of-sync: |
||||
|
for example, your audio clock and your system clock are not necessary in-sync. |
||||
|
This is the same issue between your streamer's clock and your player's clock. |
||||
|
And most clocks drift. |
||||
|
|
||||
|
[PCR]: #f "Program Clock Reference" |
||||
|
[PTS]: #f "Presentation TimeStamp" |
||||
|
[DTS]: #f "Decoding TimeStamp" |
||||
|
[ES]: #f "Elementary streams, aka Tracks" |
||||
|
|
||||
|
### Old clock system |
||||
|
|
||||
|
The old clock from VLC was mainly an "*input clock*", based on the [input |
||||
|
PCR][PCR] (from the file), inherited from the time where VLC was mostly a |
||||
|
**MPEG-2/TS** player on the network. This is the correct clock for streaming, |
||||
|
and notably when your input format carries a [PCR][] or something similar. |
||||
|
|
||||
|
This old clock is quite nice, but has quite a few shortcomings, notably it |
||||
|
requires resampling of your audio output, even for local files or simple audio |
||||
|
files. |
||||
|
|
||||
|
It also rebases all the timings on the main input [PCR][], and it loses all the |
||||
|
original [PTS][] (because it was adding the current computer date). This is |
||||
|
notably an issue for transcoding (where it loses the original timestamps), for |
||||
|
pausing (we need to keep rewriting the timestamps) and for frame-accuracy |
||||
|
(because you know accurately only the input timings). |
||||
|
|
||||
|
It also depends too much on having a valid input, which are very rare, |
||||
|
unfortunately. And it does not work well with very large delays. |
||||
|
|
||||
|
Finally, the UI seekbar advances only when the [PCR][] is updated, which makes |
||||
|
big jumps in the seekbar, and is not smooth for the end-user. This notably |
||||
|
happens with large-audio samples and is related to the file format. |
||||
|
|
||||
|
## New clock system |
||||
|
|
||||
|
The idea of the new clock system is to have multiple pluggable clocks, one of |
||||
|
which being the master clock, that could be selected depending on the |
||||
|
situation. |
||||
|
|
||||
|
For example, you could have an **audio master clock** *(local files)*, an |
||||
|
**input PCR master clock** *(streaming)*, a **video master clock** *(V-Sync)* |
||||
|
or a future **external clock** *(SDI, netsync...)*. In the *audio master |
||||
|
clock* mode, VLC would not resample the audio anymore. |
||||
|
|
||||
|
As previously, there is one clock per input-program. This **main clock** is |
||||
|
therefore mostly at the es_out level and manages mostly the [PTS][] of all the |
||||
|
Elementary Streams. |
||||
|
|
||||
|
### Different clocks: main, slave and master |
||||
|
|
||||
|
Every output *(audio, video, stream)* has a clock, managed in the core. One of |
||||
|
those clock is master, the other are slaves. |
||||
|
|
||||
|
The main clock is the part managing the selection of the clocks and it will |
||||
|
derivate the main timings from the system clock *(the monotonic clock)* and |
||||
|
will provide those timings to the rest of VLC, including outputs, modules and |
||||
|
interfaces. |
||||
|
|
||||
|
It is currently an affine function based on the system clock, where the affine |
||||
|
coefficients are the moving average of the coefficient computed from the master |
||||
|
clock (In the future, it could be a different function). |
||||
|
|
||||
|
The main clock holds a reference to all the output clocks, whether they are the |
||||
|
master or one of the slaves. Please refer to the ***src/clock/clock.c*** for |
||||
|
details about those structures |
||||
|
|
||||
|
The master clock de facto defines the slope of the affine function. |
||||
|
|
||||
|
The main clock will rebase the timestamps according to the master clock. The |
||||
|
slaves ask the main clock, what is the system time corresponding to their |
||||
|
[PTS][]. |
||||
|
|
||||
|
If you want to see it differently, the master clock is a setter and the slave |
||||
|
clocks are the getters. |
||||
|
|
||||
|
### Core outputs |
||||
|
|
||||
|
The audio will be the master clock, in the nominal case. |
||||
|
|
||||
|
## Delays |
||||
|
|
||||
|
One important feature is the delaying/hastening of [elementary streams][ES] |
||||
|
with regards to other ES, also known as "Track Synchronization". |
||||
|
|
||||
|
It's very hard to hasten ES, because most hardware decoders will not like that, |
||||
|
and because often your decoder is already fully loaded (taking a lot of CPU). |
||||
|
|
||||
|
Instead, we delay all the other [ES][] that are not in advance, by (sort of) |
||||
|
**pausing** them. That means not displaying any new image for video outputs, or |
||||
|
playing silence for audio outputs. |
||||
|
|
||||
|
However, if we are in the case where the master output is the one that is in |
||||
|
advance, pausing this output will break the main clock, and it will |
||||
|
artificially drift. |
||||
|
|
||||
|
The main clock needs therefore to be reset when you find the synchro again, aka |
||||
|
when the output is "un-paused". |
||||
Loading…
Reference in new issue