--- /dev/null
+<chapter id="chapter-negotiation" xreflabel="Caps negotiation">
+ <title>Caps negotiation</title>
+ <para>
+ Caps negotiation is the process where elements configure themselves
+ and each other for streaming a particular media format over their pads.
+ Since different types of elements have different requirements for the
+ media formats they can negotiate to, it is important that this process
+ is generic and implements all those use cases correctly.
+ </para>
+ <para>
+ In this chapter, we will discuss downstream negotiation and upstream
+ negotiation from a pipeline perspective, implicating the responsibilities
+ of different types of elements in a pipeline, and we will introduce the
+ concept of <emphasis>fixed caps</emphasis>.
+ </para>
+
+ <sect1 id="section-nego-requirements" xreflabel="Caps negotiation use cases">
+ <title>Caps negotiation use cases</title>
+ <para>
+ Let's take the case of a file source, linked to a demuxer, linked to a
+ decoder, linked to a converter with a caps filter and finally an audio
+ output. When dataflow originally starts, the demuxer will parse the
+ file header (e.g. the Ogg headers), and notice that there is, for
+ example, a Vorbis stream in this Ogg file. Noticing that, it will
+ create an output pad for the Vorbis elementary stream and set a
+ Vorbis-caps on it. Lastly, it adds the pad. As of this point, the pad
+ is ready to be used to stream data, and so the Ogg demuxer is now done.
+ This pad is <emphasis>not</emphasis> re-negotiatable, since the type of
+ the data stream is embedded within the data.
+ </para>
+ <para>
+ The Vorbis decoder will decode the Vorbis headers and the Vorbis data
+ coming in on its sinkpad. Now, some decoders may be able to output in
+ multiple output formats, for example both 16-bit integer output and
+ floating-point output, whereas other decoders may be able to only decode
+ into one specific format, e.g. only floating-point (32-bit) audio. Those
+ two cases have consequences for how caps negotiation should be
+ implemented in this decoder element. In the one case, it is possible to
+ use fixed caps, and you're done. In the other case, however, you should
+ implement the possibility for <emphasis>renegotiation</emphasis> in this
+ element, which is the possibility for the data format to be changed to
+ another format at some point in the future. We will discuss how to do
+ this in one of the sections further on in this chapter.
+ </para>
+ <para>
+ The filter can be used by applications to force, for example, a specific
+ channel configuration (5.1/surround or 2.0/stereo), on the pipeline, so
+ that the user can enjoy sound coming from all its speakers. The audio
+ sink, in this example, is a standard ALSA output element (alsasink).
+ The converter element supports any-to-any, and the filter will make sure
+ that only a specifically wanted channel configuration streams through
+ this link (as provided by the user's channel configuration preference).
+ By changing this preference while the pipeline is running, some elements
+ will have to renegotiate <emphasis>while the pipeline is
+ running</emphasis>. This is done through upstream caps renegotiation.
+ That, too, will be discussed in detail in a section further below.
+ </para>
+ <para>
+ In order for caps negotiation on non-fixed links to work correctly,
+ pads can optionally implement a function that tells peer elements what
+ formats it supports and/or preferes. When upstream renegotiation is
+ triggered, this becomes important.
+ </para>
+ <para>
+ Downstream elements are notified of a newly set caps only when data
+ is actually passing their pad. This is because caps is attached to
+ buffers during dataflow. So when the vorbis decoder sets a caps on
+ its source pad (to configure the output format), the converter will
+ not yet be notified. Instead, the converter will only be notified
+ when the decoder pushes a buffer over its source pad to the converter.
+ Right before calling the chain-function in the converter, &GStreamer;
+ will check whether the format that was previously negotiated still
+ applies to this buffer. If not, it first calls the setcaps-function
+ of the converter to configure it for the new format. Only after that
+ will it call the chain function of the converter.
+ </para>
+ </sect1>
+
+ <sect1 id="section-nego-fixedcaps" xreflabel="Fixed caps">
+ <title>Fixed caps</title>
+ <para>
+ The simplest way in which to do caps negotiation is setting a fixed
+ caps on a pad. After a fixed caps has been set, the pad can not be
+ renegotiated from the outside. The only way to reconfigure the pad
+ is for the element owning the pad to set a new fixed caps on the pad.
+ Fixed caps is a setup property for pads, called when creating the pad:
+ </para>
+ <programlisting>
+[..]
+ pad = gst_pad_new_from_template (..);
+ gst_pad_use_fixed_caps (pad);
+[..]
+ </programlisting>
+ <para>
+ The fixed caps can then be set on the pad by calling
+ <function>gst_pad_set_caps ()</function>.
+ </para>
+ <programlisting>
+[..]
+ caps = gst_caps_new_simple ("audio/x-raw-float",
+ "width", G_TYPE_INT, 32,
+ "endianness", G_TYPE_INT, G_BYTE_ORDER,
+ "buffer-frames", G_TYPE_INT, <bytes-per-frame>,
+ "rate", G_TYPE_INT, <samplerate>,
+ "channels", G_TYPE_INT, <num-channels>, NULL);
+ if (!gst_pad_set_caps (pad, caps)) {
+ GST_ELEMENT_ERROR (element, CORE, NEGOTIATION, (NULL),
+ ("Some debug information here"));
+ return GST_FLOW_ERROR;
+ }
+[..]
+ </programlisting>
+ <para>
+ Elements that could implement fixed caps (on their source pads) are,
+ in general, all elements that are not renegotiatable. Examples include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A typefinder, since the type found is part of the actual data stream
+ and can thus not be re-negotiated.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Pretty much all demuxers, since the contained elementary data
+ streams are defined in the file headers, and thus not
+ renegotiatable.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Some decoders, where the format is embedded in the datastream
+ and not part of the peercaps <emphasis>and</emphasis> where the
+ decoder itself is not reconfigureable, too.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ All other elements that need to be configured for the format should
+ implement full caps negotiation, which will be explained in the next
+ few sections.
+ </para>
+ </sect1>
+
+ <sect1 id="section-nego-downstream" xreflabel="Downstream caps negotiation">
+ <title>Downstream caps negotiation</title>
+ <para>
+ Downstream negotiation takes place when a format needs to be set on a
+ source pad to configure the output format, but this element allows
+ renegotiation because its format is configured on the sinkpad caps,
+ or because it supports multiple formats. The requirements for doing
+ the actual negotiation differ slightly.
+ </para>
+
+ <sect2 id="section-nego-downstream-embed"
+ xreflabel="Negotiating caps embedded in input caps">
+ <title>Negotiating caps embedded in input caps</title>
+ <para>
+ Many elements, particularly effects and converters, will be able
+ to parse the format of the stream from their input caps, and decide
+ the output format right at that time already. When renegotiation
+ takes place, some may merely need to "forward" the renegotiation
+ backwards upstream (more on that later). For those elements, all
+ (downstream) caps negotiation can be done in something that we
+ call the <function>_setcaps ()</function> function. This function is
+ called when a buffer is pushed over a pad, but the format on this
+ buffer is not the same as the format that was previously negotiated
+ (or, similarly, no format was negotiated yet so far).
+ </para>
+ <para>
+ In the <function>_setcaps ()</function>-function, the element can
+ forward the caps to the next element and, if that pad accepts the
+ format too, the element can parse the relevant parameters from the
+ caps and configure itself internally. The caps passed to this function
+ is <emphasis>always</emphasis> a subset of the template caps, so
+ there's no need for extensive safety checking. The following example
+ should give a clear indication of how such a function can be
+ implemented:
+ </para>
+ <programlisting><!-- example-begin forwardcaps.c a --><!--
+#include "init.func"
+static GstCaps *
+gst_my_filter_getcaps (GstPad * pad)
+{
+ return NULL;
+}
+--><!-- example-end forwardcaps.c a -->
+<!-- example-begin forwardcaps.c b -->
+static gboolean
+gst_my_filter_setcaps (GstPad *pad,
+ GstCaps *caps)
+{
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
+ GstStructure *s;
+
+ /* forward-negotiate */
+ if (!gst_pad_set_caps (filter->srcpad, caps))
+ return FALSE;
+
+ /* negotiation succeeded, so now configure ourselves */
+ s = gst_caps_get_structure (caps, 0);
+ gst_structure_get_int (s, "rate", &filter->samplerate);
+ gst_structure_get_int (s, "channels", &filter->channels);
+
+ return TRUE;
+}
+<!-- example-end forwardcaps.c b -->
+<!-- example-begin forwardcaps.c c --><!--
+#include "chain.func"
+#include "state.func"
+#include "register.func"
+ --><!-- example-end forwardcaps.c c --></programlisting>
+ <para>
+ There may also be cases where the filter actually is able to
+ <emphasis>change</emphasis> the format of the stream. In those cases,
+ it will negotiate a new format. Obviously, the element should first
+ attempt to configure <quote>pass-through</quote>, which means that
+ it does not change the stream's format. However, if that fails,
+ then it should call <function>gst_pad_get_allowed_caps ()</function>
+ on its sourcepad to get a list of supported formats on the outputs,
+ and pick the first. The return value of that function is guaranteed
+ to be a subset of the template caps.
+ </para>
+ <para>
+ Let's look at the example of an element that can convert between
+ samplerates, so where input and output samplerate don't have to be
+ the same:
+ </para>
+ <programlisting><!-- example-begin convertcaps.c a --><!--
+#include "init.func"
+static GstCaps *
+gst_my_filter_getcaps (GstPad * pad)
+{
+ return NULL;
+}
+static GstBuffer *
+gst_my_filter_convert (GstMyFilter *filter, GstBuffer *in)
+{
+ return NULL;
+}
+static gboolean
+gst_my_filter_event (GstPad * pad, GstEvent * event)
+{
+ return gst_pad_event_default (pad, event);
+}
+--><!-- example-end convertcaps.c a -->
+<!-- example-begin convertcaps.c b -->
+static gboolean
+gst_my_filter_setcaps (GstPad *pad,
+ GstCaps *caps)
+{
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
+
+ if (gst_pad_set_caps (filter->sinkpad, caps)) {
+ filter->passthrough = TRUE;
+ } else {
+ GstCaps *othercaps, *newcaps;
+ GstStructure *s = gst_caps_get_structure (caps, 0), *others;
+
+ /* no passthrough, setup internal conversion */
+ gst_structure_get_int (s, "channels", &filter->channels);
+ othercaps = gst_pad_get_allowed_caps (filter->srcpad);
+ others = gst_caps_get_structure (othercaps, 0);
+ gst_structure_set (others,
+ "channels", G_TYPE_INT, filter->channels, NULL);
+
+ /* now, the samplerate value can optionally have multiple values, so
+ * we "fixate" it, which means that one fixed value is chosen */
+ newcaps = gst_caps_copy_nth (othercaps, 0);
+ gst_caps_unref (othercaps);
+ gst_pad_fixate_caps (filter->srcpad, newcaps);
+ if (!gst_pad_set_caps (filter->srcpad, newcaps))
+ return FALSE;
+
+ /* we are now set up, configure internally */
+ filter->passthrough = FALSE;
+ gst_structure_get_int (s, "rate", &filter->from_samplerate);
+ others = gst_caps_get_structure (newcaps, 0);
+ gst_structure_get_int (others, "rate", &filter->to_samplerate);
+ }
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_my_filter_chain (GstPad *pad,
+ GstBuffer *buf)
+{
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
+ GstBuffer *out;
+
+ /* push on if in passthrough mode */
+ if (filter->passthrough)
+ return gst_pad_push (filter->srcpad, buf);
+
+ /* convert, push */
+ out = gst_my_filter_convert (filter, buf);
+ gst_buffer_unref (buf);
+
+ return gst_pad_push (filter->srcpad, out);
+}
+<!-- example-end convertcaps.c b -->
+<!-- example-begin convertcaps.c c --><!--
+#include "state.func"
+#include "register.func"
+ --><!-- example-end convertcaps.c c --></programlisting>
+ </sect2>
+
+ <sect2 id="section-nego-downstream-parse"
+ xreflabel="Parsing and setting caps">
+ <title>Parsing and setting caps</title>
+ <para>
+ Other elements, such as certain types of decoders, will not be able
+ to parse the caps from their input, simply because the input format
+ does not contain the information required to know the output format
+ yet; rather, the data headers need to be parsed, too. In many cases,
+ fixed-caps will be enough, but in some cases, particularly in cases
+ where such decoders are renegotiatable, it is also possible to use
+ full caps negotiation.
+ </para>
+ <para>
+ Fortunately, the code required to do so is very similar to the last
+ code example in <xref linkend="section-nego-downstream-embed"/>, with
+ the difference being that the caps is selected in the <function>_chain
+ ()</function>-function rather than in the <function>_setcaps
+ ()</function>-function. The rest, as for getting all allowed caps from
+ the source pad, fixating and such, is all the same. Re-negotiation,
+ which will be handled in the next section, is very different for such
+ elements, though.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="section-nego-upstream" xreflabel="Upstream caps (re)negotiation">
+ <title>Upstream caps (re)negotiation</title>
+ <para>
+ Upstream negotiation's primary use is to renegotiate (part of) an
+ already-negotiated pipeline to a new format. Some practical examples
+ include to select a different video size because the size of the video
+ window changed, and the video output itself is not capable of rescaling,
+ or because the audio channel configuration changed.
+ </para>
+ <para>
+ Upstream caps renegotiation is done in the <function>gst_pad_alloc_buffer
+ ()</function>-function. The idea here is that an element requesting a
+ buffer from downstream, has to specify the type of that buffer. If
+ renegotiation is to take place, this type will no longer apply, and the
+ downstream element will set a new caps on the provided buffer. Next,
+ &GStreamer; will trigger renegotiation on the sourcepad of the element
+ before the function returns.
+ </para>
+ <para>
+ It is important to note here that different elements actually have
+ different responsibilities here:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Elements should implement a <quote>padalloc</quote>-function in
+ order to be able to change format on renegotiation. This is also
+ true for filters and converters.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Elements should allocate new buffers using
+ <function>gst_pad_alloc_buffer ()</function>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Elements that are renegotiatable should implement a
+ <quote>setcaps</quote>-function on their sourcepad as well.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Unfortunately, not all details here have been worked out yet, so this
+ documentation is incomplete. FIXME.
+ </para>
+ </sect1>
+
+ <sect1 id="section-nego-getcaps" xreflabel="Implementing a getcaps function">
+ <title>Implementing a getcaps function</title>
+ <para>
+ A <function>_getcaps ()</function>-function is called when a peer
+ element would like to know which formats this element supports, and
+ in what order of preference. The return value should be all formats
+ that this elements supports, taking into account limitations of peer
+ elements further downstream or upstream, sorted by order of preference,
+ highest preference first.
+ </para>
+ <para>
+ </para>
+ <programlisting><!-- example-begin getcaps.c a --><!--
+#include "init.func"
+--><!-- example-end getcaps.c a -->
+<!-- example-begin getcaps.c b -->
+static GstCaps *
+gst_my_filter_getcaps (GstPad *pad)
+{
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
+ GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
+ filter->srcpad;
+ GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad), *caps;
+ gint i;
+
+ /* We support *any* samplerate, indifferent from the samplerate
+ * supported by the linked elements on both sides. */
+ for (i = 0; i < gst_caps_get_size (othercaps); i++) {
+ GstStructure *structure = gst_caps_get_structure (othercaps, i);
+
+ gst_structure_remove_field (structure, "rate");
+ }
+ caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
+ gst_caps_unref (othercaps);
+
+ return caps;
+}
+<!-- example-end getcaps.c b -->
+<!-- example-begin getcaps.c c --><!--
+static gboolean
+gst_my_filter_setcaps (GstPad * pad, GstCaps * caps)
+{
+ return FALSE;
+}
+#include "chain.func"
+#include "state.func"
+#include "register.func"
+ --><!-- example-end getcaps.c c --></programlisting>
+ <para>
+ Using all the knowledge you've acquired by reading this chapter, you
+ should be able to write an element that does correct caps negotiation.
+ If in doubt, look at other elements of the same type in our CVS
+ repository to get an idea of how they do what you want to do.
+ </para>
+ </sect1>
+</chapter>
of your element, and that makes them a very important item in the process
of element creation. In the boilerplate code, we have seen how static pad
templates take care of registering pad templates with the element class.
- Here, we will see how to create actual elements, use <function>_link ()</function>
- and <function>_getcaps ()</function> functions to let other elements know
- their capabilities and how to register functions to let data flow through
- the element.
+ Here, we will see how to create actual elements, use a <function>_setcaps
+ ()</function>-functions to configure for a particular format and how to
+ register functions to let data flow through the element.
</para>
<para>
In the element <function>_init ()</function> function, you create the pad
from the pad template that has been registered with the element class in
the <function>_base_init ()</function> function. After creating the pad,
- you have to set a <function>_link ()</function> function pointer and a
- <function>_getcaps ()</function> function pointer. Optionally, you can
- set a <function>_chain ()</function> function pointer (on sink pads in
- filter and sink elements) through which data will come in to the element,
- or (on source pads in source elements) a <function>_get ()</function>
- function pointer through which data will be pulled from the element. After
- that, you have to register the pad with the element. This happens like
- this:
+ you have to set a <function>_setcaps ()</function> function pointer and
+ optionally a <function>_getcaps ()</function> function pointer. Also, you
+ have to set a <function>_chain ()</function> function pointer.
+ Alternatively, pads can also operate in looping mode, which mans that they
+ can pull data themselves. More on this topic later. After that, you have
+ to register the pad with the element. This happens like this:
</para>
<programlisting><!-- example-begin init.func a --><!--
#include "filter.h"
<!-- example-begin init.func b -->
static gboolean gst_my_filter_setcaps (GstPad *pad,
GstCaps *caps);
-static GstCaps * gst_my_filter_getcaps (GstPad *pad);
static GstFlowReturn gst_my_filter_chain (GstPad *pad,
GstBuffer *buf);
<!-- example-end init.func b -->
<!-- example-begin init.func c --><!--
+static GstCaps * gst_my_filter_getcaps (GstPad *pad);
static gboolean gst_my_filter_event (GstPad *pad,
GstEvent *event);
--><!-- example-end init.func c -->
filter->sinkpad = gst_pad_new_from_template (
gst_element_class_get_pad_template (klass, "sink"), "sink");
gst_pad_set_setcaps_function (filter->sinkpad, gst_my_filter_setcaps);
- gst_pad_set_getcaps_function (filter->sinkpad, gst_my_filter_getcaps);
gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain);
<!-- example-end init.func d -->
<!-- example-begin init.func e --><!--
+ gst_pad_set_getcaps_function (filter->sinkpad, gst_my_filter_getcaps);
gst_pad_set_event_function (filter->sinkpad, gst_my_filter_event);
--><!-- example-end init.func e -->
<!-- example-begin init.func f -->
/* pad through which data goes out of the element */
filter->srcpad = gst_pad_new_from_template (
gst_element_class_get_pad_template (klass, "src"), "src");
- gst_pad_set_setcaps_function (filter->srcpad, gst_my_filter_setcaps);
+<!-- example-end init.func f -->
+<!-- example-begin init.func g --><!--
gst_pad_set_getcaps_function (filter->srcpad, gst_my_filter_getcaps);
+--><!-- example-end init.func g -->
+<!-- example-begin init.func h -->
gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
/* properties initial value */
filter->silent = FALSE;
}
- <!-- example-end init.func f --></programlisting>
+ <!-- example-end init.func h --></programlisting>
<sect1 id="section-pads-linkfn" xreflabel="The link function">
- <title>The link function</title>
+ <title>The setcaps-function</title>
<para>
- The <function>_link ()</function> is called during caps negotiation. This
- is the process where the linked pads decide on the streamtype that will
- transfer between them. A full list of type-definitions can be found in
- <xref linkend="chapter-building-types"/>. A <function>_link ()</function>
+ The <function>_setcaps ()</function>-function is called during caps
+ negotiation, which is discussed in great detail in <xref
+ linkend="chapter-negotiation"/>. This is the process where the linked
+ pads decide on the streamtype that will transfer between them. A full
+ list of type-definitions can be found in <xref
+ linkend="chapter-building-types"/>. A <function>_link ()</function>
receives a pointer to a <ulink type="http"
- url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps</classname>
- </ulink> struct that defines the proposed streamtype, and can respond with
- either <quote>yes</quote> (<symbol>GST_PAD_LINK_OK</symbol>),
- <quote>no</quote> (<symbol>GST_PAD_LINK_REFUSED</symbol>) or
- <quote>don't know yet</quote> (<symbol>GST_PAD_LINK_DELAYED</symbol>).
- If the element responds positively towards the streamtype, that type
- will be used on the pad. An example:
+ url="../../gstreamer/html/gstreamer-GstCaps.html"><classname>GstCaps</classname></ulink>
+ struct that defines the proposed streamtype, and can respond with
+ either <quote>yes</quote> (<symbol>TRUE</symbol>) or <quote>no</quote>
+ (<symbol>FALSE</symbol>). If the element responds positively towards
+ the streamtype, that type will be used on the pad. An example:
</para>
<programlisting><!-- example-begin caps.func a -->
static gboolean
GstCaps *caps)
{
GstStructure *structure = gst_caps_get_structure (caps, 0);
- GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
- GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
- filter->srcpad;
- GstPadLinkReturn ret;
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
const gchar *mime;
/* Since we're an audio filter, we want to handle raw audio
/* we're a filter and don't touch the properties of the data.
* That means we can set the given caps unmodified on the next
* element, and use that negotiation return value as ours. */
- ret = gst_pad_set_caps (otherpad, gst_caps_copy (caps));
- if (GST_PAD_LINK_FAILED (ret))
- return ret;
+ if (!gst_pad_set_caps (filter->srcpad, caps))
+ return FALSE;
/* Capsnego succeeded, get the stream properties for internal
* usage and return success. */
g_print ("Caps negotiation succeeded with %d Hz @ %d channels\n",
filter->samplerate, filter->channels);
- return ret;
+ return TRUE;
+}
+<!-- example-end caps.func a -->
+<!-- example-begin caps.func b --><!--
+static GstCaps *
+gst_my_filter_getcaps (GstPad * pad)
+{
+ GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad));
+ GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
+ filter->srcpad;
+ GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad);
+
+ return othercaps;
}
- <!-- example-end caps.func a --></programlisting>
+ --><!-- example-end caps.func b --></programlisting>
<para>
In here, we check the mimetype of the provided caps. Normally, you don't
need to do that in your own plugin/element, because the core does that
<para>
If your <function>_link ()</function> function does not need to perform
any specific operation (i.e. it will only forward caps), you can set it
- to <function>gst_pad_proxy_link</function>. This is a link forwarding
+ to <function>gst_pad_proxy_link ()</function>. This is a link forwarding
function implementation provided by the core. It is useful for elements
such as <classname>identity</classname>.
</para>
</sect1>
-
- <sect1 id="section-pads-getcapsfn" xreflabel="The getcaps function">
- <title>The getcaps function</title>
- <para>
- The <function>_getcaps ()</function> function is used to request the list
- of supported formats and properties from the element. In some cases, this
- will be equal to the formats provided by the pad template, in which case
- this function can be omitted. In some cases, too, it will not depend on
- anything inside this element, but it will rather depend on the input from
- another element linked to this element's sink or source pads. In that case,
- you can use <function>gst_pad_proxy_getcaps</function> as implementation,
- it provides getcaps forwarding in the core. However, in many cases, the
- format supported by this element cannot be defined externally, but is
- more specific than those provided by the pad template. In this case, you
- should use a <function>_getcaps ()</function> function. In the case as
- specified below, we assume that our filter is able to resample sound, so
- it would be able to provide any samplerate (indifferent from the samplerate
- specified on the other pad) on both pads. It explains how a
- <function>_getcaps ()</function> can be used to do this.
- </para>
- <programlisting><!-- example-begin caps.func b -->
-static GstCaps *
-gst_my_filter_getcaps (GstPad *pad)
-{
- GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad));
- GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad :
- filter->srcpad;
- GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad), *caps;
- gint i;
-
- if (gst_caps_is_empty (othercaps))
- return othercaps;
-
- /* We support *any* samplerate, indifferent from the samplerate
- * supported by the linked elements on both sides. */
- for (i = 0; i < gst_caps_get_size (othercaps); i++) {
- GstStructure *structure = gst_caps_get_structure (othercaps, i);
-
- gst_structure_remove_field (structure, "rate");
- }
- caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad));
- gst_caps_unref (othercaps);
-
- return caps;
-}
- <!-- example-end caps.func b --></programlisting>
- </sect1>
<!-- example-begin pads.c --><!--
#include "init.func"
#include "caps.func"