gstpipeline.c 26.6 KB
Newer Older
1
2
/* GStreamer
 * 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
Erik Walthinsen's avatar
Erik Walthinsen committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
22

23
24
/**
 * SECTION:gstpipeline
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
25
26
 * @short_description: Top-level bin with clocking and bus management
                       functionality.
Wim Taymans's avatar
Wim Taymans committed
27
 * @see_also: #GstElement, #GstBin, #GstClock, #GstBus
28
 *
Wim Taymans's avatar
Wim Taymans committed
29
30
31
32
33
 * A #GstPipeline is a special #GstBin used as the toplevel container for
 * the filter graph. The #GstPipeline will manage the selection and 
 * distribution of a global #GstClock as well as provide a #GstBus to the 
 * application. It will also implement a default behavour for managing
 * seek events (see gst_element_seek()).
34
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
35
 * gst_pipeline_new() is used to create a pipeline. when you are done with
36
 * the pipeline, use gst_object_unref() to free its resources including all
37
 * added #GstElement objects (if not otherwise referenced).
Wim Taymans's avatar
Wim Taymans committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 *
 * Elements are added and removed from the pipeline using the #GstBin 
 * methods like gst_bin_add() and gst_bin_remove() (see #GstBin).
 *
 * Before changing the state of the #GstPipeline (see #GstElement) a #GstBus
 * can be retrieved with gst_pipeline_get_bus(). This bus can then be
 * used to receive #GstMessage from the elements in the pipeline.
 *
 * By default, a #GstPipeline will automatically flush the pending #GstBus
 * messages when going to the NULL state to ensure that no circular
 * references exist when no messages are read from the #GstBus. This
 * behaviour can be changed with gst_pipeline_set_auto_flush_bus().
 *
 * When the #GstPipeline performs the PAUSED to PLAYING state change it will
 * select a clock for the elements. The clock selection algorithm will by
 * default select a clock provided by an element that is most upstream 
 * (closest to the source). For live pipelines (ones that return 
 * #GST_STATE_CHANGE_NO_PREROLL from the gst_element_set_state() call) this
 * will select the clock provided by the live source. For normal pipelines
 * this will select a clock provided by the sinks (most likely the audio
 * sink). If no element provides a clock, a default #GstSystemClock is used.
 *
 * The clock selection can be controlled with the gst_pipeline_use_clock()
 * method, which will enforce a given clock on the pipeline. With
 * gst_pipeline_auto_clock() the default clock selection algorithm can be 
 * restored.
 *
 * A #GstPipeline maintains a stream time for the elements. The stream
 * time is defined as the difference between the current clock time and
 * the base time. When the pipeline goes to READY or a flushing seek is
 * performed on it, the stream time is reset to 0. When the pipeline is
 * set from PLAYING to PAUSED, the current clock time is sampled and used to 
 * configure the base time for the elements when the pipeline is set
 * to PLAYING again. This default behaviour can be changed with the
 * gst_pipeline_set_new_stream_time() method. 
 * 
 * When sending a flushing seek event to a GstPipeline (see 
 * gst_element_seek()), it will make sure that the pipeline is properly 
 * PAUSED and resumed as well as set the new stream time to 0 when the
 * seek succeeded.
 *
 * Last reviewed on 2006-03-12 (0.10.5)
80
 */
Erik Walthinsen's avatar
Erik Walthinsen committed
81

82
#include "gst_private.h"
83
84
#include "gsterror.h"
#include "gst-i18n-lib.h"
Wim Taymans's avatar
Wim Taymans committed
85

86
#include "gstpipeline.h"
87
#include "gstinfo.h"
Wim Taymans's avatar
Wim Taymans committed
88
#include "gstsystemclock.h"
89

Wim Taymans's avatar
Wim Taymans committed
90
91
92
GST_DEBUG_CATEGORY_STATIC (pipeline_debug);
#define GST_CAT_DEFAULT pipeline_debug

Stefan Kost's avatar
Stefan Kost committed
93
static const GstElementDetails gst_pipeline_details =
94
95
96
GST_ELEMENT_DETAILS ("Pipeline object",
    "Generic/Bin",
    "Complete pipeline object",
97
    "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
Erik Walthinsen's avatar
Erik Walthinsen committed
98
99

/* Pipeline signals and args */
100
101
enum
{
Erik Walthinsen's avatar
Erik Walthinsen committed
102
103
104
105
  /* FILL ME */
  LAST_SIGNAL
};

106
107
#define DEFAULT_DELAY           0
#define DEFAULT_AUTO_FLUSH_BUS  TRUE
108

109
110
enum
{
111
112
  PROP_0,
  PROP_DELAY,
113
114
115
116
117
118
119
120
  PROP_AUTO_FLUSH_BUS
};

#define GST_PIPELINE_GET_PRIVATE(obj)  \
   (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PIPELINE, GstPipelinePrivate))

