Commit 3fe230ab authored by Wim Taymans's avatar Wim Taymans
Browse files

This is the one..

Original commit message from CVS:
This is the one..
parent 6bed828c
some random ramblings about the event system:
This is a round up from our IRC session on events. It's open for
discussion of course.
Possible candidates for events
------------------------------
Definition
----------
- QoS
- EOS
- Seek
- caps nego??
- bufferpool get??
- ...
The event system is designed to be a mechanism for _inter_plugin_
communication. Their scope is therefore limited in a way that they do
not serve as a way to communicate between plugins and the app (signals
and properties are still used for plugin-app communication).
Assumptions for events
----------------------
Events will be generated by either a plugin or the app. It should be
possible for a plugin to generate an event on one of its pads and it
should be possible for an app to insert an event on an abitrary pad
in the pipeline.
- They are tied to a pad.
- get rid of gst_pad_set_*_function (except for the chain/get ones)
- occur async to dataflow. (need locking?)
- fixed set of events only for core features. (elements cannot abuse
events for doing dataflow)
Questions
---------
Event handling
--------------
Events can both travel upstream or downstream. Some events, by nature, only
travel in one direction.
* downstream events
- Travel in the same way buffers do. This includes that they are handled
by the scheduler. The rationale is that the events should be kept as close
to the buffers are possible.
- plugins should check the type of the GstData passed in the _chain or _loop
function and act appropriatly. This can be done by either doing their own
stuff or by calling the default handler.
- are handled on the sink pad.
* upstream events
limit the valid directions an event can travel in? ie. Can EOS only
travel downstream (left to right)?
- are handled with an event handler attached to the srcpad. A default handler
will be implemented for pads that don't implement their own handler.
eg. Seek travels upstream, but it makes sense to also make it travel
downstream (the case of a disksink, where we overwrite the header)
- travel as fast as possible. the rationale is that a seek event should get to
the src element ASAP.
Possible candidates for events
------------------------------
- QoS
quality of service. Plugins can notify other plugins about the quality
of the pipeline. A video element can for example say that it receives
too much frames and that plugins connected to it need to slow down.
- EOS
A plugin can notify other plugins that it has run out-of-data.
- Seek
Used to notify plugins that they need to seek to a certain byte offset
or timestamp.
- discontinuous
A plugin has detected a discontinuity in the stream. Other plugins might
need to resync.
Setting an event function
-------------------------
- flush
Plugins need to get rid of any buffered data ASAP.
- caps nego??
- bufferpool get??
- ...
void gst_pad_set_event_function (GstPad *pad, gint event_mask,
GstEventFunction *function);
application generated events
----------------------------
event masks:
The application can insert events into the pipeline at arbirary places. This
will be done by calling gst_pad_event() on a pad.
typedef enum {
GST_EVENT_EOS = (1 << 0),
GST_EVENT_QOS = (1 << 1),
GST_EVENT_SEEK = (1 << 2),
GST_EVENT_CAPS = (1 << 3),
} GstEventType;
A first implementation will only cover inserting events on src pads since
inserting events on sinkpads needs changes to the scheduler.
Event structure
---------------
typedef struct {
GstEventType type;
GstEventMinorType minor;
guint64 timestamp; /* also sequence number ?? */
Effects of events on plugins
----------------------------
union {
/* EOS stuff */
/* QoS stuff */
/* Seek stuff */
GstSeekType type; /* time, bytes, ... */
gint64 offset;
gint64 lenth;
/* Caps stuff */
GstCaps *caps;
} data;
} GstEvent;
some events are going to change the state of an element. The EOS event will
for example change the state of an element to the PAUSED state. Not sure when
or how this will happen.
typedef enum {
GST_EVENT_MINOR_NONE,
/* EOS stuff */
use cases
---------
/* QoS stuff */
/* Seek stuff */
GST_EVENT_MINOR_OFFSET,
GST_EVENT_MINOR_TIME,
1) filesrc ! fakesink
/* caps nego stuff */
GST_EVENT_MINOR_CAPS_TRY,
GST_EVENT_MINOR_CAPS_START,
GST_EVENT_MINOR_CAPS_FINAL,
} GstEventMinorType;
filesrc will read until it reaches EOF. It will then create a GstEvent of type
EOS and return it in the _get function. The event will travel downstream and
will reach the fakesink element. Fakesink will detect the event in the _chain
function and will call the default handler. The default handler will set the
element to the paused state. filesrc will eventually change its state to PAUSED,
probably before sending out the event (TBD)
2) filesrc ! fakesink
Receiving events
----------------
The app wants to perform a seek on filesrc. It'll call the gst_pad_event() on
filesrcs src pad with the SEEK event type. The event handler will react and
change filesrcs internal status. filesrc will return a DISCONT event before
returning the buffer with the new offset.
a sample GstEventFunction, the event functions returns TRUE if the event is handled,
FALSE otherwise.
3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }
gboolean
gst_anelement_handle_event (GstPad *pad, GstEvent *event)
{
if (event->type == GST_EVENT_EOS) {
/* do something */
return TRUE;
}
else if (event->type == GST_EVENT_CAPS) {
if (event->minor == GST_EVENT_CAPS_TRY) {
/* try using this caps structure */
return TRUE; /* return FALSE to proxy ???*/
}
}
return FALSE;
}
lost of possibilities here: The app can choose to insert a seek event on the
filesrc element (byte offset), it can insert a byte/time offset seek on the
video_0 pad of mpeg2parse or it can insert a time seek event on mpeg2decs
src pad.
the event will travel upstream using the handlers and the intermediate elements
can convert the event from a time to a byte offset (possibly using GstTimeCache
to speed up things).
Default event handler for pads
------------------------------
Filesrc will get a byte seek event on its src pad and will proceed as in case 2.
gboolean
gst_pad_handle_event (GstPad *pad, GstEvent *event)
{
GstElement *element;
GList *pads;
GstPad *srcpad;
gboolean result = TRUE;
GstPadDirection dir = GST_PAD_DIRECTION (pad);
As can be seen from this example the app will generate an event in another
context than those of the plugins, so this will need proper locking.
g_return_val_if_fail (pad != NULL, FALSE);
g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
The app can also choose to insert a flush event on one of the src pads. The
plugins would clear their cached data and forward the event to their upstream
peer pad(s).
element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
4)...
/* send out the events to all pad with opposite direction */
pads = gst_element_get_pad_list(element);
while (pads) {
otherpad = GST_PAD(pads->data);
pads = g_list_next(pads);
Insert impossible case here..
if (gst_pad_get_direction(otherpad) != dir) {
result &= gst_pad_send_event (GST_REAL_PAD(otherpad), event);
}
}
/* result is combined result of all handlers? */
return result;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment