mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 23:18:52 +00:00
This is the one..
Original commit message from CVS: This is the one..
This commit is contained in:
parent
6bed828c63
commit
3fe230abd0
1 changed files with 117 additions and 122 deletions
|
@ -1,140 +1,135 @@
|
||||||
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.
|
||||||
|
|
||||||
|
Definition
|
||||||
|
----------
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
- travel as fast as possible. the rationale is that a seek event should get to
|
||||||
|
the src element ASAP.
|
||||||
|
|
||||||
|
|
||||||
Possible candidates for events
|
Possible candidates for events
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
- QoS
|
- 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
|
- EOS
|
||||||
|
A plugin can notify other plugins that it has run out-of-data.
|
||||||
|
|
||||||
- Seek
|
- 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.
|
||||||
|
|
||||||
|
- flush
|
||||||
|
Plugins need to get rid of any buffered data ASAP.
|
||||||
|
|
||||||
- caps nego??
|
- caps nego??
|
||||||
- bufferpool get??
|
- bufferpool get??
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
Assumptions for events
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
- They are tied to a pad.
|
application generated events
|
||||||
- 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
|
The application can insert events into the pipeline at arbirary places. This
|
||||||
|
will be done by calling gst_pad_event() on a pad.
|
||||||
|
|
||||||
|
A first implementation will only cover inserting events on src pads since
|
||||||
|
inserting events on sinkpads needs changes to the scheduler.
|
||||||
|
|
||||||
|
|
||||||
|
Effects of events on plugins
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
use cases
|
||||||
---------
|
---------
|
||||||
|
|
||||||
limit the valid directions an event can travel in? ie. Can EOS only
|
1) filesrc ! fakesink
|
||||||
travel downstream (left to right)?
|
|
||||||
|
|
||||||
eg. Seek travels upstream, but it makes sense to also make it travel
|
filesrc will read until it reaches EOF. It will then create a GstEvent of type
|
||||||
downstream (the case of a disksink, where we overwrite the header)
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
Filesrc will get a byte seek event on its src pad and will proceed as in case 2.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
4)...
|
||||||
|
|
||||||
|
Insert impossible case here..
|
||||||
|
|
||||||
|
|
||||||
Setting an event function
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
void gst_pad_set_event_function (GstPad *pad, gint event_mask,
|
|
||||||
GstEventFunction *function);
|
|
||||||
|
|
||||||
|
|
||||||
event masks:
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GST_EVENT_EOS = (1 << 0),
|
|
||||||
GST_EVENT_QOS = (1 << 1),
|
|
||||||
GST_EVENT_SEEK = (1 << 2),
|
|
||||||
GST_EVENT_CAPS = (1 << 3),
|
|
||||||
} GstEventType;
|
|
||||||
|
|
||||||
Event structure
|
|
||||||
---------------
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
GstEventType type;
|
|
||||||
GstEventMinorType minor;
|
|
||||||
guint64 timestamp; /* also sequence number ?? */
|
|
||||||
|
|
||||||
union {
|
|
||||||
/* EOS stuff */
|
|
||||||
/* QoS stuff */
|
|
||||||
/* Seek stuff */
|
|
||||||
GstSeekType type; /* time, bytes, ... */
|
|
||||||
gint64 offset;
|
|
||||||
gint64 lenth;
|
|
||||||
/* Caps stuff */
|
|
||||||
GstCaps *caps;
|
|
||||||
} data;
|
|
||||||
} GstEvent;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
GST_EVENT_MINOR_NONE,
|
|
||||||
/* EOS stuff */
|
|
||||||
|
|
||||||
/* QoS stuff */
|
|
||||||
/* Seek stuff */
|
|
||||||
GST_EVENT_MINOR_OFFSET,
|
|
||||||
GST_EVENT_MINOR_TIME,
|
|
||||||
|
|
||||||
/* caps nego stuff */
|
|
||||||
GST_EVENT_MINOR_CAPS_TRY,
|
|
||||||
GST_EVENT_MINOR_CAPS_START,
|
|
||||||
GST_EVENT_MINOR_CAPS_FINAL,
|
|
||||||
} GstEventMinorType;
|
|
||||||
|
|
||||||
|
|
||||||
Receiving events
|
|
||||||
----------------
|
|
||||||
|
|
||||||
a sample GstEventFunction, the event functions returns TRUE if the event is handled,
|
|
||||||
FALSE otherwise.
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Default event handler for pads
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
gst_pad_handle_event (GstPad *pad, GstEvent *event)
|
|
||||||
{
|
|
||||||
GstElement *element;
|
|
||||||
GList *pads;
|
|
||||||
GstPad *srcpad;
|
|
||||||
gboolean result = TRUE;
|
|
||||||
GstPadDirection dir = GST_PAD_DIRECTION (pad);
|
|
||||||
|
|
||||||
g_return_val_if_fail (pad != NULL, FALSE);
|
|
||||||
g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
|
|
||||||
|
|
||||||
element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue