There are many different event types but only 2 ways they can travel across 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.
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 gst_pad_pull
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 downstream using
gst_pad_event_default
. Here is an example for both
loop and chain based elements.
/* 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; } ... }