8.3. What capabilities are used for

Capabilities (short: caps) describe the type of data that is streamed between two pads, or that one pad (template) supports. This makes them very useful for various purposes:

8.3.1. Using capabilities for metadata

A pad can have a set (i.e. one or more) of capabilities attached to it. Capabilities (GstCaps) are represented as an array of one or more GstStructures, and each GstStructure is an array of fields where each field consists of a field name string (e.g. "width") and a typed value (e.g. G_TYPE_INT or GST_TYPE_INT_RANGE).

Note that there is a distinct difference between the possible capabilities of a pad (ie. usually what you find as caps of pad templates as they are shown in gst-inspect), the allowed caps of a pad (can be the same as the pad's template caps or a subset of them, depending on the possible caps of the peer pad) and lastly negotiated caps (these describe the exact format of a stream or buffer and contain exactly one structure and have no variable bits like ranges or lists, ie. they are fixed caps).

You can get values of properties in a set of capabilities by querying individual properties of one structure. You can get a structure from a caps using gst_caps_get_structure () and the number of structures in a GstCaps using gst_caps_get_size ().

Caps are called simple caps when they contain only one structure, and fixed caps when they contain only one structure and have no variable field types (like ranges or lists of possible values). Two other special types of caps are ANY caps and empty caps.

Here is an example of how to extract the width and height from a set of fixed video caps:


static void
read_video_props (GstCaps *caps)
{
  gint width, height;
  const GstStructure *str;

  g_return_if_fail (gst_caps_is_fixed (caps));

  str = gst_caps_get_structure (caps, 0);
  if (!gst_structure_get_int (str, "width", &width) ||
      !gst_structure_get_int (str, "height", &height)) {
    g_print ("No width/height available\n");
    return;
  }

  g_print ("The video size of this set of capabilities is %dx%d\n",
	   width, height);
}
      

8.3.2. Creating capabilities for filtering

While capabilities are mainly used inside a plugin to describe the media type of the pads, the application programmer often also has to have basic understanding of capabilities in order to interface with the plugins, especially when using filtered caps. When you're using filtered caps or fixation, you're limiting the allowed types of media that can stream between two pads to a subset of their supported media types. You do this using a capsfilter element in your pipeline. In order to do this, you also need to create your own GstCaps. The easiest way to do this is by using the convenience function gst_caps_new_simple ():


static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
  gboolean link_ok;
  GstCaps *caps;

  caps = gst_caps_new_simple ("video/x-raw-yuv",
  	      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
	      "width", G_TYPE_INT, 384,
	      "height", G_TYPE_INT, 288,
	      "framerate", GST_TYPE_FRACTION, 25, 1,
	      NULL);

  link_ok = gst_element_link_filtered (element1, element2, caps);
  gst_caps_unref (caps);

  if (!link_ok) {
    g_warning ("Failed to link element1 and element2!");
  }

  return link_ok;
}
      
This will force the data flow between those two elements to a a certain video format, width, height and framerate (or the linking will fail if that cannot be achieved in the context of the elments involved). Keep in mind that when you use gst_element_link_filtered () it will automatically create a capsfilter element for you and insert it into your bin or pipeline between the two elements you want to connect (this is important if you ever want to disconnect those elements).

In some cases, you will want to create a more elaborate set of capabilities to filter a link between two pads. Then, this function is too simplistic and you'll want to use the method gst_caps_new_full ():


static gboolean
link_elements_with_filter (GstElement *element1, GstElement *element2)
{
  gboolean link_ok;
  GstCaps *caps;
                                                                                
  caps = gst_caps_new_full (
      gst_structure_new ("video/x-raw-yuv",
			 "width", G_TYPE_INT, 384,
			 "height", G_TYPE_INT, 288,
			 "framerate", GST_TYPE_FRACTION, 25, 1,
			 NULL),
      gst_structure_new ("video/x-raw-rgb",
			 "width", G_TYPE_INT, 384,
			 "height", G_TYPE_INT, 288,
			 "framerate", GST_TYPE_FRACTION, 25, 1,
			 NULL),
      NULL);

  link_ok = gst_element_link_filtered (element1, element2, caps);
  gst_caps_unref (caps);

  if (!link_ok) {
    g_warning ("Failed to link element1 and element2!");
  }

  return link_ok;
}
      

See the API references for the full API of GstStructure and GstCaps.