struct _GstPipelinePrivate
{
Wim Taymans's avatar
Wim Taymans committed
121
  /* with LOCK */
122
  gboolean auto_flush_bus;
Erik Walthinsen's avatar
Erik Walthinsen committed
123
124
125
};


126
127
128
static void gst_pipeline_base_init (gpointer g_class);
static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
Erik Walthinsen's avatar
Erik Walthinsen committed
129

130
static void gst_pipeline_dispose (GObject * object);
Wim Taymans's avatar
Wim Taymans committed
131
132
133
134
static void gst_pipeline_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_pipeline_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
135

136
137
static gboolean gst_pipeline_send_event (GstElement * element,
    GstEvent * event);
Wim Taymans's avatar
Wim Taymans committed
138

139
static GstClock *gst_pipeline_provide_clock_func (GstElement * element);
140
141
static GstStateChangeReturn gst_pipeline_change_state (GstElement * element,
    GstStateChange transition);
Erik Walthinsen's avatar
Erik Walthinsen committed
142

143
static GstBinClass *parent_class = NULL;
144

145
/* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */
Erik Walthinsen's avatar
Erik Walthinsen committed
146

147
GType
148
149
gst_pipeline_get_type (void)
{
150
  static GType pipeline_type = 0;
Erik Walthinsen's avatar
Erik Walthinsen committed
151

Wim Taymans's avatar
Wim Taymans committed
152
  if (G_UNLIKELY (pipeline_type == 0)) {
153
    static const GTypeInfo pipeline_info = {
154
      sizeof (GstPipelineClass),
155
      gst_pipeline_base_init,
156
      NULL,
157
      (GClassInitFunc) gst_pipeline_class_init,
158
159
      NULL,
      NULL,
160
      sizeof (GstPipeline),
161
      0,
162
      gst_pipeline_init,
163
      NULL
Erik Walthinsen's avatar
Erik Walthinsen committed
164
    };
165

166
    pipeline_type =
167
        g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0);
Wim Taymans's avatar
Wim Taymans committed
168
169
170

    GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD,
        "debugging info for the 'pipeline' container element");
Erik Walthinsen's avatar
Erik Walthinsen committed
171
172
173
174
175
  }
  return pipeline_type;
}

static void
176
gst_pipeline_base_init (gpointer g_class)
Wim Taymans's avatar
Wim Taymans committed
177
{
178
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
179

180
181
  gst_element_class_set_details (gstelement_class, &gst_pipeline_details);
}
Erik Walthinsen's avatar
Erik Walthinsen committed
182

183
184
185
186
187
188
static void
gst_pipeline_class_init (gpointer g_class, gpointer class_data)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
  GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class);
Erik Walthinsen's avatar
Erik Walthinsen committed
189

190
  parent_class = g_type_class_peek_parent (klass);
Erik Walthinsen's avatar
Erik Walthinsen committed
191

192
193
  g_type_class_add_private (klass, sizeof (GstPipelinePrivate));

Wim Taymans's avatar
Wim Taymans committed
194
195
196
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property);

Wim Taymans's avatar
Wim Taymans committed
197
198
199
200
201
202
  /**
   * GstPipeline:delay
   *
   * The expected delay needed for elements to spin up to the
   * PLAYING state expressed in nanoseconds.
   * see gst_pipeline_set_delay() for more information on this option.
203
204
   *
   * Since: 0.10.5
Wim Taymans's avatar
Wim Taymans committed
205
   **/
206
  g_object_class_install_property (gobject_class, PROP_DELAY,
Wim Taymans's avatar
Wim Taymans committed
207
208
209
210
211
      g_param_spec_uint64 ("delay", "Delay",
          "Expected delay needed for elements "
          "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
          G_PARAM_READWRITE));

Wim Taymans's avatar
Wim Taymans committed
212
213
214
215
216
217
218
219
220
  /**
   * GstPipeline:auto-flush-bus:
   *
   * Whether or not to automatically flush all messages on the
   * pipeline's bus when going from READY to NULL state. Please see
   * gst_pipeline_set_auto_flush_bus() for more information on this option.
   *
   * Since: 0.10.4
   **/
221
  g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS,
222
223
224
225
226
      g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus",
          "Whether to automatically flush the pipeline's bus when going "
          "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS,
          G_PARAM_READWRITE));

227
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
228

229
  gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_pipeline_send_event);
230
231
  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
232
233
  gstelement_class->provide_clock =
      GST_DEBUG_FUNCPTR (gst_pipeline_provide_clock_func);
