94c1ee4d57bab7b7e14ab91dfe61d85432739972
[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
157   pipeline->delay = DEFAULT_DELAY;
158   pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT;
159 }
160
161 static void
162 gst_pipeline_dispose (GObject * object)
163 {
164   GstPipeline *pipeline = GST_PIPELINE (object);
165
166   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose");
167
168   gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
169
170   G_OBJECT_CLASS (parent_class)->dispose (object);
171 }
172
173 static void
174 gst_pipeline_set_property (GObject * object, guint prop_id,
175     const GValue * value, GParamSpec * pspec)
176 {
177   GstPipeline *pipeline = GST_PIPELINE (object);
178
179   GST_LOCK (pipeline);
180   switch (prop_id) {
181     case ARG_DELAY:
182       pipeline->delay = g_value_get_uint64 (value);
183       break;
184     case ARG_PLAY_TIMEOUT:
185       pipeline->play_timeout = g_value_get_uint64 (value);
186       break;
187     default:
188       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
189       break;
190   }
191   GST_UNLOCK (pipeline);
192 }
193
194 static void
195 gst_pipeline_get_property (GObject * object, guint prop_id,
196     GValue * value, GParamSpec * pspec)
197 {
198   GstPipeline *pipeline = GST_PIPELINE (object);
199
200   GST_LOCK (pipeline);
201   switch (prop_id) {
202     case ARG_DELAY:
203       g_value_set_uint64 (value, pipeline->delay);
204       break;
205     case ARG_PLAY_TIMEOUT:
206       g_value_set_uint64 (value, pipeline->play_timeout);
207       break;
208     default:
209       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
210       break;
211   }
212   GST_UNLOCK (pipeline);
213 }
214
215 static gboolean
216 do_pipeline_seek (GstElement * element, GstEvent * event)
217 {
218   gdouble rate;
219   GstSeekFlags flags;
220   gboolean flush;
221   gboolean was_playing = FALSE;
222   gboolean res;
223
224   gst_event_parse_seek (event, &rate, NULL, &flags, NULL, NULL, NULL, NULL);
225
226   flush = flags & GST_SEEK_FLAG_FLUSH;
227
228   if (flush) {
229     GstState state;
230     GTimeVal timeout;
231
232     GST_TIME_TO_TIMEVAL (0, timeout);
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, &timeout);
236     was_playing = state == GST_STATE_PLAYING;
237
238     if (was_playing)
239       gst_element_set_state (element, GST_STATE_PAUSED);
240   }
241
242   res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
243
244   if (flush && res) {
245     /* need to reset the stream time to 0 after a flushing seek */
246     gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);
247     if (was_playing) {
248       /* and continue playing */
249       gst_element_set_state (element, GST_STATE_PLAYING);
250     }
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   GstClockTime play_timeout;
299   GstClock *clock;
300
301   switch (transition) {
302     case GST_STATE_CHANGE_NULL_TO_READY:
303       GST_LOCK (element);
304       if (element->bus)
305         gst_bus_set_flushing (element->bus, FALSE);
306       GST_UNLOCK (element);
307       break;
308     case GST_STATE_CHANGE_READY_TO_PAUSED:
309       break;
310     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
311       /* when going to playing, select a clock */
312       if ((clock = gst_element_provide_clock (element))) {
313         GstClockTime start_time;
314
315         /* distribute the clock */
316         gst_element_set_clock (element, clock);
317
318         /* get start time */
319         start_time = gst_clock_get_time (clock);
320         gst_object_unref (clock);
321
322         GST_LOCK (element);
323         element->base_time = start_time -
324             pipeline->stream_time + pipeline->delay;
325         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
326             GST_TIME_FORMAT ", base time %" GST_TIME_FORMAT,
327             GST_TIME_ARGS (pipeline->stream_time),
328             GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
329         GST_UNLOCK (element);
330       } else {
331         GST_DEBUG ("no clock, using base time of 0");
332         gst_element_set_base_time (element, 0);
333       }
334       break;
335     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
336     case GST_STATE_CHANGE_PAUSED_TO_READY:
337     case GST_STATE_CHANGE_READY_TO_NULL:
338       break;
339   }
340
341   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
342
343   switch (transition) {
344     case GST_STATE_CHANGE_NULL_TO_READY:
345       break;
346     case GST_STATE_CHANGE_READY_TO_PAUSED:
347       gst_pipeline_set_new_stream_time (pipeline, 0);
348       break;
349     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
350       break;
351     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
352       GST_LOCK (element);
353       if ((clock = element->clock)) {
354         GstClockTime now;
355
356         gst_object_ref (clock);
357         GST_UNLOCK (element);
358
359         /* calculate the time when we stopped */
360         now = gst_clock_get_time (clock);
361         gst_object_unref (clock);
362
363         GST_LOCK (element);
364         /* store the current stream time */
365         pipeline->stream_time = now - element->base_time;
366         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
367             ", base time %" GST_TIME_FORMAT,
368             GST_TIME_ARGS (pipeline->stream_time),
369             GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
370       }
371       GST_UNLOCK (element);
372       break;
373     case GST_STATE_CHANGE_PAUSED_TO_READY:
374       break;
375     case GST_STATE_CHANGE_READY_TO_NULL:
376       GST_LOCK (element);
377       if (element->bus) {
378         gst_bus_set_flushing (element->bus, TRUE);
379       }
380       GST_UNLOCK (element);
381       break;
382   }
383
384   if (result == GST_STATE_CHANGE_ASYNC) {
385     GST_LOCK (pipeline);
386     play_timeout = pipeline->play_timeout;
387     GST_UNLOCK (pipeline);
388   } else {
389     play_timeout = 0;
390   }
391
392   /* we wait for async state changes ourselves when we are in an
393    * intermediate state. */
394   if (play_timeout > 0) {
395     GTimeVal *timeval, timeout;
396
397     GST_STATE_UNLOCK (pipeline);
398
399     if (play_timeout == G_MAXUINT64) {
400       timeval = NULL;
401     } else {
402       GST_TIME_TO_TIMEVAL (play_timeout, timeout);
403       timeval = &timeout;
404     }
405
406     result = gst_element_get_state (element, NULL, NULL, timeval);
407     if (result == GST_STATE_CHANGE_ASYNC) {
408       GST_WARNING_OBJECT (pipeline,
409           "timeout in PREROLL, forcing next state change");
410       g_warning ("timeout in PREROLL, forcing next state change");
411       result = GST_STATE_CHANGE_SUCCESS;
412     }
413
414     GST_STATE_LOCK (pipeline);
415   }
416
417   return result;
418 }
419
420 /**
421  * gst_pipeline_get_bus:
422  * @pipeline: the pipeline
423  *
424  * Gets the #GstBus of this pipeline.
425  *
426  * Returns: a GstBus
427  *
428  * MT safe.
429  */
430 GstBus *
431 gst_pipeline_get_bus (GstPipeline * pipeline)
432 {
433   return gst_element_get_bus (GST_ELEMENT (pipeline));
434 }
435
436 /**
437  * gst_pipeline_set_new_stream_time:
438  * @pipeline: the pipeline
439  * @time: the new stream time to set
440  *
441  * Set the new stream time of the pipeline. The stream time is used to
442  * set the base time on the elements (see @gst_element_set_base_time())
443  * in the PAUSED->PLAYING state transition.
444  *
445  * MT safe.
446  */
447 void
448 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
449 {
450   g_return_if_fail (GST_IS_PIPELINE (pipeline));
451
452   GST_LOCK (pipeline);
453   pipeline->stream_time = time;
454   GST_DEBUG ("%s: set new stream_time to %" GST_TIME_FORMAT,
455       GST_ELEMENT_NAME (pipeline), GST_TIME_ARGS (time));
456   GST_UNLOCK (pipeline);
457 }
458
459 /**
460  * gst_pipeline_get_last_stream_time:
461  * @pipeline: the pipeline
462  *
463  * Gets the last stream time of the pipeline. If the pipeline is PLAYING,
464  * the returned time is the stream time used to configure the elements
465  * in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned
466  * time is the stream time when the pipeline was paused.
467  *
468  * Returns: a GstClockTime
469  *
470  * MT safe.
471  */
472 GstClockTime
473 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
474 {
475   GstClockTime result;
476
477   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
478
479   GST_LOCK (pipeline);
480   result = pipeline->stream_time;
481   GST_UNLOCK (pipeline);
482
483   return result;
484 }
485
486 static GstClock *
487 gst_pipeline_provide_clock_func (GstElement * element)
488 {
489   GstClock *clock = NULL;
490   GstPipeline *pipeline = GST_PIPELINE (element);
491
492   /* if we have a fixed clock, use that one */
493   GST_LOCK (pipeline);
494   if (GST_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
495     clock = pipeline->fixed_clock;
496     gst_object_ref (clock);
497     GST_UNLOCK (pipeline);
498
499     GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
500         clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
501   } else {
502     GST_UNLOCK (pipeline);
503     clock =
504         GST_ELEMENT_CLASS (parent_class)->
505         provide_clock (GST_ELEMENT (pipeline));
506     /* no clock, use a system clock */
507     if (!clock) {
508       clock = gst_system_clock_obtain ();
509
510       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
511           clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
512     } else {
513       GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)",
514           clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
515     }
516   }
517   return clock;
518 }
519
520 /**
521  * gst_pipeline_get_clock:
522  * @pipeline: the pipeline
523  *
524  * Gets the current clock used by the pipeline.
525  *
526  * Returns: a GstClock
527  */
528 GstClock *
529 gst_pipeline_get_clock (GstPipeline * pipeline)
530 {
531   g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);
532
533   return gst_pipeline_provide_clock_func (GST_ELEMENT (pipeline));
534 }
535
536
537 /**
538  * gst_pipeline_use_clock:
539  * @pipeline: the pipeline
540  * @clock: the clock to use
541  *
542  * Force the pipeline to use the given clock. The pipeline will
543  * always use the given clock even if new clock providers are added
544  * to this pipeline.
545  *
546  * MT safe.
547  */
548 void
549 gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock)
550 {
551   g_return_if_fail (GST_IS_PIPELINE (pipeline));
552
553   GST_LOCK (pipeline);
554   GST_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
555
556   gst_object_replace ((GstObject **) & pipeline->fixed_clock,
557       (GstObject *) clock);
558   GST_UNLOCK (pipeline);
559
560   GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock,
561       (clock ? GST_OBJECT_NAME (clock) : "nil"));
562 }
563
564 /**
565  * gst_pipeline_set_clock:
566  * @pipeline: the pipeline
567  * @clock: the clock to set
568  *
569  * Set the clock for the pipeline. The clock will be distributed
570  * to all the elements managed by the pipeline.
571  *
572  * MT safe.
573  */
574 void
575 gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock)
576 {
577   g_return_if_fail (pipeline != NULL);
578   g_return_if_fail (GST_IS_PIPELINE (pipeline));
579
580   GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline), clock);
581 }
582
583 /**
584  * gst_pipeline_auto_clock:
585  * @pipeline: the pipeline
586  *
587  * Let the pipeline select a clock automatically.
588  *
589  * MT safe.
590  */
591 void
592 gst_pipeline_auto_clock (GstPipeline * pipeline)
593 {
594   g_return_if_fail (pipeline != NULL);
595   g_return_if_fail (GST_IS_PIPELINE (pipeline));
596
597   GST_LOCK (pipeline);
598   GST_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
599
600   gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
601   GST_UNLOCK (pipeline);
602
603   GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");
604 }