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