2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2004,2005 Wim Taymans <wim@fluendo.com>
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 #include "gst_private.h"
25 #include "gstpipeline.h"
27 #include "gstsystemclock.h"
29 static GstElementDetails gst_pipeline_details =
30 GST_ELEMENT_DETAILS ("Pipeline object",
32 "Complete pipeline object",
33 "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
35 /* Pipeline signals and args */
42 #define DEFAULT_DELAY 0
43 #define DEFAULT_PLAY_TIMEOUT (2*GST_SECOND)
53 static void gst_pipeline_base_init (gpointer g_class);
54 static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
55 static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
57 static void gst_pipeline_dispose (GObject * object);
58 static void gst_pipeline_set_property (GObject * object, guint prop_id,
59 const GValue * value, GParamSpec * pspec);
60 static void gst_pipeline_get_property (GObject * object, guint prop_id,
61 GValue * value, GParamSpec * pspec);
63 static gboolean gst_pipeline_send_event (GstElement * element,
66 static GstClock *gst_pipeline_get_clock_func (GstElement * element);
67 static GstElementStateReturn gst_pipeline_change_state (GstElement * element);
69 static GstBinClass *parent_class = NULL;
71 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
74 gst_pipeline_get_type (void)
76 static GType pipeline_type = 0;
79 static const GTypeInfo pipeline_info = {
80 sizeof (GstPipelineClass),
81 gst_pipeline_base_init,
83 (GClassInitFunc) gst_pipeline_class_init,
93 g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
99 gst_pipeline_base_init (gpointer g_class)
101 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
103 gst_element_class_set_details (gstelement_class, &gst_pipeline_details);
107 gst_pipeline_class_init (gpointer g_class, gpointer class_data)
109 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
110 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
111 GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
113 parent_class = g_type_class_peek_parent (klass);
115 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property);
116 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property);
118 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY,
119 g_param_spec_uint64 ("delay", "Delay",
120 "Expected delay needed for elements "
121 "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
123 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLAY_TIMEOUT,
124 g_param_spec_uint64 ("play-timeout", "Play Timeout",
125 "Max timeout for going to PLAYING in nanoseconds", 0, G_MAXUINT64,
126 DEFAULT_PLAY_TIMEOUT, G_PARAM_READWRITE));
128 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
130 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_pipeline_send_event);
131 gstelement_class->change_state =
132 GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
133 gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_pipeline_get_clock_func);
137 gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
139 GstPipeline *pipeline = GST_PIPELINE (instance);
141 pipeline->delay = DEFAULT_DELAY;
142 pipeline->play_timeout = DEFAULT_PLAY_TIMEOUT;
146 gst_pipeline_dispose (GObject * object)
148 GstPipeline *pipeline = GST_PIPELINE (object);
150 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose");
152 gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
154 G_OBJECT_CLASS (parent_class)->dispose (object);
158 gst_pipeline_set_property (GObject * object, guint prop_id,
159 const GValue * value, GParamSpec * pspec)
161 GstPipeline *pipeline = GST_PIPELINE (object);
166 pipeline->delay = g_value_get_uint64 (value);
168 case ARG_PLAY_TIMEOUT:
169 pipeline->play_timeout = g_value_get_uint64 (value);
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
175 GST_UNLOCK (pipeline);
179 gst_pipeline_get_property (GObject * object, guint prop_id,
180 GValue * value, GParamSpec * pspec)
182 GstPipeline *pipeline = GST_PIPELINE (object);
187 g_value_set_uint64 (value, pipeline->delay);
189 case ARG_PLAY_TIMEOUT:
190 g_value_set_uint64 (value, pipeline->play_timeout);
193 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
196 GST_UNLOCK (pipeline);
199 /* sending an event on the pipeline pauses the pipeline if it
203 gst_pipeline_send_event (GstElement * element, GstEvent * event)
205 gboolean was_playing;
207 GstElementState state;
208 GstEventType event_type = GST_EVENT_TYPE (event);
211 /* need to call _get_state() since a bin state is only updated
213 GST_TIME_TO_TIMEVAL (0, timeout);
215 gst_element_get_state (element, &state, NULL, &timeout);
216 was_playing = state == GST_STATE_PLAYING;
218 if (event_type == GST_EVENT_SEEK) {
220 gst_element_set_state (element, GST_STATE_PAUSED);
223 res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
225 if (res && event_type == GST_EVENT_SEEK) {
226 /* need to set the stream time to the seek time */
227 gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);
229 gst_element_set_state (element, GST_STATE_PLAYING);
237 * @name: name of new pipeline
239 * Create a new pipeline with the given name.
241 * Returns: newly created GstPipeline
246 gst_pipeline_new (const gchar * name)
248 return gst_element_factory_make ("pipeline", name);
252 static GstElementStateReturn
253 gst_pipeline_change_state (GstElement * element)
255 GstElementStateReturn result = GST_STATE_SUCCESS;
256 GstPipeline *pipeline = GST_PIPELINE (element);
257 gint transition = GST_STATE_TRANSITION (element);
258 GstClockTime play_timeout;
261 switch (transition) {
262 case GST_STATE_NULL_TO_READY:
265 gst_bus_set_flushing (element->bus, FALSE);
266 GST_UNLOCK (element);
268 case GST_STATE_READY_TO_PAUSED:
270 case GST_STATE_PAUSED_TO_PLAYING:
271 /* when going to playing, select a clock */
272 if ((clock = gst_element_get_clock (element))) {
273 GstClockTime start_time;
275 /* distribute the clock */
276 gst_element_set_clock (element, clock);
279 start_time = gst_clock_get_time (clock);
280 gst_object_unref (clock);
283 element->base_time = start_time -
284 pipeline->stream_time + pipeline->delay;
285 GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", start_time=%"
286 GST_TIME_FORMAT ", base time %" GST_TIME_FORMAT,
287 GST_TIME_ARGS (pipeline->stream_time),
288 GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time));
289 GST_UNLOCK (element);
291 GST_UNLOCK (element);
292 GST_DEBUG ("no clock, using base time of 0");
293 gst_element_set_base_time (element, 0);
296 case GST_STATE_PLAYING_TO_PAUSED:
297 case GST_STATE_PAUSED_TO_READY:
298 case GST_STATE_READY_TO_NULL:
302 result = GST_ELEMENT_CLASS (parent_class)->change_state (element);
304 switch (transition) {
305 case GST_STATE_READY_TO_PAUSED:
306 gst_pipeline_set_new_stream_time (pipeline, 0);
308 case GST_STATE_PAUSED_TO_PLAYING:
310 case GST_STATE_PLAYING_TO_PAUSED:
312 if ((clock = element->clock)) {
315 gst_object_ref (clock);
316 GST_UNLOCK (element);
318 /* calculate the time when we stopped */
319 now = gst_clock_get_time (clock);
320 gst_object_unref (clock);
323 /* store the current stream time */
324 pipeline->stream_time = now - element->base_time;
325 GST_DEBUG ("stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
326 ", base time %" GST_TIME_FORMAT,
327 GST_TIME_ARGS (pipeline->stream_time),
328 GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time));
330 GST_UNLOCK (element);
332 case GST_STATE_PAUSED_TO_READY:
334 case GST_STATE_READY_TO_NULL:
337 gst_bus_set_flushing (element->bus, TRUE);
339 GST_UNLOCK (element);
343 if (result == GST_STATE_ASYNC) {
345 play_timeout = pipeline->play_timeout;
346 GST_UNLOCK (pipeline);
351 /* we wait for async state changes ourselves when we are in an
352 * intermediate state. */
353 if (play_timeout > 0) {
354 GTimeVal *timeval, timeout;
356 GST_STATE_UNLOCK (pipeline);
358 if (play_timeout == G_MAXUINT64) {
361 GST_TIME_TO_TIMEVAL (play_timeout, timeout);
365 result = gst_element_get_state (element, NULL, NULL, timeval);
366 if (result == GST_STATE_ASYNC) {
367 GST_WARNING_OBJECT (pipeline,
368 "timeout in PREROLL, forcing next state change");
369 g_warning ("timeout in PREROLL, forcing next state change");
370 result = GST_STATE_SUCCESS;
373 GST_STATE_LOCK (pipeline);
380 * gst_pipeline_get_bus:
381 * @pipeline: the pipeline
383 * Gets the #GstBus of this pipeline.
390 gst_pipeline_get_bus (GstPipeline * pipeline)
392 return gst_element_get_bus (GST_ELEMENT (pipeline));
396 * gst_pipeline_set_new_stream_time:
397 * @pipeline: the pipeline
399 * Set the new stream time of the pipeline. The stream time is used to
400 * set the base time on the elements (see @gst_element_set_base_time())
401 * in the PAUSED->PLAYING state transition.
406 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
408 g_return_if_fail (GST_IS_PIPELINE (pipeline));
411 pipeline->stream_time = time;
412 GST_DEBUG ("%s: set new stream_time to %" GST_TIME_FORMAT,
413 GST_ELEMENT_NAME (pipeline), time);
414 GST_UNLOCK (pipeline);
418 * gst_pipeline_get_last_stream_time:
419 * @pipeline: the pipeline
421 * Gets the last stream time of the pipeline. If the pipeline is PLAYING,
422 * the returned time is the stream time used to configure the elements
423 * in the PAUSED->PLAYING state. If the pipeline is PAUSED, the returned
424 * time is the stream time when the pipeline was paused.
426 * Returns: a GstClockTime
431 gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
435 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);
438 result = pipeline->stream_time;
439 GST_UNLOCK (pipeline);
445 gst_pipeline_get_clock_func (GstElement * element)
447 GstClock *clock = NULL;
448 GstPipeline *pipeline = GST_PIPELINE (element);
450 /* if we have a fixed clock, use that one */
452 if (GST_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
453 clock = pipeline->fixed_clock;
454 gst_object_ref (clock);
455 GST_UNLOCK (pipeline);
457 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
458 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
460 GST_UNLOCK (pipeline);
462 GST_ELEMENT_CLASS (parent_class)->get_clock (GST_ELEMENT (pipeline));
463 /* no clock, use a system clock */
465 clock = gst_system_clock_obtain ();
467 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
468 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
470 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)",
471 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
478 * gst_pipeline_get_clock:
479 * @pipeline: the pipeline
481 * Gets the current clock used by the pipeline.
483 * Returns: a GstClock
486 gst_pipeline_get_clock (GstPipeline * pipeline)
488 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);
490 return gst_pipeline_get_clock_func (GST_ELEMENT (pipeline));
495 * gst_pipeline_use_clock:
496 * @pipeline: the pipeline
497 * @clock: the clock to use
499 * Force the pipeline to use the given clock. The pipeline will
500 * always use the given clock even if new clock providers are added
506 gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock)
508 g_return_if_fail (GST_IS_PIPELINE (pipeline));
511 GST_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
513 gst_object_replace ((GstObject **) & pipeline->fixed_clock,
514 (GstObject *) clock);
515 GST_UNLOCK (pipeline);
517 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock,
518 (clock ? GST_OBJECT_NAME (clock) : "nil"));
522 * gst_pipeline_set_clock:
523 * @pipeline: the pipeline
524 * @clock: the clock to set
526 * Set the clock for the pipeline. The clock will be distributed
527 * to all the elements managed by the pipeline.
532 gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock)
534 g_return_if_fail (pipeline != NULL);
535 g_return_if_fail (GST_IS_PIPELINE (pipeline));
537 GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline), clock);
541 * gst_pipeline_auto_clock:
542 * @pipeline: the pipeline
544 * Let the pipeline select a clock automatically.
549 gst_pipeline_auto_clock (GstPipeline * pipeline)
551 g_return_if_fail (pipeline != NULL);
552 g_return_if_fail (GST_IS_PIPELINE (pipeline));
555 GST_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
557 gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
558 GST_UNLOCK (pipeline);
560 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");