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