Chapter 17. Events: Seeking, Navigation and More

Table of Contents

Downstream events
Upstream events
All Events Together
Stream Start
Caps
Segment
Tag (metadata)
End of Stream (EOS)
Table Of Contents
Gap
Flush Start
Flush Stop
Quality Of Service (QOS)
Seek Request
Navigation

There are many different event types but only two ways they can travel in the pipeline: downstream or upstream. It is very important to understand how both of these 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

Downstream events are received through the sink pad's event handler, as set using gst_pad_set_event_function () when the pad was created.

Downstream events can travel in two ways: they can be in-band (serialised with the buffer flow) or out-of-band (travelling through the pipeline instantly, possibly not in the same thread as the streaming thread that is processing the buffers, skipping ahead of buffers being processed or queued in the pipeline). The most common downstream events (SEGMENT, CAPS, TAG, EOS) are all serialised with the buffer flow.

Here is a typical event function:

static gboolean
gst_my_filter_sink_event (GstPad  *pad, GstObject * parent, GstEvent * event)
{
  GstMyFilter *filter;
  gboolean ret;

  filter = GST_MY_FILTER (parent);
  ...

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEGMENT:
      /* maybe save and/or update the current segment (e.g. for output
       * clipping) or convert the event into one in a different format
       * (e.g. BYTES to TIME) or drop it and set a flag to send a segment
       * event in a different format later */
      ret = gst_pad_push_event (filter->src_pad, event);
      break;
    case GST_EVENT_EOS:
      /* end-of-stream, we should close down all stream leftovers here */
      gst_my_filter_stop_processing (filter);
      ret = gst_pad_push_event (filter->src_pad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      gst_my_filter_clear_temporary_buffers (filter);
      ret = gst_pad_push_event (filter->src_pad, event);
      break;      
    default:
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }

  ...
  return ret;
}
    

If your element is chain-based, you will almost always have to implement a sink event function, since that is how you are notified about segments, caps and the end of the stream.

If your element is exclusively loop-based, you may or may not want a sink event function (since the element is driving the pipeline it will know the length of the stream in advance or be notified by the flow return value of gst_pad_pull_range(). In some cases even loop-based element may receive events from upstream though (for example audio decoders with an id3demux or apedemux element in front of them, or demuxers that are being fed input from sources that send additional information about the stream in custom events, as DVD sources do).