<chapter id="chapter-other-ntoone"
    xreflabel="Writing a N-to-1 Element or Muxer">
  <title>Writing a N-to-1 Element or Muxer</title>
  <para>
    N-to-1 elements have been previously mentioned and discussed in both
    <xref linkend="chapter-advanced-request"/> and in
    <xref linkend="chapter-scheduling"/>. The main noteworthy thing
    about N-to-1 elements is that each pad is push-based in its own thread,
    and the N-to-1 element synchronizes those streams by
    expected-timestamp-based logic. This means it lets all streams wait
    except for the one that provides the earliest next-expected timestamp.
    When that stream has passwed one buffer, the next
    earliest-expected-timestamp is calculated, and we start back where we
    were, until all streams have reached EOS. There is a helper base class,
    called <classname>GstCollectPads</classname>, that will help you to do
    this.
  </para>
  <para>
    Note, however, that this helper class will only help you with grabbing
    a buffer from each input and giving you the one with earliest timestamp.
    If you need anything more difficult, such as "don't-grab-a-new-buffer
    until a given timestamp" or something like that, you'll need to do this
    yourself.
  </para>

<!--
  Note: I'd like to have something like this in the final text, but since
  the code below doesn't work and this is all 0.8'y, I commented it for now.
  <sect1 id="section-muxer-negotiation" xreflabel="Negotiation">
    <title>Negotiation</title>
    <para>
      Most container formats will have a fair amount of issues with
      changing content on an elementary stream. Therefore, you should
      not allow caps to be changed once you've started using data from
      them. The easiest way to achieve this is by using explicit caps,
      which have been explained before. However, we're going to use them
      in a slightly different way then what you're used to, having the
      core do all the work for us.
    </para>
    <para>
      The idea is that, as long as the stream/file headers have not been
      written yet and no data has been processed yet, a stream is allowed
      to renegotiate. After that point, the caps should be fixed, because
      we can only use a stream once. Caps may then only change within an
      allowed range (think MPEG, where changes in FPS are allowed), or
      sometimes not at all (such as AVI audio). In order to do that, we
      will, after data retrieval and header writing, set an explicit caps
      on each sink pad, that is the minimal caps describing the properties
      of the format that may not change. As an example, for MPEG audio
      inside an MPEG system stream, this would mean a wide caps of
      audio/mpeg with mpegversion=1 and layer=[1,2]. For the same audio type
      in MPEG, though, the samplerate, bitrate, layer and number of channels
      would become static, too. Since the (request) pads will be removed
      when the stream ends, the static caps will cease to exist too, then.
      While the explicit caps  exist, the <function>_link ()</function>-
      function will not be called, since the core will do all necessary
      checks for us. Note that the property of using explicit caps should
      be added along with the actual explicit caps, not any earlier.
    </para>
    <para>
      Below here follows the simple example of an AVI muxer's audio caps
      negotiation. The <function>_link ()</function>-function is fairly
      normal, but the <function>-Loop ()</function>-function does some of
      the tricks mentioned above. There is no <function>_getcaps ()</function>-
      function since the pad template contains all that information already
      (not shown).
    </para>
    <programlisting>
static GstPadLinkReturn
gst_avi_mux_audio_link (GstPad        *pad,
			const GstCaps *caps)
{
  GstAviMux *mux = GST_AVI_MUX (gst_pad_get_parent (pad));
  GstStructure *str = gst_caps_get_structure (caps, 0);
  const gchar *mime = gst_structure_get_name (str);

  if (!strcmp (str, "audio/mpeg")) {
    /* get version, make sure it's 1, get layer, make sure it's 1-3,
     * then create the 2-byte audio tag (0x0055) and fill an audio
     * stream structure (strh/strf). */
    [..]
    return GST_PAD_LINK_OK;
  } else if !strcmp (str, "audio/x-raw-int")) {
    /* See above, but now with the raw audio tag (0x0001). */
    [..]
    return GST_PAD_LINK_OK;
  } else [..]
[..]
}

static void
gst_avi_mux_loop (GstElement *element)
{
  GstAviMux *mux = GST_AVI_MUX (element);
[..]
  /* As we get here, we should have written the header if we hadn't done
   * that before yet, and we're supposed to have an internal buffer from
   * each pad, also from the audio one. So here, we check again whether
   * this is the first run and if so, we set static caps. */
  if (mux->first_cycle) {
    const GList *padlist = gst_element_get_pad_list (element);
    GList *item;

    for (item = padlist; item != NULL; item = item->next) {
      GstPad *pad = item->data;
      GstCaps *caps;

      if (!GST_PAD_IS_SINK (pad))
        continue;

      /* set static caps here */
      if (!strncmp (gst_pad_get_name (pad), "audio_", 6)) {
        /* the strf is the struct you filled in the _link () function. */
        switch (strf->format) {
          case 0x0055: /* mp3 */
            caps = gst_caps_new_simple ("audio/mpeg",
			"mpegversion", G_TYPE_INT, 1,
			"layer",       G_TYPE_INT, 3,
			"bitrate",     G_TYPE_INT, strf->av_bps,
			"rate",        G_TYPE_INT, strf->rate,
			"channels",    G_TYPE_INT, strf->channels,
			NULL);
            break;
          case 0x0001: /* pcm */
            caps = gst_caps_new_simple ("audio/x-raw-int",
					[..]);
            break;
          [..]
        }
      } else if (!strncmp (gst_pad_get_name (pad), "video_", 6)) {
        [..]
      } else {
        g_warning ("oi!");
        continue;
      }

      /* set static caps */
      gst_pad_use_explicit_caps (pad);
      gst_pad_set_explicit_caps (pad, caps);
    }
  }
[..]
  /* Next runs will never be the first again. */
  mux->first_cycle = FALSE;
}
    </programlisting>
    <para>
      Note that there are other ways to achieve that, which might be useful
      for more complex cases. This will do for the simple cases, though.
      This method is provided to simplify negotiation and renegotiation in
      muxers, it is not a complete solution, nor is it a pretty one.
    </para>
  </sect1>
-->
</chapter>
