<chapter id="chapter-advanced-clock"> | |
<title>Clocking</title> | |
<para> | |
When playing complex media, each sound and video sample must be played in a | |
specific order at a specific time. For this purpose, GStreamer provides a | |
synchronization mechanism. | |
</para> | |
<sect1 id="section-clocks" xreflabel="Clocks"> | |
<title>Clocks</title> | |
<para> | |
Time in &GStreamer; is defined as the value returned from a particular | |
<classname>GstClock</classname> object from the method | |
<function>gst_clock_get_time ()</function>. | |
</para> | |
<para> | |
In a typical computer, there are many sources that can be used as a | |
time source, e.g., the system time, soundcards, CPU performance | |
counters, ... For this reason, there are many | |
<classname>GstClock</classname> implementations available in &GStreamer;. | |
The clock time doesn't always start from 0 or from some known value. | |
Some clocks start counting from some known start date, other clocks start | |
counting since last reboot, etc... | |
</para> | |
<para> | |
As clocks return an absolute measure of time, they are not usually used | |
directly. Instead, differences between two clock times are used to | |
measure elapsed time according to a clock. | |
</para> | |
</sect1> | |
<sect1 id="section-clock-time-types" xreflabel="Clock running-time"> | |
<title> Clock running-time </title> | |
<para> | |
A clock returns the <emphasis role="strong">absolute-time</emphasis> | |
according to that clock with <function>gst_clock_get_time ()</function>. | |
From the absolute-time is a <emphasis role="strong">running-time</emphasis> | |
calculated, which is simply the difference between a previous snapshot | |
of the absolute-time called the <emphasis role="strong">base-time</emphasis>. | |
So: | |
</para> | |
<para> | |
running-time = absolute-time - base-time | |
</para> | |
<para> | |
A &GStreamer; <classname>GstPipeline</classname> object maintains a | |
<classname>GstClock</classname> object and a base-time when it goes | |
to the PLAYING state. The pipeline gives a handle to the selected | |
<classname>GstClock</classname> to each element in the pipeline along | |
with selected base-time. The pipeline will select a base-time in such | |
a way that the running-time reflects the total time spent in the | |
PLAYING state. As a result, when the pipeline is PAUSED, the | |
running-time stands still. | |
</para> | |
<para> | |
Because all objects in the pipeline have the same clock and base-time, | |
they can thus all calculate the running-time according to the pipeline | |
clock. | |
</para> | |
</sect1> | |
<sect1 id="section-buffer-time-types" xreflabel="Buffer running-time"> | |
<title> Buffer running-time </title> | |
<para> | |
To calculate a buffer running-time, we need a buffer timestamp and | |
the SEGMENT event that preceded the buffer. First we can convert | |
the SEGMENT event into a <classname>GstSegment</classname> object | |
and then we can use the | |
<function>gst_segment_to_running_time ()</function> function to | |
perform the calculation of the buffer running-time. | |
</para> | |
<para> | |
Synchronization is now a matter of making sure that a buffer with a | |
certain running-time is played when the clock reaches the same | |
running-time. Usually this task is done by sink elements. Sink also | |
have to take into account the latency configured in the pipeline and | |
add this to the buffer running-time before synchronizing to the | |
pipeline clock. | |
</para> | |
</sect1> | |
<sect1 id="section-clock-obligations-of-each-element" xreflabel="Obligations | |
of each element"> | |
<title> | |
Obligations of each element. | |
</title> | |
<para> | |
Let us clarify the contract between GStreamer and each element in the | |
pipeline. | |
</para> | |
<sect2> | |
<title>Non-live source elements </title> | |
<para> | |
Non-live source elements must place a timestamp in each buffer that | |
they deliver when this is possible. They must choose the timestamps | |
and the values of the SEGMENT event in such a way that the | |
running-time of the buffer starts from 0. | |
</para> | |
<para> | |
Some sources, such as filesrc, is not able to generate timestamps | |
on all buffers. It can and must however create a timestamp on the | |
first buffer (with a running-time of 0). | |
</para> | |
<para> | |
The source then pushes out the SEGMENT event followed by the | |
timestamped buffers. | |
</para> | |
</sect2> | |
<sect2> | |
<title>Live source elements </title> | |
<para> | |
Live source elements must place a timestamp in each buffer that | |
they deliver. They must choose the timestamps and the values of the | |
SEGMENT event in such a way that the running-time of the buffer | |
matches exactly the running-time of the pipeline clock when the first | |
byte in the buffer was captured. | |
</para> | |
</sect2> | |
<sect2> | |
<title>Parser/Decoder/Encoder elements </title> | |
<para> | |
Parser/Decoder elements must use the incoming timestamps and transfer | |
those to the resulting output buffers. They are allowed to interpolate | |
or reconstruct timestamps on missing input buffers when they can. | |
</para> | |
</sect2> | |
<sect2> | |
<title>Demuxer elements </title> | |
<para> | |
Demuxer elements can usually set the timestamps stored inside the media | |
file onto the outgoing buffers. They need to make sure that outgoing | |
buffers that are to be played at the same time have the same | |
running-time. Demuxers also need to take into account the incoming | |
timestamps on buffers and use that to calculate an offset on the outgoing | |
buffer timestamps. | |
</para> | |
</sect2> | |
<sect2> | |
<title>Muxer elements</title> | |
<para> | |
Muxer elements should use the incoming buffer running-time to mux the | |
different streams together. They should copy the incoming running-time | |
to the outgoing buffers. | |
</para> | |
</sect2> | |
<sect2> | |
<title>Sink elements</title> | |
<para> | |
If the element is intended to emit samples at a specific time (real time | |
playing), the element should require a clock, and thus implement the | |
method <function>set_clock</function>. | |
</para> | |
<para> | |
The sink should then make sure that the sample with running-time is played | |
exactly when the pipeline clock reaches that running-time + latency. | |
Some elements might use the clock API such as | |
<function>gst_clock_id_wait()</function> | |
to perform this action. Other sinks might need to use other means of | |
scheduling timely playback of the data. | |
</para> | |
</sect2> | |
</sect1> | |
</chapter> |