gst/gstpipeline.c: Take snapshot of state without blocking.
[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 #include "gst_private.h"
24
25 #include "gstpipeline.h"
26 #include "gstinfo.h"
27 #include "gstscheduler.h"
28 #include "gstsystemclock.h"
29
30 static GstElementDetails gst_pipeline_details =
31 GST_ELEMENT_DETAILS ("Pipeline object",
32     "Generic/Bin",
33     "Complete pipeline object",
34     "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
35
36 /* Pipeline signals and args */
37 enum
38 {
39   /* FILL ME */
40   LAST_SIGNAL
41 };
42
43 #define DEFAULT_DELAY 0
44 #define DEFAULT_PLAY_TIMEOUT  (2*GST_SECOND)
45 enum
46 {
47   ARG_0,
48   ARG_DELAY,
49   ARG_PLAY_TIMEOUT,
50   /* FILL ME */
51 };
52
53
54 static void gst_pipeline_base_init (gpointer g_class);
55 static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
56 static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
57
58 static void gst_pipeline_dispose (GObject * object);
59 static void gst_pipeline_set_property (GObject * object, guint prop_id,
60     const GValue * value, GParamSpec * pspec);
61 static void gst_pipeline_get_property (GObject * object, guint prop_id,
62     GValue * value, GParamSpec * pspec);
63
64 static gboolean gst_pipeline_send_event (GstElement * element,
65     GstEvent * event);
66 static GstBusSyncReply pipeline_bus_handler (GstBus * bus, GstMessage * message,
67     GstPipeline * pipeline);
68
69 static GstClock *gst_pipeline_get_clock_func (GstElement * element);
70 static GstElementStateReturn gst_pipeline_change_state (GstElement * element);
71
72 static GstBinClass *parent_class = NULL;
73
74 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
75
76 GType
77 gst_pipeline_get_type (void)
78 {
79   static GType pipeline_type = 0;
80
81   if (!pipeline_type) {
82     static const GTypeInfo pipeline_info = {
83       sizeof (GstPipelineClass),
84       gst_pipeline_base_init,
85       NULL,
86       (GClassInitFunc) gst_pipeline_class_init,
87       NULL,
88       NULL,
89       sizeof (GstPipeline),
90       0,
91       gst_pipeline_init,
92       NULL
93     };
94
95     pipeline_type =
96         g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
97   }
98   return pipeline_type;
99 }
100
101 static void
102 gst_pipeline_base_init (gpointer g_class)
103 {
104   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
105
106   gst_element_class_set_details (gstelement_class, &gst_pipeline_details);
107 }
108
109 static void
110 gst_pipeline_class_init (gpointer g_class, gpointer class_data)
111 {
112   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
113   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
114   GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
115
116   parent_class = g_type_class_peek_parent (klass);
117
118   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property);
119   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property);
120
121   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY,
122       g_param_spec_uint64 ("delay", "Delay",
123           "Expected delay needed for elements "
124           "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
125           G_PARAM_READWRITE));
126   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLAY_TIMEOUT,
127       g_param_spec_uint64 ("play-timeout", "Play Timeout",
128           "Max timeout for going " "to PLAYING in nanoseconds", 0, G_MAXUINT64,
129           DEFAULT_PLAY_TIMEOUT, G_PARAM_READWRITE));
130
131   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
132
133   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_pipeline_send_event);
134   gstelement_class->change_state =
135       GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
136   gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_pipeline_get_clock_func);
137 }
138
139 static void
140 gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
141 {
142   GstScheduler *scheduler;
143   GstPipeline *pipeline = GST_PIPELINE (instance);
144   GstBus *bus;
145
146   /* get an instance of the default scheduler */
147   scheduler = gst_scheduler_factory_make (NULL, GST_ELEMENT (pipeline));
148
149   /* FIXME need better error handling */
150   if (scheduler == NULL) {
151     const gchar *name = gst_scheduler_factory_get_default_name ();
152
153     g_error ("Critical error: could not get scheduler \"%s\"\n"
154         "Are you sure you have a registry ?\n"
155         "Run gst-register as root if you haven't done so yet.", name);
156   }
157   bus = g_object_new (gst_bus_get_type (), NULL);
158   gst_bus_set_sync_handler (bus,
159       (GstBusSyncHandler) pipeline_bus_handler, pipeline);
160   pipeline->eosed = NULL;
161   pipeline->delay = DEFAULT_DELAY;
162   pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT;
163   /* we are our own manager */
164   GST_ELEMENT_MANAGER (pipeline) = pipeline;
165   gst_element_set_bus (GST_ELEMENT (pipeline), bus);
166   /* set_bus refs the bus via gst_object_replace, we drop our ref */
167   gst_object_unref ((GstObject *) bus);
168   gst_element_set_scheduler (GST_ELEMENT (pipeline), scheduler);
169 }
170
171 static void
172 gst_pipeline_dispose (GObject * object)
173 {
174   GstPipeline *pipeline = GST_PIPELINE (object);
175
176   gst_element_set_bus (GST_ELEMENT (pipeline), NULL);
177   gst_scheduler_reset (GST_ELEMENT_SCHEDULER (object));
178   gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
179
180   G_OBJECT_CLASS (parent_class)->dispose (object);
181 }
182
183 static void
184 gst_pipeline_set_property (GObject * object, guint prop_id,
185     const GValue * value, GParamSpec * pspec)
186 {
187   GstPipeline *pipeline = GST_PIPELINE (object);
188
189   GST_LOCK (pipeline);
190   switch (prop_id) {
191     case ARG_DELAY:
192       pipeline->delay = g_value_get_uint64 (value);
193       break;
194     case ARG_PLAY_TIMEOUT:
195       pipeline->play_timeout = g_value_get_uint64 (value);
196       break;
197     default:
198       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
199       break;
200   }
201   GST_UNLOCK (pipeline);
202 }
203
204 static void
205 gst_pipeline_get_property (GObject * object, guint prop_id,
206     GValue * value, GParamSpec * pspec)
207 {
208   GstPipeline *pipeline = GST_PIPELINE (object);
209
210   GST_LOCK (pipeline);
211   switch (prop_id) {
212     case ARG_DELAY:
213       g_value_set_uint64 (value, pipeline->delay);
214       break;
215     case ARG_PLAY_TIMEOUT:
216       g_value_set_uint64 (value, pipeline->play_timeout);
217       break;
218     default:
219       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
220       break;
221   }
222   GST_UNLOCK (pipeline);
223 }
224
225 static gboolean
226 is_eos (GstPipeline * pipeline)
227 {
228   GstIterator *sinks;
229   gboolean result = TRUE;
230   gboolean done = FALSE;
231
232   sinks = gst_bin_iterate_sinks (GST_BIN (pipeline));
233   while (!done) {
234     gpointer data;
235
236     switch (gst_iterator_next (sinks, &data)) {
237       case GST_ITERATOR_OK:
238       {
239         GstElement *element = GST_ELEMENT (data);
240         GList *eosed;
241         GstElementState state, pending;
242         GstElementStateReturn complete;
243         gchar *name;
244
245         complete = gst_element_get_state (element, &state, &pending, NULL);
246         name = gst_element_get_name (element);
247
248         if (complete == GST_STATE_ASYNC) {
249           GST_DEBUG ("element %s still performing state change", name);
250           result = FALSE;
251           done = TRUE;
252           goto done;
253         } else if (state != GST_STATE_PLAYING) {
254           GST_DEBUG ("element %s not playing %d %d", name, state, pending);
255           goto done;
256         }
257         eosed = g_list_find (pipeline->eosed, element);
258         if (!eosed) {
259           result = FALSE;
260           done = TRUE;
261         }
262       done:
263         g_free (name);
264         gst_object_unref (GST_OBJECT (element));
265         break;
266       }
267       case GST_ITERATOR_RESYNC:
268         result = TRUE;
269         gst_iterator_resync (sinks);
270         break;
271       case GST_ITERATOR_DONE:
272         done = TRUE;
273         break;
274       default:
275         g_assert_not_reached ();
276         break;
277     }
278   }
279   gst_iterator_free (sinks);
280   return result;
281 }
282
283 /* sending an event on the pipeline pauses the pipeline if it
284  * was playing.
285  */
286 static gboolean
287 gst_pipeline_send_event (GstElement * element, GstEvent * event)
288 {
289   gboolean was_playing;
290   gboolean res;
291   GstElementState state;
292   GstEventType event_type = GST_EVENT_TYPE (event);
293   GTimeVal timeout;
294
295   /* need to call _get_state() since a bin state is only updated
296    * with this call. */
297   GST_TIME_TO_TIMEVAL (0, timeout);
298
299   gst_element_get_state (element, &state, NULL, &timeout);
300   was_playing = state == GST_STATE_PLAYING;
301
302   if (was_playing && event_type == GST_EVENT_SEEK)
303     gst_element_set_state (element, GST_STATE_PAUSED);
304
305   res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
306
307   if (was_playing && event_type == GST_EVENT_SEEK)
308     gst_element_set_state (element, GST_STATE_PLAYING);
309
310   return res;
311 }
312
313 /* FIXME, make me threadsafe */
314 static GstBusSyncReply
315 pipeline_bus_handler (GstBus * bus, GstMessage * message,
316     GstPipeline * pipeline)
317 {
318   GstBusSyncReply result = GST_BUS_PASS;
319   gboolean posteos = FALSE;
320
321   /* we don't want messages from the streaming thread while we're doing the 
322    * state change. We do want them from the state change functions. */
323
324   switch (GST_MESSAGE_TYPE (message)) {
325     case GST_MESSAGE_EOS:
326       if (GST_MESSAGE_SRC (message) != GST_OBJECT (pipeline)) {
327         GST_DEBUG ("got EOS message");
328         GST_LOCK (bus);
329         pipeline->eosed =
330             g_list_prepend (pipeline->eosed, GST_MESSAGE_SRC (message));
331         GST_UNLOCK (bus);
332         if (is_eos (pipeline)) {
333           posteos = TRUE;
334         }
335         /* we drop all EOS messages */
336         result = GST_BUS_DROP;
337         gst_message_unref (message);
338       }
339       break;
340     case GST_MESSAGE_ERROR:
341       break;
342     default:
343       break;
344   }
345
346   if (posteos) {
347     gst_bus_post (bus, gst_message_new_eos (GST_OBJECT (pipeline)));
348   }
349
350   return result;
351 }
352
353 /**
354  * gst_pipeline_new:
355  * @name: name of new pipeline
356  *
357  * Create a new pipeline with the given name.
358  *
359  * Returns: newly created GstPipeline
360  *
361  * MT safe.
362  */
363 GstElement *
364 gst_pipeline_new (const gchar * name)
365 {
366   return gst_element_factory_make ("pipeline", name);
367 }
368
369 /* MT safe */
370 static GstElementStateReturn
371 gst_pipeline_change_state (GstElement * element)
372 {
373   GstElementStateReturn result = GST_STATE_SUCCESS;
374   GstPipeline *pipeline = GST_PIPELINE (element);
375   gint transition = GST_STATE_TRANSITION (element);
376
377   switch (transition) {
378     case GST_STATE_NULL_TO_READY:
379       if (element->bus)
380         gst_bus_set_flushing (element->bus, FALSE);
381       gst_scheduler_setup (GST_ELEMENT_SCHEDULER (pipeline));
382       break;
383     case GST_STATE_READY_TO_PAUSED:
384     {
385       GstClock *clock;
386
387       clock = gst_element_get_clock (element);
388       gst_element_set_clock (element, clock);
389       pipeline->eosed = NULL;
390       break;
391     }
392     case GST_STATE_PAUSED_TO_PLAYING:
393       if (element->clock) {
394         GstClockTime start_time = gst_clock_get_time (element->clock);
395
396         element->base_time = start_time -
397             pipeline->stream_time + pipeline->delay;
398         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
399             GST_TIME_FORMAT ", base time %" GST_TIME_FORMAT,
400             GST_TIME_ARGS (pipeline->stream_time),
401             GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
402       } else {
403         element->base_time = 0;
404         GST_DEBUG ("no clock, using base time of 0");
405       }
406       break;
407     case GST_STATE_PLAYING_TO_PAUSED:
408     case GST_STATE_PAUSED_TO_READY:
409     case GST_STATE_READY_TO_NULL:
410       break;
411   }
412
413   result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
414
415   switch (transition) {
416     case GST_STATE_READY_TO_PAUSED:
417       pipeline->stream_time = 0;
418       break;
419     case GST_STATE_PAUSED_TO_PLAYING:
420       break;
421     case GST_STATE_PLAYING_TO_PAUSED:
422       if (element->clock) {
423         GstClockTime now;
424
425         now = gst_clock_get_time (element->clock);
426         pipeline->stream_time = now - element->base_time;
427         GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
428             ", base time %" GST_TIME_FORMAT,
429             GST_TIME_ARGS (pipeline->stream_time),
430             GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
431       }
432       break;
433     case GST_STATE_PAUSED_TO_READY:
434       break;
435     case GST_STATE_READY_TO_NULL:
436       if (element->bus) {
437         gst_bus_set_flushing (element->bus, TRUE);
438       }
439       break;
440   }
441
442   /* we wait for async state changes ourselves.
443    * FIXME this can block forever, better do this in a worker
444    * thread or use a timeout? */
445   if (result == GST_STATE_ASYNC) {
446     GTimeVal *timeval, timeout;
447
448     GST_STATE_UNLOCK (pipeline);
449
450     GST_LOCK (pipeline);
451     if (pipeline->play_timeout > 0) {
452       GST_TIME_TO_TIMEVAL (pipeline->play_timeout, timeout);
453       timeval = &timeout;
454     } else {
455       timeval = NULL;
456     }
457     GST_UNLOCK (pipeline);
458
459     result = gst_element_get_state (element, NULL, NULL, timeval);
460     GST_STATE_LOCK (pipeline);
461   }
462
463   return result;
464 }
465
466 /**
467  * gst_pipeline_get_scheduler:
468  * @pipeline: the pipeline
469  *
470  * Gets the #GstScheduler of this pipeline.
471  *
472  * Returns: a GstScheduler.
473  *
474  * MT safe.
475  */
476 GstScheduler *
477 gst_pipeline_get_scheduler (GstPipeline * pipeline)
478 {
479   return gst_element_get_scheduler (GST_ELEMENT (pipeline));
480 }
481
482 /**
483  * gst_pipeline_get_bus:
484  * @pipeline: the pipeline
485  *
486  * Gets the #GstBus of this pipeline.
487  *
488  * Returns: a GstBus
489  *
490  * MT safe.
491  */
492 GstBus *
493 gst_pipeline_get_bus (GstPipeline * pipeline)
494 {
495   return gst_element_get_bus (GST_ELEMENT (pipeline));
496 }
497
498 static GstClock *
499 gst_pipeline_get_clock_func (GstElement * element)
500 {
501   GstClock *clock = NULL;
502   GstPipeline *pipeline = GST_PIPELINE (element);
503
504   /* if we have a fixed clock, use that one */
505   GST_LOCK (pipeline);
506   if (GST_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
507     clock = pipeline->fixed_clock;
508     gst_object_ref (GST_OBJECT (clock));
509     GST_UNLOCK (pipeline);
510
511     GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
512         clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
513   } else {
514     GST_UNLOCK (pipeline);
515     clock =
516         GST_ELEMENT_CLASS (parent_class)->get_clock (GST_ELEMENT (pipeline));
517     /* no clock, use a system clock */
518     if (!clock) {
519       clock = gst_system_clock_obtain ();
520       /* we unref since this function is not supposed to increase refcount
521        * of clock object returned; this is ok since the systemclock always
522        * has a refcount of at least one in the current code. */
523       gst_object_unref (GST_OBJECT (clock));
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_get_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 }