|
1 /* GStreamer |
|
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> |
|
3 * 2004,2005 Wim Taymans <wim@fluendo.com> |
|
4 * |
|
5 * gstpipeline.c: Overall pipeline management element |
|
6 * |
|
7 * This library is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU Library General Public |
|
9 * License as published by the Free Software Foundation; either |
|
10 * version 2 of the License, or (at your option) any later version. |
|
11 * |
|
12 * This library is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 * Library General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU Library General Public |
|
18 * License along with this library; if not, write to the |
|
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
20 * Boston, MA 02111-1307, USA. |
|
21 */ |
|
22 |
|
23 /** |
|
24 * SECTION:gstpipeline |
|
25 * @short_description: Top-level bin with clocking and bus management |
|
26 functionality. |
|
27 * @see_also: #GstElement, #GstBin, #GstClock, #GstBus |
|
28 * |
|
29 * A #GstPipeline is a special #GstBin used as the toplevel container for |
|
30 * the filter graph. The #GstPipeline will manage the selection and |
|
31 * distribution of a global #GstClock as well as provide a #GstBus to the |
|
32 * application. It will also implement a default behavour for managing |
|
33 * seek events (see gst_element_seek()). |
|
34 * |
|
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). |
|
38 * |
|
39 * Elements are added and removed from the pipeline using the #GstBin |
|
40 * methods like gst_bin_add() and gst_bin_remove() (see #GstBin). |
|
41 * |
|
42 * Before changing the state of the #GstPipeline (see #GstElement) a #GstBus |
|
43 * can be retrieved with gst_pipeline_get_bus(). This bus can then be |
|
44 * used to receive #GstMessage from the elements in the pipeline. |
|
45 * |
|
46 * By default, a #GstPipeline will automatically flush the pending #GstBus |
|
47 * messages when going to the NULL state to ensure that no circular |
|
48 * references exist when no messages are read from the #GstBus. This |
|
49 * behaviour can be changed with gst_pipeline_set_auto_flush_bus(). |
|
50 * |
|
51 * When the #GstPipeline performs the PAUSED to PLAYING state change it will |
|
52 * select a clock for the elements. The clock selection algorithm will by |
|
53 * default select a clock provided by an element that is most upstream |
|
54 * (closest to the source). For live pipelines (ones that return |
|
55 * #GST_STATE_CHANGE_NO_PREROLL from the gst_element_set_state() call) this |
|
56 * will select the clock provided by the live source. For normal pipelines |
|
57 * this will select a clock provided by the sinks (most likely the audio |
|
58 * sink). If no element provides a clock, a default #GstSystemClock is used. |
|
59 * |
|
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 |
|
62 * gst_pipeline_auto_clock() the default clock selection algorithm can be |
|
63 * restored. |
|
64 * |
|
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 |
|
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 |
|
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 |
|
71 * to PLAYING again. This default behaviour can be changed with the |
|
72 * gst_pipeline_set_new_stream_time() method. |
|
73 * |
|
74 * When sending a flushing seek event to a GstPipeline (see |
|
75 * 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 |
|
77 * seek succeeded. |
|
78 * |
|
79 * Last reviewed on 2006-03-12 (0.10.5) |
|
80 */ |
|
81 |
|
82 #include "gst_private.h" |
|
83 #include "gsterror.h" |
|
84 #include "gst-i18n-lib.h" |
|
85 |
|
86 #include "gstpipeline.h" |
|
87 #include "gstinfo.h" |
|
88 #include "gstsystemclock.h" |
|
89 |
|
90 #ifdef __SYMBIAN32__ |
|
91 #include <glib_global.h> |
|
92 #endif |
|
93 |
|
94 GST_DEBUG_CATEGORY_STATIC (pipeline_debug); |
|
95 #define GST_CAT_DEFAULT pipeline_debug |
|
96 |
|
97 /* Pipeline signals and args */ |
|
98 enum |
|
99 { |
|
100 /* FILL ME */ |
|
101 LAST_SIGNAL |
|
102 }; |
|
103 |
|
104 #define DEFAULT_DELAY 0 |
|
105 #define DEFAULT_AUTO_FLUSH_BUS TRUE |
|
106 |
|
107 enum |
|
108 { |
|
109 PROP_0, |
|
110 PROP_DELAY, |
|
111 PROP_AUTO_FLUSH_BUS |
|
112 }; |
|
113 |
|
114 #define GST_PIPELINE_GET_PRIVATE(obj) \ |
|
115 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PIPELINE, GstPipelinePrivate)) |
|
116 |
|
117 struct _GstPipelinePrivate |
|
118 { |
|
119 /* with LOCK */ |
|
120 gboolean auto_flush_bus; |
|
121 |
|
122 /* when we need to update stream_time or clock when going back to |
|
123 * PLAYING*/ |
|
124 gboolean update_stream_time; |
|
125 gboolean update_clock; |
|
126 }; |
|
127 |
|
128 |
|
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 |
|
133 static void gst_pipeline_dispose (GObject * object); |
|
134 static void gst_pipeline_set_property (GObject * object, guint prop_id, |
|
135 const GValue * value, GParamSpec * pspec); |
|
136 static void gst_pipeline_get_property (GObject * object, guint prop_id, |
|
137 GValue * value, GParamSpec * pspec); |
|
138 |
|
139 static GstClock *gst_pipeline_provide_clock_func (GstElement * element); |
|
140 static GstStateChangeReturn gst_pipeline_change_state (GstElement * element, |
|
141 GstStateChange transition); |
|
142 |
|
143 static void gst_pipeline_handle_message (GstBin * bin, GstMessage * message); |
|
144 |
|
145 static GstBinClass *parent_class = NULL; |
|
146 |
|
147 /* static guint gst_pipeline_signals[LAST_SIGNAL] = { 0 }; */ |
|
148 #ifdef __SYMBIAN32__ |
|
149 EXPORT_C |
|
150 #endif |
|
151 |
|
152 |
|
153 GType |
|
154 gst_pipeline_get_type (void) |
|
155 { |
|
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 } |
|
180 |
|
181 static void |
|
182 gst_pipeline_base_init (gpointer g_class) |
|
183 { |
|
184 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); |
|
185 |
|
186 gst_element_class_set_details_simple (gstelement_class, "Pipeline object", |
|
187 "Generic/Bin", |
|
188 "Complete pipeline object", |
|
189 "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>"); |
|
190 } |
|
191 |
|
192 static void |
|
193 gst_pipeline_class_init (gpointer g_class, gpointer class_data) |
|
194 { |
|
195 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class); |
|
196 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); |
|
197 GstBinClass *gstbin_class = GST_BIN_CLASS (g_class); |
|
198 GstPipelineClass *klass = GST_PIPELINE_CLASS (g_class); |
|
199 |
|
200 parent_class = g_type_class_peek_parent (klass); |
|
201 |
|
202 g_type_class_add_private (klass, sizeof (GstPipelinePrivate)); |
|
203 |
|
204 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property); |
|
205 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property); |
|
206 |
|
207 /** |
|
208 * GstPipeline:delay |
|
209 * |
|
210 * The expected delay needed for elements to spin up to the |
|
211 * PLAYING state expressed in nanoseconds. |
|
212 * see gst_pipeline_set_delay() for more information on this option. |
|
213 * |
|
214 * Since: 0.10.5 |
|
215 **/ |
|
216 g_object_class_install_property (gobject_class, PROP_DELAY, |
|
217 g_param_spec_uint64 ("delay", "Delay", |
|
218 "Expected delay needed for elements " |
|
219 "to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY, |
|
220 G_PARAM_READWRITE)); |
|
221 |
|
222 /** |
|
223 * GstPipeline:auto-flush-bus: |
|
224 * |
|
225 * Whether or not to automatically flush all messages on the |
|
226 * pipeline's bus when going from READY to NULL state. Please see |
|
227 * gst_pipeline_set_auto_flush_bus() for more information on this option. |
|
228 * |
|
229 * Since: 0.10.4 |
|
230 **/ |
|
231 g_object_class_install_property (gobject_class, PROP_AUTO_FLUSH_BUS, |
|
232 g_param_spec_boolean ("auto-flush-bus", "Auto Flush Bus", |
|
233 "Whether to automatically flush the pipeline's bus when going " |
|
234 "from READY into NULL state", DEFAULT_AUTO_FLUSH_BUS, |
|
235 G_PARAM_READWRITE)); |
|
236 |
|
237 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose); |
|
238 |
|
239 gstelement_class->change_state = |
|
240 GST_DEBUG_FUNCPTR (gst_pipeline_change_state); |
|
241 gstelement_class->provide_clock = |
|
242 GST_DEBUG_FUNCPTR (gst_pipeline_provide_clock_func); |
|
243 gstbin_class->handle_message = |
|
244 GST_DEBUG_FUNCPTR (gst_pipeline_handle_message); |
|
245 } |
|
246 |
|
247 static void |
|
248 gst_pipeline_init (GTypeInstance * instance, gpointer g_class) |
|
249 { |
|
250 GstPipeline *pipeline = GST_PIPELINE (instance); |
|
251 GstBus *bus; |
|
252 |
|
253 pipeline->priv = GST_PIPELINE_GET_PRIVATE (pipeline); |
|
254 |
|
255 /* set default property values */ |
|
256 pipeline->priv->auto_flush_bus = DEFAULT_AUTO_FLUSH_BUS; |
|
257 pipeline->delay = DEFAULT_DELAY; |
|
258 |
|
259 /* create and set a default bus */ |
|
260 bus = gst_bus_new (); |
|
261 #if 0 |
|
262 /* FIXME, disabled for 0.10.5 release as it caused to many regressions */ |
|
263 /* Start our bus in flushing if appropriate */ |
|
264 if (pipeline->priv->auto_flush_bus) |
|
265 gst_bus_set_flushing (bus, TRUE); |
|
266 #endif |
|
267 |
|
268 gst_element_set_bus (GST_ELEMENT_CAST (pipeline), bus); |
|
269 GST_DEBUG_OBJECT (pipeline, "set bus %" GST_PTR_FORMAT " on pipeline", bus); |
|
270 gst_object_unref (bus); |
|
271 } |
|
272 |
|
273 static void |
|
274 gst_pipeline_dispose (GObject * object) |
|
275 { |
|
276 GstPipeline *pipeline = GST_PIPELINE (object); |
|
277 GstClock **clock_p = &pipeline->fixed_clock; |
|
278 |
|
279 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pipeline, "dispose"); |
|
280 |
|
281 /* clear and unref any fixed clock */ |
|
282 gst_object_replace ((GstObject **) clock_p, NULL); |
|
283 |
|
284 G_OBJECT_CLASS (parent_class)->dispose (object); |
|
285 } |
|
286 |
|
287 static void |
|
288 gst_pipeline_set_property (GObject * object, guint prop_id, |
|
289 const GValue * value, GParamSpec * pspec) |
|
290 { |
|
291 GstPipeline *pipeline = GST_PIPELINE (object); |
|
292 |
|
293 switch (prop_id) { |
|
294 case PROP_DELAY: |
|
295 gst_pipeline_set_delay (pipeline, g_value_get_uint64 (value)); |
|
296 break; |
|
297 case PROP_AUTO_FLUSH_BUS: |
|
298 gst_pipeline_set_auto_flush_bus (pipeline, g_value_get_boolean (value)); |
|
299 break; |
|
300 default: |
|
301 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
302 break; |
|
303 } |
|
304 } |
|
305 |
|
306 static void |
|
307 gst_pipeline_get_property (GObject * object, guint prop_id, |
|
308 GValue * value, GParamSpec * pspec) |
|
309 { |
|
310 GstPipeline *pipeline = GST_PIPELINE (object); |
|
311 |
|
312 switch (prop_id) { |
|
313 case PROP_DELAY: |
|
314 g_value_set_uint64 (value, gst_pipeline_get_delay (pipeline)); |
|
315 break; |
|
316 case PROP_AUTO_FLUSH_BUS: |
|
317 g_value_set_boolean (value, gst_pipeline_get_auto_flush_bus (pipeline)); |
|
318 break; |
|
319 default: |
|
320 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
321 break; |
|
322 } |
|
323 } |
|
324 |
|
325 /* set the stream time to 0 */ |
|
326 static void |
|
327 reset_stream_time (GstPipeline * pipeline) |
|
328 { |
|
329 GST_OBJECT_LOCK (pipeline); |
|
330 if (pipeline->stream_time != GST_CLOCK_TIME_NONE) { |
|
331 GST_DEBUG_OBJECT (pipeline, "reset stream_time to 0"); |
|
332 pipeline->stream_time = 0; |
|
333 pipeline->priv->update_stream_time = TRUE; |
|
334 } else { |
|
335 GST_DEBUG_OBJECT (pipeline, "application asked to not reset stream_time"); |
|
336 } |
|
337 GST_OBJECT_UNLOCK (pipeline); |
|
338 } |
|
339 |
|
340 /** |
|
341 * gst_pipeline_new: |
|
342 * @name: name of new pipeline |
|
343 * |
|
344 * Create a new pipeline with the given name. |
|
345 * |
|
346 * Returns: newly created GstPipeline |
|
347 * |
|
348 * MT safe. |
|
349 */ |
|
350 #ifdef __SYMBIAN32__ |
|
351 EXPORT_C |
|
352 #endif |
|
353 |
|
354 GstElement * |
|
355 gst_pipeline_new (const gchar * name) |
|
356 { |
|
357 return gst_element_factory_make ("pipeline", name); |
|
358 } |
|
359 |
|
360 /* MT safe */ |
|
361 static GstStateChangeReturn |
|
362 gst_pipeline_change_state (GstElement * element, GstStateChange transition) |
|
363 { |
|
364 GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; |
|
365 GstPipeline *pipeline = GST_PIPELINE (element); |
|
366 GstClock *clock; |
|
367 |
|
368 switch (transition) { |
|
369 case GST_STATE_CHANGE_NULL_TO_READY: |
|
370 GST_OBJECT_LOCK (element); |
|
371 if (element->bus) |
|
372 gst_bus_set_flushing (element->bus, FALSE); |
|
373 GST_OBJECT_UNLOCK (element); |
|
374 break; |
|
375 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
376 GST_OBJECT_LOCK (element); |
|
377 pipeline->priv->update_clock = TRUE; |
|
378 GST_OBJECT_UNLOCK (element); |
|
379 break; |
|
380 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
|
381 { |
|
382 GstClockTime new_base_time; |
|
383 GstClockTime start_time, stream_time, delay; |
|
384 gboolean new_clock, update_stream_time, update_clock; |
|
385 GstClock *cur_clock; |
|
386 |
|
387 GST_DEBUG_OBJECT (element, "selecting clock and base_time"); |
|
388 |
|
389 GST_OBJECT_LOCK (element); |
|
390 cur_clock = element->clock; |
|
391 if (cur_clock) |
|
392 gst_object_ref (cur_clock); |
|
393 stream_time = pipeline->stream_time; |
|
394 update_stream_time = pipeline->priv->update_stream_time; |
|
395 update_clock = pipeline->priv->update_clock; |
|
396 pipeline->priv->update_stream_time = FALSE; |
|
397 pipeline->priv->update_clock = FALSE; |
|
398 delay = pipeline->delay; |
|
399 GST_OBJECT_UNLOCK (element); |
|
400 |
|
401 /* stream time changed, either with a PAUSED or a flush, we need to check |
|
402 * if there is a new clock & update the base time */ |
|
403 if (update_stream_time) { |
|
404 GST_DEBUG_OBJECT (pipeline, "Need to update stream_time"); |
|
405 |
|
406 /* when going to PLAYING, select a clock when needed. If we just got |
|
407 * flushed, we don't reselect the clock. */ |
|
408 if (update_clock) { |
|
409 GST_DEBUG_OBJECT (pipeline, "Need to update clock."); |
|
410 clock = gst_element_provide_clock (element); |
|
411 } else { |
|
412 GST_DEBUG_OBJECT (pipeline, |
|
413 "Don't need to update clock, using old clock."); |
|
414 clock = gst_object_ref (cur_clock); |
|
415 } |
|
416 |
|
417 new_clock = (clock != cur_clock); |
|
418 |
|
419 if (clock) { |
|
420 start_time = gst_clock_get_time (clock); |
|
421 } else { |
|
422 GST_DEBUG ("no clock, using base time of NONE"); |
|
423 start_time = GST_CLOCK_TIME_NONE; |
|
424 new_base_time = GST_CLOCK_TIME_NONE; |
|
425 } |
|
426 |
|
427 if (new_clock) { |
|
428 /* now distribute the clock (which could be NULL). If some |
|
429 * element refuses the clock, this will return FALSE and |
|
430 * we effectively fail the state change. */ |
|
431 if (!gst_element_set_clock (element, clock)) |
|
432 goto invalid_clock; |
|
433 |
|
434 /* if we selected and distributed a new clock, let the app |
|
435 * know about it */ |
|
436 gst_element_post_message (element, |
|
437 gst_message_new_new_clock (GST_OBJECT_CAST (element), clock)); |
|
438 } |
|
439 |
|
440 if (clock) |
|
441 gst_object_unref (clock); |
|
442 |
|
443 if (stream_time != GST_CLOCK_TIME_NONE |
|
444 && start_time != GST_CLOCK_TIME_NONE) { |
|
445 new_base_time = start_time - stream_time + delay; |
|
446 GST_DEBUG_OBJECT (element, |
|
447 "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
|
448 ", base_time %" GST_TIME_FORMAT, |
|
449 GST_TIME_ARGS (stream_time), GST_TIME_ARGS (start_time), |
|
450 GST_TIME_ARGS (new_base_time)); |
|
451 } else |
|
452 new_base_time = GST_CLOCK_TIME_NONE; |
|
453 |
|
454 if (new_base_time != GST_CLOCK_TIME_NONE) |
|
455 gst_element_set_base_time (element, new_base_time); |
|
456 else |
|
457 GST_DEBUG_OBJECT (pipeline, |
|
458 "NOT adjusting base_time because stream_time is NONE"); |
|
459 } else { |
|
460 GST_DEBUG_OBJECT (pipeline, |
|
461 "NOT adjusting base_time because we selected one before"); |
|
462 } |
|
463 |
|
464 if (cur_clock) |
|
465 gst_object_unref (cur_clock); |
|
466 break; |
|
467 } |
|
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: |
|
488 GST_OBJECT_LOCK (element); |
|
489 if ((clock = element->clock)) { |
|
490 GstClockTime now; |
|
491 |
|
492 gst_object_ref (clock); |
|
493 GST_OBJECT_UNLOCK (element); |
|
494 |
|
495 /* calculate the time when we stopped */ |
|
496 now = gst_clock_get_time (clock); |
|
497 gst_object_unref (clock); |
|
498 |
|
499 GST_OBJECT_LOCK (element); |
|
500 /* store the current stream time */ |
|
501 if (pipeline->stream_time != GST_CLOCK_TIME_NONE) { |
|
502 pipeline->stream_time = now - element->base_time; |
|
503 /* we went to PAUSED, when going to PLAYING select clock and new |
|
504 * base_time */ |
|
505 pipeline->priv->update_stream_time = TRUE; |
|
506 pipeline->priv->update_clock = TRUE; |
|
507 } |
|
508 |
|
509 GST_DEBUG_OBJECT (element, |
|
510 "stream_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT |
|
511 ", base_time %" GST_TIME_FORMAT, |
|
512 GST_TIME_ARGS (pipeline->stream_time), GST_TIME_ARGS (now), |
|
513 GST_TIME_ARGS (element->base_time)); |
|
514 } |
|
515 GST_OBJECT_UNLOCK (element); |
|
516 break; |
|
517 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
518 break; |
|
519 case GST_STATE_CHANGE_READY_TO_NULL: |
|
520 GST_OBJECT_LOCK (element); |
|
521 if (element->bus) { |
|
522 if (pipeline->priv->auto_flush_bus) { |
|
523 gst_bus_set_flushing (element->bus, TRUE); |
|
524 } else { |
|
525 GST_INFO_OBJECT (element, "not flushing bus, auto-flushing disabled"); |
|
526 } |
|
527 } |
|
528 GST_OBJECT_UNLOCK (element); |
|
529 break; |
|
530 } |
|
531 return result; |
|
532 |
|
533 /* ERRORS */ |
|
534 invalid_clock: |
|
535 { |
|
536 /* we generate this error when the selected clock was not |
|
537 * accepted by some element */ |
|
538 GST_ELEMENT_ERROR (pipeline, CORE, CLOCK, |
|
539 (_("Selected clock cannot be used in pipeline.")), |
|
540 ("Pipeline cannot operate with selected clock")); |
|
541 GST_DEBUG_OBJECT (pipeline, |
|
542 "Pipeline cannot operate with selected clock %p", clock); |
|
543 if (clock) |
|
544 gst_object_unref (clock); |
|
545 return GST_STATE_CHANGE_FAILURE; |
|
546 } |
|
547 } |
|
548 |
|
549 static void |
|
550 gst_pipeline_handle_message (GstBin * bin, GstMessage * message) |
|
551 { |
|
552 GstPipeline *pipeline = GST_PIPELINE_CAST (bin); |
|
553 |
|
554 switch (GST_MESSAGE_TYPE (message)) { |
|
555 case GST_MESSAGE_ASYNC_START: |
|
556 { |
|
557 gboolean new_base_time; |
|
558 |
|
559 gst_message_parse_async_start (message, &new_base_time); |
|
560 |
|
561 /* reset our stream time if we need to distribute a new base_time to the |
|
562 * children. */ |
|
563 if (new_base_time) |
|
564 reset_stream_time (pipeline); |
|
565 |
|
566 break; |
|
567 } |
|
568 default: |
|
569 break; |
|
570 } |
|
571 GST_BIN_CLASS (parent_class)->handle_message (bin, message); |
|
572 } |
|
573 |
|
574 /** |
|
575 * gst_pipeline_get_bus: |
|
576 * @pipeline: a #GstPipeline |
|
577 * |
|
578 * Gets the #GstBus of @pipeline. |
|
579 * |
|
580 * Returns: a #GstBus, unref after usage. |
|
581 * |
|
582 * MT safe. |
|
583 */ |
|
584 #ifdef __SYMBIAN32__ |
|
585 EXPORT_C |
|
586 #endif |
|
587 |
|
588 GstBus * |
|
589 gst_pipeline_get_bus (GstPipeline * pipeline) |
|
590 { |
|
591 return gst_element_get_bus (GST_ELEMENT (pipeline)); |
|
592 } |
|
593 |
|
594 /** |
|
595 * gst_pipeline_set_new_stream_time: |
|
596 * @pipeline: a #GstPipeline |
|
597 * @time: the new stream time to set |
|
598 * |
|
599 * Set the new stream time of @pipeline to @time. The stream time is used to |
|
600 * set the base time on the elements (see gst_element_set_base_time()) |
|
601 * in the PAUSED->PLAYING state transition. |
|
602 * |
|
603 * 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 |
|
605 * 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 |
|
607 * pipelines have the same clock. |
|
608 * |
|
609 * MT safe. |
|
610 */ |
|
611 #ifdef __SYMBIAN32__ |
|
612 EXPORT_C |
|
613 #endif |
|
614 |
|
615 void |
|
616 gst_pipeline_set_new_stream_time (GstPipeline * pipeline, GstClockTime time) |
|
617 { |
|
618 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
|
619 |
|
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)); |
|
627 |
|
628 if (time == GST_CLOCK_TIME_NONE) |
|
629 GST_DEBUG_OBJECT (pipeline, "told not to adjust base_time"); |
|
630 } |
|
631 |
|
632 /** |
|
633 * gst_pipeline_get_last_stream_time: |
|
634 * @pipeline: a #GstPipeline |
|
635 * |
|
636 * Gets the last stream time of @pipeline. If the pipeline is PLAYING, |
|
637 * the returned time is the stream time used to configure the element's |
|
638 * 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. |
|
640 * |
|
641 * This function returns #GST_CLOCK_TIME_NONE if the pipeline was |
|
642 * configured to not handle the management of the element's base time |
|
643 * (see gst_pipeline_set_new_stream_time()). |
|
644 * |
|
645 * Returns: a #GstClockTime. |
|
646 * |
|
647 * MT safe. |
|
648 */ |
|
649 #ifdef __SYMBIAN32__ |
|
650 EXPORT_C |
|
651 #endif |
|
652 |
|
653 GstClockTime |
|
654 gst_pipeline_get_last_stream_time (GstPipeline * pipeline) |
|
655 { |
|
656 GstClockTime result; |
|
657 |
|
658 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); |
|
659 |
|
660 GST_OBJECT_LOCK (pipeline); |
|
661 result = pipeline->stream_time; |
|
662 GST_OBJECT_UNLOCK (pipeline); |
|
663 |
|
664 return result; |
|
665 } |
|
666 |
|
667 static GstClock * |
|
668 gst_pipeline_provide_clock_func (GstElement * element) |
|
669 { |
|
670 GstClock *clock = NULL; |
|
671 GstPipeline *pipeline = GST_PIPELINE (element); |
|
672 |
|
673 /* if we have a fixed clock, use that one */ |
|
674 GST_OBJECT_LOCK (pipeline); |
|
675 if (GST_OBJECT_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) { |
|
676 clock = pipeline->fixed_clock; |
|
677 if (clock) |
|
678 gst_object_ref (clock); |
|
679 GST_OBJECT_UNLOCK (pipeline); |
|
680 |
|
681 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", |
|
682 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); |
|
683 } else { |
|
684 GST_OBJECT_UNLOCK (pipeline); |
|
685 /* let the parent bin select a clock */ |
|
686 clock = |
|
687 GST_ELEMENT_CLASS (parent_class)-> |
|
688 provide_clock (GST_ELEMENT (pipeline)); |
|
689 /* no clock, use a system clock */ |
|
690 if (!clock) { |
|
691 clock = gst_system_clock_obtain (); |
|
692 |
|
693 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)", |
|
694 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); |
|
695 } else { |
|
696 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)", |
|
697 clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-"); |
|
698 } |
|
699 } |
|
700 return clock; |
|
701 } |
|
702 |
|
703 /** |
|
704 * gst_pipeline_get_clock: |
|
705 * @pipeline: a #GstPipeline |
|
706 * |
|
707 * Gets the current clock used by @pipeline. |
|
708 * |
|
709 * Returns: a #GstClock, unref after usage. |
|
710 */ |
|
711 #ifdef __SYMBIAN32__ |
|
712 EXPORT_C |
|
713 #endif |
|
714 |
|
715 GstClock * |
|
716 gst_pipeline_get_clock (GstPipeline * pipeline) |
|
717 { |
|
718 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL); |
|
719 |
|
720 return gst_pipeline_provide_clock_func (GST_ELEMENT (pipeline)); |
|
721 } |
|
722 |
|
723 |
|
724 /** |
|
725 * gst_pipeline_use_clock: |
|
726 * @pipeline: a #GstPipeline |
|
727 * @clock: the clock to use |
|
728 * |
|
729 * Force @pipeline to use the given @clock. The pipeline will |
|
730 * always use the given clock even if new clock providers are added |
|
731 * to this pipeline. |
|
732 * |
|
733 * If @clock is NULL all clocking will be disabled which will make |
|
734 * the pipeline run as fast as possible. |
|
735 * |
|
736 * MT safe. |
|
737 */ |
|
738 #ifdef __SYMBIAN32__ |
|
739 EXPORT_C |
|
740 #endif |
|
741 |
|
742 void |
|
743 gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock) |
|
744 { |
|
745 GstClock **clock_p; |
|
746 |
|
747 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
|
748 |
|
749 GST_OBJECT_LOCK (pipeline); |
|
750 GST_OBJECT_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK); |
|
751 |
|
752 clock_p = &pipeline->fixed_clock; |
|
753 gst_object_replace ((GstObject **) clock_p, (GstObject *) clock); |
|
754 GST_OBJECT_UNLOCK (pipeline); |
|
755 |
|
756 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock, |
|
757 (clock ? GST_OBJECT_NAME (clock) : "nil")); |
|
758 } |
|
759 |
|
760 /** |
|
761 * gst_pipeline_set_clock: |
|
762 * @pipeline: a #GstPipeline |
|
763 * @clock: the clock to set |
|
764 * |
|
765 * Set the clock for @pipeline. The clock will be distributed |
|
766 * to all the elements managed by the pipeline. |
|
767 * |
|
768 * Returns: TRUE if the clock could be set on the pipeline. FALSE if |
|
769 * some element did not accept the clock. |
|
770 * |
|
771 * MT safe. |
|
772 */ |
|
773 #ifdef __SYMBIAN32__ |
|
774 EXPORT_C |
|
775 #endif |
|
776 |
|
777 gboolean |
|
778 gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock) |
|
779 { |
|
780 g_return_val_if_fail (pipeline != NULL, FALSE); |
|
781 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE); |
|
782 |
|
783 return GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline), |
|
784 clock); |
|
785 } |
|
786 |
|
787 /** |
|
788 * gst_pipeline_auto_clock: |
|
789 * @pipeline: a #GstPipeline |
|
790 * |
|
791 * Let @pipeline select a clock automatically. This is the default |
|
792 * behaviour. |
|
793 * |
|
794 * Use this function if you previous forced a fixed clock with |
|
795 * gst_pipeline_use_clock() and want to restore the default |
|
796 * pipeline clock selection algorithm. |
|
797 * |
|
798 * MT safe. |
|
799 */ |
|
800 #ifdef __SYMBIAN32__ |
|
801 EXPORT_C |
|
802 #endif |
|
803 |
|
804 void |
|
805 gst_pipeline_auto_clock (GstPipeline * pipeline) |
|
806 { |
|
807 GstClock **clock_p; |
|
808 |
|
809 g_return_if_fail (pipeline != NULL); |
|
810 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
|
811 |
|
812 GST_OBJECT_LOCK (pipeline); |
|
813 GST_OBJECT_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK); |
|
814 |
|
815 clock_p = &pipeline->fixed_clock; |
|
816 gst_object_replace ((GstObject **) clock_p, NULL); |
|
817 GST_OBJECT_UNLOCK (pipeline); |
|
818 |
|
819 GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock"); |
|
820 } |
|
821 |
|
822 /** |
|
823 * gst_pipeline_set_delay: |
|
824 * @pipeline: a #GstPipeline |
|
825 * @delay: the delay |
|
826 * |
|
827 * Set the expected delay needed for all elements to perform the |
|
828 * PAUSED to PLAYING state change. @delay will be added to the |
|
829 * base time of the elements so that they wait an additional @delay |
|
830 * amount of time before starting to process buffers and cannot be |
|
831 * #GST_CLOCK_TIME_NONE. |
|
832 * |
|
833 * This option is used for tuning purposes and should normally not be |
|
834 * used. |
|
835 * |
|
836 * MT safe. |
|
837 * |
|
838 * Since: 0.10.5 |
|
839 */ |
|
840 #ifdef __SYMBIAN32__ |
|
841 EXPORT_C |
|
842 #endif |
|
843 |
|
844 void |
|
845 gst_pipeline_set_delay (GstPipeline * pipeline, GstClockTime delay) |
|
846 { |
|
847 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
|
848 g_return_if_fail (delay != GST_CLOCK_TIME_NONE); |
|
849 |
|
850 GST_OBJECT_LOCK (pipeline); |
|
851 pipeline->delay = delay; |
|
852 GST_OBJECT_UNLOCK (pipeline); |
|
853 } |
|
854 |
|
855 /** |
|
856 * gst_pipeline_get_delay: |
|
857 * @pipeline: a #GstPipeline |
|
858 * |
|
859 * Get the configured delay (see gst_pipeline_set_delay()). |
|
860 * |
|
861 * Returns: The configured delay. |
|
862 * |
|
863 * MT safe. |
|
864 * |
|
865 * Since: 0.10.5 |
|
866 */ |
|
867 #ifdef __SYMBIAN32__ |
|
868 EXPORT_C |
|
869 #endif |
|
870 |
|
871 GstClockTime |
|
872 gst_pipeline_get_delay (GstPipeline * pipeline) |
|
873 { |
|
874 GstClockTime res; |
|
875 |
|
876 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), GST_CLOCK_TIME_NONE); |
|
877 |
|
878 GST_OBJECT_LOCK (pipeline); |
|
879 res = pipeline->delay; |
|
880 GST_OBJECT_UNLOCK (pipeline); |
|
881 |
|
882 return res; |
|
883 } |
|
884 |
|
885 /** |
|
886 * gst_pipeline_set_auto_flush_bus: |
|
887 * @pipeline: a #GstPipeline |
|
888 * @auto_flush: whether or not to automatically flush the bus when |
|
889 * the pipeline goes from READY to NULL state |
|
890 * |
|
891 * Usually, when a pipeline goes from READY to NULL state, it automatically |
|
892 * flushes all pending messages on the bus, which is done for refcounting |
|
893 * purposes, to break circular references. |
|
894 * |
|
895 * This means that applications that update state using (async) bus messages |
|
896 * (e.g. do certain things when a pipeline goes from PAUSED to READY) might |
|
897 * not get to see messages when the pipeline is shut down, because they might |
|
898 * be flushed before they can be dispatched in the main thread. This behaviour |
|
899 * can be disabled using this function. |
|
900 * |
|
901 * It is important that all messages on the bus are handled when the |
|
902 * automatic flushing is disabled else memory leaks will be introduced. |
|
903 * |
|
904 * MT safe. |
|
905 * |
|
906 * Since: 0.10.4 |
|
907 */ |
|
908 #ifdef __SYMBIAN32__ |
|
909 EXPORT_C |
|
910 #endif |
|
911 |
|
912 void |
|
913 gst_pipeline_set_auto_flush_bus (GstPipeline * pipeline, gboolean auto_flush) |
|
914 { |
|
915 g_return_if_fail (GST_IS_PIPELINE (pipeline)); |
|
916 |
|
917 GST_OBJECT_LOCK (pipeline); |
|
918 pipeline->priv->auto_flush_bus = auto_flush; |
|
919 GST_OBJECT_UNLOCK (pipeline); |
|
920 } |
|
921 |
|
922 /** |
|
923 * gst_pipeline_get_auto_flush_bus: |
|
924 * @pipeline: a #GstPipeline |
|
925 * |
|
926 * Check if @pipeline will automatically flush messages when going to |
|
927 * the NULL state. |
|
928 * |
|
929 * Returns: whether the pipeline will automatically flush its bus when |
|
930 * going from READY to NULL state or not. |
|
931 * |
|
932 * MT safe. |
|
933 * |
|
934 * Since: 0.10.4 |
|
935 */ |
|
936 #ifdef __SYMBIAN32__ |
|
937 EXPORT_C |
|
938 #endif |
|
939 |
|
940 gboolean |
|
941 gst_pipeline_get_auto_flush_bus (GstPipeline * pipeline) |
|
942 { |
|
943 gboolean res; |
|
944 |
|
945 g_return_val_if_fail (GST_IS_PIPELINE (pipeline), FALSE); |
|
946 |
|
947 GST_OBJECT_LOCK (pipeline); |
|
948 res = pipeline->priv->auto_flush_bus; |
|
949 GST_OBJECT_UNLOCK (pipeline); |
|
950 |
|
951 return res; |
|
952 } |