10.3. Downstream caps negotiation

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.

10.3.1. Negotiating caps embedded in input caps

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 _setcaps () 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).

In the _setcaps ()-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 always 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:


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;
}

There may also be cases where the filter actually is able to change the format of the stream. In those cases, it will negotiate a new format. Obviously, the element should first attempt to configure "pass-through", which means that it does not change the stream's format. However, if that fails, then it should call gst_pad_get_allowed_caps () 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.

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:


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);
}

10.3.2. Parsing and setting caps

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.

Fortunately, the code required to do so is very similar to the last code example in Negotiating caps embedded in input caps, with the difference being that the caps is selected in the _chain ()-function rather than in the _setcaps ()-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.