Erik Walthinsen's avatar
Erik Walthinsen committed
234
235
}

Wim Taymans's avatar
Wim Taymans committed
236
static void
237
gst_pipeline_init (GTypeInstance * instance, gpointer g_class)
Wim Taymans's avatar
Wim Taymans committed
238
{
239
  GstPipeline *pipeline = GST_PIPELINE (instance);
240
  GstBus *bus;
241

242
243
  pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline);

Wim Taymans's avatar
Wim Taymans committed
244
245
  /* set default property values */
  pipeline->priv->auto_flush_bus = DEFAULT_AUTO_FLUSH_BUS;
Wim Taymans's avatar
Wim Taymans committed
246
  pipeline->delay = DEFAULT_DELAY;
247

Wim Taymans's avatar
Wim Taymans committed
248
  /* create and set a default bus */
249
  bus = gst_bus_new ();
250
251
#if 0
  /* FIXME, disabled for 0.10.5 release as it caused to many regressions */
252
253
254
  /* Start our bus in flushing if appropriate */
  if (pipeline->priv->auto_flush_bus)
    gst_bus_set_flushing (bus, TRUE);
255
#endif
256

257
  gst_element_set_bus (GST_ELEMENT_CAST (pipeline), bus);
258
  GST_DEBUG_OBJECT (pipeline, "set bus %" GST_PTR_FORMAT " on pipeline", bus);
259
  gst_object_unref (bus);
Erik Walthinsen's avatar
Erik Walthinsen committed
260
261
}

262
static void
263
gst_pipeline_dispose (GObject * object)
264
265
{
  GstPipeline *pipeline = GST_PIPELINE (object);
266
  GstClock **clock_p = &pipeline->fixed_clock;
267

268
269
  GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose");

Wim Taymans's avatar
Wim Taymans committed
270
  /* clear and unref any fixed clock */
271
  gst_object_replace ((GstObject **) clock_p, NULL);
272

273
  G_OBJECT_CLASS (parent_class)->dispose (object);
274
}
275

