mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
158 lines
4.8 KiB
XML
158 lines
4.8 KiB
XML
|
|
<!-- ############ chapter ############# -->
|
|
|
|
<chapter id="chapter-building-chainfn">
|
|
<title>The chain function</title>
|
|
<para>
|
|
The chain function is the function in which all data processing takes
|
|
place. In the case of a simple filter, <function>_chain ()</function>
|
|
functions are mostly linear functions - so for each incoming buffer,
|
|
one buffer will go out, too. Below is a very simple implementation of
|
|
a chain function:
|
|
</para>
|
|
<programlisting><!-- example-begin chain.c a --><!--
|
|
#include "init.func"
|
|
#include "caps.func"
|
|
static gboolean
|
|
gst_my_filter_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|
{
|
|
return gst_pad_event_default (pad, parent, event);
|
|
}
|
|
--><!-- example-end chain.c a -->
|
|
<!-- example-begin chain.c b -->
|
|
static GstFlowReturn gst_my_filter_chain (GstPad *pad,
|
|
GstObject *parent,
|
|
GstBuffer *buf);
|
|
|
|
[..]
|
|
|
|
static void
|
|
gst_my_filter_init (GstMyFilter * filter)
|
|
{
|
|
[..]
|
|
/* configure chain function on the pad before adding
|
|
* the pad to the element */
|
|
gst_pad_set_chain_function (filter->sinkpad,
|
|
gst_my_filter_chain);
|
|
[..]
|
|
}
|
|
|
|
static GstFlowReturn
|
|
gst_my_filter_chain (GstPad *pad,
|
|
GstObject *parent,
|
|
GstBuffer *buf)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (parent);
|
|
|
|
if (!filter->silent)
|
|
g_print ("Have data of size %" G_GSIZE_FORMAT" bytes!\n",
|
|
gst_buffer_get_size (buf));
|
|
|
|
return gst_pad_push (filter->srcpad, buf);
|
|
}
|
|
<!-- example-end chain.c b -->
|
|
<!-- example-begin chain.c c --><!--
|
|
static GstStateChangeReturn
|
|
gst_my_filter_change_state (GstElement * element, GstStateChange transition)
|
|
{
|
|
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS,
|
|
change_state, (element, transition), GST_STATE_CHANGE_SUCCESS);
|
|
}
|
|
#include "register.func"
|
|
--><!-- example-end chain.c c --></programlisting>
|
|
<para>
|
|
Obviously, the above doesn't do much useful. Instead of printing that the
|
|
data is in, you would normally process the data there. Remember, however,
|
|
that buffers are not always writeable.
|
|
</para>
|
|
<para>
|
|
In more advanced elements (the ones that do event processing), you may want
|
|
to additionally specify an event handling function, which will be called
|
|
when stream-events are sent (such as caps, end-of-stream, newsegment, tags, etc.).
|
|
</para>
|
|
<programlisting>
|
|
static void
|
|
gst_my_filter_init (GstMyFilter * filter)
|
|
{
|
|
[..]
|
|
gst_pad_set_event_function (filter->sinkpad,
|
|
gst_my_filter_sink_event);
|
|
[..]
|
|
}
|
|
<!-- example-begin chain2.c a --><!--
|
|
#include "init.func"
|
|
#include "caps.func"
|
|
#include "chain.func"
|
|
--><!-- example-end chain2.c a -->
|
|
<!-- example-begin chain.func a --><!--
|
|
static void
|
|
gst_my_filter_stop_processing (GstMyFilter * filter)
|
|
{
|
|
}
|
|
|
|
static GstBuffer *
|
|
gst_my_filter_process_data (GstMyFilter * filter, const GstBuffer * buf)
|
|
{
|
|
return NULL;
|
|
}
|
|
--><!-- example-end chain.func a -->
|
|
<!-- example-begin chain.func b -->
|
|
static gboolean
|
|
gst_my_filter_sink_event (GstPad *pad,
|
|
GstObject *parent,
|
|
GstEvent *event)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (parent);
|
|
|
|
switch (GST_EVENT_TYPE (event)) {
|
|
case GST_EVENT_CAPS:
|
|
/* we should handle the format here */
|
|
break;
|
|
case GST_EVENT_EOS:
|
|
/* end-of-stream, we should close down all stream leftovers here */
|
|
gst_my_filter_stop_processing (filter);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return gst_pad_event_default (pad, parent, event);
|
|
}
|
|
|
|
static GstFlowReturn
|
|
gst_my_filter_chain (GstPad *pad,
|
|
GstObject *parent,
|
|
GstBuffer *buf)
|
|
{
|
|
GstMyFilter *filter = GST_MY_FILTER (parent);
|
|
GstBuffer *outbuf;
|
|
|
|
outbuf = gst_my_filter_process_data (filter, buf);
|
|
gst_buffer_unref (buf);
|
|
if (!outbuf) {
|
|
/* something went wrong - signal an error */
|
|
GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL));
|
|
return GST_FLOW_ERROR;
|
|
}
|
|
|
|
return gst_pad_push (filter->srcpad, outbuf);
|
|
}
|
|
<!-- example-end chain.func b -->
|
|
<!-- example-begin chain2.c b --><!--
|
|
static GstStateChangeReturn
|
|
gst_my_filter_change_state (GstElement * element, GstStateChange transition)
|
|
{
|
|
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS,
|
|
change_state, (element, transition), GST_STATE_CHANGE_SUCCESS);
|
|
}
|
|
#include "register.func"
|
|
--><!-- example-end chain2.c b --></programlisting>
|
|
<para>
|
|
In some cases, it might be useful for an element to have control over the
|
|
input data rate, too. In that case, you probably want to write a so-called
|
|
<emphasis>loop-based</emphasis> element. Source elements (with only source
|
|
pads) can also be <emphasis>get-based</emphasis> elements. These concepts
|
|
will be explained in the advanced section of this guide, and in the section
|
|
that specifically discusses source pads.
|
|
</para>
|
|
</chapter>
|