11.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.

11.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. For those elements, all (downstream) caps negotiation can be done from the _event () function when a GST_EVENT_CAPS is received on the sinkpad. This CAPS event is received whenever the format changes or when no format was negotiated yet. It will always be called before you receive the buffer in the format specified in the CAPS event.

In the _event ()-function, the element can forward the CAPS event 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_sink_event (GstPad    *pad,
		          GstObject *parent,
		          GstEvent  *event)
{
  gboolean ret;
  GstMyFilter *filter = GST_MY_FILTER (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;
      GstStructure *s;

      gst_event_parse_caps (event, &caps);

      /* forward-negotiate */
      ret = gst_pad_set_caps (filter->srcpad, caps);
      if (!ret)
        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);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }
  return ret;
}

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 or NULL when there is no peer.

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 (GstMyFilter *filter,
		       GstCaps *caps)
{
  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 gboolean
gst_my_filter_sink_event (GstPad    *pad,
		          GstObject *parent,
		          GstEvent  *event)
{
  gboolean ret;
  GstMyFilter *filter = GST_MY_FILTER (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_my_filter_setcaps (filter, caps);
      break;
    }
    default:
      ret = gst_pad_event_default (pad, parent, event);
      break;
  }
  return ret;
}

static GstFlowReturn
gst_my_filter_chain (GstPad    *pad,
		     GstObject *parent,
		     GstBuffer *buf)
{
  GstMyFilter *filter = GST_MY_FILTER (parent);
  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);
}

11.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 renegotiable, 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 _event ()-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.