mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-09 05:38:58 +00:00
200 lines
5.7 KiB
Text
200 lines
5.7 KiB
Text
purpose
|
|
-------
|
|
|
|
A proposal for proper syncing and clocking of a pipeline.
|
|
|
|
Requirements
|
|
------------
|
|
|
|
- elements should be able to get the time and wait for a specific
|
|
time
|
|
- some elements should be able to control and adjust the clock.
|
|
(clock master)
|
|
- the application should be able to provide another clock.
|
|
|
|
Clocks
|
|
------
|
|
|
|
A clock extends the abstract GstClock class.
|
|
|
|
gst_clock_get_time should always report an equal or increasing
|
|
value with each succesive call.
|
|
|
|
|
|
|
|
Clock providers
|
|
---------------
|
|
|
|
Clock providers call gst_element_provides_clock (element, clock)
|
|
in their _init function. This will set some element flags.
|
|
This also means that a clock provider cannot stop being a clock
|
|
provider.
|
|
|
|
Clock providers will update the clock at specific intervals.
|
|
get_resolution/set_resolution can be used to control the resolution.
|
|
|
|
When a clock provider is not going to update the clock anymore
|
|
it should make sure elements still blocked on the clock get
|
|
unblocked at the right time. This can be done by converting all
|
|
blocking waits to a select call. All further waits on the clock
|
|
should be estimated (using gettimeofday for example)
|
|
|
|
|
|
Clock receivers
|
|
---------------
|
|
|
|
An element needing a clock must implement the element receive_clock method.
|
|
It has to use the clock received in this function or if the
|
|
clock == NULL it should not do any waiting at all.
|
|
|
|
|
|
Clocks and the scheduler
|
|
------------------------
|
|
|
|
The scheduler knows about the clocks, else a clock provider and receiver
|
|
in the same scheduler could cause a deadlock.
|
|
|
|
Only one clock provider is allowed per scheduler. multiple clock
|
|
receivers are allowed per scheduler.
|
|
|
|
|
|
|
|
Specifying clocks
|
|
-----------------
|
|
|
|
on every bin with a scheduler, gst_bin_use_clock (bin, clock) can be used
|
|
to force the use of this specific clock for all the elements in this bin.
|
|
|
|
gst_bin_use_clock (bin, NULL) to disable all clocking for this bin.
|
|
|
|
gst_bin_auto_clock (bin) to use the default algorithm to find a clock.
|
|
|
|
bins that get a use clock set a flag and store the clock, they also call
|
|
set_clock on all of their children. When other children are added, they
|
|
all get the stored clock.
|
|
|
|
|
|
Clock distribution
|
|
------------------
|
|
|
|
clock providers and receivers are collected in the bins on element
|
|
add/remove, recursing bins if needed.
|
|
|
|
the toplevel bin with a scheduler selects the global clock and calls
|
|
set_clock on itself. This happens in the NULL->READY state.
|
|
|
|
bins dispatch the set_clock to to all of the reveivers. Bins with
|
|
a scheduler and another use_clock do nothing.
|
|
|
|
Bins with a scheduler also notify the scheduler of the clock.
|
|
|
|
|
|
Clock usage
|
|
-----------
|
|
|
|
when an element wants to wait for a specific time, if calls
|
|
gst_element_clock_wait (elements, clock, time). The call is dispatched
|
|
to the scheduler of the element which can use the owner field
|
|
of the clock to check if the elements are in the same scheduler.
|
|
|
|
For elements waiting for a clock provided by an element in another
|
|
scheduler there is no problem.
|
|
|
|
When provider and receiver are in the same scheduler, a deadlock can
|
|
occur since the scheduler will block on the wait without being able to
|
|
schedule the provider again to update the clock.
|
|
|
|
A solution would be to call the async notify of the clock and schedule
|
|
some other element (the provider?). We probably need an event based
|
|
scheduler for this. When the async event arrives we can reschedule
|
|
the receiver and continue.
|
|
|
|
The current scheduler will assert on this condition for now.
|
|
|
|
|
|
Changing clocks
|
|
---------------
|
|
|
|
The clock can only be changed when the bin is in the PAUSED state.
|
|
|
|
|
|
State Changes
|
|
-------------
|
|
|
|
When the pipeline is PAUSED, the clock is stopped with
|
|
gst_clock_enable (clock, FALSE). The clock should unblock all
|
|
waiting elements ASAP and return GST_CLOCK_STOP in the wait.
|
|
|
|
Elements waiting for a clock and receiving the STOP should
|
|
process the last buffer ASAP and break out of their loop.
|
|
|
|
When the pipeline is brought to the READY state, the clock is
|
|
set to 0.
|
|
|
|
When the clock is enabled again, it should start counting from where
|
|
it was last disabled.
|
|
|
|
NULL->READY : distribute clock, clock_reset,
|
|
READY->PAUSED : clock_activate (FALSE)
|
|
PAUSED->PLAYING : clock_activate (TRUE)
|
|
PLAYING->PAUSED : clock_activate (FALSE);
|
|
PAUSED->READY : clock_reset
|
|
READY->NULL : delete clock;
|
|
|
|
|
|
automatic Clock selection
|
|
-------------------------
|
|
|
|
Select a random clock from the Src elements.
|
|
if no Src elements exist with a clock, select a random clock from the
|
|
Sink elements.
|
|
else use a default System Clock.
|
|
|
|
Src elements with a clock are prefered because they usualy provide
|
|
live audio/video.
|
|
|
|
Issues
|
|
------
|
|
|
|
ossrc ! osssink can cause clock drift if osssink doesn't process the bytes
|
|
at the same rate osssrc provides them (different hardware). Things will
|
|
stutter and cracle if this is the case. QoS and a resampler could solve
|
|
this.
|
|
|
|
|
|
Use Cases
|
|
---------
|
|
-- queue ! mpeg2dec ! videosink
|
|
/
|
|
filesrc ! mpegdemux
|
|
\
|
|
-- queue ! mad ! osssink
|
|
|
|
|
|
videosink is a receiver
|
|
osssink is a provider
|
|
|
|
osssink is selected as a clock provider since it is a Sink. The global
|
|
pipeline distributes the clock to videosink and osssink.
|
|
osssink sees that it receives its own clock.
|
|
|
|
osssink uses the OSS ioctls to determine the number of bytes processed
|
|
by the hardware. using the audio rate it can figure out the exact time
|
|
and updates its clock with a resolution that matches the resolution
|
|
as closely as possible.
|
|
|
|
videosink blocks on the clock. with each update of the clock videosink
|
|
is unblocked if the current time >= wait time and shows the frame.
|
|
|
|
when osssink is PAUSED, the clock will not be updated anymore. osssink
|
|
instructs its clock to convert all requests to select() calls.
|
|
When it is set to PLAYING again, it resumes normal operation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|