|  | 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? |