In the previous section, we have talked about how elements (or pads)
that are assigned to drive the pipeline using their own task, have
random access over their sinkpads. This means that all elements linked
to those pads (recursively) need to provide random access functions.
Requesting random access is done using the function
gst_pad_pull_range ()
, which requests a buffer of
a specified size and offset. Source pads implementing and assigned to
do random access will have a _get_range ()
-function
set using gst_pad_set_getrange_function ()
, and
that function will be called when the peer pad requests some data. The
element is then responsible for seeking to the right offset and
providing the requested data. Several elements can implement random
access:
Data sources, such as a file source, that can provide data from any offset with reasonable low latency.
Filters that would like to provide a pull-based-like scheduling mode over the whole pipeline. Note that elements assigned to do random access-based scheduling are themselves responsible for assigning this scheduling mode to their upstream peers! GStreamer will not do that for you.
Parsers who can easily provide this by skipping a small part of their input and are thus essentially "forwarding" random access requests literally without any own processing involved. Examples include tag readers (e.g. ID3) or single output parsers, such as a WAVE parser.
The following example will show how a _get_range
()
-function can be implemented in a source element:
#include "filter.h" static GstFlowReturn gst_my_filter_get_range (GstPad * pad, guint64 offset, guint length, GstBuffer ** buf); GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement, GST_TYPE_ELEMENT); static void gst_my_filter_init (GstMyFilter * filter) { GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter); filter->srcpad = gst_pad_new_from_template ( gst_element_class_get_pad_template (klass, "src"), "src"); gst_pad_set_getrange_function (filter->srcpad, gst_my_filter_get_range); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); [..] } static gboolean gst_my_filter_get_range (GstPad * pad, guint64 offset, guint length, GstBuffer ** buf) { GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad)); [.. here, you would fill *buf ..] return GST_FLOW_OK; }
In practice, many elements that could theoretically do random access,
may in practice often be assigned to do push-based scheduling anyway,
since there is no downstream element able to start its own task.
Therefore, in practice, those elements should implement both a
_get_range ()
-function and a _chain
()
-function (for filters and parsers) or a _get_range
()
-function and be prepared to start their own task by
providing _activate_* ()
-functions (for
source elements), so that GStreamer can decide for the optimal
scheduling mode and have it just work fine in practice.