Sometimes you'll want to set a specific format, for example a video
size and format or an audio bitsize and number of channels. You can
do this by forcing a specific GstCaps
on
the pipeline, which is possible by using
filtered caps. You can set a filtered caps on
a link by using the “capsfilter” element in between the
two elements, and specifying a GstCaps
as
“caps” property on this element. It will then
only allow types matching that specified capability set for
negotiation. See also the section called “Creating capabilities for filtering”.
It is also possible to dynamically change the format in a pipeline while PLAYING. This can simply be done by changing the caps property on a capsfilter. The capsfilter will send a RECONFIGURE event upstream that will make the upstream element attempt to renegotiate a new format and allocator. This only works if the upstream element is not using fixed caps on the source pad.
Below is an example of how you can change the caps of a pipeline while in the PLAYING state:
#include <stdlib.h> #include <gst/gst.h> #define MAX_ROUND 100 int main (int argc, char **argv) { GstElement *pipe, *filter; GstCaps *caps; gint width, height; gint xdir, ydir; gint round; GstMessage *message; gst_init (&argc, &argv); pipe = gst_parse_launch_full ("videotestsrc ! capsfilter name=filter ! " "ximagesink", NULL, GST_PARSE_FLAG_NONE, NULL); g_assert (pipe != NULL); filter = gst_bin_get_by_name (GST_BIN (pipe), "filter"); g_assert (filter); width = 320; height = 240; xdir = ydir = -10; for (round = 0; round < MAX_ROUND; round++) { gchar *capsstr; g_print ("resize to %dx%d (%d/%d) \r", width, height, round, MAX_ROUND); /* we prefer our fixed width and height but allow other dimensions to pass * as well */ capsstr = g_strdup_printf ("video/x-raw, width=(int)%d, height=(int)%d", width, height); caps = gst_caps_from_string (capsstr); g_free (capsstr); g_object_set (filter, "caps", caps, NULL); gst_caps_unref (caps); if (round == 0) gst_element_set_state (pipe, GST_STATE_PLAYING); width += xdir; if (width >= 320) xdir = -10; else if (width < 200) xdir = 10; height += ydir; if (height >= 240) ydir = -10; else if (height < 150) ydir = 10; message = gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 50 * GST_MSECOND); if (message) { g_print ("got error \n"); gst_message_unref (message); } } g_print ("done \n"); gst_object_unref (filter); gst_element_set_state (pipe, GST_STATE_NULL); gst_object_unref (pipe); return 0; }
Note how we use gst_bus_poll()
with a
small timeout to get messages and also introduce a short
sleep.
It is possible to set multiple caps for the capsfilter separated with a ;. The capsfilter will try to renegotiate to the first possible format from the list.