Like with the transform negotiation in
<xref linkend="section-nego-transform"/>, dynamic negotiation will
perform a transformation on the downstream/upstream caps. Unlike the
- transform
- negotiation, this transform will convert fixed caps to unfixed caps. This
- means that the sink pad input caps can be converted into unfixed (multiple)
- formats. The source pad will have to choose a format from all the
- possibilities. It would usually like to choose a format that requires the
- least amount of effort to produce but it does not have to be. The selection
- of the format should also depend on the caps that can be accepted downstream
+ transform negotiation, this transform will convert fixed caps to
+ unfixed caps. This means that the sink pad input caps can be converted
+ into unfixed (multiple) formats. The source pad will have to choose a
+ format from all the possibilities. It would usually like to choose a
+ format that requires the least amount of effort to produce but it does
+ not have to be. The selection of the format should also depend on the
+ caps that can be accepted downstream (see a QUERY_CAPS function in
+ <xref linkend="section-nego-getcaps"/>).
</para>
- </sect2>
- </sect1>
-
- <sect1 id="section-nego-pullmode">
- <title>Pull-mode Caps negotiation</title>
- <para>
- </para>
- </sect1>
-
-<!--
- <sect1 id="section-nego-old">
- <title>Old stuff</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 data flow 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-negotiable, 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 query function that tells peer elements
- what formats it supports and/or prefers. When upstream renegotiation is
- triggered, this becomes important.
- </para>
- <para>
- Downstream elements are notified of a newly set caps with a
- GST_EVENT_CAPS on the sinkpad. So when the vorbis decoder sets a caps on
- its source pad (to configure the output format), the converter will
- receive a caps event.
- When an element receives a buffer, it should check if it has received
- all needed format information in a CAPS event previously. If it hasn't,
- it should return an error from the chain function.
- </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>
- 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 or NULL when there is no peer.
+ A typical flow goes like this:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Caps are received on the sink pad of the element.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the element prefers to operate in passthrough mode, check
+ if downstream accepts the caps with the ACCEPT_CAPS query.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Calculate the possible caps for the source pad.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Query the downstream peer pad for the list of possible
+ caps.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select from the downstream list the first caps that you can
+ transform to and set this as the output caps.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Examples of this type of elements include:
</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Converter elements such as videoconvert, audioconvert, audioresample,
+ videoscale, ...
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Source elements such as audiotestsrc, videotestsrc, v4l2src,
+ pulsesrc, ...
+ </para>
+ </listitem>
+ </itemizedlist>
<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 -->
+ <programlisting>
+<![CDATA[
static gboolean
gst_my_filter_setcaps (GstMyFilter *filter,
GstCaps *caps)
{
- if (gst_pad_set_caps (filter->sinkpad, caps)) {
- filter->passthrough = TRUE;
+ 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);
+ 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);
+ "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))
+ 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);
+ 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);
+ gst_structure_get_int (others, "rate", &filter->to_samplerate);
}
return TRUE;
{
GstCaps *caps;
- gst_event_parse_caps (event, &caps);
+ gst_event_parse_caps (event, &caps);
ret = gst_my_filter_setcaps (filter, caps);
break;
}
GstBuffer *out;
/* push on if in passthrough mode */
- if (filter->passthrough)
- return gst_pad_push (filter->srcpad, buf);
+ 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);
+ 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>
+]]>
+ </programlisting>
</sect2>
</sect1>
+ <sect1 id="section-nego-pullmode">
+ <title>Pull-mode Caps negotiation</title>
+ <para>
+ </para>
+ </sect1>
+
<sect1 id="section-nego-upstream" xreflabel="Upstream caps (re)negotiation">
<title>Upstream caps (re)negotiation</title>
<para>
<itemizedlist>
<listitem>
<para>
- Elements that can be reconfigured on the srcpad should check its
- NEED_RECONFIGURE flag with
- <function>gst_pad_check_reconfigure ()</function> and it should
- start renegotiation when the function returns TRUE.
+ Elements that want to propose a new format upstream need to first
+ check if the new caps are acceptable upstream with an ACCEPT_CAPS
+ query. Then they would send a RECONFIGURE event and be prepared to
+ answer the CAPS query with the new prefered format. It should be
+ noted that when there is no upstream element that can (or wants)
+ to renegotiate, the element needs to deal with the currently
+ configured format.
</para>
</listitem>
<listitem>
<para>
- Elements that want to propose a new format upstream need to send
- a RECONFIGURE event and be prepared to answer the CAPS query with
- the new prefered format. It should be noted that when there is no
- upstream element that can (or wants) to renegotiate, the element
- needs to deal with the currently configured format.
+ Elements that operate in transform negotiation according to
+ <xref linkend="section-nego-transform"/> pass the RECONFIGURE
+ event upstream.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Elements that operate in fixed negotiation
+ (<xref linkend="section-nego-fixed"/>) drop the RECONFIGURE event.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Elements that can be reconfigured on the source pad (source pads
+ implementing dynamic negotiation in
+ <xref linkend="section-nego-dynamic"/>) should check its
+ NEED_RECONFIGURE flag with
+ <function>gst_pad_check_reconfigure ()</function> and it should
+ start renegotiation when the function returns TRUE.
</para>
</listitem>
</itemizedlist>