1 /* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2004 Wim Taymans <wim@fluendo.com>
4 *
5 * gstelement.c: The base element, all elements derive from this
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., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /**
24 * SECTION:gstelement
25 * @title: GstElement
26 * @short_description: Abstract base class for all pipeline elements
27 * @see_also: #GstElementFactory, #GstPad
28 *
29 * GstElement is the abstract base class needed to construct an element that
30 * can be used in a GStreamer pipeline. Please refer to the plugin writers
31 * guide for more information on creating #GstElement subclasses.
32 *
33 * The name of a #GstElement can be get with gst_element_get_name() and set with
34 * gst_element_set_name(). For speed, GST_ELEMENT_NAME() can be used in the
35 * core when using the appropriate locking. Do not use this in plug-ins or
36 * applications in order to retain ABI compatibility.
37 *
38 * Elements can have pads (of the type #GstPad). These pads link to pads on
39 * other elements. #GstBuffer flow between these linked pads.
40 * A #GstElement has a #GList of #GstPad structures for all their input (or sink)
41 * and output (or source) pads.
42 * Core and plug-in writers can add and remove pads with gst_element_add_pad()
43 * and gst_element_remove_pad().
44 *
45 * An existing pad of an element can be retrieved by name with
46 * gst_element_get_static_pad(). A new dynamic pad can be created using
47 * gst_element_request_pad() with a #GstPadTemplate.
48 * An iterator of all pads can be retrieved with gst_element_iterate_pads().
49 *
50 * Elements can be linked through their pads.
51 * If the link is straightforward, use the gst_element_link()
52 * convenience function to link two elements, or gst_element_link_many()
53 * for more elements in a row.
54 * Use gst_element_link_filtered() to link two elements constrained by
55 * a specified set of #GstCaps.
56 * For finer control, use gst_element_link_pads() and
57 * gst_element_link_pads_filtered() to specify the pads to link on
58 * each element by name.
59 *
60 * Each element has a state (see #GstState). You can get and set the state
61 * of an element with gst_element_get_state() and gst_element_set_state().
62 * Setting a state triggers a #GstStateChange. To get a string representation
63 * of a #GstState, use gst_element_state_get_name().
64 *
65 * You can get and set a #GstClock on an element using gst_element_get_clock()
66 * and gst_element_set_clock().
67 * Some elements can provide a clock for the pipeline if
68 * the #GST_ELEMENT_FLAG_PROVIDE_CLOCK flag is set. With the
69 * gst_element_provide_clock() method one can retrieve the clock provided by
70 * such an element.
71 * Not all elements require a clock to operate correctly. If the
72 * #GST_ELEMENT_FLAG_REQUIRE_CLOCK() flag is set, a clock should be set on the
73 * element with gst_element_set_clock().
74 *
75 * Note that clock selection and distribution is normally handled by the
76 * toplevel #GstPipeline so the clock functions are only to be used in very
77 * specific situations.
78 */
79
80 #include "gst_private.h"
81 #include <glib.h>
82 #include <stdarg.h>
83 #include <gobject/gvaluecollector.h>
84
85 #include "gstelement.h"
86 #include "gstelementmetadata.h"
87 #include "gstenumtypes.h"
88 #include "gstbus.h"
89 #include "gsterror.h"
90 #include "gstevent.h"
91 #include "gstutils.h"
92 #include "gstinfo.h"
93 #include "gstquark.h"
94 #include "gsttracerutils.h"
95 #include "gstvalue.h"
96 #include "gst-i18n-lib.h"
97 #include "glib-compat-private.h"
98
99 #ifndef GST_DISABLE_GST_DEBUG
100 #include "printf/printf.h"
101 #endif
102
103 /* Element signals and args */
104 enum
105 {
106 PAD_ADDED,
107 PAD_REMOVED,
108 NO_MORE_PADS,
109 /* add more above */
110 LAST_SIGNAL
111 };
112
113 enum
114 {
115 ARG_0
116 /* FILL ME */
117 };
118
119 static void gst_element_class_init (GstElementClass * klass);
120 static void gst_element_init (GstElement * element);
121 static void gst_element_base_class_init (gpointer g_class);
122
123 static void gst_element_constructed (GObject * object);
124 static void gst_element_dispose (GObject * object);
125 static void gst_element_finalize (GObject * object);
126
127 static GstStateChangeReturn gst_element_change_state_func (GstElement * element,
128 GstStateChange transition);
129 static GstStateChangeReturn gst_element_get_state_func (GstElement * element,
130 GstState * state, GstState * pending, GstClockTime timeout);
131 static GstStateChangeReturn gst_element_set_state_func (GstElement * element,
132 GstState state);
133 static gboolean gst_element_set_clock_func (GstElement * element,
134 GstClock * clock);
135 static void gst_element_set_bus_func (GstElement * element, GstBus * bus);
136 static gboolean gst_element_post_message_default (GstElement * element,
137 GstMessage * message);
138 static void gst_element_set_context_default (GstElement * element,
139 GstContext * context);
140
141 static gboolean gst_element_default_send_event (GstElement * element,
142 GstEvent * event);
143 static gboolean gst_element_default_query (GstElement * element,
144 GstQuery * query);
145
146 static GstPadTemplate
147 * gst_element_class_get_request_pad_template (GstElementClass *
148 element_class, const gchar * name);
149
150 static void gst_element_call_async_func (gpointer data, gpointer user_data);
151
152 static GstObjectClass *parent_class = NULL;
153 static guint gst_element_signals[LAST_SIGNAL] = { 0 };
154
155 static GThreadPool *gst_element_pool = NULL;
156
157 /* this is used in gstelementfactory.c:gst_element_register() */
158 GQuark __gst_elementclass_factory = 0;
159
160 GType
gst_element_get_type(void)161 gst_element_get_type (void)
162 {
163 static volatile gsize gst_element_type = 0;
164
165 if (g_once_init_enter (&gst_element_type)) {
166 GType _type;
167 static const GTypeInfo element_info = {
168 sizeof (GstElementClass),
169 gst_element_base_class_init,
170 NULL, /* base_class_finalize */
171 (GClassInitFunc) gst_element_class_init,
172 NULL,
173 NULL,
174 sizeof (GstElement),
175 0,
176 (GInstanceInitFunc) gst_element_init,
177 NULL
178 };
179
180 _type = g_type_register_static (GST_TYPE_OBJECT, "GstElement",
181 &element_info, G_TYPE_FLAG_ABSTRACT);
182
183 __gst_elementclass_factory =
184 g_quark_from_static_string ("GST_ELEMENTCLASS_FACTORY");
185 g_once_init_leave (&gst_element_type, _type);
186 }
187 return gst_element_type;
188 }
189
190 static void
gst_element_setup_thread_pool(void)191 gst_element_setup_thread_pool (void)
192 {
193 GError *err = NULL;
194
195 GST_DEBUG ("creating element thread pool");
196 gst_element_pool =
197 g_thread_pool_new ((GFunc) gst_element_call_async_func, NULL, -1, FALSE,
198 &err);
199 if (err != NULL) {
200 g_critical ("could not alloc threadpool %s", err->message);
201 g_clear_error (&err);
202 }
203 }
204
205 static void
gst_element_class_init(GstElementClass * klass)206 gst_element_class_init (GstElementClass * klass)
207 {
208 GObjectClass *gobject_class;
209
210 gobject_class = (GObjectClass *) klass;
211
212 parent_class = g_type_class_peek_parent (klass);
213
214 /**
215 * GstElement::pad-added:
216 * @gstelement: the object which received the signal
217 * @new_pad: the pad that has been added
218 *
219 * a new #GstPad has been added to the element. Note that this signal will
220 * usually be emitted from the context of the streaming thread. Also keep in
221 * mind that if you add new elements to the pipeline in the signal handler
222 * you will need to set them to the desired target state with
223 * gst_element_set_state() or gst_element_sync_state_with_parent().
224 */
225 gst_element_signals[PAD_ADDED] =
226 g_signal_new ("pad-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
227 G_STRUCT_OFFSET (GstElementClass, pad_added), NULL, NULL,
228 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
229 /**
230 * GstElement::pad-removed:
231 * @gstelement: the object which received the signal
232 * @old_pad: the pad that has been removed
233 *
234 * a #GstPad has been removed from the element
235 */
236 gst_element_signals[PAD_REMOVED] =
237 g_signal_new ("pad-removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
238 G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
239 g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_PAD);
240 /**
241 * GstElement::no-more-pads:
242 * @gstelement: the object which received the signal
243 *
244 * This signals that the element will not generate more dynamic pads.
245 * Note that this signal will usually be emitted from the context of
246 * the streaming thread.
247 */
248 gst_element_signals[NO_MORE_PADS] =
249 g_signal_new ("no-more-pads", G_TYPE_FROM_CLASS (klass),
250 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstElementClass, no_more_pads), NULL,
251 NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 0);
252
253 gobject_class->dispose = gst_element_dispose;
254 gobject_class->finalize = gst_element_finalize;
255 gobject_class->constructed = gst_element_constructed;
256
257 klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state_func);
258 klass->set_state = GST_DEBUG_FUNCPTR (gst_element_set_state_func);
259 klass->get_state = GST_DEBUG_FUNCPTR (gst_element_get_state_func);
260 klass->set_clock = GST_DEBUG_FUNCPTR (gst_element_set_clock_func);
261 klass->set_bus = GST_DEBUG_FUNCPTR (gst_element_set_bus_func);
262 klass->query = GST_DEBUG_FUNCPTR (gst_element_default_query);
263 klass->send_event = GST_DEBUG_FUNCPTR (gst_element_default_send_event);
264 klass->numpadtemplates = 0;
265 klass->post_message = GST_DEBUG_FUNCPTR (gst_element_post_message_default);
266 klass->set_context = GST_DEBUG_FUNCPTR (gst_element_set_context_default);
267
268 klass->elementfactory = NULL;
269
270 gst_element_setup_thread_pool ();
271 }
272
273 static void
gst_element_base_class_init(gpointer g_class)274 gst_element_base_class_init (gpointer g_class)
275 {
276 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
277 GList *node, *padtemplates;
278
279 /* Copy the element details here so elements can inherit the
280 * details from their base class and classes only need to set
281 * the details in class_init instead of base_init */
282 element_class->metadata =
283 element_class->metadata ? gst_structure_copy (element_class->metadata) :
284 gst_structure_new_empty ("metadata");
285
286 /* Copy the pad templates so elements inherit them
287 * from their base class but elements can add pad templates in class_init
288 * instead of base_init.
289 */
290 padtemplates = g_list_copy (element_class->padtemplates);
291 for (node = padtemplates; node != NULL; node = node->next) {
292 GstPadTemplate *tmpl = (GstPadTemplate *) node->data;
293 gst_object_ref (tmpl);
294 }
295 element_class->padtemplates = padtemplates;
296
297 /* set the factory, see gst_element_register() */
298 element_class->elementfactory =
299 g_type_get_qdata (G_TYPE_FROM_CLASS (element_class),
300 __gst_elementclass_factory);
301 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "type %s : factory %p",
302 G_OBJECT_CLASS_NAME (element_class), element_class->elementfactory);
303 }
304
305 static void
gst_element_init(GstElement * element)306 gst_element_init (GstElement * element)
307 {
308 GST_STATE (element) = GST_STATE_NULL;
309 GST_STATE_TARGET (element) = GST_STATE_NULL;
310 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
311 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
312 GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
313
314 g_rec_mutex_init (&element->state_lock);
315 g_cond_init (&element->state_cond);
316 }
317
318 static void
gst_element_constructed(GObject * object)319 gst_element_constructed (GObject * object)
320 {
321 GST_TRACER_ELEMENT_NEW (GST_ELEMENT_CAST (object));
322 G_OBJECT_CLASS (parent_class)->constructed (object);
323 }
324
325 /**
326 * gst_element_release_request_pad:
327 * @element: a #GstElement to release the request pad of.
328 * @pad: the #GstPad to release.
329 *
330 * Makes the element free the previously requested pad as obtained
331 * with gst_element_request_pad().
332 *
333 * This does not unref the pad. If the pad was created by using
334 * gst_element_request_pad(), gst_element_release_request_pad() needs to be
335 * followed by gst_object_unref() to free the @pad.
336 *
337 * MT safe.
338 */
339 void
gst_element_release_request_pad(GstElement * element,GstPad * pad)340 gst_element_release_request_pad (GstElement * element, GstPad * pad)
341 {
342 GstElementClass *oclass;
343
344 g_return_if_fail (GST_IS_ELEMENT (element));
345 g_return_if_fail (GST_IS_PAD (pad));
346 g_return_if_fail (GST_PAD_PAD_TEMPLATE (pad) == NULL ||
347 GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad)) ==
348 GST_PAD_REQUEST);
349 g_return_if_fail (GST_PAD_PARENT (pad) == element);
350
351 oclass = GST_ELEMENT_GET_CLASS (element);
352
353 /* if the element implements a custom release function we call that, else we
354 * simply remove the pad from the element */
355 if (oclass->release_pad)
356 oclass->release_pad (element, pad);
357 else
358 gst_element_remove_pad (element, pad);
359 }
360
361 /**
362 * gst_element_provide_clock:
363 * @element: a #GstElement to query
364 *
365 * Get the clock provided by the given element.
366 * > An element is only required to provide a clock in the PAUSED
367 * > state. Some elements can provide a clock in other states.
368 *
369 * Returns: (transfer full) (nullable): the GstClock provided by the
370 * element or %NULL if no clock could be provided. Unref after usage.
371 *
372 * MT safe.
373 */
374 GstClock *
gst_element_provide_clock(GstElement * element)375 gst_element_provide_clock (GstElement * element)
376 {
377 GstClock *result = NULL;
378 GstElementClass *oclass;
379
380 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
381
382 oclass = GST_ELEMENT_GET_CLASS (element);
383
384 if (oclass->provide_clock)
385 result = oclass->provide_clock (element);
386
387 return result;
388 }
389
390 static gboolean
gst_element_set_clock_func(GstElement * element,GstClock * clock)391 gst_element_set_clock_func (GstElement * element, GstClock * clock)
392 {
393 GstClock **clock_p;
394
395 GST_OBJECT_LOCK (element);
396 clock_p = &element->clock;
397 gst_object_replace ((GstObject **) clock_p, (GstObject *) clock);
398 GST_OBJECT_UNLOCK (element);
399
400 return TRUE;
401 }
402
403 /**
404 * gst_element_set_clock:
405 * @element: a #GstElement to set the clock for.
406 * @clock: (transfer none) (allow-none): the #GstClock to set for the element.
407 *
408 * Sets the clock for the element. This function increases the
409 * refcount on the clock. Any previously set clock on the object
410 * is unreffed.
411 *
412 * Returns: %TRUE if the element accepted the clock. An element can refuse a
413 * clock when it, for example, is not able to slave its internal clock to the
414 * @clock or when it requires a specific clock to operate.
415 *
416 * MT safe.
417 */
418 gboolean
gst_element_set_clock(GstElement * element,GstClock * clock)419 gst_element_set_clock (GstElement * element, GstClock * clock)
420 {
421 GstElementClass *oclass;
422 gboolean res = FALSE;
423
424 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
425 g_return_val_if_fail (clock == NULL || GST_IS_CLOCK (clock), FALSE);
426
427 oclass = GST_ELEMENT_GET_CLASS (element);
428
429 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element, "setting clock %p", clock);
430
431 if (oclass->set_clock)
432 res = oclass->set_clock (element, clock);
433
434 return res;
435 }
436
437 /**
438 * gst_element_get_clock:
439 * @element: a #GstElement to get the clock of.
440 *
441 * Gets the currently configured clock of the element. This is the clock as was
442 * last set with gst_element_set_clock().
443 *
444 * Elements in a pipeline will only have their clock set when the
445 * pipeline is in the PLAYING state.
446 *
447 * Returns: (transfer full) (nullable): the #GstClock of the element. unref after usage.
448 *
449 * MT safe.
450 */
451 GstClock *
gst_element_get_clock(GstElement * element)452 gst_element_get_clock (GstElement * element)
453 {
454 GstClock *result;
455
456 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
457
458 GST_OBJECT_LOCK (element);
459 if ((result = element->clock))
460 gst_object_ref (result);
461 GST_OBJECT_UNLOCK (element);
462
463 return result;
464 }
465
466 /**
467 * gst_element_set_base_time:
468 * @element: a #GstElement.
469 * @time: the base time to set.
470 *
471 * Set the base time of an element. See gst_element_get_base_time().
472 *
473 * MT safe.
474 */
475 void
gst_element_set_base_time(GstElement * element,GstClockTime time)476 gst_element_set_base_time (GstElement * element, GstClockTime time)
477 {
478 GstClockTime old;
479
480 g_return_if_fail (GST_IS_ELEMENT (element));
481
482 GST_OBJECT_LOCK (element);
483 old = element->base_time;
484 element->base_time = time;
485 GST_OBJECT_UNLOCK (element);
486
487 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element,
488 "set base_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT,
489 GST_TIME_ARGS (time), GST_TIME_ARGS (old));
490 }
491
492 /**
493 * gst_element_get_base_time:
494 * @element: a #GstElement.
495 *
496 * Returns the base time of the element. The base time is the
497 * absolute time of the clock when this element was last put to
498 * PLAYING. Subtracting the base time from the clock time gives
499 * the running time of the element.
500 *
501 * Returns: the base time of the element.
502 *
503 * MT safe.
504 */
505 GstClockTime
gst_element_get_base_time(GstElement * element)506 gst_element_get_base_time (GstElement * element)
507 {
508 GstClockTime result;
509
510 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
511
512 GST_OBJECT_LOCK (element);
513 result = element->base_time;
514 GST_OBJECT_UNLOCK (element);
515
516 return result;
517 }
518
519 /**
520 * gst_element_set_start_time:
521 * @element: a #GstElement.
522 * @time: the base time to set.
523 *
524 * Set the start time of an element. The start time of the element is the
525 * running time of the element when it last went to the PAUSED state. In READY
526 * or after a flushing seek, it is set to 0.
527 *
528 * Toplevel elements like #GstPipeline will manage the start_time and
529 * base_time on its children. Setting the start_time to #GST_CLOCK_TIME_NONE
530 * on such a toplevel element will disable the distribution of the base_time to
531 * the children and can be useful if the application manages the base_time
532 * itself, for example if you want to synchronize capture from multiple
533 * pipelines, and you can also ensure that the pipelines have the same clock.
534 *
535 * MT safe.
536 */
537 void
gst_element_set_start_time(GstElement * element,GstClockTime time)538 gst_element_set_start_time (GstElement * element, GstClockTime time)
539 {
540 GstClockTime old;
541
542 g_return_if_fail (GST_IS_ELEMENT (element));
543
544 GST_OBJECT_LOCK (element);
545 old = GST_ELEMENT_START_TIME (element);
546 GST_ELEMENT_START_TIME (element) = time;
547 GST_OBJECT_UNLOCK (element);
548
549 GST_CAT_DEBUG_OBJECT (GST_CAT_CLOCK, element,
550 "set start_time=%" GST_TIME_FORMAT ", old %" GST_TIME_FORMAT,
551 GST_TIME_ARGS (time), GST_TIME_ARGS (old));
552 }
553
554 /**
555 * gst_element_get_start_time:
556 * @element: a #GstElement.
557 *
558 * Returns the start time of the element. The start time is the
559 * running time of the clock when this element was last put to PAUSED.
560 *
561 * Usually the start_time is managed by a toplevel element such as
562 * #GstPipeline.
563 *
564 * MT safe.
565 *
566 * Returns: the start time of the element.
567 */
568 GstClockTime
gst_element_get_start_time(GstElement * element)569 gst_element_get_start_time (GstElement * element)
570 {
571 GstClockTime result;
572
573 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_CLOCK_TIME_NONE);
574
575 GST_OBJECT_LOCK (element);
576 result = GST_ELEMENT_START_TIME (element);
577 GST_OBJECT_UNLOCK (element);
578
579 return result;
580 }
581
582 #if 0
583 /**
584 * gst_element_set_index:
585 * @element: a #GstElement.
586 * @index: (transfer none): a #GstIndex.
587 *
588 * Set @index on the element. The refcount of the index
589 * will be increased, any previously set index is unreffed.
590 *
591 * MT safe.
592 */
593 void
594 gst_element_set_index (GstElement * element, GstIndex * index)
595 {
596 GstElementClass *oclass;
597
598 g_return_if_fail (GST_IS_ELEMENT (element));
599 g_return_if_fail (index == NULL || GST_IS_INDEX (index));
600
601 oclass = GST_ELEMENT_GET_CLASS (element);
602
603 if (oclass->set_index)
604 oclass->set_index (element, index);
605 }
606
607 /**
608 * gst_element_get_index:
609 * @element: a #GstElement.
610 *
611 * Gets the index from the element.
612 *
613 * Returns: (transfer full) (nullable): a #GstIndex or %NULL when no
614 * index was set on the element. unref after usage.
615 *
616 * MT safe.
617 */
618 GstIndex *
619 gst_element_get_index (GstElement * element)
620 {
621 GstElementClass *oclass;
622 GstIndex *result = NULL;
623
624 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
625
626 oclass = GST_ELEMENT_GET_CLASS (element);
627
628 if (oclass->get_index)
629 result = oclass->get_index (element);
630
631 return result;
632 }
633 #endif
634
635 /**
636 * gst_element_add_pad:
637 * @element: a #GstElement to add the pad to.
638 * @pad: (transfer floating): the #GstPad to add to the element.
639 *
640 * Adds a pad (link point) to @element. @pad's parent will be set to @element;
641 * see gst_object_set_parent() for refcounting information.
642 *
643 * Pads are automatically activated when added in the PAUSED or PLAYING
644 * state.
645 *
646 * The pad and the element should be unlocked when calling this function.
647 *
648 * This function will emit the #GstElement::pad-added signal on the element.
649 *
650 * Returns: %TRUE if the pad could be added. This function can fail when
651 * a pad with the same name already existed or the pad already had another
652 * parent.
653 *
654 * MT safe.
655 */
656 gboolean
gst_element_add_pad(GstElement * element,GstPad * pad)657 gst_element_add_pad (GstElement * element, GstPad * pad)
658 {
659 gchar *pad_name;
660 gboolean active;
661
662 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
663 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
664
665 /* locking pad to look at the name */
666 GST_OBJECT_LOCK (pad);
667 pad_name = g_strdup (GST_PAD_NAME (pad));
668 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "adding pad '%s'",
669 GST_STR_NULL (pad_name));
670 active = GST_PAD_IS_ACTIVE (pad);
671 GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_PARENT);
672 GST_OBJECT_UNLOCK (pad);
673
674 /* then check to see if there's already a pad by that name here */
675 GST_OBJECT_LOCK (element);
676 if (G_UNLIKELY (!gst_object_check_uniqueness (element->pads, pad_name)))
677 goto name_exists;
678
679 /* try to set the pad's parent */
680 if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (pad),
681 GST_OBJECT_CAST (element))))
682 goto had_parent;
683
684 /* check for active pads */
685 if (!active && (GST_STATE (element) > GST_STATE_READY ||
686 GST_STATE_NEXT (element) == GST_STATE_PAUSED)) {
687 gst_pad_set_active (pad, TRUE);
688 }
689
690 g_free (pad_name);
691
692 /* add it to the list */
693 switch (gst_pad_get_direction (pad)) {
694 case GST_PAD_SRC:
695 element->srcpads = g_list_append (element->srcpads, pad);
696 element->numsrcpads++;
697 break;
698 case GST_PAD_SINK:
699 element->sinkpads = g_list_append (element->sinkpads, pad);
700 element->numsinkpads++;
701 break;
702 default:
703 goto no_direction;
704 }
705 element->pads = g_list_append (element->pads, pad);
706 element->numpads++;
707 element->pads_cookie++;
708 GST_OBJECT_UNLOCK (element);
709
710 /* emit the PAD_ADDED signal */
711 g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);
712 GST_TRACER_ELEMENT_ADD_PAD (element, pad);
713 return TRUE;
714
715 /* ERROR cases */
716 name_exists:
717 {
718 g_critical ("Padname %s is not unique in element %s, not adding",
719 pad_name, GST_ELEMENT_NAME (element));
720 GST_OBJECT_UNLOCK (element);
721 g_free (pad_name);
722 gst_object_ref_sink (pad);
723 gst_object_unref (pad);
724 return FALSE;
725 }
726 had_parent:
727 {
728 g_critical
729 ("Pad %s already has parent when trying to add to element %s",
730 pad_name, GST_ELEMENT_NAME (element));
731 GST_OBJECT_UNLOCK (element);
732 g_free (pad_name);
733 return FALSE;
734 }
735 no_direction:
736 {
737 GST_OBJECT_LOCK (pad);
738 g_critical
739 ("Trying to add pad %s to element %s, but it has no direction",
740 GST_OBJECT_NAME (pad), GST_ELEMENT_NAME (element));
741 GST_OBJECT_UNLOCK (pad);
742 GST_OBJECT_UNLOCK (element);
743 return FALSE;
744 }
745 }
746
747 /**
748 * gst_element_remove_pad:
749 * @element: a #GstElement to remove pad from.
750 * @pad: (transfer none): the #GstPad to remove from the element.
751 *
752 * Removes @pad from @element. @pad will be destroyed if it has not been
753 * referenced elsewhere using gst_object_unparent().
754 *
755 * This function is used by plugin developers and should not be used
756 * by applications. Pads that were dynamically requested from elements
757 * with gst_element_request_pad() should be released with the
758 * gst_element_release_request_pad() function instead.
759 *
760 * Pads are not automatically deactivated so elements should perform the needed
761 * steps to deactivate the pad in case this pad is removed in the PAUSED or
762 * PLAYING state. See gst_pad_set_active() for more information about
763 * deactivating pads.
764 *
765 * The pad and the element should be unlocked when calling this function.
766 *
767 * This function will emit the #GstElement::pad-removed signal on the element.
768 *
769 * Returns: %TRUE if the pad could be removed. Can return %FALSE if the
770 * pad does not belong to the provided element.
771 *
772 * MT safe.
773 */
774 gboolean
gst_element_remove_pad(GstElement * element,GstPad * pad)775 gst_element_remove_pad (GstElement * element, GstPad * pad)
776 {
777 GstPad *peer;
778
779 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
780 g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
781
782 /* locking pad to look at the name and parent */
783 GST_OBJECT_LOCK (pad);
784 GST_CAT_INFO_OBJECT (GST_CAT_ELEMENT_PADS, element, "removing pad '%s'",
785 GST_STR_NULL (GST_PAD_NAME (pad)));
786
787 if (G_UNLIKELY (GST_PAD_PARENT (pad) != element))
788 goto not_our_pad;
789 GST_OBJECT_UNLOCK (pad);
790
791 /* unlink */
792 if ((peer = gst_pad_get_peer (pad))) {
793 /* window for MT unsafeness, someone else could unlink here
794 * and then we call unlink with wrong pads. The unlink
795 * function would catch this and safely return failed. */
796 if (GST_PAD_IS_SRC (pad))
797 gst_pad_unlink (pad, peer);
798 else
799 gst_pad_unlink (peer, pad);
800
801 gst_object_unref (peer);
802 }
803
804 GST_OBJECT_LOCK (element);
805 /* remove it from the list */
806 switch (gst_pad_get_direction (pad)) {
807 case GST_PAD_SRC:
808 element->srcpads = g_list_remove (element->srcpads, pad);
809 element->numsrcpads--;
810 break;
811 case GST_PAD_SINK:
812 element->sinkpads = g_list_remove (element->sinkpads, pad);
813 element->numsinkpads--;
814 break;
815 default:
816 g_critical ("Removing pad without direction???");
817 break;
818 }
819 element->pads = g_list_remove (element->pads, pad);
820 element->numpads--;
821 element->pads_cookie++;
822 GST_OBJECT_UNLOCK (element);
823
824 /* emit the PAD_REMOVED signal before unparenting and losing the last ref. */
825 g_signal_emit (element, gst_element_signals[PAD_REMOVED], 0, pad);
826 GST_TRACER_ELEMENT_REMOVE_PAD (element, pad);
827 gst_object_unparent (GST_OBJECT_CAST (pad));
828
829 return TRUE;
830
831 /* ERRORS */
832 not_our_pad:
833 {
834 /* locking order is element > pad */
835 GST_OBJECT_UNLOCK (pad);
836
837 GST_OBJECT_LOCK (element);
838 GST_OBJECT_LOCK (pad);
839 g_critical ("Padname %s:%s does not belong to element %s when removing",
840 GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
841 GST_OBJECT_UNLOCK (pad);
842 GST_OBJECT_UNLOCK (element);
843 return FALSE;
844 }
845 }
846
847 /**
848 * gst_element_no_more_pads:
849 * @element: a #GstElement
850 *
851 * Use this function to signal that the element does not expect any more pads
852 * to show up in the current pipeline. This function should be called whenever
853 * pads have been added by the element itself. Elements with #GST_PAD_SOMETIMES
854 * pad templates use this in combination with autopluggers to figure out that
855 * the element is done initializing its pads.
856 *
857 * This function emits the #GstElement::no-more-pads signal.
858 *
859 * MT safe.
860 */
861 void
gst_element_no_more_pads(GstElement * element)862 gst_element_no_more_pads (GstElement * element)
863 {
864 g_return_if_fail (GST_IS_ELEMENT (element));
865
866 g_signal_emit (element, gst_element_signals[NO_MORE_PADS], 0);
867 }
868
869 static gint
pad_compare_name(GstPad * pad1,const gchar * name)870 pad_compare_name (GstPad * pad1, const gchar * name)
871 {
872 gint result;
873
874 GST_OBJECT_LOCK (pad1);
875 result = strcmp (GST_PAD_NAME (pad1), name);
876 GST_OBJECT_UNLOCK (pad1);
877
878 return result;
879 }
880
881 /**
882 * gst_element_get_static_pad:
883 * @element: a #GstElement to find a static pad of.
884 * @name: the name of the static #GstPad to retrieve.
885 *
886 * Retrieves a pad from @element by name. This version only retrieves
887 * already-existing (i.e. 'static') pads.
888 *
889 * Returns: (transfer full) (nullable): the requested #GstPad if
890 * found, otherwise %NULL. unref after usage.
891 *
892 * MT safe.
893 */
894 GstPad *
gst_element_get_static_pad(GstElement * element,const gchar * name)895 gst_element_get_static_pad (GstElement * element, const gchar * name)
896 {
897 GList *find;
898 GstPad *result = NULL;
899
900 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
901 g_return_val_if_fail (name != NULL, NULL);
902
903 GST_OBJECT_LOCK (element);
904 find =
905 g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
906 if (find) {
907 result = GST_PAD_CAST (find->data);
908 gst_object_ref (result);
909 }
910
911 if (result == NULL) {
912 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "no such pad '%s' in element \"%s\"",
913 name, GST_ELEMENT_NAME (element));
914 } else {
915 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
916 GST_ELEMENT_NAME (element), name);
917 }
918 GST_OBJECT_UNLOCK (element);
919
920 return result;
921 }
922
923 static gboolean
gst_element_is_valid_request_template_name(const gchar * templ_name,const gchar * name)924 gst_element_is_valid_request_template_name (const gchar * templ_name,
925 const gchar * name)
926 {
927 gchar *endptr;
928 const gchar *templ_name_ptr, *name_ptr;
929 gboolean next_specifier;
930 guint templ_postfix_len = 0, name_postfix_len = 0;
931
932 g_return_val_if_fail (templ_name != NULL, FALSE);
933 g_return_val_if_fail (name != NULL, FALSE);
934
935 /* Is this the template name? */
936 if (strcmp (templ_name, name) == 0)
937 return TRUE;
938
939 /* otherwise check all the specifiers */
940 do {
941 /* Because of sanity checks in gst_pad_template_new(), we know that %s
942 * and %d and %u, occurring at the template_name */
943 templ_name_ptr = strchr (templ_name, '%');
944
945 /* check characters ahead of the specifier */
946 if (!templ_name_ptr || strlen (name) <= templ_name_ptr - templ_name
947 || strncmp (templ_name, name, templ_name_ptr - templ_name) != 0) {
948 return FALSE;
949 }
950
951 /* %s is not allowed for multiple specifiers, just a single specifier can be
952 * accepted in gst_pad_template_new() and can not be mixed with other
953 * specifier '%u' and '%d' */
954 if (*(templ_name_ptr + 1) == 's' && g_strcmp0 (templ_name, name) == 0) {
955 return TRUE;
956 }
957
958 name_ptr = name + (templ_name_ptr - templ_name);
959
960 /* search next specifier, each of specifier should be separated by '_' */
961 templ_name = strchr (templ_name_ptr, '_');
962 name = strchr (name_ptr, '_');
963
964 /* don't match the number of specifiers */
965 if ((templ_name && !name) || (!templ_name && name))
966 return FALSE;
967
968 if (templ_name && name)
969 next_specifier = TRUE;
970 else
971 next_specifier = FALSE;
972
973 /* check characters followed by the specifier */
974 if (*(templ_name_ptr + 2) != '\0' && *(templ_name_ptr + 2) != '_') {
975 if (next_specifier) {
976 templ_postfix_len = templ_name - (templ_name_ptr + 2);
977 name_postfix_len = name - name_ptr;
978 } else {
979 templ_postfix_len = strlen (templ_name_ptr + 2);
980 name_postfix_len = strlen (name_ptr);
981 }
982
983 if (strncmp (templ_name_ptr + 2,
984 name_ptr + name_postfix_len - templ_postfix_len,
985 templ_postfix_len) != 0) {
986 return FALSE;
987 }
988 }
989
990 /* verify the specifier */
991 if (*(name_ptr) == '%') {
992 guint len;
993
994 len = (next_specifier) ? name - name_ptr : strlen (name_ptr);
995
996 if (strncmp (name_ptr, templ_name_ptr, len) != 0)
997 return FALSE;
998
999 } else {
1000 const gchar *specifier;
1001 gchar *target = NULL;
1002
1003 /* extract specifier when it has postfix characters */
1004 if (name_postfix_len > templ_postfix_len) {
1005 target = g_strndup (name_ptr, name_postfix_len - templ_postfix_len);
1006 }
1007 specifier = target ? target : name_ptr;
1008
1009 if (*(templ_name_ptr + 1) == 'd') {
1010 gint64 tmp;
1011
1012 /* it's an int */
1013 tmp = g_ascii_strtoll (specifier, &endptr, 10);
1014 if (tmp < G_MININT || tmp > G_MAXINT || (*endptr != '\0'
1015 && *endptr != '_'))
1016 return FALSE;
1017 } else if (*(templ_name_ptr + 1) == 'u') {
1018 guint64 tmp;
1019
1020 /* it's an int */
1021 tmp = g_ascii_strtoull (specifier, &endptr, 10);
1022 if (tmp > G_MAXUINT || (*endptr != '\0' && *endptr != '_'))
1023 return FALSE;
1024 }
1025
1026 g_free (target);
1027 }
1028
1029 /* otherwise we increment these from NULL to 1 */
1030 if (next_specifier) {
1031 templ_name++;
1032 name++;
1033 }
1034 } while (next_specifier);
1035
1036 return TRUE;
1037 }
1038
1039 static GstPad *
_gst_element_request_pad(GstElement * element,GstPadTemplate * templ,const gchar * name,const GstCaps * caps)1040 _gst_element_request_pad (GstElement * element, GstPadTemplate * templ,
1041 const gchar * name, const GstCaps * caps)
1042 {
1043 GstPad *newpad = NULL;
1044 GstElementClass *oclass;
1045
1046 oclass = GST_ELEMENT_GET_CLASS (element);
1047
1048 #ifndef G_DISABLE_CHECKS
1049 /* Some sanity checking here */
1050 if (name) {
1051 GstPad *pad;
1052
1053 g_return_val_if_fail (gst_element_is_valid_request_template_name
1054 (templ->name_template, name), NULL);
1055
1056 pad = gst_element_get_static_pad (element, name);
1057 if (pad) {
1058 gst_object_unref (pad);
1059 /* FIXME 2.0: Change this to g_return_val_if_fail() */
1060 g_critical ("Element %s already has a pad named %s, the behaviour of "
1061 " gst_element_get_request_pad() for existing pads is undefined!",
1062 GST_ELEMENT_NAME (element), name);
1063 }
1064 }
1065 #endif
1066
1067 if (oclass->request_new_pad)
1068 newpad = (oclass->request_new_pad) (element, templ, name, caps);
1069
1070 if (newpad)
1071 gst_object_ref (newpad);
1072
1073 return newpad;
1074 }
1075
1076 /**
1077 * gst_element_get_request_pad:
1078 * @element: a #GstElement to find a request pad of.
1079 * @name: the name of the request #GstPad to retrieve.
1080 *
1081 * Retrieves a pad from the element by name (e.g. "src_\%d"). This version only
1082 * retrieves request pads. The pad should be released with
1083 * gst_element_release_request_pad().
1084 *
1085 * This method is slower than manually getting the pad template and calling
1086 * gst_element_request_pad() if the pads should have a specific name (e.g.
1087 * @name is "src_1" instead of "src_\%u").
1088 *
1089 * Returns: (transfer full) (nullable): requested #GstPad if found,
1090 * otherwise %NULL. Release after usage.
1091 */
1092 GstPad *
gst_element_get_request_pad(GstElement * element,const gchar * name)1093 gst_element_get_request_pad (GstElement * element, const gchar * name)
1094 {
1095 GstPadTemplate *templ = NULL;
1096 GstPad *pad;
1097 const gchar *req_name = NULL;
1098 gboolean templ_found = FALSE;
1099 GList *list;
1100 GstElementClass *class;
1101
1102 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1103 g_return_val_if_fail (name != NULL, NULL);
1104
1105 class = GST_ELEMENT_GET_CLASS (element);
1106
1107 templ = gst_element_class_get_request_pad_template (class, name);
1108 if (templ) {
1109 req_name = strstr (name, "%") ? NULL : name;
1110 templ_found = TRUE;
1111 } else {
1112 /* there is no % in the name, try to find a matching template */
1113 list = class->padtemplates;
1114 while (!templ_found && list) {
1115 templ = (GstPadTemplate *) list->data;
1116 if (templ->presence == GST_PAD_REQUEST) {
1117 GST_CAT_DEBUG (GST_CAT_PADS, "comparing %s to %s", name,
1118 templ->name_template);
1119 if (gst_element_is_valid_request_template_name (templ->name_template,
1120 name)) {
1121 templ_found = TRUE;
1122 req_name = name;
1123 break;
1124 }
1125 }
1126 list = list->next;
1127 }
1128 }
1129
1130 if (!templ_found)
1131 return NULL;
1132
1133 pad = _gst_element_request_pad (element, templ, req_name, NULL);
1134
1135 return pad;
1136 }
1137
1138 /**
1139 * gst_element_request_pad: (virtual request_new_pad)
1140 * @element: a #GstElement to find a request pad of.
1141 * @templ: a #GstPadTemplate of which we want a pad of.
1142 * @name: (transfer none) (allow-none): the name of the request #GstPad
1143 * to retrieve. Can be %NULL.
1144 * @caps: (transfer none) (allow-none): the caps of the pad we want to
1145 * request. Can be %NULL.
1146 *
1147 * Retrieves a request pad from the element according to the provided template.
1148 * Pad templates can be looked up using
1149 * gst_element_factory_get_static_pad_templates().
1150 *
1151 * The pad should be released with gst_element_release_request_pad().
1152 *
1153 * Returns: (transfer full) (nullable): requested #GstPad if found,
1154 * otherwise %NULL. Release after usage.
1155 */
1156 GstPad *
gst_element_request_pad(GstElement * element,GstPadTemplate * templ,const gchar * name,const GstCaps * caps)1157 gst_element_request_pad (GstElement * element,
1158 GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
1159 {
1160 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1161 g_return_val_if_fail (templ != NULL, NULL);
1162 g_return_val_if_fail (templ->presence == GST_PAD_REQUEST, NULL);
1163
1164 return _gst_element_request_pad (element, templ, name, caps);
1165 }
1166
1167 static GstIterator *
gst_element_iterate_pad_list(GstElement * element,GList ** padlist)1168 gst_element_iterate_pad_list (GstElement * element, GList ** padlist)
1169 {
1170 GstIterator *result;
1171
1172 GST_OBJECT_LOCK (element);
1173 result = gst_iterator_new_list (GST_TYPE_PAD,
1174 GST_OBJECT_GET_LOCK (element),
1175 &element->pads_cookie, padlist, (GObject *) element, NULL);
1176 GST_OBJECT_UNLOCK (element);
1177
1178 return result;
1179 }
1180
1181 /**
1182 * gst_element_iterate_pads:
1183 * @element: a #GstElement to iterate pads of.
1184 *
1185 * Retrieves an iterator of @element's pads. The iterator should
1186 * be freed after usage. Also more specialized iterators exists such as
1187 * gst_element_iterate_src_pads() or gst_element_iterate_sink_pads().
1188 *
1189 * The order of pads returned by the iterator will be the order in which
1190 * the pads were added to the element.
1191 *
1192 * Returns: (transfer full): the #GstIterator of #GstPad.
1193 *
1194 * MT safe.
1195 */
1196 GstIterator *
gst_element_iterate_pads(GstElement * element)1197 gst_element_iterate_pads (GstElement * element)
1198 {
1199 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1200
1201 return gst_element_iterate_pad_list (element, &element->pads);
1202 }
1203
1204 /**
1205 * gst_element_iterate_src_pads:
1206 * @element: a #GstElement.
1207 *
1208 * Retrieves an iterator of @element's source pads.
1209 *
1210 * The order of pads returned by the iterator will be the order in which
1211 * the pads were added to the element.
1212 *
1213 * Returns: (transfer full): the #GstIterator of #GstPad.
1214 *
1215 * MT safe.
1216 */
1217 GstIterator *
gst_element_iterate_src_pads(GstElement * element)1218 gst_element_iterate_src_pads (GstElement * element)
1219 {
1220 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1221
1222 return gst_element_iterate_pad_list (element, &element->srcpads);
1223 }
1224
1225 /**
1226 * gst_element_iterate_sink_pads:
1227 * @element: a #GstElement.
1228 *
1229 * Retrieves an iterator of @element's sink pads.
1230 *
1231 * The order of pads returned by the iterator will be the order in which
1232 * the pads were added to the element.
1233 *
1234 * Returns: (transfer full): the #GstIterator of #GstPad.
1235 *
1236 * MT safe.
1237 */
1238 GstIterator *
gst_element_iterate_sink_pads(GstElement * element)1239 gst_element_iterate_sink_pads (GstElement * element)
1240 {
1241 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1242
1243 return gst_element_iterate_pad_list (element, &element->sinkpads);
1244 }
1245
1246 static gboolean
gst_element_do_foreach_pad(GstElement * element,GstElementForeachPadFunc func,gpointer user_data,GList ** p_pads,guint16 * p_npads)1247 gst_element_do_foreach_pad (GstElement * element,
1248 GstElementForeachPadFunc func, gpointer user_data,
1249 GList ** p_pads, guint16 * p_npads)
1250 {
1251 gboolean ret = TRUE;
1252 GstPad **pads;
1253 guint n_pads, i;
1254 GList *l;
1255
1256 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1257 g_return_val_if_fail (func != NULL, FALSE);
1258
1259 GST_OBJECT_LOCK (element);
1260 n_pads = *p_npads;
1261 pads = g_newa (GstPad *, n_pads + 1);
1262 for (l = *p_pads, i = 0; l != NULL; l = l->next) {
1263 g_assert (i < n_pads);
1264 pads[i++] = gst_object_ref (l->data);
1265 }
1266 GST_OBJECT_UNLOCK (element);
1267
1268 if (n_pads == 0)
1269 return FALSE;
1270
1271 for (i = 0; i < n_pads; ++i) {
1272 ret = func (element, pads[i], user_data);
1273 if (!ret)
1274 break;
1275 }
1276
1277 for (i = 0; i < n_pads; ++i)
1278 gst_object_unref (pads[i]);
1279
1280 return ret;
1281 }
1282
1283 /**
1284 * gst_element_foreach_sink_pad:
1285 * @element: a #GstElement to iterate sink pads of
1286 * @func: (scope call): function to call for each sink pad
1287 * @user_data: (closure): user data passed to @func
1288 *
1289 * Call @func with @user_data for each of @element's sink pads. @func will be
1290 * called exactly once for each sink pad that exists at the time of this call,
1291 * unless one of the calls to @func returns %FALSE in which case we will stop
1292 * iterating pads and return early. If new sink pads are added or sink pads
1293 * are removed while the sink pads are being iterated, this will not be taken
1294 * into account until next time this function is used.
1295 *
1296 * Returns: %FALSE if @element had no sink pads or if one of the calls to @func
1297 * returned %FALSE.
1298 *
1299 * Since: 1.14
1300 */
1301 gboolean
gst_element_foreach_sink_pad(GstElement * element,GstElementForeachPadFunc func,gpointer user_data)1302 gst_element_foreach_sink_pad (GstElement * element,
1303 GstElementForeachPadFunc func, gpointer user_data)
1304 {
1305 return gst_element_do_foreach_pad (element, func, user_data,
1306 &element->sinkpads, &element->numsinkpads);
1307 }
1308
1309 /**
1310 * gst_element_foreach_src_pad:
1311 * @element: a #GstElement to iterate source pads of
1312 * @func: (scope call): function to call for each source pad
1313 * @user_data: (closure): user data passed to @func
1314 *
1315 * Call @func with @user_data for each of @element's source pads. @func will be
1316 * called exactly once for each source pad that exists at the time of this call,
1317 * unless one of the calls to @func returns %FALSE in which case we will stop
1318 * iterating pads and return early. If new source pads are added or source pads
1319 * are removed while the source pads are being iterated, this will not be taken
1320 * into account until next time this function is used.
1321 *
1322 * Returns: %FALSE if @element had no source pads or if one of the calls
1323 * to @func returned %FALSE.
1324 *
1325 * Since: 1.14
1326 */
1327 gboolean
gst_element_foreach_src_pad(GstElement * element,GstElementForeachPadFunc func,gpointer user_data)1328 gst_element_foreach_src_pad (GstElement * element,
1329 GstElementForeachPadFunc func, gpointer user_data)
1330 {
1331 return gst_element_do_foreach_pad (element, func, user_data,
1332 &element->srcpads, &element->numsrcpads);
1333 }
1334
1335 /**
1336 * gst_element_foreach_pad:
1337 * @element: a #GstElement to iterate pads of
1338 * @func: (scope call): function to call for each pad
1339 * @user_data: (closure): user data passed to @func
1340 *
1341 * Call @func with @user_data for each of @element's pads. @func will be called
1342 * exactly once for each pad that exists at the time of this call, unless
1343 * one of the calls to @func returns %FALSE in which case we will stop
1344 * iterating pads and return early. If new pads are added or pads are removed
1345 * while pads are being iterated, this will not be taken into account until
1346 * next time this function is used.
1347 *
1348 * Returns: %FALSE if @element had no pads or if one of the calls to @func
1349 * returned %FALSE.
1350 *
1351 * Since: 1.14
1352 */
1353 gboolean
gst_element_foreach_pad(GstElement * element,GstElementForeachPadFunc func,gpointer user_data)1354 gst_element_foreach_pad (GstElement * element, GstElementForeachPadFunc func,
1355 gpointer user_data)
1356 {
1357 return gst_element_do_foreach_pad (element, func, user_data,
1358 &element->pads, &element->numpads);
1359 }
1360
1361 /**
1362 * gst_element_class_add_pad_template:
1363 * @klass: the #GstElementClass to add the pad template to.
1364 * @templ: (transfer floating): a #GstPadTemplate to add to the element class.
1365 *
1366 * Adds a padtemplate to an element class. This is mainly used in the _class_init
1367 * functions of classes. If a pad template with the same name as an already
1368 * existing one is added the old one is replaced by the new one.
1369 *
1370 * @templ's reference count will be incremented, and any floating
1371 * reference will be removed (see gst_object_ref_sink())
1372 *
1373 */
1374 void
gst_element_class_add_pad_template(GstElementClass * klass,GstPadTemplate * templ)1375 gst_element_class_add_pad_template (GstElementClass * klass,
1376 GstPadTemplate * templ)
1377 {
1378 GList *template_list = klass->padtemplates;
1379
1380 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1381 g_return_if_fail (GST_IS_PAD_TEMPLATE (templ));
1382
1383 /* If we already have a pad template with the same name replace the
1384 * old one. */
1385 while (template_list) {
1386 GstPadTemplate *padtempl = (GstPadTemplate *) template_list->data;
1387
1388 /* Found pad with the same name, replace and return */
1389 if (strcmp (templ->name_template, padtempl->name_template) == 0) {
1390 gst_object_ref_sink (padtempl);
1391 gst_object_unref (padtempl);
1392 template_list->data = templ;
1393 return;
1394 }
1395 template_list = g_list_next (template_list);
1396 }
1397
1398 /* Take ownership of the floating ref */
1399 gst_object_ref_sink (templ);
1400
1401 klass->padtemplates = g_list_append (klass->padtemplates, templ);
1402 klass->numpadtemplates++;
1403 }
1404
1405 /**
1406 * gst_element_class_add_static_pad_template:
1407 * @klass: the #GstElementClass to add the pad template to.
1408 * @static_templ: #GstStaticPadTemplate to add as pad template to the element class.
1409 *
1410 * Adds a pad template to an element class based on the static pad template
1411 * @templ. This is mainly used in the _class_init functions of element
1412 * implementations. If a pad template with the same name already exists,
1413 * the old one is replaced by the new one.
1414 *
1415 * Since: 1.8
1416 */
1417 void
gst_element_class_add_static_pad_template(GstElementClass * klass,GstStaticPadTemplate * static_templ)1418 gst_element_class_add_static_pad_template (GstElementClass * klass,
1419 GstStaticPadTemplate * static_templ)
1420 {
1421 gst_element_class_add_pad_template (klass,
1422 gst_static_pad_template_get (static_templ));
1423 }
1424
1425 /**
1426 * gst_element_class_add_static_pad_template_with_gtype:
1427 * @klass: the #GstElementClass to add the pad template to.
1428 * @static_templ: #GstStaticPadTemplate to add as pad template to the element class.
1429 * @pad_type: The #GType of the pad to create
1430 *
1431 * Adds a pad template to an element class based on the static pad template
1432 * @templ. This is mainly used in the _class_init functions of element
1433 * implementations. If a pad template with the same name already exists,
1434 * the old one is replaced by the new one.
1435 *
1436 * Since: 1.14
1437 */
1438 void
gst_element_class_add_static_pad_template_with_gtype(GstElementClass * klass,GstStaticPadTemplate * static_templ,GType pad_type)1439 gst_element_class_add_static_pad_template_with_gtype (GstElementClass * klass,
1440 GstStaticPadTemplate * static_templ, GType pad_type)
1441 {
1442 gst_element_class_add_pad_template (klass,
1443 gst_pad_template_new_from_static_pad_template_with_gtype (static_templ,
1444 pad_type));
1445 }
1446
1447 /**
1448 * gst_element_class_add_metadata:
1449 * @klass: class to set metadata for
1450 * @key: the key to set
1451 * @value: the value to set
1452 *
1453 * Set @key with @value as metadata in @klass.
1454 */
1455 void
gst_element_class_add_metadata(GstElementClass * klass,const gchar * key,const gchar * value)1456 gst_element_class_add_metadata (GstElementClass * klass,
1457 const gchar * key, const gchar * value)
1458 {
1459 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1460 g_return_if_fail (key != NULL);
1461 g_return_if_fail (value != NULL);
1462
1463 gst_structure_set ((GstStructure *) klass->metadata,
1464 key, G_TYPE_STRING, value, NULL);
1465 }
1466
1467 /**
1468 * gst_element_class_add_static_metadata:
1469 * @klass: class to set metadata for
1470 * @key: the key to set
1471 * @value: the value to set
1472 *
1473 * Set @key with @value as metadata in @klass.
1474 *
1475 * Same as gst_element_class_add_metadata(), but @value must be a static string
1476 * or an inlined string, as it will not be copied. (GStreamer plugins will
1477 * be made resident once loaded, so this function can be used even from
1478 * dynamically loaded plugins.)
1479 */
1480 void
gst_element_class_add_static_metadata(GstElementClass * klass,const gchar * key,const gchar * value)1481 gst_element_class_add_static_metadata (GstElementClass * klass,
1482 const gchar * key, const gchar * value)
1483 {
1484 GValue val = G_VALUE_INIT;
1485
1486 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1487 g_return_if_fail (key != NULL);
1488 g_return_if_fail (value != NULL);
1489
1490 g_value_init (&val, G_TYPE_STRING);
1491 g_value_set_static_string (&val, value);
1492 gst_structure_take_value ((GstStructure *) klass->metadata, key, &val);
1493 }
1494
1495 /**
1496 * gst_element_class_set_metadata:
1497 * @klass: class to set metadata for
1498 * @longname: The long English name of the element. E.g. "File Sink"
1499 * @classification: String describing the type of element, as an unordered list
1500 * separated with slashes ('/'). See draft-klass.txt of the design docs
1501 * for more details and common types. E.g: "Sink/File"
1502 * @description: Sentence describing the purpose of the element.
1503 * E.g: "Write stream to a file"
1504 * @author: Name and contact details of the author(s). Use \n to separate
1505 * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"
1506 *
1507 * Sets the detailed information for a #GstElementClass.
1508 * > This function is for use in _class_init functions only.
1509 */
1510 void
gst_element_class_set_metadata(GstElementClass * klass,const gchar * longname,const gchar * classification,const gchar * description,const gchar * author)1511 gst_element_class_set_metadata (GstElementClass * klass,
1512 const gchar * longname, const gchar * classification,
1513 const gchar * description, const gchar * author)
1514 {
1515 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1516 g_return_if_fail (longname != NULL && *longname != '\0');
1517 g_return_if_fail (classification != NULL && *classification != '\0');
1518 g_return_if_fail (description != NULL && *description != '\0');
1519 g_return_if_fail (author != NULL && *author != '\0');
1520
1521 gst_structure_id_set ((GstStructure *) klass->metadata,
1522 GST_QUARK (ELEMENT_METADATA_LONGNAME), G_TYPE_STRING, longname,
1523 GST_QUARK (ELEMENT_METADATA_KLASS), G_TYPE_STRING, classification,
1524 GST_QUARK (ELEMENT_METADATA_DESCRIPTION), G_TYPE_STRING, description,
1525 GST_QUARK (ELEMENT_METADATA_AUTHOR), G_TYPE_STRING, author, NULL);
1526 }
1527
1528 /**
1529 * gst_element_class_set_static_metadata:
1530 * @klass: class to set metadata for
1531 * @longname: The long English name of the element. E.g. "File Sink"
1532 * @classification: String describing the type of element, as an unordered list
1533 * separated with slashes ('/'). See draft-klass.txt of the design docs
1534 * for more details and common types. E.g: "Sink/File"
1535 * @description: Sentence describing the purpose of the element.
1536 * E.g: "Write stream to a file"
1537 * @author: Name and contact details of the author(s). Use \n to separate
1538 * multiple author metadata. E.g: "Joe Bloggs <joe.blogs at foo.com>"
1539 *
1540 * Sets the detailed information for a #GstElementClass.
1541 *
1542 * > This function is for use in _class_init functions only.
1543 *
1544 * Same as gst_element_class_set_metadata(), but @longname, @classification,
1545 * @description, and @author must be static strings or inlined strings, as
1546 * they will not be copied. (GStreamer plugins will be made resident once
1547 * loaded, so this function can be used even from dynamically loaded plugins.)
1548 */
1549 void
gst_element_class_set_static_metadata(GstElementClass * klass,const gchar * longname,const gchar * classification,const gchar * description,const gchar * author)1550 gst_element_class_set_static_metadata (GstElementClass * klass,
1551 const gchar * longname, const gchar * classification,
1552 const gchar * description, const gchar * author)
1553 {
1554 GstStructure *s = (GstStructure *) klass->metadata;
1555 GValue val = G_VALUE_INIT;
1556
1557 g_return_if_fail (GST_IS_ELEMENT_CLASS (klass));
1558 g_return_if_fail (longname != NULL && *longname != '\0');
1559 g_return_if_fail (classification != NULL && *classification != '\0');
1560 g_return_if_fail (description != NULL && *description != '\0');
1561 g_return_if_fail (author != NULL && *author != '\0');
1562
1563 g_value_init (&val, G_TYPE_STRING);
1564
1565 g_value_set_static_string (&val, longname);
1566 gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_LONGNAME), &val);
1567
1568 g_value_set_static_string (&val, classification);
1569 gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_KLASS), &val);
1570
1571 g_value_set_static_string (&val, description);
1572 gst_structure_id_set_value (s, GST_QUARK (ELEMENT_METADATA_DESCRIPTION),
1573 &val);
1574
1575 g_value_set_static_string (&val, author);
1576 gst_structure_id_take_value (s, GST_QUARK (ELEMENT_METADATA_AUTHOR), &val);
1577 }
1578
1579 /**
1580 * gst_element_class_get_metadata:
1581 * @klass: class to get metadata for
1582 * @key: the key to get
1583 *
1584 * Get metadata with @key in @klass.
1585 *
1586 * Returns: the metadata for @key.
1587 */
1588 const gchar *
gst_element_class_get_metadata(GstElementClass * klass,const gchar * key)1589 gst_element_class_get_metadata (GstElementClass * klass, const gchar * key)
1590 {
1591 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (klass), NULL);
1592 g_return_val_if_fail (key != NULL, NULL);
1593
1594 return gst_structure_get_string ((GstStructure *) klass->metadata, key);
1595 }
1596
1597 /**
1598 * gst_element_get_metadata:
1599 * @element: class to get metadata for
1600 * @key: the key to get
1601 *
1602 * Get metadata with @key in @klass.
1603 *
1604 * Returns: the metadata for @key.
1605 *
1606 * Since: 1.14
1607 */
1608 const gchar *
gst_element_get_metadata(GstElement * element,const gchar * key)1609 gst_element_get_metadata (GstElement * element, const gchar * key)
1610 {
1611 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1612 g_return_val_if_fail (key != NULL, NULL);
1613
1614 return gst_element_class_get_metadata (GST_ELEMENT_GET_CLASS (element), key);
1615 }
1616
1617 /**
1618 * gst_element_class_get_pad_template_list:
1619 * @element_class: a #GstElementClass to get pad templates of.
1620 *
1621 * Retrieves a list of the pad templates associated with @element_class. The
1622 * list must not be modified by the calling code.
1623 * > If you use this function in the #GInstanceInitFunc of an object class
1624 * > that has subclasses, make sure to pass the g_class parameter of the
1625 * > #GInstanceInitFunc here.
1626 *
1627 * Returns: (transfer none) (element-type Gst.PadTemplate): the #GList of
1628 * pad templates.
1629 */
1630 GList *
gst_element_class_get_pad_template_list(GstElementClass * element_class)1631 gst_element_class_get_pad_template_list (GstElementClass * element_class)
1632 {
1633 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1634
1635 return element_class->padtemplates;
1636 }
1637
1638 /**
1639 * gst_element_get_pad_template_list:
1640 * @element: a #GstElement to get pad templates of.
1641 *
1642 * Retrieves a list of the pad templates associated with @element. The
1643 * list must not be modified by the calling code.
1644 *
1645 * Returns: (transfer none) (element-type Gst.PadTemplate): the #GList of
1646 * pad templates.
1647 *
1648 * Since: 1.14
1649 */
1650 GList *
gst_element_get_pad_template_list(GstElement * element)1651 gst_element_get_pad_template_list (GstElement * element)
1652 {
1653 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1654
1655 return
1656 gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS (element));
1657 }
1658
1659 /**
1660 * gst_element_class_get_pad_template:
1661 * @element_class: a #GstElementClass to get the pad template of.
1662 * @name: the name of the #GstPadTemplate to get.
1663 *
1664 * Retrieves a padtemplate from @element_class with the given name.
1665 * > If you use this function in the #GInstanceInitFunc of an object class
1666 * > that has subclasses, make sure to pass the g_class parameter of the
1667 * > #GInstanceInitFunc here.
1668 *
1669 * Returns: (transfer none) (nullable): the #GstPadTemplate with the
1670 * given name, or %NULL if none was found. No unreferencing is
1671 * necessary.
1672 */
1673 GstPadTemplate *
gst_element_class_get_pad_template(GstElementClass * element_class,const gchar * name)1674 gst_element_class_get_pad_template (GstElementClass *
1675 element_class, const gchar * name)
1676 {
1677 GList *padlist;
1678
1679 g_return_val_if_fail (GST_IS_ELEMENT_CLASS (element_class), NULL);
1680 g_return_val_if_fail (name != NULL, NULL);
1681
1682 padlist = element_class->padtemplates;
1683
1684 while (padlist) {
1685 GstPadTemplate *padtempl = (GstPadTemplate *) padlist->data;
1686
1687 if (strcmp (padtempl->name_template, name) == 0)
1688 return padtempl;
1689
1690 padlist = g_list_next (padlist);
1691 }
1692
1693 return NULL;
1694 }
1695
1696 /**
1697 * gst_element_get_pad_template:
1698 * @element: a #GstElement to get the pad template of.
1699 * @name: the name of the #GstPadTemplate to get.
1700 *
1701 * Retrieves a padtemplate from @element with the given name.
1702 *
1703 * Returns: (transfer none) (nullable): the #GstPadTemplate with the
1704 * given name, or %NULL if none was found. No unreferencing is
1705 * necessary.
1706 *
1707 * Since: 1.14
1708 */
1709 GstPadTemplate *
gst_element_get_pad_template(GstElement * element,const gchar * name)1710 gst_element_get_pad_template (GstElement * element, const gchar * name)
1711 {
1712 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
1713 g_return_val_if_fail (name != NULL, NULL);
1714
1715 return gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (element),
1716 name);
1717 }
1718
1719 static GstPadTemplate *
gst_element_class_get_request_pad_template(GstElementClass * element_class,const gchar * name)1720 gst_element_class_get_request_pad_template (GstElementClass *
1721 element_class, const gchar * name)
1722 {
1723 GstPadTemplate *tmpl;
1724
1725 tmpl = gst_element_class_get_pad_template (element_class, name);
1726 if (tmpl != NULL && tmpl->presence == GST_PAD_REQUEST)
1727 return tmpl;
1728
1729 return NULL;
1730 }
1731
1732 /* get a random pad on element of the given direction.
1733 * The pad is random in a sense that it is the first pad that is (optionally) linked.
1734 */
1735 static GstPad *
gst_element_get_random_pad(GstElement * element,gboolean need_linked,GstPadDirection dir)1736 gst_element_get_random_pad (GstElement * element,
1737 gboolean need_linked, GstPadDirection dir)
1738 {
1739 GstPad *result = NULL;
1740 GList *pads;
1741
1742 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "getting a random pad");
1743
1744 switch (dir) {
1745 case GST_PAD_SRC:
1746 GST_OBJECT_LOCK (element);
1747 pads = element->srcpads;
1748 break;
1749 case GST_PAD_SINK:
1750 GST_OBJECT_LOCK (element);
1751 pads = element->sinkpads;
1752 break;
1753 default:
1754 goto wrong_direction;
1755 }
1756 for (; pads; pads = g_list_next (pads)) {
1757 GstPad *pad = GST_PAD_CAST (pads->data);
1758
1759 GST_OBJECT_LOCK (pad);
1760 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "checking pad %s:%s",
1761 GST_DEBUG_PAD_NAME (pad));
1762
1763 if (need_linked && !GST_PAD_IS_LINKED (pad)) {
1764 /* if we require a linked pad, and it is not linked, continue the
1765 * search */
1766 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s is not linked",
1767 GST_DEBUG_PAD_NAME (pad));
1768 GST_OBJECT_UNLOCK (pad);
1769 continue;
1770 } else {
1771 /* found a pad, stop search */
1772 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "found pad %s:%s",
1773 GST_DEBUG_PAD_NAME (pad));
1774 GST_OBJECT_UNLOCK (pad);
1775 result = pad;
1776 break;
1777 }
1778 }
1779 if (result)
1780 gst_object_ref (result);
1781
1782 GST_OBJECT_UNLOCK (element);
1783
1784 return result;
1785
1786 /* ERROR handling */
1787 wrong_direction:
1788 {
1789 g_warning ("unknown pad direction %d", dir);
1790 return NULL;
1791 }
1792 }
1793
1794 static gboolean
gst_element_default_send_event(GstElement * element,GstEvent * event)1795 gst_element_default_send_event (GstElement * element, GstEvent * event)
1796 {
1797 gboolean result = FALSE;
1798 GstPad *pad;
1799
1800 pad = GST_EVENT_IS_DOWNSTREAM (event) ?
1801 gst_element_get_random_pad (element, TRUE, GST_PAD_SINK) :
1802 gst_element_get_random_pad (element, TRUE, GST_PAD_SRC);
1803
1804 if (pad) {
1805 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS,
1806 "pushing %s event to random %s pad %s:%s",
1807 GST_EVENT_TYPE_NAME (event),
1808 (GST_PAD_DIRECTION (pad) == GST_PAD_SRC ? "src" : "sink"),
1809 GST_DEBUG_PAD_NAME (pad));
1810
1811 result = gst_pad_send_event (pad, event);
1812 gst_object_unref (pad);
1813 } else {
1814 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "can't send %s event on element %s",
1815 GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1816 gst_event_unref (event);
1817 }
1818 return result;
1819 }
1820
1821 /**
1822 * gst_element_send_event:
1823 * @element: a #GstElement to send the event to.
1824 * @event: (transfer full): the #GstEvent to send to the element.
1825 *
1826 * Sends an event to an element. If the element doesn't implement an
1827 * event handler, the event will be pushed on a random linked sink pad for
1828 * downstream events or a random linked source pad for upstream events.
1829 *
1830 * This function takes ownership of the provided event so you should
1831 * gst_event_ref() it if you want to reuse the event after this call.
1832 *
1833 * MT safe.
1834 *
1835 * Returns: %TRUE if the event was handled. Events that trigger a preroll (such
1836 * as flushing seeks and steps) will emit %GST_MESSAGE_ASYNC_DONE.
1837 */
1838 gboolean
gst_element_send_event(GstElement * element,GstEvent * event)1839 gst_element_send_event (GstElement * element, GstEvent * event)
1840 {
1841 GstElementClass *oclass;
1842 gboolean result = FALSE;
1843
1844 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1845 g_return_val_if_fail (event != NULL, FALSE);
1846
1847 oclass = GST_ELEMENT_GET_CLASS (element);
1848
1849 GST_STATE_LOCK (element);
1850 if (oclass->send_event) {
1851 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send %s event on element %s",
1852 GST_EVENT_TYPE_NAME (event), GST_ELEMENT_NAME (element));
1853 result = oclass->send_event (element, event);
1854 } else {
1855 gst_event_unref (event);
1856 }
1857 GST_STATE_UNLOCK (element);
1858
1859 return result;
1860 }
1861
1862 /**
1863 * gst_element_seek:
1864 * @element: a #GstElement to send the event to.
1865 * @rate: The new playback rate
1866 * @format: The format of the seek values
1867 * @flags: The optional seek flags.
1868 * @start_type: The type and flags for the new start position
1869 * @start: The value of the new start position
1870 * @stop_type: The type and flags for the new stop position
1871 * @stop: The value of the new stop position
1872 *
1873 * Sends a seek event to an element. See gst_event_new_seek() for the details of
1874 * the parameters. The seek event is sent to the element using
1875 * gst_element_send_event().
1876 *
1877 * MT safe.
1878 *
1879 * Returns: %TRUE if the event was handled. Flushing seeks will trigger a
1880 * preroll, which will emit %GST_MESSAGE_ASYNC_DONE.
1881 */
1882 gboolean
gst_element_seek(GstElement * element,gdouble rate,GstFormat format,GstSeekFlags flags,GstSeekType start_type,gint64 start,GstSeekType stop_type,gint64 stop)1883 gst_element_seek (GstElement * element, gdouble rate, GstFormat format,
1884 GstSeekFlags flags, GstSeekType start_type, gint64 start,
1885 GstSeekType stop_type, gint64 stop)
1886 {
1887 GstEvent *event;
1888 gboolean result;
1889
1890 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1891
1892 event =
1893 gst_event_new_seek (rate, format, flags, start_type, start, stop_type,
1894 stop);
1895 result = gst_element_send_event (element, event);
1896
1897 return result;
1898 }
1899
1900 static gboolean
gst_element_default_query(GstElement * element,GstQuery * query)1901 gst_element_default_query (GstElement * element, GstQuery * query)
1902 {
1903 gboolean result = FALSE;
1904 GstPad *pad;
1905
1906 pad = gst_element_get_random_pad (element, FALSE, GST_PAD_SRC);
1907 if (pad) {
1908 result = gst_pad_query (pad, query);
1909
1910 gst_object_unref (pad);
1911 } else {
1912 pad = gst_element_get_random_pad (element, TRUE, GST_PAD_SINK);
1913 if (pad) {
1914 GstPad *peer = gst_pad_get_peer (pad);
1915
1916 if (peer) {
1917 result = gst_pad_query (peer, query);
1918
1919 gst_object_unref (peer);
1920 }
1921 gst_object_unref (pad);
1922 }
1923 }
1924 return result;
1925 }
1926
1927 /**
1928 * gst_element_query:
1929 * @element: a #GstElement to perform the query on.
1930 * @query: (transfer none): the #GstQuery.
1931 *
1932 * Performs a query on the given element.
1933 *
1934 * For elements that don't implement a query handler, this function
1935 * forwards the query to a random srcpad or to the peer of a
1936 * random linked sinkpad of this element.
1937 *
1938 * Please note that some queries might need a running pipeline to work.
1939 *
1940 * Returns: %TRUE if the query could be performed.
1941 *
1942 * MT safe.
1943 */
1944 gboolean
gst_element_query(GstElement * element,GstQuery * query)1945 gst_element_query (GstElement * element, GstQuery * query)
1946 {
1947 GstElementClass *klass;
1948 gboolean res = FALSE;
1949
1950 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1951 g_return_val_if_fail (query != NULL, FALSE);
1952
1953 GST_TRACER_ELEMENT_QUERY_PRE (element, query);
1954
1955 klass = GST_ELEMENT_GET_CLASS (element);
1956 if (klass->query) {
1957 GST_CAT_DEBUG (GST_CAT_ELEMENT_PADS, "send query on element %s",
1958 GST_ELEMENT_NAME (element));
1959 res = klass->query (element, query);
1960 }
1961
1962 GST_TRACER_ELEMENT_QUERY_POST (element, query, res);
1963 return res;
1964 }
1965
1966 static gboolean
gst_element_post_message_default(GstElement * element,GstMessage * message)1967 gst_element_post_message_default (GstElement * element, GstMessage * message)
1968 {
1969 GstBus *bus;
1970 gboolean result = FALSE;
1971
1972 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
1973 g_return_val_if_fail (message != NULL, FALSE);
1974
1975 GST_OBJECT_LOCK (element);
1976 bus = element->bus;
1977
1978 if (G_UNLIKELY (bus == NULL))
1979 goto no_bus;
1980
1981 gst_object_ref (bus);
1982 GST_OBJECT_UNLOCK (element);
1983
1984 /* we release the element lock when posting the message so that any
1985 * (synchronous) message handlers can operate on the element */
1986 result = gst_bus_post (bus, message);
1987 gst_object_unref (bus);
1988
1989 return result;
1990
1991 /* ERRORS */
1992 no_bus:
1993 {
1994 GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element,
1995 "not posting message %p: no bus", message);
1996 GST_OBJECT_UNLOCK (element);
1997 gst_message_unref (message);
1998 return FALSE;
1999 }
2000 }
2001
2002 /**
2003 * gst_element_post_message:
2004 * @element: a #GstElement posting the message
2005 * @message: (transfer full): a #GstMessage to post
2006 *
2007 * Post a message on the element's #GstBus. This function takes ownership of the
2008 * message; if you want to access the message after this call, you should add an
2009 * additional reference before calling.
2010 *
2011 * Returns: %TRUE if the message was successfully posted. The function returns
2012 * %FALSE if the element did not have a bus.
2013 *
2014 * MT safe.
2015 */
2016 gboolean
gst_element_post_message(GstElement * element,GstMessage * message)2017 gst_element_post_message (GstElement * element, GstMessage * message)
2018 {
2019 GstElementClass *klass;
2020 gboolean res = FALSE;
2021
2022 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2023 g_return_val_if_fail (message != NULL, FALSE);
2024
2025 GST_TRACER_ELEMENT_POST_MESSAGE_PRE (element, message);
2026
2027 klass = GST_ELEMENT_GET_CLASS (element);
2028 if (klass->post_message)
2029 res = klass->post_message (element, message);
2030 else
2031 gst_message_unref (message);
2032
2033 GST_TRACER_ELEMENT_POST_MESSAGE_POST (element, res);
2034 return res;
2035 }
2036
2037 /**
2038 * _gst_element_error_printf:
2039 * @format: (allow-none): the printf-like format to use, or %NULL
2040 *
2041 * This function is only used internally by the gst_element_error() macro.
2042 *
2043 * Returns: (transfer full) (nullable): a newly allocated string, or
2044 * %NULL if the format was %NULL or ""
2045 *
2046 * MT safe.
2047 */
2048 gchar *
_gst_element_error_printf(const gchar * format,...)2049 _gst_element_error_printf (const gchar * format, ...)
2050 {
2051 va_list args;
2052 gchar *buffer;
2053 int len;
2054
2055 if (format == NULL)
2056 return NULL;
2057 if (format[0] == 0)
2058 return NULL;
2059
2060 va_start (args, format);
2061
2062 len = __gst_vasprintf (&buffer, format, args);
2063
2064 va_end (args);
2065
2066 if (len < 0)
2067 buffer = NULL;
2068
2069 return buffer;
2070 }
2071
2072 /**
2073 * gst_element_message_full_with_details:
2074 * @element: a #GstElement to send message from
2075 * @type: the #GstMessageType
2076 * @domain: the GStreamer GError domain this message belongs to
2077 * @code: the GError code belonging to the domain
2078 * @text: (allow-none) (transfer full): an allocated text string to be used
2079 * as a replacement for the default message connected to code,
2080 * or %NULL
2081 * @debug: (allow-none) (transfer full): an allocated debug message to be
2082 * used as a replacement for the default debugging information,
2083 * or %NULL
2084 * @file: the source code file where the error was generated
2085 * @function: the source code function where the error was generated
2086 * @line: the source code line where the error was generated
2087 * @structure:(transfer full): optional details structure
2088 *
2089 * Post an error, warning or info message on the bus from inside an element.
2090 *
2091 * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
2092 * #GST_MESSAGE_INFO.
2093 *
2094 * Since: 1.10
2095 */
gst_element_message_full_with_details(GstElement * element,GstMessageType type,GQuark domain,gint code,gchar * text,gchar * debug,const gchar * file,const gchar * function,gint line,GstStructure * structure)2096 void gst_element_message_full_with_details
2097 (GstElement * element, GstMessageType type,
2098 GQuark domain, gint code, gchar * text,
2099 gchar * debug, const gchar * file, const gchar * function, gint line,
2100 GstStructure * structure)
2101 {
2102 GError *gerror = NULL;
2103 gchar *name;
2104 gchar *sent_text;
2105 gchar *sent_debug;
2106 gboolean has_debug = TRUE;
2107 GstMessage *message = NULL;
2108
2109 /* checks */
2110 GST_CAT_DEBUG_OBJECT (GST_CAT_MESSAGE, element, "start");
2111 g_return_if_fail (GST_IS_ELEMENT (element));
2112 g_return_if_fail ((type == GST_MESSAGE_ERROR) ||
2113 (type == GST_MESSAGE_WARNING) || (type == GST_MESSAGE_INFO));
2114
2115 /* check if we send the given text or the default error text */
2116 if ((text == NULL) || (text[0] == 0)) {
2117 /* text could have come from g_strdup_printf (""); */
2118 g_free (text);
2119 sent_text = gst_error_get_message (domain, code);
2120 } else
2121 sent_text = text;
2122
2123 /* construct a sent_debug with extra information from source */
2124 if ((debug == NULL) || (debug[0] == 0)) {
2125 /* debug could have come from g_strdup_printf (""); */
2126 has_debug = FALSE;
2127 }
2128
2129 name = gst_object_get_path_string (GST_OBJECT_CAST (element));
2130 if (has_debug)
2131 sent_debug = g_strdup_printf ("%s(%d): %s (): %s:\n%s",
2132 file, line, function, name, debug);
2133 else
2134 sent_debug = g_strdup_printf ("%s(%d): %s (): %s",
2135 file, line, function, name);
2136 g_free (name);
2137 g_free (debug);
2138
2139 /* create gerror and post message */
2140 GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posting message: %s",
2141 sent_text);
2142 gerror = g_error_new_literal (domain, code, sent_text);
2143
2144 switch (type) {
2145 case GST_MESSAGE_ERROR:
2146 message =
2147 gst_message_new_error_with_details (GST_OBJECT_CAST (element), gerror,
2148 sent_debug, structure);
2149 break;
2150 case GST_MESSAGE_WARNING:
2151 message =
2152 gst_message_new_warning_with_details (GST_OBJECT_CAST (element),
2153 gerror, sent_debug, structure);
2154 break;
2155 case GST_MESSAGE_INFO:
2156 message =
2157 gst_message_new_info_with_details (GST_OBJECT_CAST (element), gerror,
2158 sent_debug, structure);
2159 break;
2160 default:
2161 g_assert_not_reached ();
2162 break;
2163 }
2164
2165 gst_element_post_message (element, message);
2166
2167 GST_CAT_INFO_OBJECT (GST_CAT_ERROR_SYSTEM, element, "posted %s message: %s",
2168 (type == GST_MESSAGE_ERROR ? "error" : "warning"), sent_text);
2169
2170 /* cleanup */
2171 g_error_free (gerror);
2172 g_free (sent_debug);
2173 g_free (sent_text);
2174 }
2175
2176 /**
2177 * gst_element_message_full:
2178 * @element: a #GstElement to send message from
2179 * @type: the #GstMessageType
2180 * @domain: the GStreamer GError domain this message belongs to
2181 * @code: the GError code belonging to the domain
2182 * @text: (allow-none) (transfer full): an allocated text string to be used
2183 * as a replacement for the default message connected to code,
2184 * or %NULL
2185 * @debug: (allow-none) (transfer full): an allocated debug message to be
2186 * used as a replacement for the default debugging information,
2187 * or %NULL
2188 * @file: the source code file where the error was generated
2189 * @function: the source code function where the error was generated
2190 * @line: the source code line where the error was generated
2191 *
2192 * Post an error, warning or info message on the bus from inside an element.
2193 *
2194 * @type must be of #GST_MESSAGE_ERROR, #GST_MESSAGE_WARNING or
2195 * #GST_MESSAGE_INFO.
2196 *
2197 * MT safe.
2198 */
gst_element_message_full(GstElement * element,GstMessageType type,GQuark domain,gint code,gchar * text,gchar * debug,const gchar * file,const gchar * function,gint line)2199 void gst_element_message_full
2200 (GstElement * element, GstMessageType type,
2201 GQuark domain, gint code, gchar * text,
2202 gchar * debug, const gchar * file, const gchar * function, gint line)
2203 {
2204 gst_element_message_full_with_details (element, type, domain, code, text,
2205 debug, file, function, line, NULL);
2206 }
2207
2208 /**
2209 * gst_element_is_locked_state:
2210 * @element: a #GstElement.
2211 *
2212 * Checks if the state of an element is locked.
2213 * If the state of an element is locked, state changes of the parent don't
2214 * affect the element.
2215 * This way you can leave currently unused elements inside bins. Just lock their
2216 * state before changing the state from #GST_STATE_NULL.
2217 *
2218 * MT safe.
2219 *
2220 * Returns: %TRUE, if the element's state is locked.
2221 */
2222 gboolean
gst_element_is_locked_state(GstElement * element)2223 gst_element_is_locked_state (GstElement * element)
2224 {
2225 gboolean result;
2226
2227 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2228
2229 GST_OBJECT_LOCK (element);
2230 result = GST_ELEMENT_IS_LOCKED_STATE (element);
2231 GST_OBJECT_UNLOCK (element);
2232
2233 return result;
2234 }
2235
2236 /**
2237 * gst_element_set_locked_state:
2238 * @element: a #GstElement
2239 * @locked_state: %TRUE to lock the element's state
2240 *
2241 * Locks the state of an element, so state changes of the parent don't affect
2242 * this element anymore.
2243 *
2244 * Note that this is racy if the state lock of the parent bin is not taken.
2245 * The parent bin might've just checked the flag in another thread and as the
2246 * next step proceed to change the child element's state.
2247 *
2248 * MT safe.
2249 *
2250 * Returns: %TRUE if the state was changed, %FALSE if bad parameters were given
2251 * or the elements state-locking needed no change.
2252 */
2253 gboolean
gst_element_set_locked_state(GstElement * element,gboolean locked_state)2254 gst_element_set_locked_state (GstElement * element, gboolean locked_state)
2255 {
2256 gboolean old;
2257
2258 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2259
2260 GST_OBJECT_LOCK (element);
2261 old = GST_ELEMENT_IS_LOCKED_STATE (element);
2262
2263 if (G_UNLIKELY (old == locked_state))
2264 goto was_ok;
2265
2266 if (locked_state) {
2267 GST_CAT_DEBUG (GST_CAT_STATES, "locking state of element %s",
2268 GST_ELEMENT_NAME (element));
2269 GST_OBJECT_FLAG_SET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
2270 } else {
2271 GST_CAT_DEBUG (GST_CAT_STATES, "unlocking state of element %s",
2272 GST_ELEMENT_NAME (element));
2273 GST_OBJECT_FLAG_UNSET (element, GST_ELEMENT_FLAG_LOCKED_STATE);
2274 }
2275 GST_OBJECT_UNLOCK (element);
2276
2277 return TRUE;
2278
2279 was_ok:
2280 {
2281 GST_CAT_DEBUG (GST_CAT_STATES,
2282 "elements %s was already in locked state %d",
2283 GST_ELEMENT_NAME (element), old);
2284 GST_OBJECT_UNLOCK (element);
2285
2286 return FALSE;
2287 }
2288 }
2289
2290 /**
2291 * gst_element_sync_state_with_parent:
2292 * @element: a #GstElement.
2293 *
2294 * Tries to change the state of the element to the same as its parent.
2295 * If this function returns %FALSE, the state of element is undefined.
2296 *
2297 * Returns: %TRUE, if the element's state could be synced to the parent's state.
2298 *
2299 * MT safe.
2300 */
2301 gboolean
gst_element_sync_state_with_parent(GstElement * element)2302 gst_element_sync_state_with_parent (GstElement * element)
2303 {
2304 GstElement *parent;
2305 GstState target;
2306 GstStateChangeReturn ret;
2307
2308 g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
2309
2310 if ((parent = GST_ELEMENT_CAST (gst_element_get_parent (element)))) {
2311 GstState parent_current, parent_pending;
2312
2313 GST_OBJECT_LOCK (parent);
2314 parent_current = GST_STATE (parent);
2315 parent_pending = GST_STATE_PENDING (parent);
2316 GST_OBJECT_UNLOCK (parent);
2317
2318 /* set to pending if there is one, else we set it to the current state of
2319 * the parent */
2320 if (parent_pending != GST_STATE_VOID_PENDING)
2321 target = parent_pending;
2322 else
2323 target = parent_current;
2324
2325 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2326 "syncing state (%s) to parent %s %s (%s, %s)",
2327 gst_element_state_get_name (GST_STATE (element)),
2328 GST_ELEMENT_NAME (parent), gst_element_state_get_name (target),
2329 gst_element_state_get_name (parent_current),
2330 gst_element_state_get_name (parent_pending));
2331
2332 ret = gst_element_set_state (element, target);
2333 if (ret == GST_STATE_CHANGE_FAILURE)
2334 goto failed;
2335
2336 gst_object_unref (parent);
2337
2338 return TRUE;
2339 } else {
2340 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "element has no parent");
2341 }
2342 return FALSE;
2343
2344 /* ERROR */
2345 failed:
2346 {
2347 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2348 "syncing state failed (%s)",
2349 gst_element_state_change_return_get_name (ret));
2350 gst_object_unref (parent);
2351 return FALSE;
2352 }
2353 }
2354
2355 /* MT safe */
2356 static GstStateChangeReturn
gst_element_get_state_func(GstElement * element,GstState * state,GstState * pending,GstClockTime timeout)2357 gst_element_get_state_func (GstElement * element,
2358 GstState * state, GstState * pending, GstClockTime timeout)
2359 {
2360 GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
2361 GstState old_pending;
2362
2363 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "getting state, timeout %"
2364 GST_TIME_FORMAT, GST_TIME_ARGS (timeout));
2365
2366 GST_OBJECT_LOCK (element);
2367 ret = GST_STATE_RETURN (element);
2368 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "RETURN is %s",
2369 gst_element_state_change_return_get_name (ret));
2370
2371 /* we got an error, report immediately */
2372 if (ret == GST_STATE_CHANGE_FAILURE)
2373 goto done;
2374
2375 /* we got no_preroll, report immediately */
2376 if (ret == GST_STATE_CHANGE_NO_PREROLL)
2377 goto done;
2378
2379 /* no need to wait async if we are not async */
2380 if (ret != GST_STATE_CHANGE_ASYNC)
2381 goto done;
2382
2383 old_pending = GST_STATE_PENDING (element);
2384 if (old_pending != GST_STATE_VOID_PENDING) {
2385 gboolean signaled;
2386 guint32 cookie;
2387
2388 /* get cookie to detect state changes during waiting */
2389 cookie = element->state_cookie;
2390
2391 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2392 "waiting for element to commit state");
2393
2394 /* we have a pending state change, wait for it to complete */
2395 if (timeout != GST_CLOCK_TIME_NONE) {
2396 gint64 end_time;
2397 /* make timeout absolute */
2398 end_time = g_get_monotonic_time () + (timeout / 1000);
2399 signaled = GST_STATE_WAIT_UNTIL (element, end_time);
2400 } else {
2401 GST_STATE_WAIT (element);
2402 signaled = TRUE;
2403 }
2404
2405 if (!signaled) {
2406 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "timed out");
2407 /* timeout triggered */
2408 ret = GST_STATE_CHANGE_ASYNC;
2409 } else {
2410 if (cookie != element->state_cookie)
2411 goto interrupted;
2412
2413 /* could be success or failure */
2414 if (old_pending == GST_STATE (element)) {
2415 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got success");
2416 ret = GST_STATE_CHANGE_SUCCESS;
2417 } else {
2418 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "got failure");
2419 ret = GST_STATE_CHANGE_FAILURE;
2420 }
2421 }
2422 /* if nothing is pending anymore we can return SUCCESS */
2423 if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
2424 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "nothing pending");
2425 ret = GST_STATE_CHANGE_SUCCESS;
2426 }
2427 }
2428
2429 done:
2430 if (state)
2431 *state = GST_STATE (element);
2432 if (pending)
2433 *pending = GST_STATE_PENDING (element);
2434
2435 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2436 "state current: %s, pending: %s, result: %s",
2437 gst_element_state_get_name (GST_STATE (element)),
2438 gst_element_state_get_name (GST_STATE_PENDING (element)),
2439 gst_element_state_change_return_get_name (ret));
2440 GST_OBJECT_UNLOCK (element);
2441
2442 return ret;
2443
2444 interrupted:
2445 {
2446 if (state)
2447 *state = GST_STATE_VOID_PENDING;
2448 if (pending)
2449 *pending = GST_STATE_VOID_PENDING;
2450
2451 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "interrupted");
2452
2453 GST_OBJECT_UNLOCK (element);
2454
2455 return GST_STATE_CHANGE_FAILURE;
2456 }
2457 }
2458
2459 /**
2460 * gst_element_get_state:
2461 * @element: a #GstElement to get the state of.
2462 * @state: (out) (allow-none): a pointer to #GstState to hold the state.
2463 * Can be %NULL.
2464 * @pending: (out) (allow-none): a pointer to #GstState to hold the pending
2465 * state. Can be %NULL.
2466 * @timeout: a #GstClockTime to specify the timeout for an async
2467 * state change or %GST_CLOCK_TIME_NONE for infinite timeout.
2468 *
2469 * Gets the state of the element.
2470 *
2471 * For elements that performed an ASYNC state change, as reported by
2472 * gst_element_set_state(), this function will block up to the
2473 * specified timeout value for the state change to complete.
2474 * If the element completes the state change or goes into
2475 * an error, this function returns immediately with a return value of
2476 * %GST_STATE_CHANGE_SUCCESS or %GST_STATE_CHANGE_FAILURE respectively.
2477 *
2478 * For elements that did not return %GST_STATE_CHANGE_ASYNC, this function
2479 * returns the current and pending state immediately.
2480 *
2481 * This function returns %GST_STATE_CHANGE_NO_PREROLL if the element
2482 * successfully changed its state but is not able to provide data yet.
2483 * This mostly happens for live sources that only produce data in
2484 * %GST_STATE_PLAYING. While the state change return is equivalent to
2485 * %GST_STATE_CHANGE_SUCCESS, it is returned to the application to signal that
2486 * some sink elements might not be able to complete their state change because
2487 * an element is not producing data to complete the preroll. When setting the
2488 * element to playing, the preroll will complete and playback will start.
2489 *
2490 * Returns: %GST_STATE_CHANGE_SUCCESS if the element has no more pending state
2491 * and the last state change succeeded, %GST_STATE_CHANGE_ASYNC if the
2492 * element is still performing a state change or
2493 * %GST_STATE_CHANGE_FAILURE if the last state change failed.
2494 *
2495 * MT safe.
2496 */
2497 GstStateChangeReturn
gst_element_get_state(GstElement * element,GstState * state,GstState * pending,GstClockTime timeout)2498 gst_element_get_state (GstElement * element,
2499 GstState * state, GstState * pending, GstClockTime timeout)
2500 {
2501 GstElementClass *oclass;
2502 GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2503
2504 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2505
2506 oclass = GST_ELEMENT_GET_CLASS (element);
2507
2508 if (oclass->get_state)
2509 result = (oclass->get_state) (element, state, pending, timeout);
2510
2511 return result;
2512 }
2513
2514 /**
2515 * gst_element_abort_state:
2516 * @element: a #GstElement to abort the state of.
2517 *
2518 * Abort the state change of the element. This function is used
2519 * by elements that do asynchronous state changes and find out
2520 * something is wrong.
2521 *
2522 * This function should be called with the STATE_LOCK held.
2523 *
2524 * MT safe.
2525 */
2526 void
gst_element_abort_state(GstElement * element)2527 gst_element_abort_state (GstElement * element)
2528 {
2529 GstState pending;
2530
2531 #ifndef GST_DISABLE_GST_DEBUG
2532 GstState old_state;
2533 #endif
2534
2535 g_return_if_fail (GST_IS_ELEMENT (element));
2536
2537 GST_OBJECT_LOCK (element);
2538 pending = GST_STATE_PENDING (element);
2539
2540 if (pending == GST_STATE_VOID_PENDING ||
2541 GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
2542 goto nothing_aborted;
2543
2544 #ifndef GST_DISABLE_GST_DEBUG
2545 old_state = GST_STATE (element);
2546
2547 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2548 "aborting state from %s to %s", gst_element_state_get_name (old_state),
2549 gst_element_state_get_name (pending));
2550 #endif
2551
2552 /* flag error */
2553 GST_STATE_RETURN (element) = GST_STATE_CHANGE_FAILURE;
2554
2555 GST_STATE_BROADCAST (element);
2556 GST_OBJECT_UNLOCK (element);
2557
2558 return;
2559
2560 nothing_aborted:
2561 {
2562 GST_OBJECT_UNLOCK (element);
2563 return;
2564 }
2565 }
2566
2567 /* Not static because GstBin has manual state handling too */
2568 void
_priv_gst_element_state_changed(GstElement * element,GstState oldstate,GstState newstate,GstState pending)2569 _priv_gst_element_state_changed (GstElement * element, GstState oldstate,
2570 GstState newstate, GstState pending)
2571 {
2572 GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
2573 GstMessage *message;
2574
2575 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2576 "notifying about state-changed %s to %s (%s pending)",
2577 gst_element_state_get_name (oldstate),
2578 gst_element_state_get_name (newstate),
2579 gst_element_state_get_name (pending));
2580
2581 if (klass->state_changed)
2582 klass->state_changed (element, oldstate, newstate, pending);
2583
2584 message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
2585 oldstate, newstate, pending);
2586 gst_element_post_message (element, message);
2587 }
2588
2589 /**
2590 * gst_element_continue_state:
2591 * @element: a #GstElement to continue the state change of.
2592 * @ret: The previous state return value
2593 *
2594 * Commit the state change of the element and proceed to the next
2595 * pending state if any. This function is used
2596 * by elements that do asynchronous state changes.
2597 * The core will normally call this method automatically when an
2598 * element returned %GST_STATE_CHANGE_SUCCESS from the state change function.
2599 *
2600 * If after calling this method the element still has not reached
2601 * the pending state, the next state change is performed.
2602 *
2603 * This method is used internally and should normally not be called by plugins
2604 * or applications.
2605 *
2606 * This function must be called with STATE_LOCK held.
2607 *
2608 * Returns: The result of the commit state change.
2609 *
2610 * MT safe.
2611 */
2612 GstStateChangeReturn
gst_element_continue_state(GstElement * element,GstStateChangeReturn ret)2613 gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
2614 {
2615 GstStateChangeReturn old_ret;
2616 GstState old_state, old_next;
2617 GstState current, next, pending;
2618 GstStateChange transition;
2619
2620 GST_OBJECT_LOCK (element);
2621 old_ret = GST_STATE_RETURN (element);
2622 GST_STATE_RETURN (element) = ret;
2623 pending = GST_STATE_PENDING (element);
2624
2625 /* check if there is something to commit */
2626 if (pending == GST_STATE_VOID_PENDING)
2627 goto nothing_pending;
2628
2629 old_state = GST_STATE (element);
2630 /* this is the state we should go to next */
2631 old_next = GST_STATE_NEXT (element);
2632 /* update current state */
2633 current = GST_STATE (element) = old_next;
2634
2635 /* see if we reached the final state */
2636 if (pending == current)
2637 goto complete;
2638
2639 next = GST_STATE_GET_NEXT (current, pending);
2640 transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2641
2642 GST_STATE_NEXT (element) = next;
2643 /* mark busy */
2644 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2645 GST_OBJECT_UNLOCK (element);
2646
2647 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2648 "committing state from %s to %s, pending %s, next %s",
2649 gst_element_state_get_name (old_state),
2650 gst_element_state_get_name (old_next),
2651 gst_element_state_get_name (pending), gst_element_state_get_name (next));
2652
2653 _priv_gst_element_state_changed (element, old_state, old_next, pending);
2654
2655 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2656 "continue state change %s to %s, final %s",
2657 gst_element_state_get_name (current),
2658 gst_element_state_get_name (next), gst_element_state_get_name (pending));
2659
2660 ret = gst_element_change_state (element, transition);
2661
2662 return ret;
2663
2664 nothing_pending:
2665 {
2666 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "nothing pending");
2667 GST_OBJECT_UNLOCK (element);
2668 return ret;
2669 }
2670 complete:
2671 {
2672 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2673 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2674
2675 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2676 "completed state change to %s", gst_element_state_get_name (pending));
2677 GST_OBJECT_UNLOCK (element);
2678
2679 /* don't post silly messages with the same state. This can happen
2680 * when an element state is changed to what it already was. For bins
2681 * this can be the result of a lost state, which we check with the
2682 * previous return value.
2683 * We do signal the cond though as a _get_state() might be blocking
2684 * on it. */
2685 if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC)
2686 _priv_gst_element_state_changed (element, old_state, old_next,
2687 GST_STATE_VOID_PENDING);
2688
2689 GST_STATE_BROADCAST (element);
2690
2691 return ret;
2692 }
2693 }
2694
2695 /**
2696 * gst_element_lost_state:
2697 * @element: a #GstElement the state is lost of
2698 *
2699 * Brings the element to the lost state. The current state of the
2700 * element is copied to the pending state so that any call to
2701 * gst_element_get_state() will return %GST_STATE_CHANGE_ASYNC.
2702 *
2703 * An ASYNC_START message is posted. If the element was PLAYING, it will
2704 * go to PAUSED. The element will be restored to its PLAYING state by
2705 * the parent pipeline when it prerolls again.
2706 *
2707 * This is mostly used for elements that lost their preroll buffer
2708 * in the %GST_STATE_PAUSED or %GST_STATE_PLAYING state after a flush,
2709 * they will go to their pending state again when a new preroll buffer is
2710 * queued. This function can only be called when the element is currently
2711 * not in error or an async state change.
2712 *
2713 * This function is used internally and should normally not be called from
2714 * plugins or applications.
2715 */
2716 void
gst_element_lost_state(GstElement * element)2717 gst_element_lost_state (GstElement * element)
2718 {
2719 GstState old_state, new_state;
2720 GstMessage *message;
2721
2722 g_return_if_fail (GST_IS_ELEMENT (element));
2723
2724 GST_OBJECT_LOCK (element);
2725 if (GST_STATE_RETURN (element) == GST_STATE_CHANGE_FAILURE)
2726 goto nothing_lost;
2727
2728 if (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING)
2729 goto only_async_start;
2730
2731 old_state = GST_STATE (element);
2732
2733 /* when we were PLAYING, the new state is PAUSED. We will also not
2734 * automatically go to PLAYING but let the parent bin(s) set us to PLAYING
2735 * when we preroll. */
2736 if (old_state > GST_STATE_PAUSED)
2737 new_state = GST_STATE_PAUSED;
2738 else
2739 new_state = old_state;
2740
2741 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2742 "lost state of %s to %s", gst_element_state_get_name (old_state),
2743 gst_element_state_get_name (new_state));
2744
2745 GST_STATE (element) = new_state;
2746 GST_STATE_NEXT (element) = new_state;
2747 GST_STATE_PENDING (element) = new_state;
2748 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2749 GST_OBJECT_UNLOCK (element);
2750
2751 _priv_gst_element_state_changed (element, new_state, new_state, new_state);
2752
2753 message = gst_message_new_async_start (GST_OBJECT_CAST (element));
2754 gst_element_post_message (element, message);
2755
2756 return;
2757
2758 nothing_lost:
2759 {
2760 GST_OBJECT_UNLOCK (element);
2761 return;
2762 }
2763 only_async_start:
2764 {
2765 GST_OBJECT_UNLOCK (element);
2766
2767 message = gst_message_new_async_start (GST_OBJECT_CAST (element));
2768 gst_element_post_message (element, message);
2769 return;
2770 }
2771 }
2772
2773 /**
2774 * gst_element_set_state:
2775 * @element: a #GstElement to change state of.
2776 * @state: the element's new #GstState.
2777 *
2778 * Sets the state of the element. This function will try to set the
2779 * requested state by going through all the intermediary states and calling
2780 * the class's state change function for each.
2781 *
2782 * This function can return #GST_STATE_CHANGE_ASYNC, in which case the
2783 * element will perform the remainder of the state change asynchronously in
2784 * another thread.
2785 * An application can use gst_element_get_state() to wait for the completion
2786 * of the state change or it can wait for a %GST_MESSAGE_ASYNC_DONE or
2787 * %GST_MESSAGE_STATE_CHANGED on the bus.
2788 *
2789 * State changes to %GST_STATE_READY or %GST_STATE_NULL never return
2790 * #GST_STATE_CHANGE_ASYNC.
2791 *
2792 * Returns: Result of the state change using #GstStateChangeReturn.
2793 *
2794 * MT safe.
2795 */
2796 GstStateChangeReturn
gst_element_set_state(GstElement * element,GstState state)2797 gst_element_set_state (GstElement * element, GstState state)
2798 {
2799 GstElementClass *oclass;
2800 GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2801
2802 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2803
2804 oclass = GST_ELEMENT_GET_CLASS (element);
2805
2806 if (oclass->set_state)
2807 result = (oclass->set_state) (element, state);
2808
2809 return result;
2810 }
2811
2812 /*
2813 * default set state function, calculates the next state based
2814 * on current state and calls the change_state function
2815 */
2816 static GstStateChangeReturn
gst_element_set_state_func(GstElement * element,GstState state)2817 gst_element_set_state_func (GstElement * element, GstState state)
2818 {
2819 GstState current, next, old_pending;
2820 GstStateChangeReturn ret;
2821 GstStateChange transition;
2822 GstStateChangeReturn old_ret;
2823
2824 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
2825
2826 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "set_state to %s",
2827 gst_element_state_get_name (state));
2828
2829 /* state lock is taken to protect the set_state() and get_state()
2830 * procedures, it does not lock any variables. */
2831 GST_STATE_LOCK (element);
2832
2833 /* now calculate how to get to the new state */
2834 GST_OBJECT_LOCK (element);
2835 old_ret = GST_STATE_RETURN (element);
2836 /* previous state change returned an error, remove all pending
2837 * and next states */
2838 if (old_ret == GST_STATE_CHANGE_FAILURE) {
2839 GST_STATE_NEXT (element) = GST_STATE_VOID_PENDING;
2840 GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
2841 GST_STATE_RETURN (element) = GST_STATE_CHANGE_SUCCESS;
2842 }
2843
2844 current = GST_STATE (element);
2845 next = GST_STATE_NEXT (element);
2846 old_pending = GST_STATE_PENDING (element);
2847
2848 /* this is the (new) state we should go to. TARGET is the last state we set on
2849 * the element. */
2850 if (state != GST_STATE_TARGET (element)) {
2851 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2852 "setting target state to %s", gst_element_state_get_name (state));
2853 GST_STATE_TARGET (element) = state;
2854 /* increment state cookie so that we can track each state change. We only do
2855 * this if this is actually a new state change. */
2856 element->state_cookie++;
2857 }
2858 GST_STATE_PENDING (element) = state;
2859
2860 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2861 "current %s, old_pending %s, next %s, old return %s",
2862 gst_element_state_get_name (current),
2863 gst_element_state_get_name (old_pending),
2864 gst_element_state_get_name (next),
2865 gst_element_state_change_return_get_name (old_ret));
2866
2867 /* if the element was busy doing a state change, we just update the
2868 * target state, it'll get to it async then. */
2869 if (old_pending != GST_STATE_VOID_PENDING) {
2870 /* upwards state change will happen ASYNC */
2871 if (old_pending <= state)
2872 goto was_busy;
2873 /* element is going to this state already */
2874 else if (next == state)
2875 goto was_busy;
2876 /* element was performing an ASYNC upward state change and
2877 * we request to go downward again. Start from the next pending
2878 * state then. */
2879 else if (next > state
2880 && GST_STATE_RETURN (element) == GST_STATE_CHANGE_ASYNC) {
2881 current = next;
2882 }
2883 }
2884 next = GST_STATE_GET_NEXT (current, state);
2885 /* now we store the next state */
2886 GST_STATE_NEXT (element) = next;
2887 /* mark busy, we need to check that there is actually a state change
2888 * to be done else we could accidentally override SUCCESS/NO_PREROLL and
2889 * the default element change_state function has no way to know what the
2890 * old value was... could consider this a FIXME...*/
2891 if (current != next)
2892 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2893
2894 transition = (GstStateChange) GST_STATE_TRANSITION (current, next);
2895
2896 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2897 "%s: setting state from %s to %s",
2898 (next != state ? "intermediate" : "final"),
2899 gst_element_state_get_name (current), gst_element_state_get_name (next));
2900
2901 /* now signal any waiters, they will error since the cookie was incremented */
2902 GST_STATE_BROADCAST (element);
2903
2904 GST_OBJECT_UNLOCK (element);
2905
2906 ret = gst_element_change_state (element, transition);
2907
2908 GST_STATE_UNLOCK (element);
2909
2910 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element, "returned %s",
2911 gst_element_state_change_return_get_name (ret));
2912
2913 return ret;
2914
2915 was_busy:
2916 {
2917 GST_STATE_RETURN (element) = GST_STATE_CHANGE_ASYNC;
2918 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2919 "element was busy with async state change");
2920 GST_OBJECT_UNLOCK (element);
2921
2922 GST_STATE_UNLOCK (element);
2923
2924 return GST_STATE_CHANGE_ASYNC;
2925 }
2926 }
2927
2928 /**
2929 * gst_element_change_state:
2930 * @element: a #GstElement
2931 * @transition: the requested transition
2932 *
2933 * Perform @transition on @element.
2934 *
2935 * This function must be called with STATE_LOCK held and is mainly used
2936 * internally.
2937 *
2938 * Returns: the #GstStateChangeReturn of the state transition.
2939 */
2940 GstStateChangeReturn
gst_element_change_state(GstElement * element,GstStateChange transition)2941 gst_element_change_state (GstElement * element, GstStateChange transition)
2942 {
2943 GstElementClass *oclass;
2944 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2945
2946 oclass = GST_ELEMENT_GET_CLASS (element);
2947
2948 GST_TRACER_ELEMENT_CHANGE_STATE_PRE (element, transition);
2949
2950 /* call the state change function so it can set the state */
2951 if (oclass->change_state)
2952 ret = (oclass->change_state) (element, transition);
2953 else
2954 ret = GST_STATE_CHANGE_FAILURE;
2955
2956 GST_TRACER_ELEMENT_CHANGE_STATE_POST (element, transition, ret);
2957
2958 switch (ret) {
2959 case GST_STATE_CHANGE_FAILURE:
2960 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2961 "have FAILURE change_state return");
2962 /* state change failure */
2963 gst_element_abort_state (element);
2964 break;
2965 case GST_STATE_CHANGE_ASYNC:
2966 {
2967 GstState target;
2968
2969 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2970 "element will change state ASYNC");
2971
2972 target = GST_STATE_TARGET (element);
2973
2974 if (target > GST_STATE_READY)
2975 goto async;
2976
2977 /* else we just continue the state change downwards */
2978 GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
2979 "forcing commit state %s <= %s",
2980 gst_element_state_get_name (target),
2981 gst_element_state_get_name (GST_STATE_READY));
2982
2983 ret = gst_element_continue_state (element, GST_STATE_CHANGE_SUCCESS);
2984 break;
2985 }
2986 case GST_STATE_CHANGE_SUCCESS:
2987 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2988 "element changed state SUCCESS");
2989 /* we can commit the state now which will proceed to
2990 * the next state */
2991 ret = gst_element_continue_state (element, ret);
2992 break;
2993 case GST_STATE_CHANGE_NO_PREROLL:
2994 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
2995 "element changed state NO_PREROLL");
2996 /* we can commit the state now which will proceed to
2997 * the next state */
2998 ret = gst_element_continue_state (element, ret);
2999 break;
3000 default:
3001 goto invalid_return;
3002 }
3003
3004 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit state change %d", ret);
3005
3006 return ret;
3007
3008 async:
3009 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element, "exit async state change %d",
3010 ret);
3011
3012 return ret;
3013
3014 /* ERROR */
3015 invalid_return:
3016 {
3017 GST_OBJECT_LOCK (element);
3018 /* somebody added a GST_STATE_ and forgot to do stuff here ! */
3019 g_critical ("%s: unknown return value %d from a state change function",
3020 GST_ELEMENT_NAME (element), ret);
3021
3022 /* we are in error now */
3023 ret = GST_STATE_CHANGE_FAILURE;
3024 GST_STATE_RETURN (element) = ret;
3025 GST_OBJECT_UNLOCK (element);
3026
3027 return ret;
3028 }
3029 }
3030
3031 /* gst_iterator_fold functions for pads_activate
3032 * Stop the iterator if activating one pad failed, but only if that pad
3033 * has not been removed from the element. */
3034 static gboolean
activate_pads(const GValue * vpad,GValue * ret,gboolean * active)3035 activate_pads (const GValue * vpad, GValue * ret, gboolean * active)
3036 {
3037 GstPad *pad = g_value_get_object (vpad);
3038 gboolean cont = TRUE;
3039
3040 if (!gst_pad_set_active (pad, *active)) {
3041 if (GST_PAD_PARENT (pad) != NULL) {
3042 cont = FALSE;
3043 g_value_set_boolean (ret, FALSE);
3044 }
3045 }
3046
3047 return cont;
3048 }
3049
3050 /* returns false on error or early cutout of the fold, true if all
3051 * pads in @iter were (de)activated successfully. */
3052 static gboolean
iterator_activate_fold_with_resync(GstIterator * iter,GstIteratorFoldFunction func,gpointer user_data)3053 iterator_activate_fold_with_resync (GstIterator * iter,
3054 GstIteratorFoldFunction func, gpointer user_data)
3055 {
3056 GstIteratorResult ires;
3057 GValue ret = { 0 };
3058
3059 /* no need to unset this later, it's just a boolean */
3060 g_value_init (&ret, G_TYPE_BOOLEAN);
3061 g_value_set_boolean (&ret, TRUE);
3062
3063 while (1) {
3064 ires = gst_iterator_fold (iter, func, &ret, user_data);
3065 switch (ires) {
3066 case GST_ITERATOR_RESYNC:
3067 /* need to reset the result again */
3068 g_value_set_boolean (&ret, TRUE);
3069 gst_iterator_resync (iter);
3070 break;
3071 case GST_ITERATOR_DONE:
3072 /* all pads iterated, return collected value */
3073 goto done;
3074 default:
3075 /* iterator returned _ERROR or premature end with _OK,
3076 * mark an error and exit */
3077 g_value_set_boolean (&ret, FALSE);
3078 goto done;
3079 }
3080 }
3081 done:
3082 /* return collected value */
3083 return g_value_get_boolean (&ret);
3084 }
3085
3086 /* is called with STATE_LOCK
3087 *
3088 * Pads are activated from source pads to sinkpads.
3089 */
3090 static gboolean
gst_element_pads_activate(GstElement * element,gboolean active)3091 gst_element_pads_activate (GstElement * element, gboolean active)
3092 {
3093 GstIterator *iter;
3094 gboolean res;
3095
3096 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3097 "%s pads", active ? "activate" : "deactivate");
3098
3099 iter = gst_element_iterate_src_pads (element);
3100 res =
3101 iterator_activate_fold_with_resync (iter,
3102 (GstIteratorFoldFunction) activate_pads, &active);
3103 gst_iterator_free (iter);
3104 if (G_UNLIKELY (!res))
3105 goto src_failed;
3106
3107 iter = gst_element_iterate_sink_pads (element);
3108 res =
3109 iterator_activate_fold_with_resync (iter,
3110 (GstIteratorFoldFunction) activate_pads, &active);
3111 gst_iterator_free (iter);
3112 if (G_UNLIKELY (!res))
3113 goto sink_failed;
3114
3115 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3116 "pad %sactivation successful", active ? "" : "de");
3117
3118 return TRUE;
3119
3120 /* ERRORS */
3121 src_failed:
3122 {
3123 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3124 "pad %sactivation failed", active ? "" : "de");
3125 return FALSE;
3126 }
3127 sink_failed:
3128 {
3129 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3130 "sink pads_activate failed");
3131 return FALSE;
3132 }
3133 }
3134
3135 /* is called with STATE_LOCK */
3136 static GstStateChangeReturn
gst_element_change_state_func(GstElement * element,GstStateChange transition)3137 gst_element_change_state_func (GstElement * element, GstStateChange transition)
3138 {
3139 GstState state, next;
3140 GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
3141
3142 g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
3143
3144 state = (GstState) GST_STATE_TRANSITION_CURRENT (transition);
3145 next = GST_STATE_TRANSITION_NEXT (transition);
3146
3147 /* if the element already is in the given state, we just return success */
3148 if (next == GST_STATE_VOID_PENDING || state == next)
3149 goto was_ok;
3150
3151 GST_CAT_LOG_OBJECT (GST_CAT_STATES, element,
3152 "default handler tries setting state from %s to %s (%04x)",
3153 gst_element_state_get_name (state),
3154 gst_element_state_get_name (next), transition);
3155
3156 switch (transition) {
3157 case GST_STATE_CHANGE_NULL_TO_READY:
3158 break;
3159 case GST_STATE_CHANGE_READY_TO_PAUSED:
3160 if (!gst_element_pads_activate (element, TRUE)) {
3161 result = GST_STATE_CHANGE_FAILURE;
3162 }
3163 break;
3164 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3165 break;
3166 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3167 break;
3168 case GST_STATE_CHANGE_PAUSED_TO_READY:
3169 case GST_STATE_CHANGE_READY_TO_NULL:{
3170 GList *l;
3171
3172 /* deactivate pads in both cases, since they are activated on
3173 ready->paused but the element might not have made it to paused */
3174 if (!gst_element_pads_activate (element, FALSE)) {
3175 result = GST_STATE_CHANGE_FAILURE;
3176 }
3177
3178 /* Remove all non-persistent contexts */
3179 GST_OBJECT_LOCK (element);
3180 for (l = element->contexts; l;) {
3181 GstContext *context = l->data;
3182
3183 if (!gst_context_is_persistent (context)) {
3184 GList *next;
3185
3186 gst_context_unref (context);
3187 next = l->next;
3188 element->contexts = g_list_delete_link (element->contexts, l);
3189 l = next;
3190 } else {
3191 l = l->next;
3192 }
3193 }
3194 GST_OBJECT_UNLOCK (element);
3195 break;
3196 }
3197 default:
3198 /* this will catch real but unhandled state changes;
3199 * can only be caused by:
3200 * - a new state was added
3201 * - somehow the element was asked to jump across an intermediate state
3202 */
3203 g_warning ("Unhandled state change from %s to %s",
3204 gst_element_state_get_name (state),
3205 gst_element_state_get_name (next));
3206 break;
3207 }
3208 return result;
3209
3210 was_ok:
3211 {
3212 GST_OBJECT_LOCK (element);
3213 result = GST_STATE_RETURN (element);
3214 GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
3215 "element is already in the %s state",
3216 gst_element_state_get_name (state));
3217 GST_OBJECT_UNLOCK (element);
3218
3219 return result;
3220 }
3221 }
3222
3223 /**
3224 * gst_element_get_factory:
3225 * @element: a #GstElement to request the element factory of.
3226 *
3227 * Retrieves the factory that was used to create this element.
3228 *
3229 * Returns: (transfer none) (nullable): the #GstElementFactory used for creating this
3230 * element or %NULL if element has not been registered (static element). no refcounting is needed.
3231 */
3232 GstElementFactory *
gst_element_get_factory(GstElement * element)3233 gst_element_get_factory (GstElement * element)
3234 {
3235 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3236
3237 return GST_ELEMENT_GET_CLASS (element)->elementfactory;
3238 }
3239
3240 static void
gst_element_dispose(GObject * object)3241 gst_element_dispose (GObject * object)
3242 {
3243 GstElement *element = GST_ELEMENT_CAST (object);
3244 GstClock **clock_p;
3245 GstBus **bus_p;
3246 GstElementClass *oclass;
3247 GList *walk;
3248
3249 oclass = GST_ELEMENT_GET_CLASS (element);
3250
3251 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p dispose", element);
3252
3253 if (GST_STATE (element) != GST_STATE_NULL)
3254 goto not_null;
3255
3256 /* start by releasing all request pads, this might also remove some dynamic
3257 * pads */
3258 walk = element->pads;
3259 while (walk) {
3260 GstPad *pad = GST_PAD_CAST (walk->data);
3261
3262 walk = walk->next;
3263
3264 if (oclass->release_pad && GST_PAD_PAD_TEMPLATE (pad) &&
3265 GST_PAD_TEMPLATE_PRESENCE (GST_PAD_PAD_TEMPLATE (pad))
3266 == GST_PAD_REQUEST) {
3267 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3268 "removing request pad %s:%s", GST_DEBUG_PAD_NAME (pad));
3269 oclass->release_pad (element, pad);
3270
3271 /* in case the release_pad function removed the next pad too */
3272 if (walk && g_list_position (element->pads, walk) == -1)
3273 walk = element->pads;
3274 }
3275 }
3276 /* remove the remaining pads */
3277 while (element->pads) {
3278 GstPad *pad = GST_PAD_CAST (element->pads->data);
3279 GST_CAT_DEBUG_OBJECT (GST_CAT_ELEMENT_PADS, element,
3280 "removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));
3281 if (!gst_element_remove_pad (element, pad)) {
3282 /* only happens when someone unparented our pad.. */
3283 g_critical ("failed to remove pad %s:%s", GST_DEBUG_PAD_NAME (pad));
3284 break;
3285 }
3286 }
3287
3288 GST_OBJECT_LOCK (element);
3289 clock_p = &element->clock;
3290 bus_p = &element->bus;
3291 gst_object_replace ((GstObject **) clock_p, NULL);
3292 gst_object_replace ((GstObject **) bus_p, NULL);
3293 g_list_free_full (element->contexts, (GDestroyNotify) gst_context_unref);
3294 GST_OBJECT_UNLOCK (element);
3295
3296 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p parent class dispose",
3297 element);
3298
3299 G_OBJECT_CLASS (parent_class)->dispose (object);
3300
3301 return;
3302
3303 /* ERRORS */
3304 not_null:
3305 {
3306 gboolean is_locked;
3307
3308 is_locked = GST_ELEMENT_IS_LOCKED_STATE (element);
3309 g_critical
3310 ("\nTrying to dispose element %s, but it is in %s%s instead of the NULL"
3311 " state.\n"
3312 "You need to explicitly set elements to the NULL state before\n"
3313 "dropping the final reference, to allow them to clean up.\n"
3314 "This problem may also be caused by a refcounting bug in the\n"
3315 "application or some element.\n",
3316 GST_OBJECT_NAME (element),
3317 gst_element_state_get_name (GST_STATE (element)),
3318 is_locked ? " (locked)" : "");
3319 return;
3320 }
3321 }
3322
3323 static void
gst_element_finalize(GObject * object)3324 gst_element_finalize (GObject * object)
3325 {
3326 GstElement *element = GST_ELEMENT_CAST (object);
3327
3328 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p finalize", element);
3329
3330 g_cond_clear (&element->state_cond);
3331 g_rec_mutex_clear (&element->state_lock);
3332
3333 GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "%p finalize parent",
3334 element);
3335
3336 G_OBJECT_CLASS (parent_class)->finalize (object);
3337 }
3338
3339 static void
gst_element_set_bus_func(GstElement * element,GstBus * bus)3340 gst_element_set_bus_func (GstElement * element, GstBus * bus)
3341 {
3342 GstBus **bus_p;
3343
3344 g_return_if_fail (GST_IS_ELEMENT (element));
3345
3346 GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, element, "setting bus to %p", bus);
3347
3348 GST_OBJECT_LOCK (element);
3349 bus_p = &GST_ELEMENT_BUS (element);
3350 gst_object_replace ((GstObject **) bus_p, GST_OBJECT_CAST (bus));
3351 GST_OBJECT_UNLOCK (element);
3352 }
3353
3354 /**
3355 * gst_element_set_bus:
3356 * @element: a #GstElement to set the bus of.
3357 * @bus: (transfer none) (allow-none): the #GstBus to set.
3358 *
3359 * Sets the bus of the element. Increases the refcount on the bus.
3360 * For internal use only, unless you're testing elements.
3361 *
3362 * MT safe.
3363 */
3364 void
gst_element_set_bus(GstElement * element,GstBus * bus)3365 gst_element_set_bus (GstElement * element, GstBus * bus)
3366 {
3367 GstElementClass *oclass;
3368
3369 g_return_if_fail (GST_IS_ELEMENT (element));
3370
3371 oclass = GST_ELEMENT_GET_CLASS (element);
3372
3373 if (oclass->set_bus)
3374 oclass->set_bus (element, bus);
3375 }
3376
3377 /**
3378 * gst_element_get_bus:
3379 * @element: a #GstElement to get the bus of.
3380 *
3381 * Returns the bus of the element. Note that only a #GstPipeline will provide a
3382 * bus for the application.
3383 *
3384 * Returns: (transfer full) (nullable): the element's #GstBus. unref after
3385 * usage.
3386 *
3387 * MT safe.
3388 */
3389 GstBus *
gst_element_get_bus(GstElement * element)3390 gst_element_get_bus (GstElement * element)
3391 {
3392 GstBus *result = NULL;
3393
3394 g_return_val_if_fail (GST_IS_ELEMENT (element), result);
3395
3396 GST_OBJECT_LOCK (element);
3397 if ((result = GST_ELEMENT_BUS (element)))
3398 gst_object_ref (result);
3399 GST_OBJECT_UNLOCK (element);
3400
3401 GST_CAT_DEBUG_OBJECT (GST_CAT_BUS, element, "got bus %" GST_PTR_FORMAT,
3402 result);
3403
3404 return result;
3405 }
3406
3407 static void
gst_element_set_context_default(GstElement * element,GstContext * context)3408 gst_element_set_context_default (GstElement * element, GstContext * context)
3409 {
3410 const gchar *context_type;
3411 GList *l;
3412
3413 g_return_if_fail (GST_IS_CONTEXT (context));
3414 context_type = gst_context_get_context_type (context);
3415 g_return_if_fail (context_type != NULL);
3416
3417 GST_OBJECT_LOCK (element);
3418 for (l = element->contexts; l; l = l->next) {
3419 GstContext *tmp = l->data;
3420 const gchar *tmp_type = gst_context_get_context_type (tmp);
3421
3422 /* Always store newest context but never replace
3423 * a persistent one by a non-persistent one */
3424 if (g_strcmp0 (context_type, tmp_type) == 0 &&
3425 (gst_context_is_persistent (context) ||
3426 !gst_context_is_persistent (tmp))) {
3427 gst_context_replace ((GstContext **) & l->data, context);
3428 break;
3429 }
3430 }
3431 /* Not found? Add */
3432 if (l == NULL) {
3433 element->contexts =
3434 g_list_prepend (element->contexts, gst_context_ref (context));
3435 }
3436 GST_OBJECT_UNLOCK (element);
3437 }
3438
3439 /**
3440 * gst_element_set_context:
3441 * @element: a #GstElement to set the context of.
3442 * @context: (transfer none): the #GstContext to set.
3443 *
3444 * Sets the context of the element. Increases the refcount of the context.
3445 *
3446 * MT safe.
3447 */
3448 void
gst_element_set_context(GstElement * element,GstContext * context)3449 gst_element_set_context (GstElement * element, GstContext * context)
3450 {
3451 GstElementClass *oclass;
3452
3453 g_return_if_fail (GST_IS_ELEMENT (element));
3454 g_return_if_fail (GST_IS_CONTEXT (context));
3455
3456 oclass = GST_ELEMENT_GET_CLASS (element);
3457
3458 GST_CAT_DEBUG_OBJECT (GST_CAT_CONTEXT, element,
3459 "set context %p %" GST_PTR_FORMAT, context,
3460 gst_context_get_structure (context));
3461
3462 if (oclass->set_context)
3463 oclass->set_context (element, context);
3464 }
3465
3466 /**
3467 * gst_element_get_contexts:
3468 * @element: a #GstElement to set the context of.
3469 *
3470 * Gets the contexts set on the element.
3471 *
3472 * MT safe.
3473 *
3474 * Returns: (element-type Gst.Context) (transfer full): List of #GstContext
3475 *
3476 * Since: 1.8
3477 */
3478 GList *
gst_element_get_contexts(GstElement * element)3479 gst_element_get_contexts (GstElement * element)
3480 {
3481 GList *ret;
3482
3483 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3484
3485 GST_OBJECT_LOCK (element);
3486 ret = g_list_copy_deep (element->contexts, (GCopyFunc) gst_context_ref, NULL);
3487 GST_OBJECT_UNLOCK (element);
3488
3489 return ret;
3490 }
3491
3492 static gint
_match_context_type(GstContext * c1,const gchar * context_type)3493 _match_context_type (GstContext * c1, const gchar * context_type)
3494 {
3495 const gchar *c1_type;
3496
3497 c1_type = gst_context_get_context_type (c1);
3498
3499 return g_strcmp0 (c1_type, context_type);
3500 }
3501
3502 /**
3503 * gst_element_get_context_unlocked:
3504 * @element: a #GstElement to get the context of.
3505 * @context_type: a name of a context to retrieve
3506 *
3507 * Gets the context with @context_type set on the element or NULL.
3508 *
3509 * Returns: (transfer full) (nullable): A #GstContext or NULL
3510 *
3511 * Since: 1.8
3512 */
3513 GstContext *
gst_element_get_context_unlocked(GstElement * element,const gchar * context_type)3514 gst_element_get_context_unlocked (GstElement * element,
3515 const gchar * context_type)
3516 {
3517 GstContext *ret = NULL;
3518 GList *node;
3519
3520 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3521
3522 node =
3523 g_list_find_custom (element->contexts, context_type,
3524 (GCompareFunc) _match_context_type);
3525 if (node && node->data)
3526 ret = gst_context_ref (node->data);
3527
3528 return ret;
3529 }
3530
3531 /**
3532 * gst_element_get_context:
3533 * @element: a #GstElement to get the context of.
3534 * @context_type: a name of a context to retrieve
3535 *
3536 * Gets the context with @context_type set on the element or NULL.
3537 *
3538 * MT safe.
3539 *
3540 * Returns: (transfer full): A #GstContext or NULL
3541 *
3542 * Since: 1.8
3543 */
3544 GstContext *
gst_element_get_context(GstElement * element,const gchar * context_type)3545 gst_element_get_context (GstElement * element, const gchar * context_type)
3546 {
3547 GstContext *ret = NULL;
3548
3549 g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
3550
3551 GST_OBJECT_LOCK (element);
3552 ret = gst_element_get_context_unlocked (element, context_type);
3553 GST_OBJECT_UNLOCK (element);
3554
3555 return ret;
3556 }
3557
3558 static void
gst_element_property_post_notify_msg(GstElement * element,GObject * obj,GParamSpec * pspec,gboolean include_value)3559 gst_element_property_post_notify_msg (GstElement * element, GObject * obj,
3560 GParamSpec * pspec, gboolean include_value)
3561 {
3562 GValue val = G_VALUE_INIT;
3563 GValue *v;
3564
3565 GST_LOG_OBJECT (element, "property '%s' of object %" GST_PTR_FORMAT " has "
3566 "changed, posting message with%s value", pspec->name, obj,
3567 include_value ? "" : "out");
3568
3569 if (include_value && (pspec->flags & G_PARAM_READABLE) != 0) {
3570 g_value_init (&val, pspec->value_type);
3571 g_object_get_property (obj, pspec->name, &val);
3572 v = &val;
3573 } else {
3574 v = NULL;
3575 }
3576 gst_element_post_message (element,
3577 gst_message_new_property_notify (GST_OBJECT_CAST (obj), pspec->name, v));
3578 }
3579
3580 static void
gst_element_property_deep_notify_cb(GstElement * element,GObject * prop_obj,GParamSpec * pspec,gpointer user_data)3581 gst_element_property_deep_notify_cb (GstElement * element, GObject * prop_obj,
3582 GParamSpec * pspec, gpointer user_data)
3583 {
3584 gboolean include_value = GPOINTER_TO_INT (user_data);
3585
3586 gst_element_property_post_notify_msg (element, prop_obj, pspec,
3587 include_value);
3588 }
3589
3590 static void
gst_element_property_notify_cb(GObject * obj,GParamSpec * pspec,gpointer user_data)3591 gst_element_property_notify_cb (GObject * obj, GParamSpec * pspec,
3592 gpointer user_data)
3593 {
3594 gboolean include_value = GPOINTER_TO_INT (user_data);
3595
3596 gst_element_property_post_notify_msg (GST_ELEMENT_CAST (obj), obj, pspec,
3597 include_value);
3598 }
3599
3600 /**
3601 * gst_element_add_property_notify_watch:
3602 * @element: a #GstElement to watch for property changes
3603 * @property_name: (allow-none): name of property to watch for changes, or
3604 * NULL to watch all properties
3605 * @include_value: whether to include the new property value in the message
3606 *
3607 * Returns: a watch id, which can be used in connection with
3608 * gst_element_remove_property_notify_watch() to remove the watch again.
3609 *
3610 * Since: 1.10
3611 */
3612 gulong
gst_element_add_property_notify_watch(GstElement * element,const gchar * property_name,gboolean include_value)3613 gst_element_add_property_notify_watch (GstElement * element,
3614 const gchar * property_name, gboolean include_value)
3615 {
3616 const gchar *sep;
3617 gchar *signal_name;
3618 gulong id;
3619
3620 g_return_val_if_fail (GST_IS_ELEMENT (element), 0);
3621
3622 sep = (property_name != NULL) ? "::" : NULL;
3623 signal_name = g_strconcat ("notify", sep, property_name, NULL);
3624 id = g_signal_connect (element, signal_name,
3625 G_CALLBACK (gst_element_property_notify_cb),
3626 GINT_TO_POINTER (include_value));
3627 g_free (signal_name);
3628
3629 return id;
3630 }
3631
3632 /**
3633 * gst_element_add_property_deep_notify_watch:
3634 * @element: a #GstElement to watch (recursively) for property changes
3635 * @property_name: (allow-none): name of property to watch for changes, or
3636 * NULL to watch all properties
3637 * @include_value: whether to include the new property value in the message
3638 *
3639 * Returns: a watch id, which can be used in connection with
3640 * gst_element_remove_property_notify_watch() to remove the watch again.
3641 *
3642 * Since: 1.10
3643 */
3644 gulong
gst_element_add_property_deep_notify_watch(GstElement * element,const gchar * property_name,gboolean include_value)3645 gst_element_add_property_deep_notify_watch (GstElement * element,
3646 const gchar * property_name, gboolean include_value)
3647 {
3648 const gchar *sep;
3649 gchar *signal_name;
3650 gulong id;
3651
3652 g_return_val_if_fail (GST_IS_ELEMENT (element), 0);
3653
3654 sep = (property_name != NULL) ? "::" : NULL;
3655 signal_name = g_strconcat ("deep-notify", sep, property_name, NULL);
3656 id = g_signal_connect (element, signal_name,
3657 G_CALLBACK (gst_element_property_deep_notify_cb),
3658 GINT_TO_POINTER (include_value));
3659 g_free (signal_name);
3660
3661 return id;
3662 }
3663
3664 /**
3665 * gst_element_remove_property_notify_watch:
3666 * @element: a #GstElement being watched for property changes
3667 * @watch_id: watch id to remove
3668 *
3669 * Since: 1.10
3670 */
3671 void
gst_element_remove_property_notify_watch(GstElement * element,gulong watch_id)3672 gst_element_remove_property_notify_watch (GstElement * element, gulong watch_id)
3673 {
3674 g_signal_handler_disconnect (element, watch_id);
3675 }
3676
3677 typedef struct
3678 {
3679 GstElement *element;
3680 GstElementCallAsyncFunc func;
3681 gpointer user_data;
3682 GDestroyNotify destroy_notify;
3683 } GstElementCallAsyncData;
3684
3685 static void
gst_element_call_async_func(gpointer data,gpointer user_data)3686 gst_element_call_async_func (gpointer data, gpointer user_data)
3687 {
3688 GstElementCallAsyncData *async_data = data;
3689
3690 async_data->func (async_data->element, async_data->user_data);
3691 if (async_data->destroy_notify)
3692 async_data->destroy_notify (async_data->user_data);
3693 gst_object_unref (async_data->element);
3694 g_free (async_data);
3695 }
3696
3697 /**
3698 * gst_element_call_async:
3699 * @element: a #GstElement
3700 * @func: Function to call asynchronously from another thread
3701 * @user_data: Data to pass to @func
3702 * @destroy_notify: GDestroyNotify for @user_data
3703 *
3704 * Calls @func from another thread and passes @user_data to it. This is to be
3705 * used for cases when a state change has to be performed from a streaming
3706 * thread, directly via gst_element_set_state() or indirectly e.g. via SEEK
3707 * events.
3708 *
3709 * Calling those functions directly from the streaming thread will cause
3710 * deadlocks in many situations, as they might involve waiting for the
3711 * streaming thread to shut down from this very streaming thread.
3712 *
3713 * MT safe.
3714 *
3715 * Since: 1.10
3716 */
3717 void
gst_element_call_async(GstElement * element,GstElementCallAsyncFunc func,gpointer user_data,GDestroyNotify destroy_notify)3718 gst_element_call_async (GstElement * element, GstElementCallAsyncFunc func,
3719 gpointer user_data, GDestroyNotify destroy_notify)
3720 {
3721 GstElementCallAsyncData *async_data;
3722
3723 g_return_if_fail (GST_IS_ELEMENT (element));
3724
3725 async_data = g_new0 (GstElementCallAsyncData, 1);
3726 async_data->element = gst_object_ref (element);
3727 async_data->func = func;
3728 async_data->user_data = user_data;
3729 async_data->destroy_notify = destroy_notify;
3730
3731 g_thread_pool_push (gst_element_pool, async_data, NULL);
3732 }
3733
3734 void
_priv_gst_element_cleanup(void)3735 _priv_gst_element_cleanup (void)
3736 {
3737 if (gst_element_pool) {
3738 g_thread_pool_free (gst_element_pool, FALSE, TRUE);
3739 gst_element_setup_thread_pool ();
3740 }
3741 }
3742
3743 GstStructure *
gst_make_element_message_details(const char * name,...)3744 gst_make_element_message_details (const char *name, ...)
3745 {
3746 GstStructure *structure;
3747 va_list varargs;
3748
3749 if (name == NULL)
3750 return NULL;
3751
3752 va_start (varargs, name);
3753 structure = gst_structure_new_valist ("details", name, varargs);
3754 va_end (varargs);
3755
3756 return structure;
3757 }
3758