Wim Taymans's avatar
Wim Taymans committed
276
277
278
279
280
281
282
static void
gst_pipeline_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstPipeline *pipeline = GST_PIPELINE (object);

  switch (prop_id) {
283
    case PROP_DELAY:
Wim Taymans's avatar
Wim Taymans committed
284
      gst_pipeline_set_delay (pipeline, g_value_get_uint64 (value));
Wim Taymans's avatar
Wim Taymans committed
285
      break;
286
    case PROP_AUTO_FLUSH_BUS:
Wim Taymans's avatar
Wim Taymans committed
287
      gst_pipeline_set_auto_flush_bus (pipeline, g_value_get_boolean (value));
288
      break;
Wim Taymans's avatar
Wim Taymans committed
289
290
291
292
293
294
295
296
297
298
299
300
301
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_pipeline_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstPipeline *pipeline = GST_PIPELINE (object);

  switch (prop_id) {
302
    case PROP_DELAY:
Wim Taymans's avatar
Wim Taymans committed
303
      g_value_set_uint64 (value, gst_pipeline_get_delay (pipeline));
Wim Taymans's avatar
Wim Taymans committed
304
      break;
305
    case PROP_AUTO_FLUSH_BUS:
Wim Taymans's avatar
Wim Taymans committed
306
      g_value_set_boolean (value, gst_pipeline_get_auto_flush_bus (pipeline));
307
      break;
Wim Taymans's avatar
Wim Taymans committed
308
309
310
311
312
313
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

Wim Taymans's avatar
Wim Taymans committed
314
315
316
317
318
319
320
321
322
/* default pipeline seeking code:
 *
 * If the pipeline is PLAYING and a flushing seek is done, set
 * the pipeline to PAUSED before doing the seek.
 *
 * A flushing seek also resets the stream time to 0 so that when
 * we go back to PLAYING after the seek, the base_time is recalculated
 * and redistributed to the elements.
 */
323
static gboolean
324
do_pipeline_seek (GstElement * element, GstEvent * event)
325
{
326
327
328
329
  gdouble rate;
  GstSeekFlags flags;
  gboolean flush;
  gboolean was_playing = FALSE;
330
331
  gboolean res;

Wim Taymans's avatar
Wim Taymans committed
332
  /* we are only interested in the FLUSH flag of the seek event. */
333
334
335
336
  gst_event_parse_seek (event, &rate, NULL, &flags, NULL, NULL, NULL, NULL);

  flush = flags & GST_SEEK_FLAG_FLUSH;

Wim Taymans's avatar
Wim Taymans committed
337
  /* if flushing seek, get the current state */
338
339
  if (flush) {
    GstState state;
340

341
342
    /* need to call _get_state() since a bin state is only updated
     * with this call. */
343
    gst_element_get_state (element, &state, NULL, 0);
344
    was_playing = (state == GST_STATE_PLAYING);
345

346
    if (was_playing) {
Wim Taymans's avatar
Wim Taymans committed
347
348
      /* and PAUSE when the pipeline was PLAYING, we don't need
       * to wait for the state change to complete since we are going
349
       * to flush out any preroll sample anyway. */
350
      gst_element_set_state (element, GST_STATE_PAUSED);
351
    }
352
  }
353

Wim Taymans's avatar
Wim Taymans committed
354
  /* let parent class implement the seek behaviour */
355
356
  res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);

Wim Taymans's avatar
Wim Taymans committed
357
358
  /* if flushing seek restore previous state */
  if (flush) {
359
360
    gboolean need_reset;

361
    GST_OBJECT_LOCK (element);
362
    need_reset = GST_PIPELINE (element)->stream_time != GST_CLOCK_TIME_NONE;
363
    GST_OBJECT_UNLOCK (element);
364

Wim Taymans's avatar
Wim Taymans committed
365
366
367
368
    /* need to reset the stream time to 0 after a successfull flushing seek, 
     * unless the user explicitly disabled this behavior by setting stream 
     * time to NONE */
    if (need_reset && res)
369
370
      gst_pipeline_set_new_stream_time (GST_PIPELINE (element), 0);

371
    if (was_playing)
Wim Taymans's avatar
Wim Taymans committed
372
373
374
      /* and continue playing, this might return ASYNC in which case the
       * application can wait for the PREROLL to complete after the seek. 
       */
375
      gst_element_set_state (element, GST_STATE_PLAYING);
376
377
378
379
380
381
382
383
384
385
386
387
  }
  return res;
}

static gboolean
gst_pipeline_send_event (GstElement * element, GstEvent * event)
{
  gboolean res;
  GstEventType event_type = GST_EVENT_TYPE (event);

  switch (event_type) {
    case GST_EVENT_SEEK:
Wim Taymans's avatar
Wim Taymans committed
388
      /* do the default seek handling */
389
390
391
      res = do_pipeline_seek (element, event);
      break;
    default:
Wim Taymans's avatar
Wim Taymans committed
392
      /* else parent implements the defaults */
393
394
      res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
      break;
395
  }
396
397
398
399

  return res;
}

400
401
402
403
404
405
406
/**
 * gst_pipeline_new:
 * @name: name of new pipeline
 *
 * Create a new pipeline with the given name.
 *
 * Returns: newly created GstPipeline
407
408
 *
 * MT safe.
409
 */
410
411
GstElement *
gst_pipeline_new (const gchar * name)
Wim Taymans's avatar
Wim Taymans committed
412
{
413
  return gst_element_factory_make ("pipeline", name);
Erik Walthinsen's avatar
Erik Walthinsen committed
414
415
}

Wim Taymans's avatar
Wim Taymans committed
416
/* MT safe */
417
418
static GstStateChangeReturn
gst_pipeline_change_state (GstElement * element, GstStateChange transition)
Wim Taymans's avatar
Wim Taymans committed
419
{
420
  GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
Wim Taymans's avatar
Wim Taymans committed
421
  GstPipeline *pipeline = GST_PIPELINE (element);
422
  GstClock *clock;
Wim Taymans's avatar
Wim Taymans committed
423
424

  switch (transition) {
425
    case GST_STATE_CHANGE_NULL_TO_READY:
426
      GST_OBJECT_LOCK (element);
427
428
      if (element->bus)
        gst_bus_set_flushing (element->bus, FALSE);
429
      GST_OBJECT_UNLOCK (element);
Wim Taymans's avatar
Wim Taymans committed
430
      break;
431
    case GST_STATE_CHANGE_READY_TO_PAUSED:
Wim Taymans's avatar
Wim Taymans committed
432
      break;
433
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
434
435
436
    {
      GstClockTime new_base_time;

437
      /* when going to playing, select a clock */
438
439
440
441
      clock = gst_element_provide_clock (element);

      if (clock) {
        GstClockTime start_time, stream_time, delay;
Wim Taymans's avatar
Wim Taymans committed
442
        gboolean new_clock;
443
444

        start_time = gst_clock_get_time (clock);
Wim Taymans's avatar
Wim Taymans committed
445

446
        GST_OBJECT_LOCK (element);
Wim Taymans's avatar
Wim Taymans committed
447
        new_clock = element->clock != clock;
448
449
        stream_time = pipeline->stream_time;
        delay = pipeline->delay;
450
        GST_OBJECT_UNLOCK (element);
Wim Taymans's avatar
Wim Taymans committed
451
452

        if (new_clock) {
Wim Taymans's avatar
Wim Taymans committed
453
454
455
          /* now distribute the clock (which could be NULL). If some
           * element refuses the clock, this will return FALSE and
           * we effectively fail the state change. */
456
457
          if (!gst_element_set_clock (element, clock))
            goto invalid_clock;
458

Wim Taymans's avatar
Wim Taymans committed
459
460
          /* if we selected and distributed a new clock, let the app 
           * know about it */
Wim Taymans's avatar
Wim Taymans committed
461
462
463
464
          gst_element_post_message (element,
              gst_message_new_new_clock (GST_OBJECT_CAST (element), clock));
        }

465
466
467
468
469
        if (stream_time != GST_CLOCK_TIME_NONE)
          new_base_time = start_time - stream_time + delay;
        else
          new_base_time = GST_CLOCK_TIME_NONE;

Wim Taymans's avatar
Wim Taymans committed
470
        gst_object_unref (clock);
Wim Taymans's avatar
Wim Taymans committed
471
472
      } else {
        GST_DEBUG ("no clock, using base time of 0");
473
        new_base_time = 0;
Wim Taymans's avatar
Wim Taymans committed
474
      }
475
476
477
478
479
480
481

      if (new_base_time != GST_CLOCK_TIME_NONE)
        gst_element_set_base_time (element, new_base_time);
      else
        GST_DEBUG_OBJECT (pipeline,
            "NOT adjusting base time because stream time is NONE");
    }
Wim Taymans's avatar
Wim Taymans committed
482
      break;
483
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
Wim Taymans's avatar
Wim Taymans committed
484
      break;
485
486
    case GST_STATE_CHANGE_PAUSED_TO_READY:
    case GST_STATE_CHANGE_READY_TO_NULL:
Wim Taymans's avatar
Wim Taymans committed
487
488
489
      break;
  }

490
  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
Wim Taymans's avatar
Wim Taymans committed
491
492

  switch (transition) {
493
494
495
    case GST_STATE_CHANGE_NULL_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
496
497
498
    {
      gboolean need_reset;

Wim Taymans's avatar
Wim Taymans committed
499
500
      /* only reset the stream time when the application did not
       * specify a stream time explicitly */
501
      GST_OBJECT_LOCK (element);
502
      need_reset = pipeline->stream_time != GST_CLOCK_TIME_NONE;
503
      GST_OBJECT_UNLOCK (element);
504
505
506

      if (need_reset)
        gst_pipeline_set_new_stream_time (pipeline, 0);
507

Wim Taymans's avatar
Wim Taymans committed
508
      break;
509
    }
510
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
Wim Taymans's avatar
Wim Taymans committed
511
      break;
512
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
513
      GST_OBJECT_LOCK (element);
514
      if ((clock = element->clock)) {
515
516
        GstClockTime now;

517
        gst_object_ref (clock);
518
        GST_OBJECT_UNLOCK (element);
519
520
521
522
523

        /* calculate the time when we stopped */
        now = gst_clock_get_time (clock);
        gst_object_unref (clock);

524
        GST_OBJECT_LOCK (element);
525
        /* store the current stream time */
526
527
        if (pipeline->stream_time != GST_CLOCK_TIME_NONE)
          pipeline->stream_time = now - element->base_time;
528
529
        GST_DEBUG_OBJECT (element,
            "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
530
            ", base time %" GST_TIME_FORMAT,
531
532
            GST_TIME_ARGS (pipeline->stream_time), GST_TIME_ARGS (now),
            GST_TIME_ARGS (element->base_time));
Wim Taymans's avatar
Wim Taymans committed
533
      }
534
      GST_OBJECT_UNLOCK (element);
Wim Taymans's avatar
Wim Taymans committed
535
      break;
536
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Wim Taymans's avatar
Wim Taymans committed
537
      break;
538
    case GST_STATE_CHANGE_READY_TO_NULL:
539
      GST_OBJECT_LOCK (element);
540
      if (element->bus) {
541
542
543
544
545
        if (pipeline->priv->auto_flush_bus) {
          gst_bus_set_flushing (element->bus, TRUE);
        } else {
          GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled");
        }
546
      }
547
      GST_OBJECT_UNLOCK (element);
Wim Taymans's avatar
Wim Taymans committed
548
549
550
      break;
  }
  return result;
551

Wim Taymans's avatar
Wim Taymans committed
552
  /* ERRORS */
553
554
invalid_clock:
  {
Wim Taymans's avatar
Wim Taymans committed
555
556
    /* we generate this error when the selected clock was not
     * accepted by some element */
557
558
559
    GST_ELEMENT_ERROR (pipeline, CORE, CLOCK,
        (_("Selected clock cannot be used in pipeline.")),
        ("Pipeline cannot operate with selected clock"));
560
561
562
563
    GST_DEBUG_OBJECT (pipeline,
        "Pipeline cannot operate with selected clock %p", clock);
    return GST_STATE_CHANGE_FAILURE;
  }
Wim Taymans's avatar
Wim Taymans committed
564
}
565

Wim Taymans's avatar
Wim Taymans committed
566
567
/**
 * gst_pipeline_get_bus:
Wim Taymans's avatar
Wim Taymans committed
568
 * @pipeline: a #GstPipeline
Wim Taymans's avatar
Wim Taymans committed
569
 *
Wim Taymans's avatar
Wim Taymans committed
570
 * Gets the #GstBus of @pipeline.
Wim Taymans's avatar
Wim Taymans committed
571
 *
Wim Taymans's avatar
Wim Taymans committed
572
 * Returns: a #GstBus, unref after usage.
Wim Taymans's avatar
Wim Taymans committed
573
574
575
576
577
578
579
 *
 * MT safe.
 */
GstBus *
gst_pipeline_get_bus (GstPipeline * pipeline)
{
  return gst_element_get_bus (GST_ELEMENT (pipeline));
Erik Walthinsen's avatar
Erik Walthinsen committed
580
}
Wim Taymans's avatar
Wim Taymans committed
581

582
583
/**
 * gst_pipeline_set_new_stream_time:
Wim Taymans's avatar
Wim Taymans committed
584
 * @pipeline: a #GstPipeline
585
 * @time: the new stream time to set
586
 *
Wim Taymans's avatar
Wim Taymans committed
587
588
 * Set the new stream time of @pipeline to @time. The stream time is used to
 * set the base time on the elements (see gst_element_set_base_time())
589
590
 * in the PAUSED->PLAYING state transition.
 *
591
592
593
594
595
596
 * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management
 * of element base time. The application will then be responsible for
 * performing base time distribution. This is sometimes useful if you want to
 * synchronize capture from multiple pipelines, and you can also ensure that the
 * pipelines have the same clock.
 *
597
598
599
600
601
602
603
 * MT safe.
 */
void
gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time)
{
  g_return_if_fail (GST_IS_PIPELINE (pipeline));

604
  GST_OBJECT_LOCK (pipeline);
605
  pipeline->stream_time = time;
606
  GST_OBJECT_UNLOCK (pipeline);
607
608
609
610
611
612

  GST_DEBUG_OBJECT (pipeline, "set new stream_time to %" GST_TIME_FORMAT,
      GST_TIME_ARGS (time));

  if (time == GST_CLOCK_TIME_NONE)
    GST_DEBUG_OBJECT (pipeline, "told not to adjust base time");
613
614
615
616
}

