| <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> |