some thoughts about clocking - this looks suspiciously easy. Either i'm missing something (it's late) or it's a quite...

Original commit message from CVS:
some thoughts about clocking - this looks suspiciously easy. Either i'm missing something (it's late) or it's a quite good approach.
This commit is contained in:
Benjamin Otte 2003-04-15 01:11:05 +00:00
parent 54b35086ea
commit 8703409089

View file

@ -0,0 +1,93 @@
TIME
In this document, the word "time" is not meant to represent a representation of
time that is close to reality. Though that is the idea in most cases, it is not
the focus. Time in this document is meant to represent time inside a stream that
is played back by GStreamer. There might be reasons to represent time in non-
realtime, for example when the processor is too slow to allow for video playback
in realtime, the clock might not update fast enough. Or one might want to use
a clock that purposefully increases/reduces the speed of time.
Time in this document is not meant to be linear either. Whereas elements can set
time freely by seeking, clocks should do their best to supply linear time. It is
not a requirement however, there might for example be slight inconsistencies
when audio clocks have buffer over/underruns.
TIME IN A CLOCK
The job of a clock is to report the time as exactly as possible that has elapsed
in the stream since the stream was started.
A Clock does never seek, so if someone seeks the stream back to the beginning,
the clock will still represent the time since a start.
The state of the clock is managed by all elements using its time as a state of a
bin is changed according to its children. A clock will try to synchronize its
state with its provider. (FIXME: or with all its children like a bin? FIXME:
What to do in the case of a providerless clock like _a_ systemclock (we might
use multiple systemclocks)? Attach to one element that uses it and reattach if
element is removed? FIXME: What do we do when a provider is removed from a
scheduler? Sounds like a good time to get a new clock to take over. FIXME:
Write a test that does exactly this in Gst-Player when changing the GConf Key.)
- NULL / READY
Nobody cares about time reported by the clock.
- PLAYING
Clock is supposed to present the time elapsed since it was started.
- PAUSED
The clock has to remember the time it was stopped and resume with that time
when it restarts playing.
TIME IN AN ELEMENT
An element only can request time information if it uses a clock. The element can
query functions that give information about the elements time. Time information
for the element is always in relation to the timestamps the element expects on
its buffers.
Example: XVideosink will output a new frame, when xvideosinks time matches the
timestamps of the buffer.
The elements time is in no relation to the time of its clock because of seeks.
If an element seeks, it adjusts its time by the difference the seek has
introduced.
Example: Playback of a song with duration 1000 that is looping. Clock and
element start at time offset 0, when the element is first set to
PLAYING. After the first loop, the elements time is (by request of that
element) reset to 0. The clock's time stays at 1000.
Note: If an element goes into the PAUSED state the elements time will continue
running. (FIXME: possibility to change that needed? Why would you want to
pause an element that should be synced while the others continue running?
FIXME: What happens if a clock provider and therefore the clock are
already at EOS while other elements are still playing? I'd vote for make
all other elements go as fast as possible. FIXME: Ask some video people if
that sounds reasonable or if we gotta force the clock to go on, which
would make it difficult to detect the difference between EOS and pause.
PROVIDERS
Providers are elements that can provide timing information and therefore provide
a clock to other elements. These elements have to update the clock, when it is
used. When a clock is used (state != NULL - FIXME: or other states?), the
provider is guaranteed to use this clock. (FIXME: necessary?). The element is
however required to synchronize to the clock it was assigned to, wether it is
its own clock or not.
SYNC POINTS
FIXME: Is it necessary to have sync points? This would allow to supply a fixed
time between sync point "SOURCE" and "SINK" so one could buffer the time
inbetween. Or is there another solution for this problem? It's possibly easier
to use an element that does TIMESTAMP = TIMESTAMP - x inside the pipeline and
drops every buffer before.
FUNCTIONS
FIXME: Use GstTime(Diff) instead of GstClockTime(Diff) ?
GstClockTime gst_clock_get_time (GstClock *clock);
GstElementState gst_clock_get_state (GstClock *clock); /* setting works internally */
GstClockReturn gst_clock_wait (GstClock *clock, GstClockTime until, GstClockTimeDiff *jitter);
GST_FLAG GST_ELEMENT_NEEDS_CLOCK; /* wether we want a clock or not */
GstClockTime gst_element_get_time (GstElement *element);
void gst_element_(clock_)seek (GstElement *element, GstClockTimeDiff diff);
GstClock * gst_element_get_clock (GstElement *element);
GstClockReturn gst_element_(clock_)wait (GstElement *element, GstClockTime until, GstClockTimeDiff *jitter);
possible extensions:
GstClockTime gst_clock_get_resolution (GstClock *clock); /* sounds interesting */
void gst_clock_wait_async (GstClock *clock, GFunc callback, gpointer data); /* useless IMO */
void gst_clock_unlock (GstClock *clock); /* dunno what for */
void gst_clock_set_state (GstClock *clock, GstElementState state); /* might be needed, but screw up alot */
Hm, this looks to easy when you only need an API of 8 functions. But it's quite
a bit of internal hacking because of the state changes.