gstreamer/docs/design/part-events.txt

209 lines
8.2 KiB
Text
Raw Normal View History

Events
------
Events are objects passed around in parallel to the buffer dataflow to
notify elements of various events.
Events are received on pads using the event function. Some events should
be interleaved with the data stream so they require taking the STREAM_LOCK,
others don't.
Different types of events exist to implement various functionalities.
GST_EVENT_EOS: no more data is to be expected on a pad.
GST_EVENT_FLUSH: data is to be discarded or allowed again
GST_EVENT_DISCONTINUOUS: A new group of buffers with common start time
GST_EVENT_QOS: A notification of the quality of service of the stream
GST_EVENT_SEEK: A seek should be performed to a new position in the stream
GST_EVENT_SIZE: Notification of suggested buffer size.
GST_EVENT_RATE: Notification to change the processing speed of a stream
GST_EVENT_NAVIGATION: A navigation event.
GST_EVENT_TAG: Stream metadata.
EOS
---
The EOS event can only be sent on a sinkpad. It is typically emited by the
source element when it has finished sending data. This event is mainly sent
in the streaming thread but can also be sent from the application thread.
The downstream element should forward the EOS event to its downstream peer
elements. This way the event will eventually reach the renderers which should
then post an EOS message on the bus.
For elements with multiple sink pads it might be possible to wait for EOS on
all the pads before forwarding the event.
The EOS event should always be interleaved with the data flow, therefore the
STREAM_LOCK should be taken.
Sometimes the EOS event is generated by another element than the source, for
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.
An element that sends EOS on a pad should stop sending data on that pad. Source
elements typically pause() their task for that purpose.
By default, the pipeline collects all EOS events from all the sinks before
passing the EOS message to the application.
The EOS is only posted on the bus by the sink elements in the PLAYING state. If
the EOS event is received in the PAUSED state, it is queued until the element
goes to PLAYING.
FLUSH
-----
A flush event is sent both downstream and upstream to clear any pending data
from the pipeline. This might be needed to make the graph more responsive
when the normal dataflow gets interrupted by for example a seek event.
Flushing happens in two stages.
1) a source filter sends the flush event to the downstream peer element. The
downstream element starts rejecting buffers from the upstream elements. It
sends the flush event further downstream and discards any buffers it is
holding as well as return from the chain function as soon as possible.
This makes sure that all upstream elements get unblocked.
This event is not synchronized with the STREAM_LOCK and can be done in the
application thread.
2) a source filter sends the flush event with the done flag set to indicate
that the downstream element can accept buffers again. The downstream
element sends the flush event to its peer elements. After this step dataflow
continues. The endflush call is synchronized with the STREAM_LOCK so any
data used by the chain function can safely freed here if needed. Any
pending EOS events should be discarded too.
After the flush completes the second stage, data is flowing again in the pipeline
and all buffers are more recent than those before the flush.
For elements that use the pullregion function, they send both flush events to
the upstream pads in the same way top make sure that the pullregion function
unlocks and any pending buffers are cleared in the upstream elements.
DISCONTINUOUS
-------------
A discont event is sent downstream by an element to indicate that the following
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 (see part-clocks.txt).
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 and should be serialized with the buffers.
SEEK
----
A seek event is issued by the application to start playback of a new
position in the stream. It is called form the application thread and
travels upstream.
The seek event contains the new start and end position of playback
after the seek is performed. Optionally the end position can be left
at -1 to continue playback to the end of the stream.
A seek usually flushes the graph to minimize latency after the seek this
behaviour is triggered by using the SEEK_FLUSH flag.
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. 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
therefore important that before executing the seek, the element acquires
the STREAM_LOCK so that the streaming thread and the seek gets serialized.
The general flow of executing the seek with FLUSH is as follows:
1) unblock the streaming threads, they could be blocked in a chain
function. This is done by sending a flush on all srcpads.
The flush will make sure that all downstream elements unlock and
that control will return to this element chain/loop function.
We cannot lock the STREAM_LOCK before doing this since it might
cause a deadlock.
2) lock the STREAM_LOCK. This will work since the chain/loop function
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. 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) 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.
More information about the different seek types can be found in
part-seeking.txt.
SIZE
----
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 for a prefered buffer size.
RATE
----
When the application wants to change the playback rate of the stream, it
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. 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 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. A tag is serialized with buffers.