new proggy I never checked in
[platform/upstream/gstreamer.git] / docs / manual / dynamic.xml
1 <chapter id="cha-dynamic">
2   <title>Dynamic pipelines</title>
3   <para> 
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.
10   </para>
11   <para> 
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.
15   </para>
16
17   <para> 
18     We'll start with a simple main function:
19   </para>
20   <programlisting>
21
22 /* example-begin dynamic.c */
23 #include &lt;string.h&gt;
24 #include &lt;gst/gst.h&gt;
25
26 void 
27 eof (GstElement *src) 
28 {
29   g_print ("have eos, quitting\n");
30   exit (0);
31 }
32
33 gboolean 
34 idle_func (gpointer data) 
35 {
36   gst_bin_iterate (GST_BIN (data));
37   return TRUE;
38 }
39
40 void 
41 new_pad_created (GstElement *parse, GstPad *pad, GstElement *pipeline) 
42 {
43   GstElement *decode_video = NULL;
44   GstElement *decode_audio, *play, *color, *show;
45   GstElement *audio_queue, *video_queue;
46   GstElement *audio_thread, *video_thread;
47
48   g_print ("***** a new pad %s was created\n", gst_pad_get_name (pad));
49   
50   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PAUSED);
51
52   /* link to audio pad */
53   if (strncmp (gst_pad_get_name (pad), "audio_", 6) == 0) {
54
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);
60
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);
64
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);
68
69     gst_bin_add_many (GST_BIN (audio_thread), 
70                       audio_queue, decode_audio, play, NULL);
71
72     /* set up pad links */
73     gst_element_add_ghost_pad (audio_thread,
74                                gst_element_get_pad (audio_queue, "sink"),
75                                "sink");
76     gst_element_link (audio_queue, decode_audio);
77     gst_element_link (decode_audio, play);
78
79     gst_bin_add (GST_BIN (pipeline), audio_thread);
80
81     gst_pad_link (pad, gst_element_get_pad (audio_thread, "sink"));
82
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);
86
87   } 
88   else if (strncmp (gst_pad_get_name (pad), "video_", 6) == 0) {
89
90     /* construct internal pipeline elements */
91     decode_video = gst_element_factory_make ("mpeg2dec", "decode_video");
92     g_return_if_fail (decode_video != NULL);
93
94     color = gst_element_factory_make ("colorspace", "color");
95     g_return_if_fail (color != NULL);
96
97    
98     show = gst_element_factory_make ("xvideosink", "show");
99     g_return_if_fail (show != NULL);
100
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);
104
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);
110
111     /* set up pad links */
112     gst_element_add_ghost_pad (video_thread,
113                                gst_element_get_pad (video_queue, "sink"),
114                                "sink");
115     gst_element_link (video_queue, decode_video);
116     gst_element_link_many (decode_video, color, show, NULL);
117
118     gst_bin_add (GST_BIN (pipeline), video_thread);
119
120     gst_pad_link (pad, gst_element_get_pad (video_thread, "sink"));
121
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);
125   }
126   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
127 }
128
129 int 
130 main (int argc, char *argv[]) 
131 {
132   GstElement *pipeline, *src, *demux;
133
134   gst_init (&amp;argc, &amp;argv);
135
136   pipeline = gst_pipeline_new ("pipeline");
137   g_return_val_if_fail (pipeline != NULL, -1);
138
139   src = gst_element_factory_make ("filesrc", "src");
140   g_return_val_if_fail (src != NULL, -1);
141   if (argc &lt; 2) 
142     g_error ("Please specify a video file to play !");
143
144   g_object_set (G_OBJECT (src), "location", argv[1], NULL);
145
146   demux = gst_element_factory_make ("mpegdemux", "demux");
147   g_return_val_if_fail (demux != NULL, -1);
148
149   gst_bin_add_many (GST_BIN (pipeline), src, demux, NULL);
150
151   g_signal_connect (G_OBJECT (demux), "new_pad",
152                      G_CALLBACK (new_pad_created), pipeline);
153
154   g_signal_connect (G_OBJECT (src), "eos",
155                      G_CALLBACK (eof), NULL);
156
157   gst_element_link (src, demux);
158
159   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
160
161   g_idle_add (idle_func, pipeline);
162
163   gst_main ();
164
165   return 0;
166 }
167 /* example-end dynamic.c */
168   </programlisting>
169   <para>
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 
173     element using:
174   </para>
175   <programlisting>
176   g_signal_connect (G_OBJECT (demux), "new_pad",
177                      G_CALLBACK (new_pad_created), pipeline);
178   </programlisting>
179   <para> 
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
183     the pad is created.
184   </para>
185   <para>
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.
190   </para>
191   <para>
192     Note that the pipeline has to be in the PAUSED state before changes
193     can be made to its structure.
194   </para>
195 </chapter>