60 * The clock selection can be controlled with the gst_pipeline_use_clock() |
60 * The clock selection can be controlled with the gst_pipeline_use_clock() |
61 * method, which will enforce a given clock on the pipeline. With |
61 * method, which will enforce a given clock on the pipeline. With |
62 * gst_pipeline_auto_clock() the default clock selection algorithm can be |
62 * gst_pipeline_auto_clock() the default clock selection algorithm can be |
63 * restored. |
63 * restored. |
64 * |
64 * |
65 * A #GstPipeline maintains a stream time for the elements. The stream |
65 * A #GstPipeline maintains a running time for the elements. The running |
66 * time is defined as the difference between the current clock time and |
66 * time is defined as the difference between the current clock time and |
67 * the base time. When the pipeline goes to READY or a flushing seek is |
67 * the base time. When the pipeline goes to READY or a flushing seek is |
68 * performed on it, the stream time is reset to 0. When the pipeline is |
68 * performed on it, the running time is reset to 0. When the pipeline is |
69 * set from PLAYING to PAUSED, the current clock time is sampled and used to |
69 * set from PLAYING to PAUSED, the current clock time is sampled and used to |
70 * configure the base time for the elements when the pipeline is set |
70 * configure the base time for the elements when the pipeline is set |
71 * to PLAYING again. This default behaviour can be changed with the |
71 * to PLAYING again. The effect is that the running time (as the difference |
72 * gst_pipeline_set_new_stream_time() method. |
72 * between the clock time and the base time) will count how much time was spent |
|
73 * in the PLAYING state. This default behaviour can be changed with the |
|
74 * gst_element_set_start_time() method. |
73 * |
75 * |
74 * When sending a flushing seek event to a GstPipeline (see |
76 * When sending a flushing seek event to a GstPipeline (see |
75 * gst_element_seek()), it will make sure that the pipeline is properly |
77 * gst_element_seek()), it will make sure that the pipeline is properly |
76 * PAUSED and resumed as well as set the new stream time to 0 when the |
78 * PAUSED and resumed as well as set the new running time to 0 when the |
77 * seek succeeded. |
79 * seek succeeded. |
78 * |
80 * |
79 * Last reviewed on 2006-03-12 (0.10.5) |
81 * Last reviewed on 2009-05-29 (0.10.24) |
80 */ |
82 */ |
81 |
83 |
82 #include "gst_private.h" |
84 #include "gst_private.h" |
83 #include "gsterror.h" |
85 #include "gsterror.h" |
84 #include "gst-i18n-lib.h" |
86 #include "gst-i18n-lib.h" |
85 |
87 |
86 #include "gstpipeline.h" |
88 #include "gstpipeline.h" |
87 #include "gstinfo.h" |
89 #include "gstinfo.h" |
88 #include "gstsystemclock.h" |
90 #include "gstsystemclock.h" |
89 |
91 #include "gstutils.h" |
90 #ifdef __SYMBIAN32__ |
92 #ifdef __SYMBIAN32__ |
91 #include <glib_global.h> |
93 #include <glib_global.h> |
92 #endif |
94 #endif |
93 |
95 |
94 GST_DEBUG_CATEGORY_STATIC (pipeline_debug); |
96 GST_DEBUG_CATEGORY_STATIC (pipeline_debug); |
119 /* with LOCK */ |
121 /* with LOCK */ |
120 gboolean auto_flush_bus; |
122 gboolean auto_flush_bus; |
121 |
123 |
122 /* when we need to update stream_time or clock when going back to |
124 /* when we need to update stream_time or clock when going back to |
123 * PLAYING*/ |
125 * PLAYING*/ |
124 gboolean update_stream_time; |
126 GstClockTime last_start_time; |
125 gboolean update_clock; |
127 gboolean update_clock; |
126 }; |
128 }; |
127 |
129 |
128 |
130 |
129 static void gst_pipeline_base_init (gpointer g_class); |
131 static void gst_pipeline_base_init (gpointer g_class); |
130 static void gst_pipeline_class_init (gpointer g_class, gpointer class_data); |
|
131 static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class); |
|
132 |
132 |
133 static void gst_pipeline_dispose (GObject * object); |
133 static void gst_pipeline_dispose (GObject * object); |
134 static void gst_pipeline_set_property (GObject * object, guint prop_id, |
134 static void gst_pipeline_set_property (GObject * object, guint prop_id, |
135 const GValue * value, GParamSpec * pspec); |
135 const GValue * value, GParamSpec * pspec); |
136 static void gst_pipeline_get_property (GObject * object, guint prop_id, |
136 static void gst_pipeline_get_property (GObject * object, guint prop_id, |
140 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element, |
140 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element, |
141 GstStateChange transition); |
141 GstStateChange transition); |
142 |
142 |
143 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message); |
143 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message); |
144 |
144 |
145 static GstBinClass *parent_class = NULL; |
|
146 |
|
147 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */ |
145 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */ |
148 #ifdef __SYMBIAN32__ |
146 |
149 EXPORT_C |
147 #define _do_init(type) \ |
150 #endif |
148 { \ |
151 |
149 GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, \ |
152 |
150 "debugging info for the 'pipeline' container element"); \ |
153 GType |
151 } |
154 gst_pipeline_get_type (void) |
152 |
155 { |
153 GST_BOILERPLATE_FULL (GstPipeline, gst_pipeline, GstBin, GST_TYPE_BIN, |
156 static GType pipeline_type = 0; |
154 _do_init); |
157 |
|
158 if (G_UNLIKELY (pipeline_type == 0)) { |
|
159 static const GTypeInfo pipeline_info = { |
|
160 sizeof (GstPipelineClass), |
|
161 gst_pipeline_base_init, |
|
162 NULL, |
|
163 (GClassInitFunc) gst_pipeline_class_init, |
|
164 NULL, |
|
165 NULL, |
|
166 sizeof (GstPipeline), |
|
167 0, |
|
168 gst_pipeline_init, |
|
169 NULL |
|
170 }; |
|
171 |
|
172 pipeline_type = |
|
173 g_type_register_static (GST_TYPE_BIN, "GstPipeline", &pipeline_info, 0); |
|
174 |
|
175 GST_DEBUG_CATEGORY_INIT (pipeline_debug, "pipeline", GST_DEBUG_BOLD, |
|
176 "debugging info for the 'pipeline' container element"); |
|
177 } |
|
178 return pipeline_type; |
|
179 } |
|
180 |
155 |
181 static void |
156 static void |
182 gst_pipeline_base_init (gpointer g_class) |
157 gst_pipeline_base_init (gpointer g_class) |
183 { |
158 { |
184 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); |
159 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); |
188 "Complete pipeline object", |
163 "Complete pipeline object", |
189 "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>"); |
164 "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>"); |
190 } |
165 } |
191 |
166 |
192 static void |
167 static void |
193 gst_pipeline_class_init (gpointer g_class, gpointer class_data) |
168 gst_pipeline_class_init (GstPipelineClass * klass) |
194 { |
169 { |
195 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); |
170 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
196 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); |
171 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); |
197 GstBinClass *gstbin_class = GST_BIN_CLASS (g_class); |
172 GstBinClass *gstbin_class = GST_BIN_CLASS (klass); |
198 GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class); |
|
199 |
173 |
200 parent_class = g_type_class_peek_parent (klass); |
174 parent_class = g_type_class_peek_parent (klass); |
201 |
175 |
202 g_type_class_add_private (klass, sizeof (GstPipelinePrivate)); |
176 g_type_class_add_private (klass, sizeof (GstPipelinePrivate)); |
203 |
177 |
215 **/ |
189 **/ |
216 g_object_class_install_property (gobject_class, PROP_DELAY, |
190 g_object_class_install_property (gobject_class, PROP_DELAY, |
217 g_param_spec_uint64 ("delay", "Delay", |
191 g_param_spec_uint64 ("delay", "Delay", |
218 "Expected delay needed for elements " |
192 "Expected delay needed for elements " |
219 "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY, |
193 "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY, |
220 G_PARAM_READWRITE)); |
194 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
221 |
195 |
222 /** |
196 /** |
223 * GstPipeline:auto-flush-bus: |
197 * GstPipeline:auto-flush-bus: |
224 * |
198 * |
225 * Whether or not to automatically flush all messages on the |
199 * Whether or not to automatically flush all messages on the |
230 **/ |
204 **/ |
231 g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS, |
205 g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS, |
232 g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus", |
206 g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus", |
233 "Whether to automatically flush the pipeline's bus when going " |
207 "Whether to automatically flush the pipeline's bus when going " |
234 "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS, |
208 "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS, |
235 G_PARAM_READWRITE)); |
209 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
236 |
210 |
237 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose); |
211 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose); |
238 |
212 |
239 gstelement_class->change_state = |
213 gstelement_class->change_state = |
240 GST_DEBUG_FUNCPTR (gst_pipeline_change_state); |
214 GST_DEBUG_FUNCPTR (gst_pipeline_change_state); |
320 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
293 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
321 break; |
294 break; |
322 } |
295 } |
323 } |
296 } |
324 |
297 |
325 /* set the stream time to 0 */ |
298 /* set the start_time to 0, this will cause us to select a new base_time and |
|
299 * make the running_time start from 0 again. */ |
326 static void |
300 static void |
327 reset_stream_time (GstPipeline * pipeline) |
301 reset_start_time (GstPipeline * pipeline) |
328 { |
302 { |
329 GST_OBJECT_LOCK (pipeline); |
303 GST_OBJECT_LOCK (pipeline); |
330 if (pipeline->stream_time != GST_CLOCK_TIME_NONE) { |
304 if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) { |
331 GST_DEBUG_OBJECT (pipeline, "reset stream_time to 0"); |
305 GST_DEBUG_OBJECT (pipeline, "reset start_time to 0"); |
332 pipeline->stream_time = 0; |
306 GST_ELEMENT_START_TIME (pipeline) = 0; |
333 pipeline->priv->update_stream_time = TRUE; |
307 pipeline->priv->last_start_time = -1; |
334 } else { |
308 } else { |
335 GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time"); |
309 GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time"); |
336 } |
310 } |
337 GST_OBJECT_UNLOCK (pipeline); |
311 GST_OBJECT_UNLOCK (pipeline); |
338 } |
312 } |
378 GST_OBJECT_UNLOCK (element); |
352 GST_OBJECT_UNLOCK (element); |
379 break; |
353 break; |
380 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
354 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
381 { |
355 { |
382 GstClockTime new_base_time; |
356 GstClockTime new_base_time; |
383 GstClockTime start_time, stream_time, delay; |
357 GstClockTime now, start_time, last_start_time, delay; |
384 gboolean new_clock, update_stream_time, update_clock; |
358 gboolean update_clock; |
385 GstClock *cur_clock; |
359 GstClock *cur_clock; |
386 |
360 |
387 GST_DEBUG_OBJECT (element, "selecting clock and base_time"); |
361 GST_DEBUG_OBJECT (element, "selecting clock and base_time"); |
388 |
362 |
389 GST_OBJECT_LOCK (element); |
363 GST_OBJECT_LOCK (element); |
390 cur_clock = element->clock; |
364 cur_clock = element->clock; |
391 if (cur_clock) |
365 if (cur_clock) |
392 gst_object_ref (cur_clock); |
366 gst_object_ref (cur_clock); |
393 stream_time = pipeline->stream_time; |
367 /* get the desired running_time of the first buffer aka the start_time */ |
394 update_stream_time = pipeline->priv->update_stream_time; |
368 start_time = GST_ELEMENT_START_TIME (pipeline); |
|
369 last_start_time = pipeline->priv->last_start_time; |
|
370 pipeline->priv->last_start_time = start_time; |
|
371 /* see if we need to update the clock */ |
395 update_clock = pipeline->priv->update_clock; |
372 update_clock = pipeline->priv->update_clock; |
396 pipeline->priv->update_stream_time = FALSE; |
|
397 pipeline->priv->update_clock = FALSE; |
373 pipeline->priv->update_clock = FALSE; |
398 delay = pipeline->delay; |
374 delay = pipeline->delay; |
399 GST_OBJECT_UNLOCK (element); |
375 GST_OBJECT_UNLOCK (element); |
400 |
376 |
401 /* stream time changed, either with a PAUSED or a flush, we need to check |
377 /* running time changed, either with a PAUSED or a flush, we need to check |
402 * if there is a new clock & update the base time */ |
378 * if there is a new clock & update the base time */ |
403 if (update_stream_time) { |
379 if (last_start_time != start_time) { |
404 GST_DEBUG_OBJECT (pipeline, "Need to update stream_time"); |
380 GST_DEBUG_OBJECT (pipeline, "Need to update start_time"); |
405 |
381 |
406 /* when going to PLAYING, select a clock when needed. If we just got |
382 /* when going to PLAYING, select a clock when needed. If we just got |
407 * flushed, we don't reselect the clock. */ |
383 * flushed, we don't reselect the clock. */ |
408 if (update_clock) { |
384 if (update_clock) { |
409 GST_DEBUG_OBJECT (pipeline, "Need to update clock."); |
385 GST_DEBUG_OBJECT (pipeline, "Need to update clock."); |
412 GST_DEBUG_OBJECT (pipeline, |
388 GST_DEBUG_OBJECT (pipeline, |
413 "Don't need to update clock, using old clock."); |
389 "Don't need to update clock, using old clock."); |
414 clock = gst_object_ref (cur_clock); |
390 clock = gst_object_ref (cur_clock); |
415 } |
391 } |
416 |
392 |
417 new_clock = (clock != cur_clock); |
|
418 |
|
419 if (clock) { |
393 if (clock) { |
420 start_time = gst_clock_get_time (clock); |
394 now = gst_clock_get_time (clock); |
421 } else { |
395 } else { |
422 GST_DEBUG ("no clock, using base time of NONE"); |
396 GST_DEBUG ("no clock, using base time of NONE"); |
423 start_time = GST_CLOCK_TIME_NONE; |
397 now = GST_CLOCK_TIME_NONE; |
424 new_base_time = GST_CLOCK_TIME_NONE; |
|
425 } |
398 } |
426 |
399 |
427 if (new_clock) { |
400 if (clock != cur_clock) { |
428 /* now distribute the clock (which could be NULL). If some |
401 /* now distribute the clock (which could be NULL). If some |
429 * element refuses the clock, this will return FALSE and |
402 * element refuses the clock, this will return FALSE and |
430 * we effectively fail the state change. */ |
403 * we effectively fail the state change. */ |
431 if (!gst_element_set_clock (element, clock)) |
404 if (!gst_element_set_clock (element, clock)) |
432 goto invalid_clock; |
405 goto invalid_clock; |
438 } |
411 } |
439 |
412 |
440 if (clock) |
413 if (clock) |
441 gst_object_unref (clock); |
414 gst_object_unref (clock); |
442 |
415 |
443 if (stream_time != GST_CLOCK_TIME_NONE |
416 if (start_time != GST_CLOCK_TIME_NONE && now != GST_CLOCK_TIME_NONE) { |
444 && start_time != GST_CLOCK_TIME_NONE) { |
417 new_base_time = now - start_time + delay; |
445 new_base_time = start_time - stream_time + delay; |
|
446 GST_DEBUG_OBJECT (element, |
418 GST_DEBUG_OBJECT (element, |
447 "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
419 "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
448 ", base_time %" GST_TIME_FORMAT, |
420 ", base_time %" GST_TIME_FORMAT, |
449 GST_TIME_ARGS (stream_time), GST_TIME_ARGS (start_time), |
421 GST_TIME_ARGS (start_time), GST_TIME_ARGS (now), |
450 GST_TIME_ARGS (new_base_time)); |
422 GST_TIME_ARGS (new_base_time)); |
451 } else |
423 } else |
452 new_base_time = GST_CLOCK_TIME_NONE; |
424 new_base_time = GST_CLOCK_TIME_NONE; |
453 |
425 |
454 if (new_base_time != GST_CLOCK_TIME_NONE) |
426 if (new_base_time != GST_CLOCK_TIME_NONE) |
455 gst_element_set_base_time (element, new_base_time); |
427 gst_element_set_base_time (element, new_base_time); |
456 else |
428 else |
457 GST_DEBUG_OBJECT (pipeline, |
429 GST_DEBUG_OBJECT (pipeline, |
458 "NOT adjusting base_time because stream_time is NONE"); |
430 "NOT adjusting base_time because start_time is NONE"); |
459 } else { |
431 } else { |
460 GST_DEBUG_OBJECT (pipeline, |
432 GST_DEBUG_OBJECT (pipeline, |
461 "NOT adjusting base_time because we selected one before"); |
433 "NOT adjusting base_time because we selected one before"); |
462 } |
434 } |
463 |
435 |
464 if (cur_clock) |
436 if (cur_clock) |
465 gst_object_unref (cur_clock); |
437 gst_object_unref (cur_clock); |
466 break; |
438 break; |
467 } |
439 } |
468 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
440 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
469 break; |
|
470 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
471 case GST_STATE_CHANGE_READY_TO_NULL: |
|
472 break; |
|
473 } |
|
474 |
|
475 result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
476 |
|
477 switch (transition) { |
|
478 case GST_STATE_CHANGE_NULL_TO_READY: |
|
479 break; |
|
480 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
481 { |
|
482 reset_stream_time (pipeline); |
|
483 break; |
|
484 } |
|
485 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
|
486 break; |
|
487 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
|
488 GST_OBJECT_LOCK (element); |
441 GST_OBJECT_LOCK (element); |
489 if ((clock = element->clock)) { |
442 if ((clock = element->clock)) { |
490 GstClockTime now; |
443 GstClockTime now; |
491 |
444 |
492 gst_object_ref (clock); |
445 gst_object_ref (clock); |
495 /* calculate the time when we stopped */ |
448 /* calculate the time when we stopped */ |
496 now = gst_clock_get_time (clock); |
449 now = gst_clock_get_time (clock); |
497 gst_object_unref (clock); |
450 gst_object_unref (clock); |
498 |
451 |
499 GST_OBJECT_LOCK (element); |
452 GST_OBJECT_LOCK (element); |
500 /* store the current stream time */ |
453 /* store the current running time */ |
501 if (pipeline->stream_time != GST_CLOCK_TIME_NONE) { |
454 if (GST_ELEMENT_START_TIME (pipeline) != GST_CLOCK_TIME_NONE) { |
502 pipeline->stream_time = now - element->base_time; |
455 GST_ELEMENT_START_TIME (pipeline) = now - element->base_time; |
503 /* we went to PAUSED, when going to PLAYING select clock and new |
456 /* we went to PAUSED, when going to PLAYING select clock and new |
504 * base_time */ |
457 * base_time */ |
505 pipeline->priv->update_stream_time = TRUE; |
|
506 pipeline->priv->update_clock = TRUE; |
458 pipeline->priv->update_clock = TRUE; |
507 } |
459 } |
508 |
|
509 GST_DEBUG_OBJECT (element, |
460 GST_DEBUG_OBJECT (element, |
510 "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
461 "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
511 ", base_time %" GST_TIME_FORMAT, |
462 ", base_time %" GST_TIME_FORMAT, |
512 GST_TIME_ARGS (pipeline->stream_time), GST_TIME_ARGS (now), |
463 GST_TIME_ARGS (GST_ELEMENT_START_TIME (pipeline)), |
513 GST_TIME_ARGS (element->base_time)); |
464 GST_TIME_ARGS (now), GST_TIME_ARGS (element->base_time)); |
514 } |
465 } |
515 GST_OBJECT_UNLOCK (element); |
466 GST_OBJECT_UNLOCK (element); |
516 break; |
467 break; |
|
468 break; |
517 case GST_STATE_CHANGE_PAUSED_TO_READY: |
469 case GST_STATE_CHANGE_PAUSED_TO_READY: |
518 break; |
|
519 case GST_STATE_CHANGE_READY_TO_NULL: |
470 case GST_STATE_CHANGE_READY_TO_NULL: |
|
471 break; |
|
472 } |
|
473 |
|
474 result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
|
475 |
|
476 switch (transition) { |
|
477 case GST_STATE_CHANGE_NULL_TO_READY: |
|
478 break; |
|
479 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
480 { |
|
481 reset_start_time (pipeline); |
|
482 break; |
|
483 } |
|
484 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
|
485 break; |
|
486 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
|
487 break; |
|
488 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
489 break; |
|
490 case GST_STATE_CHANGE_READY_TO_NULL: |
|
491 { |
|
492 GstBus *bus; |
|
493 gboolean auto_flush; |
|
494 |
|
495 /* grab some stuff before we release the lock to flush out the bus */ |
520 GST_OBJECT_LOCK (element); |
496 GST_OBJECT_LOCK (element); |
521 if (element->bus) { |
497 if ((bus = element->bus)) |
522 if (pipeline->priv->auto_flush_bus) { |
498 gst_object_ref (bus); |
523 gst_bus_set_flushing (element->bus, TRUE); |
499 auto_flush = pipeline->priv->auto_flush_bus; |
|
500 GST_OBJECT_UNLOCK (element); |
|
501 |
|
502 if (bus) { |
|
503 if (auto_flush) { |
|
504 gst_bus_set_flushing (bus, TRUE); |
524 } else { |
505 } else { |
525 GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled"); |
506 GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled"); |
526 } |
507 } |
|
508 gst_object_unref (bus); |
527 } |
509 } |
528 GST_OBJECT_UNLOCK (element); |
510 break; |
529 break; |
511 } |
530 } |
512 } |
531 return result; |
513 return result; |
532 |
514 |
533 /* ERRORS */ |
515 /* ERRORS */ |
534 invalid_clock: |
516 invalid_clock: |
592 } |
580 } |
593 |
581 |
594 /** |
582 /** |
595 * gst_pipeline_set_new_stream_time: |
583 * gst_pipeline_set_new_stream_time: |
596 * @pipeline: a #GstPipeline |
584 * @pipeline: a #GstPipeline |
597 * @time: the new stream time to set |
585 * @time: the new running time to set |
598 * |
586 * |
599 * Set the new stream time of @pipeline to @time. The stream time is used to |
587 * Set the new start time of @pipeline to @time. The start time is used to |
600 * set the base time on the elements (see gst_element_set_base_time()) |
588 * set the base time on the elements (see gst_element_set_base_time()) |
601 * in the PAUSED->PLAYING state transition. |
589 * in the PAUSED->PLAYING state transition. |
602 * |
590 * |
603 * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management |
591 * Setting @time to #GST_CLOCK_TIME_NONE will disable the pipeline's management |
604 * of element base time. The application will then be responsible for |
592 * of element base time. The application will then be responsible for |
605 * performing base time distribution. This is sometimes useful if you want to |
593 * performing base time distribution. This is sometimes useful if you want to |
606 * synchronize capture from multiple pipelines, and you can also ensure that the |
594 * synchronize capture from multiple pipelines, and you can also ensure that the |
607 * pipelines have the same clock. |
595 * pipelines have the same clock. |
608 * |
596 * |
609 * MT safe. |
597 * MT safe. |
610 */ |
598 * |
611 #ifdef __SYMBIAN32__ |
599 * Deprecated: This function has the wrong name and is equivalent to |
612 EXPORT_C |
600 * gst_element_set_start_time(). |
613 #endif |
601 */ |
614 |
602 #ifndef GST_REMOVE_DEPRECATED |
|
603 #ifdef __SYMBIAN32__ |
|
604 EXPORT_C |
|
605 #endif |
615 void |
606 void |
616 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time) |
607 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time) |
617 { |
608 { |
618 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
609 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
619 |
610 |
620 GST_OBJECT_LOCK (pipeline); |
611 gst_element_set_start_time (GST_ELEMENT_CAST (pipeline), time); |
621 pipeline->stream_time = time; |
|
622 pipeline->priv->update_stream_time = TRUE; |
|
623 GST_OBJECT_UNLOCK (pipeline); |
|
624 |
|
625 GST_DEBUG_OBJECT (pipeline, "set new stream_time to %" GST_TIME_FORMAT, |
|
626 GST_TIME_ARGS (time)); |
|
627 |
612 |
628 if (time == GST_CLOCK_TIME_NONE) |
613 if (time == GST_CLOCK_TIME_NONE) |
629 GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time"); |
614 GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time"); |
630 } |
615 } |
|
616 #endif /* GST_REMOVE_DEPRECATED */ |
631 |
617 |
632 /** |
618 /** |
633 * gst_pipeline_get_last_stream_time: |
619 * gst_pipeline_get_last_stream_time: |
634 * @pipeline: a #GstPipeline |
620 * @pipeline: a #GstPipeline |
635 * |
621 * |
636 * Gets the last stream time of @pipeline. If the pipeline is PLAYING, |
622 * Gets the last running time of @pipeline. If the pipeline is PLAYING, |
637 * the returned time is the stream time used to configure the element's |
623 * the returned time is the running time used to configure the element's |
638 * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the |
624 * base time in the PAUSED->PLAYING state. If the pipeline is PAUSED, the |
639 * returned time is the stream time when the pipeline was paused. |
625 * returned time is the running time when the pipeline was paused. |
640 * |
626 * |
641 * This function returns #GST_CLOCK_TIME_NONE if the pipeline was |
627 * This function returns #GST_CLOCK_TIME_NONE if the pipeline was |
642 * configured to not handle the management of the element's base time |
628 * configured to not handle the management of the element's base time |
643 * (see gst_pipeline_set_new_stream_time()). |
629 * (see gst_pipeline_set_new_stream_time()). |
644 * |
630 * |
|
631 * MT safe. |
|
632 * |
645 * Returns: a #GstClockTime. |
633 * Returns: a #GstClockTime. |
646 * |
634 * |
647 * MT safe. |
635 * Deprecated: This function has the wrong name and is equivalent to |
648 */ |
636 * gst_element_get_start_time(). |
649 #ifdef __SYMBIAN32__ |
637 */ |
650 EXPORT_C |
638 #ifndef GST_REMOVE_DEPRECATED |
651 #endif |
639 #ifdef __SYMBIAN32__ |
652 |
640 EXPORT_C |
|
641 #endif |
653 GstClockTime |
642 GstClockTime |
654 gst_pipeline_get_last_stream_time (GstPipeline * pipeline) |
643 gst_pipeline_get_last_stream_time (GstPipeline * pipeline) |
655 { |
644 { |
656 GstClockTime result; |
645 GstClockTime result; |
657 |
646 |
658 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); |
647 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); |
659 |
648 |
660 GST_OBJECT_LOCK (pipeline); |
649 result = gst_element_get_start_time (GST_ELEMENT_CAST (pipeline)); |
661 result = pipeline->stream_time; |
|
662 GST_OBJECT_UNLOCK (pipeline); |
|
663 |
650 |
664 return result; |
651 return result; |
665 } |
652 } |
|
653 #endif /* GST_REMOVE_DEPRECATED */ |
666 |
654 |
667 static GstClock * |
655 static GstClock * |
668 gst_pipeline_provide_clock_func (GstElement * element) |
656 gst_pipeline_provide_clock_func (GstElement * element) |
669 { |
657 { |
670 GstClock *clock = NULL; |
658 GstClock *clock = NULL; |
682 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); |
670 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); |
683 } else { |
671 } else { |
684 GST_OBJECT_UNLOCK (pipeline); |
672 GST_OBJECT_UNLOCK (pipeline); |
685 /* let the parent bin select a clock */ |
673 /* let the parent bin select a clock */ |
686 clock = |
674 clock = |
687 GST_ELEMENT_CLASS (parent_class)-> |
675 GST_ELEMENT_CLASS (parent_class)->provide_clock (GST_ELEMENT |
688 provide_clock (GST_ELEMENT (pipeline)); |
676 (pipeline)); |
689 /* no clock, use a system clock */ |
677 /* no clock, use a system clock */ |
690 if (!clock) { |
678 if (!clock) { |
691 clock = gst_system_clock_obtain (); |
679 clock = gst_system_clock_obtain (); |
692 |
680 |
693 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)", |
681 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)", |