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