1 <chapter id="cha-dynamic">
2 <title>Dynamic pipelines</title>
4 In this chapter we will see how you can create a dynamic pipeline. A
5 dynamic pipeline is a pipeline that is updated or created while data
6 is flowing through it. We will create a partial pipeline first and add
7 more elements while the pipeline is playing. Dynamic pipelines cause
8 all sorts of scheduling issues and will remain a topic of research for
9 a long time in GStreamer.
12 We will show how to create an MPEG1 video player using dynamic pipelines.
13 As you have seen in the pad section, we can attach a signal to an element
14 when a pad is created. We will use this to create our MPEG1 player.
18 We'll start with a simple main function:
22 /* example-begin dynamic.c */
23 #include <string.h>
24 #include <gst/gst.h>
29 g_print ("have eos, quitting\n");
34 idle_func (gpointer data)
36 gst_bin_iterate (GST_BIN (data));
41 new_pad_created (GstElement *parse, GstPad *pad, GstElement *pipeline)
43 GstElement *decode_video = NULL;
44 GstElement *decode_audio, *play, *color, *show;
45 GstElement *audio_queue, *video_queue;
46 GstElement *audio_thread, *video_thread;
48 g_print ("***** a new pad %s was created\n", gst_pad_get_name (pad));
50 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
52 /* link to audio pad */
53 if (strncmp (gst_pad_get_name (pad), "audio_", 6) == 0) {
55 /* construct internal pipeline elements */
56 decode_audio = gst_element_factory_make ("mad", "decode_audio");
57 g_return_if_fail (decode_audio != NULL);
58 play = gst_element_factory_make ("osssink", "play_audio");
59 g_return_if_fail (play != NULL);
61 /* create the thread and pack stuff into it */
62 audio_thread = gst_thread_new ("audio_thread");
63 g_return_if_fail (audio_thread != NULL);
65 /* construct queue and link everything in the main pipeline */
66 audio_queue = gst_element_factory_make ("queue", "audio_queue");
67 g_return_if_fail (audio_queue != NULL);
69 gst_bin_add_many (GST_BIN (audio_thread),
70 audio_queue, decode_audio, play, NULL);
72 /* set up pad links */
73 gst_element_add_ghost_pad (audio_thread,
74 gst_element_get_pad (audio_queue, "sink"),
76 gst_element_link (audio_queue, decode_audio);
77 gst_element_link (decode_audio, play);
79 gst_bin_add (GST_BIN (pipeline), audio_thread);
81 gst_pad_link (pad, gst_element_get_pad (audio_thread, "sink"));
83 /* set up thread state and kick things off */
84 g_print ("setting to READY state\n");
85 gst_element_set_state (GST_ELEMENT (audio_thread), GST_STATE_READY);
88 else if (strncmp (gst_pad_get_name (pad), "video_", 6) == 0) {
90 /* construct internal pipeline elements */
91 decode_video = gst_element_factory_make ("mpeg2dec", "decode_video");
92 g_return_if_fail (decode_video != NULL);
94 color = gst_element_factory_make ("colorspace", "color");
95 g_return_if_fail (color != NULL);
98 show = gst_element_factory_make ("xvideosink", "show");
99 g_return_if_fail (show != NULL);
101 /* construct queue and link everything in the main pipeline */
102 video_queue = gst_element_factory_make ("queue", "video_queue");
103 g_return_if_fail (video_queue != NULL);
105 /* create the thread and pack stuff into it */
106 video_thread = gst_thread_new ("video_thread");
107 g_return_if_fail (video_thread != NULL);
108 gst_bin_add_many (GST_BIN (video_thread), video_queue,
109 decode_video, color, show, NULL);
111 /* set up pad links */
112 gst_element_add_ghost_pad (video_thread,
113 gst_element_get_pad (video_queue, "sink"),
115 gst_element_link (video_queue, decode_video);
116 gst_element_link_many (decode_video, color, show, NULL);
118 gst_bin_add (GST_BIN (pipeline), video_thread);
120 gst_pad_link (pad, gst_element_get_pad (video_thread, "sink"));
122 /* set up thread state and kick things off */
123 g_print ("setting to READY state\n");
124 gst_element_set_state (GST_ELEMENT (video_thread), GST_STATE_READY);
126 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
130 main (int argc, char *argv[])
132 GstElement *pipeline, *src, *demux;
134 gst_init (&argc, &argv);
136 pipeline = gst_pipeline_new ("pipeline");
137 g_return_val_if_fail (pipeline != NULL, -1);
139 src = gst_element_factory_make ("filesrc", "src");
140 g_return_val_if_fail (src != NULL, -1);
142 g_error ("Please specify a video file to play !");
144 g_object_set (G_OBJECT (src), "location", argv[1], NULL);
146 demux = gst_element_factory_make ("mpegdemux", "demux");
147 g_return_val_if_fail (demux != NULL, -1);
149 gst_bin_add_many (GST_BIN (pipeline), src, demux, NULL);
151 g_signal_connect (G_OBJECT (demux), "new_pad",
152 G_CALLBACK (new_pad_created), pipeline);
154 g_signal_connect (G_OBJECT (src), "eos",
155 G_CALLBACK (eof), NULL);
157 gst_element_link (src, demux);
159 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
161 g_idle_add (idle_func, pipeline);
167 /* example-end dynamic.c */
170 We create two elements: a file source and an MPEG demuxer.
171 There's nothing special about this piece of code except for
172 the signal 'new_pad' that we linked to the mpegdemux
176 g_signal_connect (G_OBJECT (demux), "new_pad",
177 G_CALLBACK (new_pad_created), pipeline);
180 When an elementary stream has been detected in the system stream,
181 mpegdemux will create a new pad that will provide the data of the
182 elementary stream. A function 'new_pad_created' will be called when
186 In the above example, we created new elements based on the name of
187 the newly created pad. We then added them to a new thread.
188 There are other possibilities to check the type of the pad, for
189 example by using the MIME type and the properties of the pad.
192 Note that the pipeline has to be in the PAUSED state before changes
193 can be made to its structure.