/**
 * gst_pipeline_get_last_stream_time:
Wim Taymans's avatar
Wim Taymans committed
617
 * @pipeline: a #GstPipeline
618
 *
Wim Taymans's avatar
Wim Taymans committed
619
620
621
622
 * Gets the last stream time of @pipeline. If the pipeline is PLAYING,
 * the returned time is the stream time used to configure the element's
 * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the 
 * returned time is the stream time when the pipeline was paused.
623
 *
Wim Taymans's avatar
Wim Taymans committed
624
625
626
627
628
 * This function returns #GST_CLOCK_TIME_NONE if the pipeline was
 * configured to not handle the management of the element's base time 
 * (see gst_pipeline_set_new_stream_time()).
 *
 * Returns: a #GstClockTime.
629
630
631
632
633
634
635
636
637
638
 *
 * MT safe.
 */
GstClockTime
gst_pipeline_get_last_stream_time (GstPipeline * pipeline)
{
  GstClockTime result;

  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);

639
  GST_OBJECT_LOCK (pipeline);
640
  result = pipeline->stream_time;
641
  GST_OBJECT_UNLOCK (pipeline);
642
643
644
645

  return result;
}

Wim Taymans's avatar
Wim Taymans committed
646
static GstClock *
647
gst_pipeline_provide_clock_func (GstElement * element)
Wim Taymans's avatar
Wim Taymans committed
648
649
650
651
652
{
  GstClock *clock = NULL;
  GstPipeline *pipeline = GST_PIPELINE (element);

  /* if we have a fixed clock, use that one */
653
  GST_OBJECT_LOCK (pipeline);
654
  if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
Wim Taymans's avatar
Wim Taymans committed
655
    clock = pipeline->fixed_clock;
656
    gst_object_ref (clock);
657
    GST_OBJECT_UNLOCK (pipeline);
Wim Taymans's avatar
Wim Taymans committed
658
659
660
661

    GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
        clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
  } else {
662
    GST_OBJECT_UNLOCK (pipeline);
Wim Taymans's avatar
Wim Taymans committed
663
    /* let the parent bin select a clock */
Wim Taymans's avatar
Wim Taymans committed
664
    clock =
665
666
        GST_ELEMENT_CLASS (parent_class)->
        provide_clock (GST_ELEMENT (pipeline));
Wim Taymans's avatar
Wim Taymans committed
667
668
669
    /* no clock, use a system clock */
    if (!clock) {
      clock = gst_system_clock_obtain ();
670

Wim Taymans's avatar
Wim Taymans committed
671
672
673
674
675
676
677
678
679
680
681
682
      GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
          clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
    } else {
      GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)",
          clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
    }
  }
  return clock;
}

