mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
a093da6d7d
Original commit message from CVS: 2004-01-29 Julien MOUTTE <julien@moutte.net> * docs/pwg/advanced-events.xml: Adding documentation on advanced event handling (up and downstream). * docs/pwg/advanced-interfaces.xml: Make it coherent with the my_filter thing.
154 lines
5.6 KiB
XML
154 lines
5.6 KiB
XML
<chapter id="chapter-advanced-events">
|
|
<title>Events: Seeking, Navigation and More</title>
|
|
<para>
|
|
There are many different event types but only 2 ways they can travel accross
|
|
the pipeline: downstream or upstream. It is very important to understand
|
|
how both of those methods work because if one element in the pipeline is not
|
|
handling them correctly the whole event system of the pipeline is broken.
|
|
We will try to explain here how these methods work and how elements are
|
|
supposed to implement them.
|
|
</para>
|
|
<sect1 id="section-events-downstream" xreflabel="Downstream events">
|
|
<title>Downstream events</title>
|
|
<para>
|
|
Downstream events are received through the sink pad's dataflow. Depending
|
|
if your element is loop or chain based you will receive events in your
|
|
loop/chain function as a GstData with <function>gst_pad_pull</function>
|
|
or directly in the function call arguments. So when receiving dataflow
|
|
from the sink pad you have to check first if this data chunk is an event.
|
|
If that's the case you check what kind of event it is to react on relevant
|
|
ones and then forward others dowstream using
|
|
<function>gst_pad_event_default</function>. Here is an example for both
|
|
loop and chain based elements.
|
|
</para>
|
|
<programlisting><![CDATA[
|
|
/* Chain based element */
|
|
static void
|
|
gst_my_filter_chain (GstPad *pad,
|
|
GstData *data)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
|
|
...
|
|
if (GST_IS_EVENT (data)) {
|
|
GstEvent *event = GST_EVENT (data);
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
case GST_EVENT_EOS:
|
|
/* end-of-stream, we should close down all stream leftovers here */
|
|
gst_my_filter_stop_processing (filter);
|
|
/* fall-through to default event handling */
|
|
default:
|
|
gst_pad_event_default (pad, event);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
...
|
|
}
|
|
|
|
/* Loop based element */
|
|
static void
|
|
gst_my_filter_loop (GstElement *element)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (element);
|
|
GstData *data = NULL;
|
|
|
|
data = gst_pad_pull (filter->sinkpad);
|
|
|
|
if (GST_IS_EVENT (data)) {
|
|
GstEvent *event = GST_EVENT (data);
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
case GST_EVENT_EOS:
|
|
/* end-of-stream, we should close down all stream leftovers here */
|
|
gst_my_filter_stop_processing (filter);
|
|
/* fall-through to default event handling */
|
|
default:
|
|
gst_pad_event_default (filter->sinkpad, event);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
...
|
|
}
|
|
]]></programlisting>
|
|
</sect1>
|
|
<sect1 id="section-events-upstream" xreflabel="Upstream events">
|
|
<title>Upstream events</title>
|
|
<para>
|
|
Upstream events are generated by an element somewhere in the pipeline and
|
|
sent using the <function>gst_pad_send_event</function> function. This
|
|
function simply realizes the pad and call the default event handler of that
|
|
pad. The default event handler of pads is <function>gst_pad_event_default</function>
|
|
, it basically sends the event to the peer pad. So upstream events always
|
|
arrive on the src pad of your element and are handled by the default event
|
|
handler except if you override that handler to handle it yourself. There
|
|
are some specific cases where you have to do that :
|
|
</para>
|
|
<itemizedlist mark="opencircle">
|
|
<listitem>
|
|
<para>
|
|
If you have multiple sink pads in your element. In that case you will
|
|
have to decide which one of the sink pads you will send the event to.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If you need to handle that event locally. For example a navigation
|
|
event that you will want to convert before sending it upstream.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
The processing you will do in that event handler does not really matter
|
|
but there are important rules you have to absolutely respect because
|
|
one broken element event handler is breaking the whole pipeline event
|
|
handling. Here they are :
|
|
</para>
|
|
<itemizedlist mark="opencircle">
|
|
<listitem>
|
|
<para>
|
|
Always forward events you won't handle upstream using the default
|
|
<function>gst_pad_event_default</function> method.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If you are generating some new event based on the one you received
|
|
don't forget to gst_event_unref the event you received.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Event handler function are supposed to return TRUE or FALSE indicating
|
|
if the event has been handled or not. Never simply return TRUE/FALSE
|
|
in that handler except if you really know that you have handled that
|
|
event.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
Here is an example of correct upstream event handling for a plugin
|
|
that wants to modify navigation events.
|
|
</para>
|
|
<programlisting><![CDATA[
|
|
static gboolean
|
|
gst_my_plugin_handle_src_event (GstPad *pad, GstEvent *event)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
case GST_EVENT_NAVIGATION:
|
|
GstEvent *new_event = gst_event_new (GST_EVENT_NAVIGATION);;
|
|
/* Create a new event based on received one and then send it */
|
|
...
|
|
gst_event_unref (event);
|
|
return gst_pad_event_default (pad, new_event);
|
|
default:
|
|
/* Falling back to default event handling for that pad */
|
|
return gst_pad_event_default (pad, event);
|
|
}
|
|
}
|
|
]]></programlisting>
|
|
</sect1>
|
|
</chapter>
|