pwg: improve negotiation documentation some more
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 15 Oct 2012 11:44:51 +0000 (13:44 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 15 Oct 2012 11:44:51 +0000 (13:44 +0200)
docs/pwg/advanced-negotiation.xml

index 77ac5a4..7cc7fd8 100644 (file)
@@ -296,161 +296,102 @@ gst_my_filter_sink_event (GstPad    *pad,
         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-&gt;sinkpad, caps)) {
-    filter-&gt;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", &amp;filter-&gt;channels);
-    othercaps = gst_pad_get_allowed_caps (filter-&gt;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-&gt;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-&gt;srcpad, newcaps);
-    if (!gst_pad_set_caps (filter-&gt;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-&gt;passthrough = FALSE;
-    gst_structure_get_int (s, "rate", &amp;filter-&gt;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", &amp;filter-&gt;to_samplerate);
+    gst_structure_get_int (others, "rate", &filter->to_samplerate);
   }
 
   return TRUE;
@@ -469,7 +410,7 @@ gst_my_filter_sink_event (GstPad    *pad,
     {
       GstCaps *caps;
 
-      gst_event_parse_caps (event, &amp;caps);
+      gst_event_parse_caps (event, &caps);
       ret = gst_my_filter_setcaps (filter, caps);
       break;
     }
@@ -489,23 +430,26 @@ gst_my_filter_chain (GstPad    *pad,
   GstBuffer *out;
 
   /* push on if in passthrough mode */
-  if (filter-&gt;passthrough)
-    return gst_pad_push (filter-&gt;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-&gt;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>
@@ -532,19 +476,36 @@ gst_my_filter_chain (GstPad    *pad,
     <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>