/**
 * gst_pipeline_get_clock:
Wim Taymans's avatar
Wim Taymans committed
683
 * @pipeline: a #GstPipeline
Wim Taymans's avatar
Wim Taymans committed
684
 *
Wim Taymans's avatar
Wim Taymans committed
685
 * Gets the current clock used by @pipeline.
Wim Taymans's avatar
Wim Taymans committed
686
 *
Wim Taymans's avatar
Wim Taymans committed
687
 * Returns: a #GstClock, unref after usage.
Wim Taymans's avatar
Wim Taymans committed
688
689
690
691
692
693
 */
GstClock *
gst_pipeline_get_clock (GstPipeline * pipeline)
{
  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);

694
  return gst_pipeline_provide_clock_func (GST_ELEMENT (pipeline));
Wim Taymans's avatar
Wim Taymans committed
695
696
697
698
699
}


/**
 * gst_pipeline_use_clock:
Wim Taymans's avatar
Wim Taymans committed
700
 * @pipeline: a #GstPipeline
Wim Taymans's avatar
Wim Taymans committed
701
702
 * @clock: the clock to use
 *
Wim Taymans's avatar
Wim Taymans committed
703
 * Force @pipeline to use the given @clock. The pipeline will
Wim Taymans's avatar
Wim Taymans committed
704
705
706
 * always use the given clock even if new clock providers are added
 * to this pipeline.
 *
Wim Taymans's avatar
Wim Taymans committed
707
708
709
 * If @clock is NULL all clocking will be disabled which will make
 * the pipeline run as fast as possible.
 *
Wim Taymans's avatar
Wim Taymans committed
710
711
712
713
714
 * MT safe.
 */
