2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstpipeline.c: Overall pipeline management element
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
26 #include "gstpipeline.h"
27 #include "gstthread.h"
30 #include "gstautoplug.h"
33 GstElementDetails gst_pipeline_details = {
36 "Complete pipeline object",
38 "Erik Walthinsen <omega@cse.ogi.edu>",
42 /* Pipeline signals and args */
54 static void gst_pipeline_class_init (GstPipelineClass *klass);
55 static void gst_pipeline_init (GstPipeline *pipeline);
57 static GstElementStateReturn gst_pipeline_change_state (GstElement *element);
59 static void gst_pipeline_prepare (GstPipeline *pipeline);
61 static void gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data);
62 static void gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink);
64 static GstBinClass *parent_class = NULL;
65 //static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 };
68 gst_pipeline_get_type (void) {
69 static GtkType pipeline_type = 0;
72 static const GtkTypeInfo pipeline_info = {
75 sizeof(GstPipelineClass),
76 (GtkClassInitFunc)gst_pipeline_class_init,
77 (GtkObjectInitFunc)gst_pipeline_init,
80 (GtkClassInitFunc)NULL,
82 pipeline_type = gtk_type_unique (gst_bin_get_type (), &pipeline_info);
88 gst_pipeline_class_init (GstPipelineClass *klass)
90 GstElementClass *gstelement_class;
92 gstelement_class = (GstElementClass*)klass;
94 parent_class = gtk_type_class(gst_bin_get_type());
96 gstelement_class->change_state = gst_pipeline_change_state;
100 gst_pipeline_init (GstPipeline *pipeline)
102 // we're a manager by default
103 GST_FLAG_SET (pipeline, GST_BIN_FLAG_MANAGER);
105 pipeline->src = NULL;
106 pipeline->sinks = NULL;
112 * @name: name of new pipeline
114 * Create a new pipeline with the given name.
116 * Returns: newly created GstPipeline
119 gst_pipeline_new (guchar *name)
121 return gst_elementfactory_make ("pipeline", name);
125 gst_pipeline_prepare (GstPipeline *pipeline)
127 GST_DEBUG (0,"GstPipeline: preparing pipeline \"%s\" for playing\n",
128 GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
132 gst_pipeline_have_type (GstElement *sink, GstElement *sink2, gpointer data)
134 GST_DEBUG (0,"GstPipeline: pipeline have type %p\n", (gboolean *)data);
136 *(gboolean *)data = TRUE;
140 gst_pipeline_typefind (GstPipeline *pipeline, GstElement *element)
142 gboolean found = FALSE;
143 GstElement *typefind;
144 GstCaps *caps = NULL;
146 GST_DEBUG (0,"GstPipeline: typefind for element \"%s\" %p\n",
147 GST_ELEMENT_NAME(element), &found);
149 typefind = gst_elementfactory_make ("typefind", "typefind");
150 g_return_val_if_fail (typefind != NULL, FALSE);
152 gtk_signal_connect (GTK_OBJECT (typefind), "have_type",
153 GTK_SIGNAL_FUNC (gst_pipeline_have_type), &found);
155 gst_pad_connect (gst_element_get_pad (element, "src"),
156 gst_element_get_pad (typefind, "sink"));
158 gst_bin_add (GST_BIN (pipeline), typefind);
160 //gst_bin_create_plan (GST_BIN (pipeline));
161 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY);
162 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
164 // keep pushing buffers... the have_type signal handler will set the found flag
166 gst_bin_iterate (GST_BIN (pipeline));
169 gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
172 caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps");
174 gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps));
177 gst_pad_disconnect (gst_element_get_pad (element, "src"),
178 gst_element_get_pad (typefind, "sink"));
179 gst_bin_remove (GST_BIN (pipeline), typefind);
180 gst_object_unref (GST_OBJECT (typefind));
186 gst_pipeline_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
189 gboolean connected = FALSE;
191 GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n",
192 GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
194 sinkpads = gst_element_get_pad_list(sink);
196 GstPad *sinkpad = (GstPad *)sinkpads->data;
198 // if we have a match, connect the pads
199 if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
200 !GST_PAD_CONNECTED(sinkpad))
202 if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
203 gst_pad_connect(pad, sinkpad);
204 GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
205 GST_ELEMENT_NAME(src));
206 GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
207 GST_ELEMENT_NAME(sink));
212 GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
215 sinkpads = g_list_next(sinkpads);
219 GST_DEBUG (0,"gstpipeline: no path to sinks for type\n");
225 gst_pipeline_pads_autoplug (GstElement *src, GstElement *sink)
228 gboolean connected = FALSE;
230 srcpads = gst_element_get_pad_list(src);
232 while (srcpads && !connected) {
233 GstPad *srcpad = (GstPad *)srcpads->data;
235 if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
236 connected = gst_pipeline_pads_autoplug_func (src, srcpad, sink);
238 srcpads = g_list_next(srcpads);
242 GST_DEBUG (0,"gstpipeline: delaying pad connections for \"%s\" to \"%s\"\n",
243 GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink));
244 gtk_signal_connect(GTK_OBJECT(src),"new_pad",
245 GTK_SIGNAL_FUNC(gst_pipeline_pads_autoplug_func), sink);
250 * gst_pipeline_add_src:
251 * @pipeline: the pipeline to add the src to
252 * @src: the src to add to the pipeline
254 * Adds a src element to the pipeline. This element
255 * will be used as a src for autoplugging. If you add more
256 * than one src element, the previously added element will
260 gst_pipeline_add_src (GstPipeline *pipeline, GstElement *src)
262 g_return_if_fail (pipeline != NULL);
263 g_return_if_fail (GST_IS_PIPELINE (pipeline));
264 g_return_if_fail (src != NULL);
265 g_return_if_fail (GST_IS_ELEMENT (src));
268 printf("gstpipeline: *WARNING* removing previously added element \"%s\"\n",
269 GST_ELEMENT_NAME(pipeline->src));
270 gst_bin_remove(GST_BIN(pipeline), pipeline->src);
273 gst_bin_add(GST_BIN(pipeline), src);
277 * gst_pipeline_add_sink:
278 * @pipeline: the pipeline to add the sink to
279 * @sink: the sink to add to the pipeline
281 * Adds a sink element to the pipeline. This element
282 * will be used as a sink for autoplugging.
285 gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *sink)
287 g_return_if_fail (pipeline != NULL);
288 g_return_if_fail (GST_IS_PIPELINE (pipeline));
289 g_return_if_fail (sink != NULL);
290 g_return_if_fail (GST_IS_ELEMENT (sink));
292 pipeline->sinks = g_list_prepend (pipeline->sinks, sink);
293 //gst_bin_add(GST_BIN(pipeline), sink);
297 * gst_pipeline_autoplug:
298 * @pipeline: the pipeline to autoplug
300 * Constructs a complete pipeline by automatically
301 * detecting the plugins needed.
303 * Returns: a gboolean indicating success or failure.
306 gst_pipeline_autoplug (GstPipeline *pipeline)
309 GstElement *element, *srcelement = NULL, *sinkelement= NULL;
311 GList **base_factories;
312 GstElementFactory *factory;
313 GstCaps *src_caps = 0;
315 gboolean use_thread = FALSE, have_common = FALSE;
318 g_return_val_if_fail(pipeline != NULL, FALSE);
319 g_return_val_if_fail(GST_IS_PIPELINE(pipeline), FALSE);
321 GST_DEBUG (0,"GstPipeline: autopluging pipeline \"%s\"\n",
322 GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
325 // fase 1, run typedetect on the source if needed...
326 if (!pipeline->src) {
327 GST_DEBUG (0,"GstPipeline: no source detected, can't autoplug pipeline \"%s\"\n",
328 GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
332 GST_DEBUG (0,"GstPipeline: source \"%s\" has no MIME type, running typefind...\n",
333 GST_ELEMENT_NAME(pipeline->src));
335 src_caps = gst_pipeline_typefind(pipeline, pipeline->src);
338 GST_DEBUG (0,"GstPipeline: source \"%s\" type found %d\n", GST_ELEMENT_NAME(pipeline->src),
342 GST_DEBUG (0,"GstPipeline: source \"%s\" has no type\n", GST_ELEMENT_NAME(pipeline->src));
346 srcelement = pipeline->src;
348 elements = pipeline->sinks;
350 sinkstart = g_list_copy (elements);
352 numsinks = g_list_length(elements);
353 factories = g_new0(GList *, numsinks);
354 base_factories = g_new0(GList *, numsinks);
357 // fase 2, loop over all the sinks..
361 element = GST_ELEMENT(elements->data);
363 pad = (GstPad *)gst_element_get_pad_list (element)->data;
365 base_factories[i] = factories[i] = gst_autoplug_caps_list (g_list_append(NULL,src_caps),
366 gst_pad_get_caps_list(pad));
367 // if we have a succesfull connection, proceed
368 if (factories[i] != NULL) {
372 sinkstart = g_list_remove (sinkstart, element);
375 elements = g_list_next(elements);
378 while (factories[0]) {
379 // fase 3: add common elements
380 factory = (GstElementFactory *)(factories[0]->data);
382 // check to other paths for mathing elements (factories)
383 for (i=1; i<numsinks; i++) {
384 if (!factories[i] || (factory != (GstElementFactory *)(factories[i]->data))) {
387 factories[i] = g_list_next(factories[i]);
389 factory = (GstElementFactory *)(factories[0]->data);
391 GST_DEBUG (0,"common factory \"%s\"\n", factory->name);
393 element = gst_elementfactory_create(factory, factory->name);
394 gst_bin_add(GST_BIN(pipeline), element);
396 gst_pipeline_pads_autoplug(srcelement, element);
398 srcelement = element;
400 factories[0] = g_list_next(factories[0]);
406 // loop over all the sink elements
407 elements = sinkstart;
411 GstElement *thesrcelement = srcelement;
412 GstElement *thebin = GST_ELEMENT(pipeline);
414 if (g_list_length(base_factories[i]) == 0) goto next;
416 sinkelement = (GstElement *)elements->data;
418 use_thread = have_common;
420 while (factories[i] || sinkelement) {
421 // fase 4: add other elements...
424 factory = (GstElementFactory *)(factories[i]->data);
425 GST_DEBUG (0,"factory \"%s\"\n", factory->name);
426 element = gst_elementfactory_create(factory, factory->name);
427 factories[i] = g_list_next(factories[i]);
429 // we have arived to the final sink element
431 element = sinkelement;
435 // this element suggests the use of a thread, so we set one up...
436 if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
439 GstPad *srcpad, *sinkpad;
443 GST_DEBUG (0,"sugest new thread for \"%s\" %08x\n", GST_ELEMENT_NAME (element), GST_FLAGS(element));
445 // create a new queue and add to the previous bin
446 queue = gst_elementfactory_make("queue", g_strconcat("queue_", GST_ELEMENT_NAME(element), NULL));
447 GST_DEBUG (0,"adding element \"%s\"\n", GST_ELEMENT_NAME (element));
448 gst_bin_add(GST_BIN(thebin), queue);
450 // this will be the new bin for all following elements
451 thebin = gst_elementfactory_make("thread", g_strconcat("thread_", GST_ELEMENT_NAME(element), NULL));
453 srcpad = gst_element_get_pad(queue, "src");
455 sinkpads = gst_element_get_pad_list(element);
457 sinkpad = (GstPad *)sinkpads->data;
459 // FIXME connect matching pads, not just the first one...
460 if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
461 !GST_PAD_CONNECTED(sinkpad)) {
462 GList *caps = gst_pad_get_caps_list (sinkpad);
464 // the queue has the type of the elements it connects
465 gst_pad_set_caps_list (srcpad, caps);
466 gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
469 sinkpads = g_list_next(sinkpads);
471 gst_pipeline_pads_autoplug(thesrcelement, queue);
473 GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
474 gst_bin_add(GST_BIN(thebin), element);
475 GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (thebin));
476 gst_bin_add(GST_BIN(pipeline), thebin);
477 thesrcelement = queue;
479 // no thread needed, easy case
481 GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
482 gst_bin_add(GST_BIN(thebin), element);
484 gst_pipeline_pads_autoplug(thesrcelement, element);
486 // this element is now the new source element
487 thesrcelement = element;
490 elements = g_list_next(elements);
495 GST_DEBUG (0,"GstPipeline: unable to autoplug pipeline \"%s\"\n",
496 GST_ELEMENT_NAME(GST_ELEMENT(pipeline)));
500 static GstElementStateReturn
501 gst_pipeline_change_state (GstElement *element)
503 GstPipeline *pipeline;
505 g_return_val_if_fail (GST_IS_PIPELINE (element), FALSE);
507 pipeline = GST_PIPELINE (element);
509 switch (GST_STATE_TRANSITION (pipeline)) {
510 case GST_STATE_NULL_TO_READY:
511 // we need to set up internal state
512 gst_pipeline_prepare (pipeline);
518 if (GST_ELEMENT_CLASS (parent_class)->change_state)
519 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
521 return GST_STATE_SUCCESS;
526 * gst_pipeline_iterate:
527 * @pipeline: #GstPipeline to iterate
529 * Cause the pipeline's contents to be run through one full 'iteration'.
532 gst_pipeline_iterate (GstPipeline *pipeline)
534 g_return_if_fail (pipeline != NULL);
535 g_return_if_fail (GST_IS_PIPELINE(pipeline));