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