void
gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock)
{
715
716
  GstClock **clock_p;

Wim Taymans's avatar
Wim Taymans committed
717
718
  g_return_if_fail (GST_IS_PIPELINE (pipeline));

719
  GST_OBJECT_LOCK (pipeline);
720
  GST_OBJECT_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
Wim Taymans's avatar
Wim Taymans committed
721

722
723
  clock_p = &pipeline->fixed_clock;
  gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
724
  GST_OBJECT_UNLOCK (pipeline);
Wim Taymans's avatar
Wim Taymans committed
725
726
727
728
729
730
731

  GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock,
      (clock ? GST_OBJECT_NAME (clock) : "nil"));
}

/**
 * gst_pipeline_set_clock:
Wim Taymans's avatar
Wim Taymans committed
732
 * @pipeline: a #GstPipeline
Wim Taymans's avatar
Wim Taymans committed
733
734
 * @clock: the clock to set
 *
Wim Taymans's avatar
Wim Taymans committed
735
 * Set the clock for @pipeline. The clock will be distributed
736
 * to all the elements managed by the pipeline. 
Wim Taymans's avatar
Wim Taymans committed
737
 *
Wim Taymans's avatar
Wim Taymans committed
738
739
 * Returns: TRUE if the clock could be set on the pipeline. FALSE if
 *   some element did not accept the clock.
740
 *
Wim Taymans's avatar
Wim Taymans committed
741
742
 * MT safe.
 */
743
gboolean
Wim Taymans's avatar
Wim Taymans committed
744
745
gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock)
{
746
747
  g_return_val_if_fail (pipeline != NULL, FALSE);
  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE);
Wim Taymans's avatar
Wim Taymans committed
748

749
750
  return GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline),
      clock);
Wim Taymans's avatar
Wim Taymans committed
751
752
753
754
}

