mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
added event proposal - probably a bit long, you may shorten it, if you can.
Original commit message from CVS: added event proposal - probably a bit long, you may shorten it, if you can.
This commit is contained in:
parent
7fe00b9485
commit
08faf88f0d
1 changed files with 327 additions and 0 deletions
327
docs/random/events
Normal file
327
docs/random/events
Normal file
|
@ -0,0 +1,327 @@
|
|||
EVENTS RFC
|
||||
==========
|
||||
|
||||
|
||||
Scope
|
||||
-----
|
||||
This document tries to describe a possible implementation of an event
|
||||
system for GStreamer that is able to handle all known problems and works
|
||||
better than the current (0.3.1) system which evolved over time.
|
||||
|
||||
|
||||
Definition
|
||||
----------
|
||||
|
||||
The event system is designed to be a mechanism for communication between
|
||||
elements. They are used to get information to the right point when this
|
||||
point cannot be known in advance.
|
||||
Events can be generated by either an element or the application and are
|
||||
processed by elements.
|
||||
|
||||
|
||||
Event Handling
|
||||
--------------
|
||||
|
||||
Events may be inserted into a pipeline in the PAUSED or PLAYING state. Some
|
||||
events may travel during the PAUSED state, others may only travel when PLAYING.
|
||||
The insertion of events during the NULL or READY state should be supported if
|
||||
at all possible. Events may not be processed in those states though.
|
||||
After an event is inserted into the pipeline, no assumption may be made on how
|
||||
the event will be processed. It is eg wrong to assume that an event that is
|
||||
inserted at the beginning of the pipeline may come out at the end.
|
||||
There are 3 different directions an event can be processed.
|
||||
|
||||
* downstream events
|
||||
|
||||
Downstream events are inserted on source pads and travel along the pipeline.
|
||||
They are handled like buffers and processed in order. If event x is inserted
|
||||
into a pipeline after buffer y, they are guaranteed to travel in that order.
|
||||
Downstream events therefore only travel when the pipeline is PLAYING.
|
||||
Downstream events must be handled by the routines that handle buffers, too.
|
||||
An example downstream event is the event signalling that the stream has ended.
|
||||
Please keep in mind that downstream events take the same way as buffers. So a
|
||||
ghost pad will never receive these events.
|
||||
|
||||
* upstream events
|
||||
|
||||
Upstream events are inserted on sink pads and travel backwards through the
|
||||
pipeline. They travel as fast as possible. Source pads must have a handler
|
||||
function in place to process events. A default handler is implemented.
|
||||
An example upstream event is an event that seeks inside the stream.
|
||||
Please keep in mind that upstream events take the same way as buffers in reverse
|
||||
direction. This means that ghost pads will never receive them.
|
||||
|
||||
* vertical events
|
||||
|
||||
Vertical events travel from elements to their parents. They are targetted at
|
||||
the application. Vertical events should be used for information that an
|
||||
application cannot receive in an easy way by using callbacks or properties.
|
||||
Vertical events are send to the application by the pipeline that collects those
|
||||
events and supplies a callback for the application. Vertical events are also only
|
||||
happening when the pipeline is in PAUSED or PLAZING state.
|
||||
An example vertical event is the error event informing the application about
|
||||
unexpected behaviour.
|
||||
|
||||
|
||||
The GstEvent object
|
||||
-------------------
|
||||
|
||||
struct _GstEvent {
|
||||
GstData data;
|
||||
|
||||
GstEventType type;
|
||||
guint64 timestamp;
|
||||
GstObject *src;
|
||||
|
||||
union {
|
||||
...
|
||||
} event_data;
|
||||
};
|
||||
|
||||
data: The parent object.
|
||||
type: The type of the event. GStreamer aims to keep the number of different
|
||||
plugin types as small as possible.
|
||||
timestamp: The time when the event was created. This property is used to identify
|
||||
duplicated events. If the application inserts an event, the timestamp
|
||||
is set by the element receiving the event from the application.
|
||||
src: The element that created the event. If an application inserts an event,
|
||||
the element that received the event from the application sets itself as
|
||||
the source.
|
||||
event_data: data specific to the event type.
|
||||
|
||||
|
||||
The different event types
|
||||
-------------------------
|
||||
|
||||
The following names in brackets correspong to the event's type property.
|
||||
|
||||
GST_EVENT_DISCONTINUOUS
|
||||
direction(s): downstream
|
||||
event_data: struct {
|
||||
GstDiscontType type;
|
||||
} discontinuous;
|
||||
This event is used to indicate that the current stream does not continue. Possible
|
||||
indications are a new stream (type = GST_DISCONT_NEW), the happening of a seek
|
||||
(type = GST_DISCONT_SEEK) or the end of the stream when no more data is available.
|
||||
(type = GST_DISCONT_EOS)
|
||||
|
||||
GST_EVENT_SEEK
|
||||
direction(s): upstream
|
||||
event_data: struct {
|
||||
GstSeekType type;
|
||||
gint64 offset;
|
||||
gboolean flush;
|
||||
} seek;
|
||||
This event is used if a seek is needed. Uses include applications or the avi demuxer
|
||||
element requesting the end of the stream first. The seek can happen absolute (SET),
|
||||
relative to the current position (CUR) or relative to the end (END). It is possible
|
||||
to seek by frames (FRAME), time in microseconds (TIME) or bytes (BYTE). This is
|
||||
indicated by the type field, which takes the values
|
||||
GST_SEEK_FRAME/TIME/BYTEOFFSET_SET/CUR/END. The offset field indicates how many units
|
||||
should be seeked. Negative values indicate seeking backwards from the indicated position.
|
||||
The flush field indicates if buffered data shuold be flushed or discarded.
|
||||
|
||||
GST_EVENT_FLUSH
|
||||
direction(s): upstream
|
||||
event_data: none
|
||||
This event indicates that all buffered data should be flushed out immediately.
|
||||
|
||||
GST_EVENT_INFO
|
||||
direction(s): downstream, vertical
|
||||
event_data: struct {
|
||||
GstProps *props;
|
||||
} info;
|
||||
The Info event is used to transport meta information like bitrate, author, title,
|
||||
interpret or stream length. Most info events will be emitted vertical and downstream
|
||||
at the same time. Vertical emission ensures that an application knows about those
|
||||
properties and downstream emission ensures that elements can compute own information
|
||||
from these infos. (eg converting stream length in bytes to song length in
|
||||
microseconds).
|
||||
Props consist of key / value pairs, where the key is a string identifier and the value
|
||||
is a GstPropEntry. Many key strings are predefined to allow consistency between elements.
|
||||
Elements should try to suppy any information they can as soon as possible.
|
||||
|
||||
GST_EVENT_HAS_INFO
|
||||
direction(s): upstream
|
||||
void (*GstHasInfoCallback) (gchar *name, GstPropsEntry *info, gpointer data);
|
||||
event_data: struct {
|
||||
GList *info;
|
||||
GstHasInfoCallback callback;
|
||||
gpointer data;
|
||||
} has_info;
|
||||
The has_info event might be inserted by an application to find out if a pipeline can supply
|
||||
the specified infos. the info list contains all information that the application is
|
||||
interested in. If an element can supply information it calls the supplied callback with the
|
||||
name of the information it can supply, the information if it is already available or NULL and
|
||||
the data. If this event is destroyed, it will call the callback with name = NULL to indicate
|
||||
that no more data will be received.
|
||||
This event will for example be used by playlists when they generate information.
|
||||
|
||||
GST_EVENT_ERROR
|
||||
direction(s): vertical
|
||||
event_data: struct {
|
||||
gchar *message
|
||||
} error;
|
||||
An error event is emitted, whenever a recoverable error occurs that the application
|
||||
should know about. The usage should be similar to GLibs GError. An example would be
|
||||
"connection closed" for a host to host plugin.
|
||||
|
||||
|
||||
Reference Counting
|
||||
------------------
|
||||
|
||||
References to events are handled similar to buffers. An element receives an event with
|
||||
a single reference. If it forwards the event, this reference is lost.
|
||||
Events own a reference to the element that created them. They take care of all of all
|
||||
data inside them too (strings, props). So elements and applications that want to keep
|
||||
this informations need to copy or add a reference them.
|
||||
|
||||
|
||||
Changing Events
|
||||
---------------
|
||||
It is not allowed to change any data inside an event. Changing events can only be
|
||||
accomplished by removing the reference to them and not forwarding the event and then
|
||||
creating a new one.
|
||||
|
||||
|
||||
Default Behaviour
|
||||
-----------------
|
||||
|
||||
* downstream events
|
||||
|
||||
These are not handled by default, because they must be handled by the chain handler
|
||||
of the sink pad. There is however a function called gst_pad_event_default(GstPad *,
|
||||
GstData *) that will take care of events if your code doesn't want to handle them.
|
||||
But your code must be aware that not everything that your chain function receives
|
||||
is a buffer. It could be an event.
|
||||
|
||||
* upstream events
|
||||
|
||||
Upstream events are handled by a default handler function that is inserted on sink
|
||||
pads when they are created. This function simply forwards the event to all connected
|
||||
sink pads of the element. You are free to change this handler.
|
||||
|
||||
* vertical events
|
||||
|
||||
Vertical events can not be received by elements. Bins have a default handler function
|
||||
that simply forwards the event to their parent. Pipelines offer callbacks for events.
|
||||
You may change this handler for your custom bins.
|
||||
|
||||
|
||||
Use Cases
|
||||
---------
|
||||
|
||||
Following are some simple use cases describing how events are generated. The pipeline
|
||||
decriptions use gst-launch syntax. "..." indicates that something follows there but is
|
||||
not important for the example.
|
||||
|
||||
* filesrc ! fakesink
|
||||
|
||||
- When starting the pipeline, filesrc will emit a DISCONTINUOUS event of type NEW
|
||||
indicating a new stream.
|
||||
- Following that event will be an INFO event containing the length of the file/stream
|
||||
in bytes.
|
||||
- After the file was played, the filesrc emits a "DISCONTINUOUS" of type EOS.
|
||||
|
||||
* filesrc ! mad ! ...
|
||||
|
||||
- When starting, filesrc emits a DISCONTINUOUS event followed by an INFO event (see above).
|
||||
The mad plugin remembers the length of the file and removes the INFO element as it
|
||||
is no longer of use. The DISCONTINUOUS event has passed mad after making sure, that all
|
||||
buffers are cleared.
|
||||
- Mad will emit a SEEK event to BYTEOFFSET_END; offset = -sizeof(ID3_info) to read out the ID3
|
||||
information.
|
||||
- Filesrc emits a DISCONTINUOUS event of type SEEK to indicate that it seeked to the end.
|
||||
This event will not be passed on by mad.
|
||||
- after receiving the ID 3 information, mad will issue an INFO event containing all data
|
||||
it extracted. This event will probably only be passed vertical as ID3 information is of
|
||||
no use to other elements.
|
||||
- mad then ISSUES a SEEK event of type BYTEOFFSET_SET; offset = 0 to make the filesrc start
|
||||
playing the file.
|
||||
- The filesrc will reset its offset and issue a DISCONTINUOUS event of type SEEK. This event
|
||||
will not be forwarded by mad.
|
||||
- When playing starts, mad is able to compute bitrate and other information including playing
|
||||
time with the help of the previous length information supplied by the filesrc. It will then
|
||||
issue another INFO event with that informations. This one will be send downstream and vertical.
|
||||
|
||||
* ... ! avimux ! disksink
|
||||
|
||||
This example is showing a more exotic way of using events. The reader should be aware that AVI
|
||||
files have a limited filesize. Only 4 GB are allowed. We now show what happens when the avimux
|
||||
encoder hits that limit.
|
||||
- When the internal counter of avimux shows that it is approaching the filesize limit, the
|
||||
avimux element pushes a buffer containig the footer to the disksink.
|
||||
- After that it issues a DISCONTINUOUS event of the type DISCONT_NEW indicating a new stream.
|
||||
The disksink will close the file and reopen a new one.
|
||||
- The avimux plugin resets its internal size counter and restarts sending data to the new file.
|
||||
|
||||
* filesrc ! gunzip ! mikmod ! osssink
|
||||
|
||||
(please note that this example is purely theoretical. It should just show ideas)
|
||||
During playback, an application is interested in "interpret", "title", "length_time",
|
||||
"length_size" and "URI" of the current stream.
|
||||
- The appplication creates a HAS_INFO event and inserts it at the end of the pipeline into the
|
||||
osssink.
|
||||
- The osssink cannot supply any info so it forwards the event to the mikmod element.
|
||||
- The mikmod element can supply "title" and "length_time". It calls the supplied callback twice
|
||||
and gives these two options. It forwards the event to the gunzip element.
|
||||
- The gunzip element has already decoded the whole data so it knows the size of the stream. It
|
||||
calls the callback for "length_size" and forwards the event.
|
||||
- The filesrc supplies the "URI" and the "length_size" for a second time. It is now up to the
|
||||
application's callback function to handle this second occurence of "length_size" information.
|
||||
The filesrc does not forward the event and dereferences it.
|
||||
- During disposal of the event, the callback function is called again with name=NULL. The
|
||||
application now knows that no "title" can be supplied.
|
||||
|
||||
|
||||
Open Questions
|
||||
--------------
|
||||
|
||||
Open questions are issues that should probably be solved by events but can not be solved
|
||||
currently.
|
||||
|
||||
* A disksink needs to be able to inform elements of a restricted file size. Simply closing
|
||||
the file and opening a new one might not work because elements might need to supply a
|
||||
footer. (eg avimux)
|
||||
|
||||
|
||||
|
||||
Issues / changes (to be deleted in final version)
|
||||
----------------
|
||||
|
||||
? Are the event directions distinct? Or is it possible that some type of event
|
||||
can travel eg upstream _and_ vertical?
|
||||
? How are upstream/vertical events supposed to be handled if they occur when
|
||||
the element is READY or NULL? Buffer the event? How many events should be
|
||||
buffered? Maybe a READY element is attached to a PLAYING/PAUSED one and
|
||||
constantly receiving events, no?
|
||||
! The EOS event was merged with the DISCONTINUOUS event.
|
||||
? Does the DISCONTINUOUS event need a "flush" option?
|
||||
? Should chain funcs be changed to expect GstData instead of GstBuffer?
|
||||
It's a little bit misleading if events can arrive there.
|
||||
! added information about timestamp.
|
||||
? Should timestamps of "follow up" events (eg conversion of seek) keep the
|
||||
timestamp?
|
||||
? src = NULL, when app inserts event?
|
||||
? How do elements handle events they cannot use? (eg filesrc getting timebased
|
||||
seek request)
|
||||
? Somebody fix the GST_EVENT_FLUSH part.
|
||||
? GValue or GstProps for INFO events? First requires to open up the props headers
|
||||
and writing some API to ease the retrieval of the elements, the second requires
|
||||
a rewrite of GST_EVENT_INFO.
|
||||
? GQuark/GValue possible in INFO events?
|
||||
! Merged INFO and PROPS event. They are nearly the same. Added documentation.
|
||||
? Need to work out the ERROR event.
|
||||
! changed prototype for gst_pad_event_default to accept buffers so the function checks
|
||||
if it is an event and not every chain handler has to.
|
||||
! added HAS_INFO event. An alternative to the callback function could be another vertical
|
||||
event.
|
||||
? Should HAS_INFO callback supply the element calling the function?
|
||||
? Use case one: start with discont event?
|
||||
? Do we need a state change event?
|
||||
? Should we make elements supply information as soon as possible or only upon HAS_INFO
|
||||
request?
|
||||
? should the second example be done with region requesting instead of events?
|
||||
? "location" or "URI"?
|
||||
? What about suggesting buffer sizes?
|
||||
? What about QoS?
|
Loading…
Reference in a new issue