various style fixes
[platform/upstream/gstreamer.git] / gst / gstpipeline.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2004,2005 Wim Taymans <wim@fluendo.com>
4  *
5  * gstpipeline.c: Overall pipeline management element
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 /**
24  * SECTION:gstpipeline
25  * @short_description: Top-level bin with clocking and bus management
26                        functionality.
27  * @see_also: #GstBin
28  *
29  * In almost all cases, you'll want to use a GstPipeline when creating a filter
30  * graph.  The GstPipeline will manage the selection and distribution of a
31  * global
32  * clock as well as provide a GstBus to the application.
33  *
34  * The pipeline will also use the selected clock to calculate the stream time
35  * of the pipeline.
36  *
37  * When sending a seek event to a GstPipeline, it will make sure that the
38  * pipeline is properly PAUSED and resumed as well as update the new stream
39  * time after the seek.
40  *
41  * gst_pipeline_new() is used to create a pipeline. when you are done with
42  * the pipeline, use gst_object_unref() to free its resources including all
43  * added #GstElement objects (if not otherwiese referenced).
44  */
45
46 #include "gst_private.h"
47
48 #include "gstpipeline.h"
49 #include "gstinfo.h"
50 #include "gstsystemclock.h"
51
52 static GstElementDetails gst_pipeline_details =
53 GST_ELEMENT_DETAILS ("Pipeline object",
54     "Generic/Bin",
55     "Complete pipeline object",
56     "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
57
58 /* Pipeline signals and args */
59 enum
60 {
61   /* FILL ME */
62   LAST_SIGNAL
63 };
64
65 #define DEFAULT_DELAY 0
66
67 enum
68 {
69   PROP_0,
70   PROP_DELAY,
71   /* FILL ME */
72 };
73
74
75 static void gst_pipeline_base_init (gpointer g_class);
76 static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
77 static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
78
79 static void gst_pipeline_dispose (GObject * object);
80 static void gst_pipeline_set_property (GObject * object, guint prop_id,
81     const GValue * value, GParamSpec * pspec);
82 static void gst_pipeline_get_property (GObject * object, guint prop_id,
83     GValue * value, GParamSpec * pspec);
84
85 static gboolean gst_pipeline_send_event (GstElement * element,
86     GstEvent * event);
87
88 static GstClock *gst_pipeline_provide_clock_func (GstElement * element);
89 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element,
90     GstStateChange transition);
91
92 static GstBinClass *parent_class = NULL;
93
94 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
95
96 GType
97 gst_pipeline_get_type (void)
98 {
99   static GType pipeline_type = 0;
100
101   if (!pipeline_type) {
102     static const GTypeInfo pipeline_info = {
103       sizeof (GstPipelineClass),
104       gst_pipeline_base_init,
105       NULL,
106       (GClassInitFunc) gst_pipeline_class_init,
107       NULL,
108       NULL,
109       sizeof (GstPipeline),
110       0,
111       gst_pipeline_init,
112       NULL
113     };
114
115     pipeline_type =
116         g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
117   }
118   return pipeline_type;
119 }
120
121 static void
122 gst_pipeline_base_init (gpointer g_class)
123 {
124   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
125
126   gst_element_class_set_details (gstelement_class, &gst_pipeline_details);
127 }
128
129 static void
130 gst_pipeline_class_init (gpointer g_class, gpointer class_data)
131 {
132   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
133   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
134   GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
135
136   parent_class = g_type_class_peek_parent (klass);
137
138   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property);
139   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property);
140
141   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELAY,
142       g_param_spec_uint64 ("delay", "Delay",
143           "Expected delay needed for elements "
144           "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
145           G_PARAM_READWRITE));
146
147   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
148
149   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_pipeline_send_event);
150   gstelement_class->change_state =
151       GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
152   gstelement_class->provide_clock =
153       GST_DEBUG_FUNCPTR (gst_pipeline_provide_clock_func);
154 }
155
156 static void
157 gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
158 {
159   GstPipeline *pipeline = GST_PIPELINE (instance);
160   GstBus *bus;
161
162   pipeline->delay = DEFAULT_DELAY;
163
164   bus = g_object_new (gst_bus_get_type (), NULL);
165   gst_element_set_bus (GST_ELEMENT_CAST (pipeline), bus);
166   gst_object_unref (bus);
167 }
168
169 static void
170 gst_pipeline_dispose (GObject * object)
171 {
172   GstPipeline *pipeline = GST_PIPELINE (object);
173
174   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose");
175
176   gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
177
178   G_OBJECT_CLASS (parent_class)->dispose (object);
179 }
180
181 static void
182 gst_pipeline_set_property (GObject * object, guint prop_id,
183     const GValue * value, GParamSpec * pspec)
184 {
185   GstPipeline *pipeline = GST_PIPELINE (object);
186
187   GST_LOCK (pipeline);
188   switch (prop_id) {
189     case PROP_DELAY:
190       pipeline->delay = g_value_get_uint64 (value);
191       break;
192     default:
193       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194       break;
195   }
196   GST_UNLOCK (pipeline);
197 }
198
199 static void
200 gst_pipeline_get_property (GObject * object, guint prop_id,
201     GValue * value, GParamSpec * pspec)
202 {
203   GstPipeline *pipeline = GST_PIPELINE (object);
204
205   GST_LOCK (pipeline);
206   switch (prop_id) {
207     case PROP_DELAY:
208       g_value_set_uint64 (value, pipeline->delay);
209       break;
210     default:
211       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
212       break;
213   }
214   GST_UNLOCK (pipeline);
215 }
216
217 static gboolean
218 do_pipeline_seek (GstElement * element, GstEvent * event)
219 {
220   gdouble rate;
221   GstSeekFlags flags;
222   gboolean flush;
223   gboolean was_playing = FALSE;
224   gboolean res;
225
226   gst_event_parse_seek (event, &rate, NULL, &flags, NULL, NULL, NULL, NULL);
227
228   flush = flags & GST_SEEK_FLAG_FLUSH;
229
230   if (flush) {
231     GstState state;
232
233     /* need to call _get_state() since a bin state is only updated
234      * with this call. */
235     gst_element_get_state (element, &state, NULL, 0);
236     was_playing = state == GST_STATE_PLAYING;
237
238     if (was_playing) {
239       gst_element_set_state (element, GST_STATE_PAUSED);
240     }
241   }
242
243   res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
244
245   if (flush && res) {
246     /* need to reset the stream time to 0 after a flushing seek */
247     gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);
248     if (was_playing)
249       /* and continue playing */
250       gst_element_set_state (element, GST_STATE_PLAYING);
251   }
252   return res;
253 }
254
255 /* sending a seek event on the pipeline pauses the pipeline if it
256  * was playing.
257  */
258 static gboolean
259 gst_pipeline_send_event (GstElement * element, GstEvent * event)
260 {
261   gboolean res;
262   GstEventType event_type = GST_EVENT_TYPE (event);
263
264   switch (event_type) {
265     case GST_EVENT_SEEK:
266       res = do_pipeline_seek (element, event);
267       break;
268     default:
269       res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
270       break;
271   }
272
273   return res;
274 }
275
276 /**
277  * gst_pipeline_new:
278  * @name: name of new pipeline
279  *
280  * Create a new pipeline with the given name.
281  *
282  * Returns: newly created GstPipeline
283  *
284  * MT safe.
285  */
286 GstElement *
287 gst_pipeline_new (const gchar * name)
288 {
289   return gst_element_factory_make ("pipeline", name);
290 }
291
292 /* MT safe */
293 static GstStateChangeReturn
294 gst_pipeline_change_state (GstElement * element, GstStateChange transition)
295 {
296   GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
297   GstPipeline *pipeline = GST_PIPELINE (element);
298   GstClock *clock;
299
300   switch (transition) {
301     case GST_STATE_CHANGE_NULL_TO_READY:
302       GST_LOCK (element);
303       if (element->bus)
304         gst_bus_set_flushing (element->bus, FALSE);
305       GST_UNLOCK (element);
306       break;
307     case GST_STATE_CHANGE_READY_TO_PAUSED:
308       break;
309     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
310       /* when going to playing, select a clock */
311       if ((clock = gst_element_provide_clock (element))) {
312         GstClockTime start_time;
313         gboolean new_clock;
314
315         /* get start time */
316         start_time = gst_clock_get_time (clock);
317
318         GST_LOCK (element);
319         new_clock = element->clock != clock;
320         element->base_time = start_time -
321             pipeline->stream_time + pipeline->delay;
322         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
323             GST_TIME_FORMAT ", base time %" GST_TIME_FORMAT,
324             GST_TIME_ARGS (pipeline->stream_time),
325             GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
326         GST_UNLOCK (element);
327
328         if (new_clock) {
329           /* now distribute the clock */
330           gst_element_set_clock (element, clock);
331
332           /* if we selected a new clock, let the app know about it */
333           gst_element_post_message (element,
334               gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
335         }
336
337         gst_object_unref (clock);
338       } else {
339         GST_DEBUG ("no clock, using base time of 0");
340         gst_element_set_base_time (element, 0);
341       }
342       break;
343     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
344     case GST_STATE_CHANGE_PAUSED_TO_READY:
345     case GST_STATE_CHANGE_READY_TO_NULL:
346       break;
347   }
348
349   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
350
351   switch (transition) {
352     case GST_STATE_CHANGE_NULL_TO_READY:
353       break;
354     case GST_STATE_CHANGE_READY_TO_PAUSED:
355       gst_pipeline_set_new_stream_time (pipeline, 0);
356       break;
357     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
358       break;
359     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
360       GST_LOCK (element);
361       if ((clock = element->clock)) {
362         GstClockTime now;
363
364         gst_object_ref (clock);
365         GST_UNLOCK (element);
366
367         /* calculate the time when we stopped */
368         now = gst_clock_get_time (clock);
369         gst_object_unref (clock);
370
371         GST_LOCK (element);
372         /* store the current stream time */
373         pipeline->stream_time = now - element->base_time;
374         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
375             ", base time %" GST_TIME_FORMAT,
376             GST_TIME_ARGS (pipeline->stream_time),
377             GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
378       }
379       GST_UNLOCK (element);
380       break;
381     case GST_STATE_CHANGE_PAUSED_TO_READY:
382       break;
383     case GST_STATE_CHANGE_READY_TO_NULL:
384       GST_LOCK (element);
385       if (element->bus) {
386         gst_bus_set_flushing (element->bus, TRUE);
387       }
388       GST_UNLOCK (element);
389       break;
390   }
391   return result;
392 }
393
394 /**
395  * gst_pipeline_get_bus:
396  * @pipeline: the pipeline
397  *
398  * Gets the #GstBus of this pipeline.
399  *
400  * Returns: a GstBus
401  *
402  * MT safe.
403  */
404 GstBus *
405 gst_pipeline_get_bus (GstPipeline * pipeline)
406 {
407   return gst_element_get_bus (GST_ELEMENT (pipeline));
408 }
409
410 /**
411  * gst_pipeline_set_new_stream_time:
412  * @pipeline: the pipeline
413  * @time: the new stream time to set
414  *
415  * Set the new stream time of the pipeline. The stream time is used to
416  * set the base time on the elements (see @gst_element_set_base_time())
417  * in the PAUSED->PLAYING state transition.
418  *
419  * MT safe.
420  */
421 void
422 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
423 {
424   g_return_if_fail (GST_IS_PIPELINE (pipeline));
425
426   GST_LOCK (pipeline);
427   pipeline->stream_time = time;
428   GST_DEBUG ("%s: set new stream_time to %" GST_TIME_FORMAT,
429       GST_ELEMENT_NAME (pipeline), GST_TIME_ARGS (time));
430   GST_UNLOCK (pipeline);
431 }
432
433 /**
434  * gst_pipeline_get_last_stream_time:
435  * @pipeline: the pipeline
436  *
437  * Gets the last stream time of the pipeline. If the pipeline is PLAYING,
438  * the returned time is the stream time used to configure the elements
439  * in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned
440  * time is the stream time when the pipeline was paused.
441  *
442  * Returns: a GstClockTime
443  *
444  * MT safe.
445  */
446 GstClockTime
447 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
448 {
449   GstClockTime result;
450
451   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
452
453   GST_LOCK (pipeline);
454   result = pipeline->stream_time;
455   GST_UNLOCK (pipeline);
456
457   return result;
458 }
459
460 static GstClock *
461 gst_pipeline_provide_clock_func (GstElement * element)
462 {
463   GstClock *clock = NULL;
464   GstPipeline *pipeline = GST_PIPELINE (element);
465
466   /* if we have a fixed clock, use that one */
467   GST_LOCK (pipeline);
468   if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
469     clock = pipeline->fixed_clock;
470     gst_object_ref (clock);
471     GST_UNLOCK (pipeline);
472
473     GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
474         clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
475   } else {
476     GST_UNLOCK (pipeline);
477     clock =
478         GST_ELEMENT_CLASS (parent_class)->
479         provide_clock (GST_ELEMENT (pipeline));
480     /* no clock, use a system clock */
481     if (!clock) {
482       clock = gst_system_clock_obtain ();
483
484       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
485           clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
486     } else {
487       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)",
488           clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
489     }
490   }
491   return clock;
492 }
493
494 /**
495  * gst_pipeline_get_clock:
496  * @pipeline: the pipeline
497  *
498  * Gets the current clock used by the pipeline.
499  *
500  * Returns: a GstClock
501  */
502 GstClock *
503 gst_pipeline_get_clock (GstPipeline * pipeline)
504 {
505   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);
506
507   return gst_pipeline_provide_clock_func (GST_ELEMENT (pipeline));
508 }
509
510
511 /**
512  * gst_pipeline_use_clock:
513  * @pipeline: the pipeline
514  * @clock: the clock to use
515  *
516  * Force the pipeline to use the given clock. The pipeline will
517  * always use the given clock even if new clock providers are added
518  * to this pipeline.
519  *
520  * MT safe.
521  */
522 void
523 gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock)
524 {
525   g_return_if_fail (GST_IS_PIPELINE (pipeline));
526
527   GST_LOCK (pipeline);
528   GST_OBJECT_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
529
530   gst_object_replace ((GstObject **) & pipeline->fixed_clock,
531       (GstObject *) clock);
532   GST_UNLOCK (pipeline);
533
534   GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock,
535       (clock ? GST_OBJECT_NAME (clock) : "nil"));
536 }
537
538 /**
539  * gst_pipeline_set_clock:
540  * @pipeline: the pipeline
541  * @clock: the clock to set
542  *
543  * Set the clock for the pipeline. The clock will be distributed
544  * to all the elements managed by the pipeline.
545  *
546  * MT safe.
547  */
548 void
549 gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock)
550 {
551   g_return_if_fail (pipeline != NULL);
552   g_return_if_fail (GST_IS_PIPELINE (pipeline));
553
554   GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline), clock);
555 }
556
557 /**
558  * gst_pipeline_auto_clock:
559  * @pipeline: the pipeline
560  *
561  * Let the pipeline select a clock automatically.
562  *
563  * MT safe.
564  */
565 void
566 gst_pipeline_auto_clock (GstPipeline * pipeline)
567 {
568   g_return_if_fail (pipeline != NULL);
569   g_return_if_fail (GST_IS_PIPELINE (pipeline));
570
571   GST_LOCK (pipeline);
572   GST_OBJECT_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
573
574   gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
575   GST_UNLOCK (pipeline);
576
577   GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");
578 }