/**
 * gst_pipeline_auto_clock:
Wim Taymans's avatar
Wim Taymans committed
755
 * @pipeline: a #GstPipeline
Wim Taymans's avatar
Wim Taymans committed
756
 *
Wim Taymans's avatar
Wim Taymans committed
757
758
759
760
761
762
 * Let @pipeline select a clock automatically. This is the default
 * behaviour. 
 *
 * Use this function if you previous forced a fixed clock with 
 * gst_pipeline_use_clock() and want to restore the default
 * pipeline clock selection algorithm.
Wim Taymans's avatar
Wim Taymans committed
763
764
765
766
767
768
 *
 * MT safe.
 */
void
gst_pipeline_auto_clock (GstPipeline * pipeline)
{
769
770
  GstClock **clock_p;

Wim Taymans's avatar
Wim Taymans committed
771
772
773
  g_return_if_fail (pipeline != NULL);
  g_return_if_fail (GST_IS_PIPELINE (pipeline));

774
  GST_OBJECT_LOCK (pipeline);
775
  GST_OBJECT_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
Wim Taymans's avatar
Wim Taymans committed
776

777
778
  clock_p = &pipeline->fixed_clock;
  gst_object_replace ((GstObject **) clock_p, NULL);
779
  GST_OBJECT_UNLOCK (pipeline);
Wim Taymans's avatar
Wim Taymans committed
780
781
782

  GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");
}
783

Wim Taymans's avatar
Wim Taymans committed
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
/**
 * gst_pipeline_set_delay:
 * @pipeline: a #GstPipeline
 * @delay: the delay
 *
 * Set the expected delay needed for all elements to perform the
 * PAUSED to PLAYING state change. @delay will be added to the
 * base time of the elements so that they wait an additional @delay
 * amount of time before starting to process buffers.
 *
 * This option is used for tuning purposes and should normally not be 
 * used.
 *
 * MT safe.
 *
 * Since: 0.10.5
 */
void
gst_pipeline_set_delay (GstPipeline * pipeline, GstClockTime delay)
{
  g_return_if_fail (GST_IS_PIPELINE (pipeline));

  GST_OBJECT_LOCK (pipeline);
  pipeline->delay = delay;
  GST_OBJECT_UNLOCK (pipeline);
}

/**
 * gst_pipeline_get_delay:
 * @pipeline: a #GstPipeline
 *
 * Get the configured delay (see gst_pipeline_set_delay()).
 *
 * Returns: The configured delay.
 *
 * MT safe.
 *
 * Since: 0.10.5
 */
GstClockTime
gst_pipeline_get_delay (GstPipeline * pipeline)
{
  GstClockTime res;

  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE);

  GST_OBJECT_LOCK (pipeline);
  res = pipeline->delay;
  GST_OBJECT_UNLOCK (pipeline);

  return res;
}

837
838
839
840
841
842
843
844
/**
 * gst_pipeline_set_auto_flush_bus:
 * @pipeline: a #GstPipeline
 * @auto_flush: whether or not to automatically flush the bus when
 * the pipeline goes from READY to NULL state
 *
 * Usually, when a pipeline goes from READY to NULL state, it automatically
 * flushes all pending messages on the bus, which is done for refcounting
Wim Taymans's avatar
Wim Taymans committed
845
846
847
848
849
850
851
852
853
854
 * purposes, to break circular references. 
 *
 * This means that applications that update state using (async) bus messages 
 * (e.g. do certain things when a pipeline goes from PAUSED to READY) might 
 * not get to see messages when the pipeline is shut down, because they might 
 * be flushed before they can be dispatched in the main thread. This behaviour
 * can be disabled using this function.
 *
 * It is important that all messages on the bus are handled when the 
 * automatic flushing is disabled else memory leaks will be introduced.
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
 *
 * MT safe.
 *
 * Since: 0.10.4
 */
void
gst_pipeline_set_auto_flush_bus (GstPipeline * pipeline, gboolean auto_flush)
{
  g_return_if_fail (GST_IS_PIPELINE (pipeline));

  GST_OBJECT_LOCK (pipeline);
  pipeline->priv->auto_flush_bus = auto_flush;
  GST_OBJECT_UNLOCK (pipeline);
}

/**
 * gst_pipeline_get_auto_flush_bus:
 * @pipeline: a #GstPipeline
 *
Wim Taymans's avatar
Wim Taymans committed
874
875
876
 * Check if @pipeline will automatically flush messages when going to
 * the NULL state.
 *
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
 * Returns: whether the pipeline will automatically flush its bus when
 * going from READY to NULL state or not.
 *
 * MT safe.
 *
 * Since: 0.10.4
 */
gboolean
gst_pipeline_get_auto_flush_bus (GstPipeline * pipeline)
{
  gboolean res;

  g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE);

  GST_OBJECT_LOCK (pipeline);
  res = pipeline->priv->auto_flush_bus;
  GST_OBJECT_UNLOCK (pipeline);

  return res;
}