| EARLY DOCUMENT, NOT EXACTLY AS IMPLEMENTED |
| ------------------------------------------ |
| |
| 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 ! filesink |
| |
| 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 filesink. |
| - After that it issues a DISCONTINUOUS event of the type DISCONT_NEW indicating a new stream. |
| The filesink 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 application 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 filesink 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? |