2005-06-30 Wim Taymans <wim@fluendo.com>
+ * docs/design/part-clocks.txt:
+ * docs/design/part-element-sink.txt:
+ * docs/design/part-events.txt:
+ * docs/design/part-preroll.txt:
+ * docs/design/part-states.txt:
+ Some more tweeks and additions to the docs.
+
+2005-06-30 Wim Taymans <wim@fluendo.com>
+
* gst/gstpad.c: (_gst_do_pass_data_accumulator),
(default_have_data), (gst_pad_class_init), (gst_pad_init),
(gst_pad_emit_have_data_signal), (gst_pad_chain), (gst_pad_push),
- In PLAYING, the stream time is the delta between the absolute time
and the base time. The base time is defined as the absolute time minus
the stream time at the time when the pipeline is set to PLAYING.
- - after a seek, the stream time is set to seek time.
+ - after a seek, the stream time is set to 0 (see part-seeking.txt)
The stream time is completely managed by the GstPipeline object using the
GstClock absolute time.
None of the wait operations unref the GstClockID, the owner is
responsible for unreffing the ids itself. This holds for both periodic and
-single shot notifications.
+single shot notifications. The reason being that the owner of the ClockID
+has to keep a handle to the ID to unblock the wait on FLUSHING events
+or state changes and if we unref it automatically, the handle might be
+invalid.
These clock operations do not operate on the stream time, so the callbacks
will also occur when not in PLAYING state as if the clock just keeps on
Sinks are harder to construct than other element types as they are
treated specially by the GStreamer core.
+state changes
+-------------
+
+A sink always returns ASYNC from the state change to PAUSED, this
+includes a state change from READY->PAUSED and PLAYING->PAUSED. The
+reason for this is that this way we can detect when the first buffer
+or event arrives in the sink when the state change completes.
+
+A sink should block on the first event or buffer received in the
+PAUSED state before commiting the state to PAUSED.
+
+FLUSHING events have to be handled out of sync with the buffer flow
+and take no part in the preroll procedure.
+
+
+
STREAM_LOCK should be taken.
Sometimes the EOS event is generated by another element than the source, for
-example a demuxer filter can generate an EOS event before the source element.
+example a demuxer element can generate an EOS event before the source element.
This is not a problem, the demuxer does not send an EOS event to the upstream
element but returns GST_FLOW_UNEXPECTED, causing the source element to stop
sending data.
-------------
A discont event is sent downstream by an element to indicate that the following
-group of buffers start and end at the specified time.
+group of buffers start and end at the specified time. The discont event
+also contains the playback speed of the stream.
+
+Since the stream time is always set to 0 at start and after a seek, a 0
+point for all next buffer's timestamps has to be propagated through the
+pipeline using the DISCONT event.
+
+Elements that sync to the clock should store the DISCONT start and end values
+and substract the start value from the buffer timestamp before comparing
+it against the stream time.
+
+An element is allowed to send out buffers with the DISCONT start time already
+substracted from the timestamp. If it does so, it needs to send a corrected
+DISCONT downstream, ie, one with start time 0.
+
+A DISCONT event should be generated as soon as possible in the pipeline and
+is usually generated by a demuxer. The event is generated before pushing the
+first buffer and after a seek, right before pushing the new buffer.
+
+The DISCONT event can be send from both the application and the streaming
+thread.
-After a seek event for example, a discont event is sent.
SEEK
after the seek is performed. Optionally the end position can be left
at -1 to continue playback to the end of the stream.
-A stream usually flushes the graph to minimize latency after the seek.
+A seek usually flushes the graph to minimize latency after the seek.
The seek event is passed along from element to element until it reaches
an element that can perform the seek. No intermediate element is allowed
to assume that a seek to this location will happen. It is allowed to
-modify the start and stop times if it needs to do so.
+modify the start and stop times if it needs to do so. this is typically
+the case if a seek is requested for a non-time position.
The actual seek is performed in the application thread so that success
or failure can be reported as a return value of the seek event. It is
was unlocked in step 1).
3) perform the seek. since the STREAM_LOCK is held, the streaming thread
- will wait for the seek to complete.
+ will wait for the seek to complete. Most likely, the stream thread
+ will pause because the peer elements are flushing.
4) send a flush event with the done flag set to allow streaming again.
- 5) start stopped tasks and unlock the STREAM_LOCK, dataflow will continue
+ 5) send a DISCONT event to signal the new buffer timestamp base time.
+
+ 6) start stopped tasks and unlock the STREAM_LOCK, dataflow will continue
now from the new position.
Some demuxers know an optimal size for any downstream buffers. They can
use this event to signal this fact. Similary an element can signal an
-upstream element of a prefered buffer size.
+upstream element for a prefered buffer size.
RATE
----
When the application wants to change the playback rate of the stream, it
-issues a rate event. A rate of 1.0 is the normal playback rate, 2.0 plays
-at twice the speed and negative values play backwards.
+issues a rate event on the sinks. A rate of 1.0 is the normal playback rate,
+2.0 plays at twice the speed and negative values play backwards.
+
+The rate event travels upstream. After the rate event reaches an element
+that can handle the rate event, it issues a flush and generates a new
+DISCONT event with the updated rate.
-Note that the clock speed does not change.
+Note that the clock speed does not change. More specific information about
+changing the playback rate are to be thought out and written down.
NAVIGATION
A navigation event is generated by a sink element to signal the elements
of a navigation event such as a mouse movement or button click.
-Navigation events travel downstream.
+Navigation events travel upstream.
TAG
The tag event is sent downstream when an element has discovered metadata
tags in a media file. Encoders can use this event to adjust their tagging
-system.
+system. A tag is serialized with buffers.
We require the state change to be commited in EOS as well since an EOS means
by definition that no buffer is going to arrive anymore.
+After the state is commited, a blocking wait should be performed for the
+next event. Some sinks might render the preroll buffer before starting this
+blocking wait.
+
Unlocking the preroll
---------------------
- a state change
- a flush event
-When the preroll is unlocked by one of these events, a return value of
+When the preroll is unlocked by a flush event, a return value of
GST_FLOW_WRONG_STATE is to be returned to the peer pad.
-
-
-Result of the preroll
----------------------
-After the preroll is unlocked, the element can be in the following states:
+When preroll is unlocked by a state change to PLAYING, playback and
+rendering of the buffers shall start.
- - in a state that disallows it to process the data (flushing, pad inactive)
- - in a state that allows it to process the data.
+When preroll is unlocked by a state change to READY, the buffer is
+to be discarded and a GST_FLOW_WRONG_STATE shall be returned to the
+peer element.
- STATE
- PENDING_STATE
- STATE_ERROR flag
+ - NO_PREROLL flag
The STATE always reflects the current state of the element. The PENDING_STATE
always reflects the required state of the element. The PENDING_STATE can be
VOID_PENDING if the element is in the right state. The STATE_ERROR flag
indicates that an error occured while doing the last state change.
+The NO_PREROLL flag indicates that the element said it was not able to preroll
+in its last state change. This flag is used in live sources.
+
Setting state on elements
-------------------------
- If the element returned SUCCESS to the previous _set_state() function, this
function will return the last state set on the element and VOID_PENDING in
- the pending state value.
+ the pending state value. The function returns GST_STATE_SUCCESS.
+
+ - If the element returned NO_PREROLL to the previous _set_state() function, this
+ function will return the last state set on the element and VOID_PENDING in
+ the pending state value. The function returns GST_STATE_NO_PREROLL.
- If the element returned FAILURE to the previous _set_state() call, this
funciton will return FAILURE with the state set to the current state of
call the _get_state() function on all the elements.
First the bin will perform a _get_state() on all children with a 0 timeout. This
-is to find any children with an ERROR/NO_PREROLL result value.
+is to find any children with an ERROR/NO_PREROLL result value.
Then the bin performs the _get_state() with the requested timeout. The reason for
the 2 phases is that when an ERROR or NO_PREROLL result is found, a blocking