Coverage Report

Created: 2026-02-24 07:11

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