• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstpad.c: Pads for linking elements together
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  * SECTION:gstpad
24  * @title: GstPad
25  * @short_description: Object contained by elements that allows links to
26  *                     other elements
27  * @see_also: #GstPadTemplate, #GstElement, #GstEvent, #GstQuery, #GstBuffer
28  *
29  * A #GstElement is linked to other elements via "pads", which are extremely
30  * light-weight generic link points.
31  *
32  * Pads have a #GstPadDirection, source pads produce data, sink pads consume
33  * data.
34  *
35  * Pads are typically created from a #GstPadTemplate with
36  * gst_pad_new_from_template() and are then added to a #GstElement. This usually
37  * happens when the element is created but it can also happen dynamically based
38  * on the data that the element is processing or based on the pads that the
39  * application requests.
40  *
41  * Pads without pad templates can be created with gst_pad_new(),
42  * which takes a direction and a name as an argument.  If the name is %NULL,
43  * then a guaranteed unique name will be assigned to it.
44  *
45  * A #GstElement creating a pad will typically use the various
46  * gst_pad_set_*_function\() calls to register callbacks for events, queries or
47  * dataflow on the pads.
48  *
49  * gst_pad_get_parent() will retrieve the #GstElement that owns the pad.
50  *
51  * After two pads are retrieved from an element by gst_element_get_static_pad(),
52  * the pads can be linked with gst_pad_link(). (For quick links,
53  * you can also use gst_element_link(), which will make the obvious
54  * link for you if it's straightforward.). Pads can be unlinked again with
55  * gst_pad_unlink(). gst_pad_get_peer() can be used to check what the pad is
56  * linked to.
57  *
58  * Before dataflow is possible on the pads, they need to be activated with
59  * gst_pad_set_active().
60  *
61  * gst_pad_query() and gst_pad_peer_query() can be used to query various
62  * properties of the pad and the stream.
63  *
64  * To send a #GstEvent on a pad, use gst_pad_send_event() and
65  * gst_pad_push_event(). Some events will be sticky on the pad, meaning that
66  * after they pass on the pad they can be queried later with
67  * gst_pad_get_sticky_event() and gst_pad_sticky_events_foreach().
68  * gst_pad_get_current_caps() and gst_pad_has_current_caps() are convenience
69  * functions to query the current sticky CAPS event on a pad.
70  *
71  * GstElements will use gst_pad_push() and gst_pad_pull_range() to push out
72  * or pull in a buffer.
73  *
74  * The dataflow, events and queries that happen on a pad can be monitored with
75  * probes that can be installed with gst_pad_add_probe(). gst_pad_is_blocked()
76  * can be used to check if a block probe is installed on the pad.
77  * gst_pad_is_blocking() checks if the blocking probe is currently blocking the
78  * pad. gst_pad_remove_probe() is used to remove a previously installed probe
79  * and unblock blocking probes if any.
80  *
81  * Pad have an offset that can be retrieved with gst_pad_get_offset(). This
82  * offset will be applied to the running_time of all data passing over the pad.
83  * gst_pad_set_offset() can be used to change the offset.
84  *
85  * Convenience functions exist to start, pause and stop the task on a pad with
86  * gst_pad_start_task(), gst_pad_pause_task() and gst_pad_stop_task()
87  * respectively.
88  */
89 
90 #include "gst_private.h"
91 
92 #include "gstpad.h"
93 #include "gstpadtemplate.h"
94 #include "gstenumtypes.h"
95 #include "gstutils.h"
96 #include "gstinfo.h"
97 #include "gsterror.h"
98 #include "gsttracerutils.h"
99 #include "gstvalue.h"
100 #include "glib-compat-private.h"
101 
102 GST_DEBUG_CATEGORY_STATIC (debug_dataflow);
103 #define GST_CAT_DEFAULT GST_CAT_PADS
104 
105 /* Pad signals and args */
106 enum
107 {
108   PAD_LINKED,
109   PAD_UNLINKED,
110   /* FILL ME */
111   LAST_SIGNAL
112 };
113 
114 enum
115 {
116   PAD_PROP_0,
117   PAD_PROP_CAPS,
118   PAD_PROP_DIRECTION,
119   PAD_PROP_TEMPLATE,
120   PAD_PROP_OFFSET
121       /* FILL ME */
122 };
123 
124 #define _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH (GST_PAD_PROBE_TYPE_ALL_BOTH | GST_PAD_PROBE_TYPE_EVENT_FLUSH)
125 
126 /* we have a pending and an active event on the pad. On source pads only the
127  * active event is used. On sinkpads, events are copied to the pending entry and
128  * moved to the active event when the eventfunc returned %TRUE. */
129 typedef struct
130 {
131   gboolean received;
132   GstEvent *event;
133 } PadEvent;
134 
135 struct _GstPadPrivate
136 {
137   guint events_cookie;
138   GArray *events;
139   guint last_cookie;
140 
141   gint using;
142   guint probe_list_cookie;
143 
144   /* counter of how many idle probes are running directly from the add_probe
145    * call. Used to block any data flowing in the pad while the idle callback
146    * Doesn't finish its work */
147   gint idle_running;
148 
149   /* conditional and variable used to ensure pads only get (de)activated
150    * by a single thread at a time. Protected by the object lock */
151   GCond activation_cond;
152   gboolean in_activation;
153 };
154 
155 typedef struct
156 {
157   GHook hook;
158 } GstProbe;
159 
160 #define GST_PAD_IS_RUNNING_IDLE_PROBE(p) \
161     (((GstPad *)(p))->priv->idle_running > 0)
162 
163 typedef struct
164 {
165   GstPad *pad;
166   GstPadProbeInfo *info;
167   gboolean dropped;
168   gboolean pass;
169   gboolean handled;
170   gboolean marshalled;
171 
172   gulong *called_probes;
173   guint n_called_probes;
174   guint called_probes_size;
175   gboolean retry;
176 } ProbeMarshall;
177 
178 static void gst_pad_dispose (GObject * object);
179 static void gst_pad_finalize (GObject * object);
180 static void gst_pad_set_property (GObject * object, guint prop_id,
181     const GValue * value, GParamSpec * pspec);
182 static void gst_pad_get_property (GObject * object, guint prop_id,
183     GValue * value, GParamSpec * pspec);
184 
185 static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ);
186 static gboolean gst_pad_activate_default (GstPad * pad, GstObject * parent);
187 static GstFlowReturn gst_pad_chain_list_default (GstPad * pad,
188     GstObject * parent, GstBufferList * list);
189 
190 static GstFlowReturn gst_pad_send_event_unchecked (GstPad * pad,
191     GstEvent * event, GstPadProbeType type);
192 static GstFlowReturn gst_pad_push_event_unchecked (GstPad * pad,
193     GstEvent * event, GstPadProbeType type);
194 
195 static gboolean activate_mode_internal (GstPad * pad, GstObject * parent,
196     GstPadMode mode, gboolean active);
197 
198 static guint gst_pad_signals[LAST_SIGNAL] = { 0 };
199 
200 static GParamSpec *pspec_caps = NULL;
201 
202 /* quarks for probe signals */
203 static GQuark buffer_quark;
204 static GQuark buffer_list_quark;
205 static GQuark event_quark;
206 
207 typedef struct
208 {
209   const gint ret;
210   const gchar *name;
211   GQuark quark;
212 } GstFlowQuarks;
213 
214 static GstFlowQuarks flow_quarks[] = {
215   {GST_FLOW_CUSTOM_SUCCESS, "custom-success", 0},
216   {GST_FLOW_OK, "ok", 0},
217   {GST_FLOW_NOT_LINKED, "not-linked", 0},
218   {GST_FLOW_FLUSHING, "flushing", 0},
219   {GST_FLOW_EOS, "eos", 0},
220   {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0},
221   {GST_FLOW_ERROR, "error", 0},
222   {GST_FLOW_NOT_SUPPORTED, "not-supported", 0},
223   {GST_FLOW_CUSTOM_ERROR, "custom-error", 0}
224 };
225 
226 /**
227  * gst_flow_get_name:
228  * @ret: a #GstFlowReturn to get the name of.
229  *
230  * Gets a string representing the given flow return.
231  *
232  * Returns: a static string with the name of the flow return.
233  */
234 const gchar *
gst_flow_get_name(GstFlowReturn ret)235 gst_flow_get_name (GstFlowReturn ret)
236 {
237   gint i;
238 
239   ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
240 
241   for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
242     if (ret == flow_quarks[i].ret)
243       return flow_quarks[i].name;
244   }
245   return "unknown";
246 }
247 
248 /**
249  * gst_flow_to_quark:
250  * @ret: a #GstFlowReturn to get the quark of.
251  *
252  * Get the unique quark for the given GstFlowReturn.
253  *
254  * Returns: the quark associated with the flow return or 0 if an
255  * invalid return was specified.
256  */
257 GQuark
gst_flow_to_quark(GstFlowReturn ret)258 gst_flow_to_quark (GstFlowReturn ret)
259 {
260   gint i;
261 
262   ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
263 
264   for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
265     if (ret == flow_quarks[i].ret)
266       return flow_quarks[i].quark;
267   }
268   return 0;
269 }
270 
271 /**
272  * gst_pad_link_get_name:
273  * @ret: a #GstPadLinkReturn to get the name of.
274  *
275  * Gets a string representing the given pad-link return.
276  *
277  * Returns: a static string with the name of the pad-link return.
278  *
279  * Since: 1.4
280  */
281 const gchar *
gst_pad_link_get_name(GstPadLinkReturn ret)282 gst_pad_link_get_name (GstPadLinkReturn ret)
283 {
284   switch (ret) {
285     case GST_PAD_LINK_OK:
286       return "ok";
287     case GST_PAD_LINK_WRONG_HIERARCHY:
288       return "wrong hierarchy";
289     case GST_PAD_LINK_WAS_LINKED:
290       return "was linked";
291     case GST_PAD_LINK_WRONG_DIRECTION:
292       return "wrong direction";
293     case GST_PAD_LINK_NOFORMAT:
294       return "no common format";
295     case GST_PAD_LINK_NOSCHED:
296       return "incompatible scheduling";
297     case GST_PAD_LINK_REFUSED:
298       return "refused";
299   }
300   g_return_val_if_reached ("unknown");
301 }
302 
303 #define _do_init \
304 { \
305   gint i; \
306   \
307   buffer_quark = g_quark_from_static_string ("buffer"); \
308   buffer_list_quark = g_quark_from_static_string ("bufferlist"); \
309   event_quark = g_quark_from_static_string ("event"); \
310   \
311   for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {			\
312     flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); \
313   } \
314   \
315   GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", \
316       GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \
317 }
318 
319 #define gst_pad_parent_class parent_class
320 G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT,
321     G_ADD_PRIVATE (GstPad) _do_init);
322 
323 static void
gst_pad_class_init(GstPadClass * klass)324 gst_pad_class_init (GstPadClass * klass)
325 {
326   GObjectClass *gobject_class;
327   GstObjectClass *gstobject_class;
328 
329   gobject_class = G_OBJECT_CLASS (klass);
330   gstobject_class = GST_OBJECT_CLASS (klass);
331 
332   gobject_class->dispose = gst_pad_dispose;
333   gobject_class->finalize = gst_pad_finalize;
334   gobject_class->set_property = gst_pad_set_property;
335   gobject_class->get_property = gst_pad_get_property;
336 
337   /**
338    * GstPad::linked:
339    * @pad: the pad that emitted the signal
340    * @peer: the peer pad that has been connected
341    *
342    * Signals that a pad has been linked to the peer pad.
343    */
344   gst_pad_signals[PAD_LINKED] =
345       g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
346       G_STRUCT_OFFSET (GstPadClass, linked), NULL, NULL,
347       NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
348   /**
349    * GstPad::unlinked:
350    * @pad: the pad that emitted the signal
351    * @peer: the peer pad that has been disconnected
352    *
353    * Signals that a pad has been unlinked from the peer pad.
354    */
355   gst_pad_signals[PAD_UNLINKED] =
356       g_signal_new ("unlinked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
357       G_STRUCT_OFFSET (GstPadClass, unlinked), NULL, NULL,
358       NULL, G_TYPE_NONE, 1, GST_TYPE_PAD);
359 
360   pspec_caps = g_param_spec_boxed ("caps", "Caps",
361       "The capabilities of the pad", GST_TYPE_CAPS,
362       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
363   g_object_class_install_property (gobject_class, PAD_PROP_CAPS, pspec_caps);
364 
365   g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION,
366       g_param_spec_enum ("direction", "Direction", "The direction of the pad",
367           GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
368           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
369 
370   /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */
371   g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE,
372       g_param_spec_object ("template", "Template",
373           "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE,
374           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
375 
376   /**
377    * GstPad:offset:
378    *
379    * The offset that will be applied to the running time of the pad.
380    *
381    * Since: 1.6
382    */
383   g_object_class_install_property (gobject_class, PAD_PROP_OFFSET,
384       g_param_spec_int64 ("offset", "Offset",
385           "The running time offset of the pad", 0, G_MAXINT64, 0,
386           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
387 
388   gstobject_class->path_string_separator = ".";
389 
390   /* Register common function pointer descriptions */
391   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_activate_default);
392   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_event_default);
393   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_query_default);
394   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_iterate_internal_links_default);
395   GST_DEBUG_REGISTER_FUNCPTR (gst_pad_chain_list_default);
396 }
397 
398 static void
gst_pad_init(GstPad * pad)399 gst_pad_init (GstPad * pad)
400 {
401   pad->priv = gst_pad_get_instance_private (pad);
402 
403   GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN;
404 
405   GST_PAD_ACTIVATEFUNC (pad) = gst_pad_activate_default;
406   GST_PAD_EVENTFUNC (pad) = gst_pad_event_default;
407   GST_PAD_QUERYFUNC (pad) = gst_pad_query_default;
408   GST_PAD_ITERINTLINKFUNC (pad) = gst_pad_iterate_internal_links_default;
409   GST_PAD_CHAINLISTFUNC (pad) = gst_pad_chain_list_default;
410 
411   GST_PAD_SET_FLUSHING (pad);
412 
413   g_rec_mutex_init (&pad->stream_rec_lock);
414 
415   g_cond_init (&pad->block_cond);
416 
417   g_hook_list_init (&pad->probes, sizeof (GstProbe));
418 
419   pad->priv->events = g_array_sized_new (FALSE, TRUE, sizeof (PadEvent), 16);
420   pad->priv->events_cookie = 0;
421   pad->priv->last_cookie = -1;
422   g_cond_init (&pad->priv->activation_cond);
423 
424   pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
425 }
426 
427 /* called when setting the pad inactive. It removes all sticky events from
428  * the pad. must be called with object lock */
429 static void
remove_events(GstPad * pad)430 remove_events (GstPad * pad)
431 {
432   guint i, len;
433   GArray *events;
434   gboolean notify = FALSE;
435 
436   events = pad->priv->events;
437 
438   len = events->len;
439   for (i = 0; i < len; i++) {
440     PadEvent *ev = &g_array_index (events, PadEvent, i);
441     GstEvent *event = ev->event;
442 
443     ev->event = NULL;
444 
445     if (event && GST_EVENT_TYPE (event) == GST_EVENT_CAPS)
446       notify = TRUE;
447 
448     gst_event_unref (event);
449   }
450 
451   GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
452   g_array_set_size (events, 0);
453   pad->priv->events_cookie++;
454 
455   if (notify) {
456     GST_OBJECT_UNLOCK (pad);
457 
458     GST_DEBUG_OBJECT (pad, "notify caps");
459     g_object_notify_by_pspec ((GObject *) pad, pspec_caps);
460 
461     GST_OBJECT_LOCK (pad);
462   }
463 }
464 
465 /* should be called with object lock */
466 static PadEvent *
find_event_by_type(GstPad * pad,GstEventType type,guint idx)467 find_event_by_type (GstPad * pad, GstEventType type, guint idx)
468 {
469   guint i, len;
470   GArray *events;
471   PadEvent *ev;
472 
473   events = pad->priv->events;
474   len = events->len;
475 
476   for (i = 0; i < len; i++) {
477     ev = &g_array_index (events, PadEvent, i);
478     if (ev->event == NULL)
479       continue;
480 
481     if (GST_EVENT_TYPE (ev->event) == type) {
482       if (idx == 0)
483         goto found;
484       idx--;
485     } else if (GST_EVENT_TYPE (ev->event) > type) {
486       break;
487     }
488   }
489   ev = NULL;
490 found:
491   return ev;
492 }
493 
494 /* should be called with OBJECT lock */
495 static PadEvent *
find_event(GstPad * pad,GstEvent * event)496 find_event (GstPad * pad, GstEvent * event)
497 {
498   guint i, len;
499   GArray *events;
500   PadEvent *ev;
501 
502   events = pad->priv->events;
503   len = events->len;
504 
505   for (i = 0; i < len; i++) {
506     ev = &g_array_index (events, PadEvent, i);
507     if (event == ev->event)
508       goto found;
509     else if (GST_EVENT_TYPE (ev->event) > GST_EVENT_TYPE (event))
510       break;
511   }
512   ev = NULL;
513 found:
514   return ev;
515 }
516 
517 /* should be called with OBJECT lock */
518 static void
remove_event_by_type(GstPad * pad,GstEventType type)519 remove_event_by_type (GstPad * pad, GstEventType type)
520 {
521   guint i, len;
522   GArray *events;
523   PadEvent *ev;
524 
525   events = pad->priv->events;
526   len = events->len;
527 
528   i = 0;
529   while (i < len) {
530     ev = &g_array_index (events, PadEvent, i);
531     if (ev->event == NULL)
532       goto next;
533 
534     if (GST_EVENT_TYPE (ev->event) > type)
535       break;
536     else if (GST_EVENT_TYPE (ev->event) != type)
537       goto next;
538 
539     gst_event_unref (ev->event);
540     g_array_remove_index (events, i);
541     len--;
542     pad->priv->events_cookie++;
543     continue;
544 
545   next:
546     i++;
547   }
548 }
549 
550 /* check all events on srcpad against those on sinkpad. All events that are not
551  * on sinkpad are marked as received=%FALSE and the PENDING_EVENTS is set on the
552  * srcpad so that the events will be sent next time */
553 /* should be called with srcpad and sinkpad LOCKS */
554 static void
schedule_events(GstPad * srcpad,GstPad * sinkpad)555 schedule_events (GstPad * srcpad, GstPad * sinkpad)
556 {
557   gint i, len;
558   GArray *events;
559   PadEvent *ev;
560   gboolean pending = FALSE;
561 
562   events = srcpad->priv->events;
563   len = events->len;
564 
565   for (i = 0; i < len; i++) {
566     ev = &g_array_index (events, PadEvent, i);
567     if (ev->event == NULL)
568       continue;
569 
570     if (sinkpad == NULL || !find_event (sinkpad, ev->event)) {
571       ev->received = FALSE;
572       pending = TRUE;
573     }
574   }
575   if (pending)
576     GST_OBJECT_FLAG_SET (srcpad, GST_PAD_FLAG_PENDING_EVENTS);
577 }
578 
579 typedef gboolean (*PadEventFunction) (GstPad * pad, PadEvent * ev,
580     gpointer user_data);
581 
582 /* should be called with pad LOCK */
583 static void
events_foreach(GstPad * pad,PadEventFunction func,gpointer user_data)584 events_foreach (GstPad * pad, PadEventFunction func, gpointer user_data)
585 {
586   guint i, len;
587   GArray *events;
588   gboolean ret;
589   guint cookie;
590 
591   events = pad->priv->events;
592 
593 restart:
594   cookie = pad->priv->events_cookie;
595   i = 0;
596   len = events->len;
597   while (i < len) {
598     PadEvent *ev, ev_ret;
599 
600     ev = &g_array_index (events, PadEvent, i);
601     if (G_UNLIKELY (ev->event == NULL))
602       goto next;
603 
604     /* take additional ref, func might release the lock */
605     ev_ret.event = gst_event_ref (ev->event);
606     ev_ret.received = ev->received;
607 
608     ret = func (pad, &ev_ret, user_data);
609 
610     /* recheck the cookie, lock might have been released and the list could have
611      * changed */
612     if (G_UNLIKELY (cookie != pad->priv->events_cookie)) {
613       if (G_LIKELY (ev_ret.event))
614         gst_event_unref (ev_ret.event);
615       goto restart;
616     }
617 
618     /* store the received state */
619     ev->received = ev_ret.received;
620 
621     /* if the event changed, we need to do something */
622     if (G_UNLIKELY (ev->event != ev_ret.event)) {
623       if (G_UNLIKELY (ev_ret.event == NULL)) {
624         /* function unreffed and set the event to NULL, remove it */
625         gst_event_unref (ev->event);
626         g_array_remove_index (events, i);
627         len--;
628         cookie = ++pad->priv->events_cookie;
629         continue;
630       } else {
631         /* function gave a new event for us */
632         gst_event_take (&ev->event, ev_ret.event);
633       }
634     } else {
635       /* just unref, nothing changed */
636       gst_event_unref (ev_ret.event);
637     }
638     if (!ret)
639       break;
640   next:
641     i++;
642   }
643 }
644 
645 /* should be called with LOCK */
646 static GstEvent *
_apply_pad_offset(GstPad * pad,GstEvent * event,gboolean upstream,gint64 pad_offset)647 _apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream,
648     gint64 pad_offset)
649 {
650   gint64 offset;
651 
652   GST_DEBUG_OBJECT (pad, "apply pad offset %" GST_STIME_FORMAT,
653       GST_STIME_ARGS (pad_offset));
654 
655   if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
656     GstSegment segment;
657 
658     g_assert (!upstream);
659 
660     /* copy segment values */
661     gst_event_copy_segment (event, &segment);
662     gst_event_unref (event);
663 
664     gst_segment_offset_running_time (&segment, segment.format, pad_offset);
665     event = gst_event_new_segment (&segment);
666   }
667 
668   event = gst_event_make_writable (event);
669   offset = gst_event_get_running_time_offset (event);
670   if (upstream)
671     offset -= pad_offset;
672   else
673     offset += pad_offset;
674   gst_event_set_running_time_offset (event, offset);
675 
676   return event;
677 }
678 
679 static inline GstEvent *
apply_pad_offset(GstPad * pad,GstEvent * event,gboolean upstream)680 apply_pad_offset (GstPad * pad, GstEvent * event, gboolean upstream)
681 {
682   if (G_UNLIKELY (pad->offset != 0))
683     return _apply_pad_offset (pad, event, upstream, pad->offset);
684   return event;
685 }
686 
687 /* should be called with the OBJECT_LOCK */
688 static GstCaps *
get_pad_caps(GstPad * pad)689 get_pad_caps (GstPad * pad)
690 {
691   GstCaps *caps = NULL;
692   PadEvent *ev;
693 
694   ev = find_event_by_type (pad, GST_EVENT_CAPS, 0);
695   if (ev && ev->event)
696     gst_event_parse_caps (ev->event, &caps);
697 
698   return caps;
699 }
700 
701 static void
gst_pad_dispose(GObject * object)702 gst_pad_dispose (GObject * object)
703 {
704   GstPad *pad = GST_PAD_CAST (object);
705   GstPad *peer;
706 
707   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pad, "%p dispose", pad);
708 
709   /* unlink the peer pad */
710   if ((peer = gst_pad_get_peer (pad))) {
711     /* window for MT unsafeness, someone else could unlink here
712      * and then we call unlink with wrong pads. The unlink
713      * function would catch this and safely return failed. */
714     if (GST_PAD_IS_SRC (pad))
715       gst_pad_unlink (pad, peer);
716     else
717       gst_pad_unlink (peer, pad);
718 
719     gst_object_unref (peer);
720   }
721 
722   gst_pad_set_pad_template (pad, NULL);
723 
724   GST_OBJECT_LOCK (pad);
725   remove_events (pad);
726   g_hook_list_clear (&pad->probes);
727   GST_OBJECT_UNLOCK (pad);
728 
729   G_OBJECT_CLASS (parent_class)->dispose (object);
730 }
731 
732 static void
gst_pad_finalize(GObject * object)733 gst_pad_finalize (GObject * object)
734 {
735   GstPad *pad = GST_PAD_CAST (object);
736   GstTask *task;
737 
738   /* in case the task is still around, clean it up */
739   if ((task = GST_PAD_TASK (pad))) {
740     gst_task_join (task);
741     GST_PAD_TASK (pad) = NULL;
742     gst_object_unref (task);
743   }
744 
745   if (pad->activatenotify)
746     pad->activatenotify (pad->activatedata);
747   if (pad->activatemodenotify)
748     pad->activatemodenotify (pad->activatemodedata);
749   if (pad->linknotify)
750     pad->linknotify (pad->linkdata);
751   if (pad->unlinknotify)
752     pad->unlinknotify (pad->unlinkdata);
753   if (pad->chainnotify)
754     pad->chainnotify (pad->chaindata);
755   if (pad->chainlistnotify)
756     pad->chainlistnotify (pad->chainlistdata);
757   if (pad->getrangenotify)
758     pad->getrangenotify (pad->getrangedata);
759   if (pad->eventnotify)
760     pad->eventnotify (pad->eventdata);
761   if (pad->querynotify)
762     pad->querynotify (pad->querydata);
763   if (pad->iterintlinknotify)
764     pad->iterintlinknotify (pad->iterintlinkdata);
765 
766   g_rec_mutex_clear (&pad->stream_rec_lock);
767   g_cond_clear (&pad->block_cond);
768   g_cond_clear (&pad->priv->activation_cond);
769   g_array_free (pad->priv->events, TRUE);
770 
771   G_OBJECT_CLASS (parent_class)->finalize (object);
772 }
773 
774 static void
gst_pad_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)775 gst_pad_set_property (GObject * object, guint prop_id,
776     const GValue * value, GParamSpec * pspec)
777 {
778   g_return_if_fail (GST_IS_PAD (object));
779 
780   switch (prop_id) {
781     case PAD_PROP_DIRECTION:
782       GST_PAD_DIRECTION (object) = (GstPadDirection) g_value_get_enum (value);
783       break;
784     case PAD_PROP_TEMPLATE:
785       gst_pad_set_pad_template (GST_PAD_CAST (object),
786           (GstPadTemplate *) g_value_get_object (value));
787       break;
788     case PAD_PROP_OFFSET:
789       gst_pad_set_offset (GST_PAD_CAST (object), g_value_get_int64 (value));
790       break;
791     default:
792       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
793       break;
794   }
795 }
796 
797 static void
gst_pad_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)798 gst_pad_get_property (GObject * object, guint prop_id,
799     GValue * value, GParamSpec * pspec)
800 {
801   g_return_if_fail (GST_IS_PAD (object));
802 
803   switch (prop_id) {
804     case PAD_PROP_CAPS:
805       GST_OBJECT_LOCK (object);
806       g_value_set_boxed (value, get_pad_caps (GST_PAD_CAST (object)));
807       GST_OBJECT_UNLOCK (object);
808       break;
809     case PAD_PROP_DIRECTION:
810       g_value_set_enum (value, GST_PAD_DIRECTION (object));
811       break;
812     case PAD_PROP_TEMPLATE:
813       g_value_set_object (value, GST_PAD_PAD_TEMPLATE (object));
814       break;
815     case PAD_PROP_OFFSET:
816       g_value_set_int64 (value, gst_pad_get_offset (GST_PAD_CAST (object)));
817       break;
818     default:
819       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
820       break;
821   }
822 }
823 
824 /**
825  * gst_pad_new:
826  * @name: (allow-none): the name of the new pad.
827  * @direction: the #GstPadDirection of the pad.
828  *
829  * Creates a new pad with the given name in the given direction.
830  * If name is %NULL, a guaranteed unique name (across all pads)
831  * will be assigned.
832  * This function makes a copy of the name so you can safely free the name.
833  *
834  * Returns: (transfer floating): a new #GstPad.
835  *
836  * MT safe.
837  */
838 GstPad *
gst_pad_new(const gchar * name,GstPadDirection direction)839 gst_pad_new (const gchar * name, GstPadDirection direction)
840 {
841   return g_object_new (GST_TYPE_PAD,
842       "name", name, "direction", direction, NULL);
843 }
844 
845 /**
846  * gst_pad_new_from_template:
847  * @templ: the pad template to use
848  * @name: (allow-none): the name of the pad
849  *
850  * Creates a new pad with the given name from the given template.
851  * If name is %NULL, a guaranteed unique name (across all pads)
852  * will be assigned.
853  * This function makes a copy of the name so you can safely free the name.
854  *
855  * Returns: (transfer floating): a new #GstPad.
856  */
857 GstPad *
gst_pad_new_from_template(GstPadTemplate * templ,const gchar * name)858 gst_pad_new_from_template (GstPadTemplate * templ, const gchar * name)
859 {
860   GType pad_type =
861       GST_PAD_TEMPLATE_GTYPE (templ) ==
862       G_TYPE_NONE ? GST_TYPE_PAD : GST_PAD_TEMPLATE_GTYPE (templ);
863 
864   g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL);
865 
866   return g_object_new (pad_type,
867       "name", name, "direction", templ->direction, "template", templ, NULL);
868 }
869 
870 /**
871  * gst_pad_new_from_static_template:
872  * @templ: the #GstStaticPadTemplate to use
873  * @name: the name of the pad
874  *
875  * Creates a new pad with the given name from the given static template.
876  * If name is %NULL, a guaranteed unique name (across all pads)
877  * will be assigned.
878  * This function makes a copy of the name so you can safely free the name.
879  *
880  * Returns: (transfer floating): a new #GstPad.
881  */
882 GstPad *
gst_pad_new_from_static_template(GstStaticPadTemplate * templ,const gchar * name)883 gst_pad_new_from_static_template (GstStaticPadTemplate * templ,
884     const gchar * name)
885 {
886   GstPad *pad;
887   GstPadTemplate *template;
888 
889   template = gst_static_pad_template_get (templ);
890   pad = gst_pad_new_from_template (template, name);
891   gst_object_unref (template);
892   return pad;
893 }
894 
895 #define ACQUIRE_PARENT(pad, parent, label)                      \
896   G_STMT_START {                                                \
897     if (G_LIKELY ((parent = GST_OBJECT_PARENT (pad))))          \
898       gst_object_ref (parent);                                  \
899     else if (G_LIKELY (GST_PAD_NEEDS_PARENT (pad)))             \
900       goto label;                                               \
901   } G_STMT_END
902 
903 #define RELEASE_PARENT(parent)                                  \
904   G_STMT_START {                                                \
905     if (G_LIKELY (parent))                                      \
906       gst_object_unref (parent);                                \
907   } G_STMT_END
908 
909 /**
910  * gst_pad_get_direction:
911  * @pad: a #GstPad to get the direction of.
912  *
913  * Gets the direction of the pad. The direction of the pad is
914  * decided at construction time so this function does not take
915  * the LOCK.
916  *
917  * Returns: the #GstPadDirection of the pad.
918  *
919  * MT safe.
920  */
921 GstPadDirection
gst_pad_get_direction(GstPad * pad)922 gst_pad_get_direction (GstPad * pad)
923 {
924   GstPadDirection result;
925 
926   /* PAD_UNKNOWN is a little silly but we need some sort of
927    * error return value */
928   g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
929 
930   result = GST_PAD_DIRECTION (pad);
931 
932   return result;
933 }
934 
935 static gboolean
gst_pad_activate_default(GstPad * pad,GstObject * parent)936 gst_pad_activate_default (GstPad * pad, GstObject * parent)
937 {
938   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
939 
940   return activate_mode_internal (pad, parent, GST_PAD_MODE_PUSH, TRUE);
941 }
942 
943 /**
944  * gst_pad_mode_get_name:
945  * @mode: the pad mode
946  *
947  * Return the name of a pad mode, for use in debug messages mostly.
948  *
949  * Returns: short mnemonic for pad mode @mode
950  */
951 const gchar *
gst_pad_mode_get_name(GstPadMode mode)952 gst_pad_mode_get_name (GstPadMode mode)
953 {
954   switch (mode) {
955     case GST_PAD_MODE_NONE:
956       return "none";
957     case GST_PAD_MODE_PUSH:
958       return "push";
959     case GST_PAD_MODE_PULL:
960       return "pull";
961     default:
962       break;
963   }
964   return "unknown";
965 }
966 
967 /* Returns TRUE if pad wasn't already in the new_mode */
968 static gboolean
pre_activate(GstPad * pad,GstPadMode new_mode)969 pre_activate (GstPad * pad, GstPadMode new_mode)
970 {
971   switch (new_mode) {
972     case GST_PAD_MODE_NONE:
973       GST_OBJECT_LOCK (pad);
974       while (G_UNLIKELY (pad->priv->in_activation))
975         g_cond_wait (&pad->priv->activation_cond, GST_OBJECT_GET_LOCK (pad));
976       if (new_mode == GST_PAD_MODE (pad)) {
977         GST_WARNING_OBJECT (pad,
978             "Pad is already in the process of being deactivated");
979         GST_OBJECT_UNLOCK (pad);
980         return FALSE;
981       }
982       pad->priv->in_activation = TRUE;
983       GST_DEBUG_OBJECT (pad, "setting PAD_MODE NONE, set flushing");
984       GST_PAD_SET_FLUSHING (pad);
985       pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
986       GST_PAD_MODE (pad) = new_mode;
987       /* unlock blocked pads so element can resume and stop */
988       GST_PAD_BLOCK_BROADCAST (pad);
989       GST_OBJECT_UNLOCK (pad);
990       break;
991     case GST_PAD_MODE_PUSH:
992     case GST_PAD_MODE_PULL:
993       GST_OBJECT_LOCK (pad);
994       while (G_UNLIKELY (pad->priv->in_activation))
995         g_cond_wait (&pad->priv->activation_cond, GST_OBJECT_GET_LOCK (pad));
996       if (new_mode == GST_PAD_MODE (pad)) {
997         GST_WARNING_OBJECT (pad,
998             "Pad is already in the process of being activated");
999         GST_OBJECT_UNLOCK (pad);
1000         return FALSE;
1001       }
1002       pad->priv->in_activation = TRUE;
1003       GST_DEBUG_OBJECT (pad, "setting pad into %s mode, unset flushing",
1004           gst_pad_mode_get_name (new_mode));
1005       GST_PAD_UNSET_FLUSHING (pad);
1006       pad->ABI.abi.last_flowret = GST_FLOW_OK;
1007       GST_PAD_MODE (pad) = new_mode;
1008       if (GST_PAD_IS_SINK (pad)) {
1009         GstPad *peer;
1010         /* make sure the peer src pad sends us all events */
1011         if ((peer = GST_PAD_PEER (pad))) {
1012           gst_object_ref (peer);
1013           GST_OBJECT_UNLOCK (pad);
1014 
1015           GST_DEBUG_OBJECT (pad, "reschedule events on peer %s:%s",
1016               GST_DEBUG_PAD_NAME (peer));
1017 
1018           GST_OBJECT_LOCK (peer);
1019           schedule_events (peer, NULL);
1020           GST_OBJECT_UNLOCK (peer);
1021 
1022           gst_object_unref (peer);
1023         } else {
1024           GST_OBJECT_UNLOCK (pad);
1025         }
1026       } else {
1027         GST_OBJECT_UNLOCK (pad);
1028       }
1029       break;
1030   }
1031   return TRUE;
1032 }
1033 
1034 static void
post_activate(GstPad * pad,GstPadMode new_mode)1035 post_activate (GstPad * pad, GstPadMode new_mode)
1036 {
1037   switch (new_mode) {
1038     case GST_PAD_MODE_NONE:
1039       GST_OBJECT_LOCK (pad);
1040       pad->priv->in_activation = FALSE;
1041       g_cond_broadcast (&pad->priv->activation_cond);
1042       GST_OBJECT_UNLOCK (pad);
1043 
1044       /* ensures that streaming stops */
1045       GST_PAD_STREAM_LOCK (pad);
1046       GST_DEBUG_OBJECT (pad, "stopped streaming");
1047       GST_OBJECT_LOCK (pad);
1048       remove_events (pad);
1049       GST_OBJECT_UNLOCK (pad);
1050       GST_PAD_STREAM_UNLOCK (pad);
1051       break;
1052     case GST_PAD_MODE_PUSH:
1053     case GST_PAD_MODE_PULL:
1054       GST_OBJECT_LOCK (pad);
1055       pad->priv->in_activation = FALSE;
1056       g_cond_broadcast (&pad->priv->activation_cond);
1057       GST_OBJECT_UNLOCK (pad);
1058       /* NOP */
1059       break;
1060   }
1061 }
1062 
1063 /**
1064  * gst_pad_set_active:
1065  * @pad: the #GstPad to activate or deactivate.
1066  * @active: whether or not the pad should be active.
1067  *
1068  * Activates or deactivates the given pad.
1069  * Normally called from within core state change functions.
1070  *
1071  * If @active, makes sure the pad is active. If it is already active, either in
1072  * push or pull mode, just return. Otherwise dispatches to the pad's activate
1073  * function to perform the actual activation.
1074  *
1075  * If not @active, calls gst_pad_activate_mode() with the pad's current mode
1076  * and a %FALSE argument.
1077  *
1078  * Returns: %TRUE if the operation was successful.
1079  *
1080  * MT safe.
1081  */
1082 gboolean
gst_pad_set_active(GstPad * pad,gboolean active)1083 gst_pad_set_active (GstPad * pad, gboolean active)
1084 {
1085   GstObject *parent;
1086   GstPadMode old;
1087   gboolean ret = FALSE;
1088 
1089   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1090 
1091   GST_OBJECT_LOCK (pad);
1092   old = GST_PAD_MODE (pad);
1093   ACQUIRE_PARENT (pad, parent, no_parent);
1094   GST_OBJECT_UNLOCK (pad);
1095 
1096   if (active) {
1097     if (old == GST_PAD_MODE_NONE) {
1098       GST_DEBUG_OBJECT (pad, "activating pad from none");
1099       ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad, parent);
1100       if (ret)
1101         pad->ABI.abi.last_flowret = GST_FLOW_OK;
1102     } else {
1103       GST_DEBUG_OBJECT (pad, "pad was active in %s mode",
1104           gst_pad_mode_get_name (old));
1105       ret = TRUE;
1106     }
1107   } else {
1108     if (old == GST_PAD_MODE_NONE) {
1109       GST_DEBUG_OBJECT (pad, "pad was inactive");
1110       ret = TRUE;
1111     } else {
1112       GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode",
1113           gst_pad_mode_get_name (old));
1114       ret = activate_mode_internal (pad, parent, old, FALSE);
1115       if (ret)
1116         pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
1117     }
1118   }
1119 
1120   RELEASE_PARENT (parent);
1121 
1122   if (G_UNLIKELY (!ret))
1123     goto failed;
1124 
1125   return ret;
1126 
1127   /* ERRORS */
1128 no_parent:
1129   {
1130     GST_DEBUG_OBJECT (pad, "no parent");
1131     GST_OBJECT_UNLOCK (pad);
1132     return FALSE;
1133   }
1134 failed:
1135   {
1136     GST_OBJECT_LOCK (pad);
1137     if (!active) {
1138       g_critical ("Failed to deactivate pad %s:%s, very bad",
1139           GST_DEBUG_PAD_NAME (pad));
1140     } else {
1141       GST_WARNING_OBJECT (pad, "Failed to activate pad");
1142     }
1143     GST_OBJECT_UNLOCK (pad);
1144     return FALSE;
1145   }
1146 }
1147 
1148 static gboolean
activate_mode_internal(GstPad * pad,GstObject * parent,GstPadMode mode,gboolean active)1149 activate_mode_internal (GstPad * pad, GstObject * parent, GstPadMode mode,
1150     gboolean active)
1151 {
1152   gboolean res = FALSE;
1153   GstPadMode old, new;
1154   GstPadDirection dir;
1155   GstPad *peer;
1156 
1157   GST_OBJECT_LOCK (pad);
1158   old = GST_PAD_MODE (pad);
1159   dir = GST_PAD_DIRECTION (pad);
1160   GST_OBJECT_UNLOCK (pad);
1161 
1162   new = active ? mode : GST_PAD_MODE_NONE;
1163 
1164   if (old == new)
1165     goto was_ok;
1166 
1167   if (active && old != mode && old != GST_PAD_MODE_NONE) {
1168     /* pad was activate in the wrong direction, deactivate it
1169      * and reactivate it in the requested mode */
1170     GST_DEBUG_OBJECT (pad, "deactivating pad from %s mode",
1171         gst_pad_mode_get_name (old));
1172 
1173     if (G_UNLIKELY (!activate_mode_internal (pad, parent, old, FALSE)))
1174       goto deactivate_failed;
1175     old = GST_PAD_MODE_NONE;
1176   }
1177 
1178   switch (mode) {
1179     case GST_PAD_MODE_PULL:
1180     {
1181       if (dir == GST_PAD_SINK) {
1182         if ((peer = gst_pad_get_peer (pad))) {
1183           GST_DEBUG_OBJECT (pad, "calling peer");
1184           if (G_UNLIKELY (!gst_pad_activate_mode (peer, mode, active)))
1185             goto peer_failed;
1186           gst_object_unref (peer);
1187         } else {
1188           /* there is no peer, this is only fatal when we activate. When we
1189            * deactivate, we must assume the application has unlinked the peer and
1190            * will deactivate it eventually. */
1191           if (active)
1192             goto not_linked;
1193           else
1194             GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
1195         }
1196       } else {
1197         if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
1198           goto failure;         /* Can't activate pull on a src without a
1199                                    getrange function */
1200       }
1201       break;
1202     }
1203     default:
1204       break;
1205   }
1206 
1207   /* Mark pad as needing reconfiguration */
1208   if (active)
1209     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
1210 
1211   /* pre_activate returns TRUE if we weren't already in the process of
1212    * switching to the 'new' mode */
1213   if (pre_activate (pad, new)) {
1214 
1215     if (GST_PAD_ACTIVATEMODEFUNC (pad)) {
1216       if (G_UNLIKELY (!GST_PAD_ACTIVATEMODEFUNC (pad) (pad, parent, mode,
1217                   active)))
1218         goto failure;
1219     } else {
1220       /* can happen for sinks of passthrough elements */
1221     }
1222 
1223     post_activate (pad, new);
1224   }
1225 
1226   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in %s mode",
1227       active ? "activated" : "deactivated", gst_pad_mode_get_name (mode));
1228 
1229 exit_success:
1230   res = TRUE;
1231 
1232   /* Clear sticky flags on deactivation */
1233   if (!active) {
1234     GST_OBJECT_LOCK (pad);
1235     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
1236     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
1237     GST_OBJECT_UNLOCK (pad);
1238   }
1239 
1240 exit:
1241   return res;
1242 
1243 was_ok:
1244   {
1245     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in %s mode",
1246         active ? "activated" : "deactivated", gst_pad_mode_get_name (mode));
1247     goto exit_success;
1248   }
1249 deactivate_failed:
1250   {
1251     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
1252         "failed to %s in switch to %s mode from %s mode",
1253         (active ? "activate" : "deactivate"), gst_pad_mode_get_name (mode),
1254         gst_pad_mode_get_name (old));
1255     goto exit;
1256   }
1257 peer_failed:
1258   {
1259     GST_OBJECT_LOCK (peer);
1260     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
1261         "activate_mode on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer));
1262     GST_OBJECT_UNLOCK (peer);
1263     gst_object_unref (peer);
1264     goto exit;
1265   }
1266 not_linked:
1267   {
1268     GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "can't activate unlinked sink "
1269         "pad in pull mode");
1270     goto exit;
1271   }
1272 failure:
1273   {
1274     GST_OBJECT_LOCK (pad);
1275     GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in %s mode",
1276         active ? "activate" : "deactivate", gst_pad_mode_get_name (mode));
1277     GST_PAD_SET_FLUSHING (pad);
1278     GST_PAD_MODE (pad) = old;
1279     pad->priv->in_activation = FALSE;
1280     g_cond_broadcast (&pad->priv->activation_cond);
1281     GST_OBJECT_UNLOCK (pad);
1282     goto exit;
1283   }
1284 }
1285 
1286 /**
1287  * gst_pad_activate_mode:
1288  * @pad: the #GstPad to activate or deactivate.
1289  * @mode: the requested activation mode
1290  * @active: whether or not the pad should be active.
1291  *
1292  * Activates or deactivates the given pad in @mode via dispatching to the
1293  * pad's activatemodefunc. For use from within pad activation functions only.
1294  *
1295  * If you don't know what this is, you probably don't want to call it.
1296  *
1297  * Returns: %TRUE if the operation was successful.
1298  *
1299  * MT safe.
1300  */
1301 gboolean
gst_pad_activate_mode(GstPad * pad,GstPadMode mode,gboolean active)1302 gst_pad_activate_mode (GstPad * pad, GstPadMode mode, gboolean active)
1303 {
1304   GstObject *parent;
1305   gboolean res;
1306   GstPadMode old, new;
1307 
1308   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1309 
1310   GST_OBJECT_LOCK (pad);
1311 
1312   old = GST_PAD_MODE (pad);
1313   new = active ? mode : GST_PAD_MODE_NONE;
1314   if (old == new)
1315     goto was_ok;
1316 
1317   ACQUIRE_PARENT (pad, parent, no_parent);
1318 
1319   GST_OBJECT_UNLOCK (pad);
1320 
1321   res = activate_mode_internal (pad, parent, mode, active);
1322 
1323   RELEASE_PARENT (parent);
1324 
1325   return res;
1326 
1327 was_ok:
1328   {
1329     GST_OBJECT_UNLOCK (pad);
1330     GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in %s mode",
1331         active ? "activated" : "deactivated", gst_pad_mode_get_name (mode));
1332     return TRUE;
1333   }
1334 no_parent:
1335   {
1336     GST_WARNING_OBJECT (pad, "no parent");
1337     GST_OBJECT_UNLOCK (pad);
1338     return FALSE;
1339   }
1340 }
1341 
1342 /**
1343  * gst_pad_is_active:
1344  * @pad: the #GstPad to query
1345  *
1346  * Query if a pad is active
1347  *
1348  * Returns: %TRUE if the pad is active.
1349  *
1350  * MT safe.
1351  */
1352 gboolean
gst_pad_is_active(GstPad * pad)1353 gst_pad_is_active (GstPad * pad)
1354 {
1355   gboolean result = FALSE;
1356 
1357   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1358 
1359   GST_OBJECT_LOCK (pad);
1360   result = GST_PAD_IS_ACTIVE (pad);
1361   GST_OBJECT_UNLOCK (pad);
1362 
1363   return result;
1364 }
1365 
1366 static void
cleanup_hook(GstPad * pad,GHook * hook)1367 cleanup_hook (GstPad * pad, GHook * hook)
1368 {
1369   GstPadProbeType type;
1370 
1371   GST_DEBUG_OBJECT (pad,
1372       "cleaning up hook %lu with flags %08x", hook->hook_id, hook->flags);
1373 
1374   if (!G_HOOK_IS_VALID (hook)) {
1375     /* We've already destroyed this hook */
1376     return;
1377   }
1378 
1379   type = (hook->flags) >> G_HOOK_FLAG_USER_SHIFT;
1380 
1381   if (type & GST_PAD_PROBE_TYPE_BLOCKING) {
1382     /* unblock when we remove the last blocking probe */
1383     pad->num_blocked--;
1384     GST_DEBUG_OBJECT (pad, "remove blocking probe, now %d left",
1385         pad->num_blocked);
1386 
1387     /* Might have new probes now that want to be called */
1388     GST_PAD_BLOCK_BROADCAST (pad);
1389 
1390     if (pad->num_blocked == 0) {
1391       GST_DEBUG_OBJECT (pad, "last blocking probe removed, unblocking");
1392       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKED);
1393     }
1394   }
1395   g_hook_destroy_link (&pad->probes, hook);
1396   pad->num_probes--;
1397 }
1398 
1399 /**
1400  * gst_pad_add_probe:
1401  * @pad: the #GstPad to add the probe to
1402  * @mask: the probe mask
1403  * @callback: #GstPadProbeCallback that will be called with notifications of
1404  *           the pad state
1405  * @user_data: (closure): user data passed to the callback
1406  * @destroy_data: #GDestroyNotify for user_data
1407  *
1408  * Be notified of different states of pads. The provided callback is called for
1409  * every state that matches @mask.
1410  *
1411  * Probes are called in groups: First GST_PAD_PROBE_TYPE_BLOCK probes are
1412  * called, then others, then finally GST_PAD_PROBE_TYPE_IDLE. The only
1413  * exception here are GST_PAD_PROBE_TYPE_IDLE probes that are called
1414  * immediately if the pad is already idle while calling gst_pad_add_probe().
1415  * In each of the groups, probes are called in the order in which they were
1416  * added.
1417  *
1418  * Returns: an id or 0 if no probe is pending. The id can be used to remove the
1419  * probe with gst_pad_remove_probe(). When using GST_PAD_PROBE_TYPE_IDLE it can
1420  * happen that the probe can be run immediately and if the probe returns
1421  * GST_PAD_PROBE_REMOVE this functions returns 0.
1422  *
1423  * MT safe.
1424  */
1425 gulong
gst_pad_add_probe(GstPad * pad,GstPadProbeType mask,GstPadProbeCallback callback,gpointer user_data,GDestroyNotify destroy_data)1426 gst_pad_add_probe (GstPad * pad, GstPadProbeType mask,
1427     GstPadProbeCallback callback, gpointer user_data,
1428     GDestroyNotify destroy_data)
1429 {
1430   GHook *hook;
1431   gulong res;
1432 
1433   g_return_val_if_fail (GST_IS_PAD (pad), 0);
1434   g_return_val_if_fail (mask != 0, 0);
1435 
1436   GST_OBJECT_LOCK (pad);
1437 
1438   /* make a new probe */
1439   hook = g_hook_alloc (&pad->probes);
1440 
1441   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "adding probe for mask 0x%08x",
1442       mask);
1443 
1444   /* when no constraints are given for the types, assume all types are
1445    * acceptable */
1446   if ((mask & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH) == 0)
1447     mask |= GST_PAD_PROBE_TYPE_ALL_BOTH;
1448   if ((mask & GST_PAD_PROBE_TYPE_SCHEDULING) == 0)
1449     mask |= GST_PAD_PROBE_TYPE_SCHEDULING;
1450 
1451   /* store our flags and other fields */
1452   hook->flags |= (mask << G_HOOK_FLAG_USER_SHIFT);
1453   hook->func = callback;
1454   hook->data = user_data;
1455   hook->destroy = destroy_data;
1456 
1457   /* add the probe */
1458   g_hook_append (&pad->probes, hook);
1459   pad->num_probes++;
1460   /* incremenent cookie so that the new hook gets called */
1461   pad->priv->probe_list_cookie++;
1462 
1463   /* get the id of the hook, we return this and it can be used to remove the
1464    * probe later */
1465   res = hook->hook_id;
1466 
1467   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got probe id %lu", res);
1468 
1469   if (mask & GST_PAD_PROBE_TYPE_BLOCKING) {
1470     /* we have a block probe */
1471     pad->num_blocked++;
1472     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKED);
1473     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "added blocking probe, "
1474         "now %d blocking probes", pad->num_blocked);
1475 
1476     /* Might have new probes now that want to be called */
1477     GST_PAD_BLOCK_BROADCAST (pad);
1478   }
1479 
1480   /* call the callback if we need to be called for idle callbacks */
1481   if ((mask & GST_PAD_PROBE_TYPE_IDLE) && (callback != NULL)) {
1482     if (pad->priv->using > 0) {
1483       /* the pad is in use, we can't signal the idle callback yet. Since we set the
1484        * flag above, the last thread to leave the push will do the callback. New
1485        * threads going into the push will block. */
1486       GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
1487           "pad is in use, delay idle callback");
1488       GST_OBJECT_UNLOCK (pad);
1489     } else {
1490       GstPadProbeInfo info = { GST_PAD_PROBE_TYPE_IDLE, res, };
1491       GstPadProbeReturn ret;
1492 
1493       /* Keep another ref, the callback could destroy the pad */
1494       gst_object_ref (pad);
1495       pad->priv->idle_running++;
1496 
1497       /* Ref the hook, it could be destroyed by the callback or concurrently */
1498       g_hook_ref (&pad->probes, hook);
1499 
1500       /* the pad is idle now, we can signal the idle callback now */
1501       GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
1502           "pad is idle, trigger idle callback");
1503       GST_OBJECT_UNLOCK (pad);
1504 
1505       ret = callback (pad, &info, user_data);
1506 
1507       GST_OBJECT_LOCK (pad);
1508       switch (ret) {
1509         case GST_PAD_PROBE_REMOVE:
1510           /* remove the probe */
1511           GST_DEBUG_OBJECT (pad, "asked to remove hook");
1512           cleanup_hook (pad, hook);
1513           res = 0;
1514           break;
1515         case GST_PAD_PROBE_DROP:
1516           GST_DEBUG_OBJECT (pad, "asked to drop item");
1517           break;
1518         case GST_PAD_PROBE_PASS:
1519           GST_DEBUG_OBJECT (pad, "asked to pass item");
1520           break;
1521         case GST_PAD_PROBE_OK:
1522           GST_DEBUG_OBJECT (pad, "probe returned OK");
1523           break;
1524         case GST_PAD_PROBE_HANDLED:
1525           GST_DEBUG_OBJECT (pad, "probe handled the data");
1526           break;
1527         default:
1528           GST_DEBUG_OBJECT (pad, "probe returned %d", ret);
1529           break;
1530       }
1531       g_hook_unref (&pad->probes, hook);
1532       pad->priv->idle_running--;
1533       if (pad->priv->idle_running == 0) {
1534         GST_PAD_BLOCK_BROADCAST (pad);
1535       }
1536       GST_OBJECT_UNLOCK (pad);
1537 
1538       gst_object_unref (pad);
1539     }
1540   } else {
1541     GST_OBJECT_UNLOCK (pad);
1542   }
1543   return res;
1544 }
1545 
1546 /**
1547  * gst_pad_remove_probe:
1548  * @pad: the #GstPad with the probe
1549  * @id: the probe id to remove
1550  *
1551  * Remove the probe with @id from @pad.
1552  *
1553  * MT safe.
1554  */
1555 void
gst_pad_remove_probe(GstPad * pad,gulong id)1556 gst_pad_remove_probe (GstPad * pad, gulong id)
1557 {
1558   GHook *hook;
1559 
1560   g_return_if_fail (GST_IS_PAD (pad));
1561 
1562   GST_OBJECT_LOCK (pad);
1563 
1564   hook = g_hook_get (&pad->probes, id);
1565   if (hook == NULL)
1566     goto not_found;
1567 
1568   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "removing hook %ld",
1569       hook->hook_id);
1570   cleanup_hook (pad, hook);
1571   GST_OBJECT_UNLOCK (pad);
1572 
1573   return;
1574 
1575 not_found:
1576   {
1577     GST_OBJECT_UNLOCK (pad);
1578     g_warning ("%s: pad `%p' has no probe with id `%lu'", G_STRLOC, pad, id);
1579     return;
1580   }
1581 }
1582 
1583 /**
1584  * gst_pad_is_blocked:
1585  * @pad: the #GstPad to query
1586  *
1587  * Checks if the pad is blocked or not. This function returns the
1588  * last requested state of the pad. It is not certain that the pad
1589  * is actually blocking at this point (see gst_pad_is_blocking()).
1590  *
1591  * Returns: %TRUE if the pad is blocked.
1592  *
1593  * MT safe.
1594  */
1595 gboolean
gst_pad_is_blocked(GstPad * pad)1596 gst_pad_is_blocked (GstPad * pad)
1597 {
1598   gboolean result = FALSE;
1599 
1600   g_return_val_if_fail (GST_IS_PAD (pad), result);
1601 
1602   GST_OBJECT_LOCK (pad);
1603   result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED);
1604   GST_OBJECT_UNLOCK (pad);
1605 
1606   return result;
1607 }
1608 
1609 /**
1610  * gst_pad_is_blocking:
1611  * @pad: the #GstPad to query
1612  *
1613  * Checks if the pad is blocking or not. This is a guaranteed state
1614  * of whether the pad is actually blocking on a #GstBuffer or a #GstEvent.
1615  *
1616  * Returns: %TRUE if the pad is blocking.
1617  *
1618  * MT safe.
1619  */
1620 gboolean
gst_pad_is_blocking(GstPad * pad)1621 gst_pad_is_blocking (GstPad * pad)
1622 {
1623   gboolean result = FALSE;
1624 
1625   g_return_val_if_fail (GST_IS_PAD (pad), result);
1626 
1627   GST_OBJECT_LOCK (pad);
1628   /* the blocking flag is only valid if the pad is not flushing */
1629   result = GST_PAD_IS_BLOCKING (pad) && !GST_PAD_IS_FLUSHING (pad);
1630   GST_OBJECT_UNLOCK (pad);
1631 
1632   return result;
1633 }
1634 
1635 /**
1636  * gst_pad_needs_reconfigure:
1637  * @pad: the #GstPad to check
1638  *
1639  * Check the #GST_PAD_FLAG_NEED_RECONFIGURE flag on @pad and return %TRUE
1640  * if the flag was set.
1641  *
1642  * Returns: %TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag is set on @pad.
1643  */
1644 gboolean
gst_pad_needs_reconfigure(GstPad * pad)1645 gst_pad_needs_reconfigure (GstPad * pad)
1646 {
1647   gboolean reconfigure;
1648 
1649   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1650 
1651   GST_OBJECT_LOCK (pad);
1652   reconfigure = GST_PAD_NEEDS_RECONFIGURE (pad);
1653   GST_DEBUG_OBJECT (pad, "peeking RECONFIGURE flag %d", reconfigure);
1654   GST_OBJECT_UNLOCK (pad);
1655 
1656   return reconfigure;
1657 }
1658 
1659 /**
1660  * gst_pad_check_reconfigure:
1661  * @pad: the #GstPad to check
1662  *
1663  * Check and clear the #GST_PAD_FLAG_NEED_RECONFIGURE flag on @pad and return %TRUE
1664  * if the flag was set.
1665  *
1666  * Returns: %TRUE is the GST_PAD_FLAG_NEED_RECONFIGURE flag was set on @pad.
1667  */
1668 gboolean
gst_pad_check_reconfigure(GstPad * pad)1669 gst_pad_check_reconfigure (GstPad * pad)
1670 {
1671   gboolean reconfigure;
1672 
1673   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
1674 
1675   GST_OBJECT_LOCK (pad);
1676   reconfigure = GST_PAD_NEEDS_RECONFIGURE (pad);
1677   if (reconfigure) {
1678     GST_DEBUG_OBJECT (pad, "remove RECONFIGURE flag");
1679     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
1680   }
1681   GST_OBJECT_UNLOCK (pad);
1682 
1683   return reconfigure;
1684 }
1685 
1686 /**
1687  * gst_pad_mark_reconfigure:
1688  * @pad: the #GstPad to mark
1689  *
1690  * Mark a pad for needing reconfiguration. The next call to
1691  * gst_pad_check_reconfigure() will return %TRUE after this call.
1692  */
1693 void
gst_pad_mark_reconfigure(GstPad * pad)1694 gst_pad_mark_reconfigure (GstPad * pad)
1695 {
1696   g_return_if_fail (GST_IS_PAD (pad));
1697 
1698   GST_OBJECT_LOCK (pad);
1699   GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
1700   GST_OBJECT_UNLOCK (pad);
1701 }
1702 
1703 /**
1704  * gst_pad_set_activate_function:
1705  * @p: a #GstPad.
1706  * @f: the #GstPadActivateFunction to set.
1707  *
1708  * Calls gst_pad_set_activate_function_full() with %NULL for the user_data and
1709  * notify.
1710  */
1711 /**
1712  * gst_pad_set_activate_function_full:
1713  * @pad: a #GstPad.
1714  * @activate: the #GstPadActivateFunction to set.
1715  * @user_data: user_data passed to @notify
1716  * @notify: notify called when @activate will not be used anymore.
1717  *
1718  * Sets the given activate function for @pad. The activate function will
1719  * dispatch to gst_pad_activate_mode() to perform the actual activation.
1720  * Only makes sense to set on sink pads.
1721  *
1722  * Call this function if your sink pad can start a pull-based task.
1723  */
1724 void
gst_pad_set_activate_function_full(GstPad * pad,GstPadActivateFunction activate,gpointer user_data,GDestroyNotify notify)1725 gst_pad_set_activate_function_full (GstPad * pad,
1726     GstPadActivateFunction activate, gpointer user_data, GDestroyNotify notify)
1727 {
1728   g_return_if_fail (GST_IS_PAD (pad));
1729 
1730   if (pad->activatenotify)
1731     pad->activatenotify (pad->activatedata);
1732   GST_PAD_ACTIVATEFUNC (pad) = activate;
1733   pad->activatedata = user_data;
1734   pad->activatenotify = notify;
1735 
1736   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s",
1737       GST_DEBUG_FUNCPTR_NAME (activate));
1738 }
1739 
1740 /**
1741  * gst_pad_set_activatemode_function:
1742  * @p: a #GstPad.
1743  * @f: the #GstPadActivateModeFunction to set.
1744  *
1745  * Calls gst_pad_set_activatemode_function_full() with %NULL for the user_data and
1746  * notify.
1747  */
1748 /**
1749  * gst_pad_set_activatemode_function_full:
1750  * @pad: a #GstPad.
1751  * @activatemode: the #GstPadActivateModeFunction to set.
1752  * @user_data: user_data passed to @notify
1753  * @notify: notify called when @activatemode will not be used anymore.
1754  *
1755  * Sets the given activate_mode function for the pad. An activate_mode function
1756  * prepares the element for data passing.
1757  */
1758 void
gst_pad_set_activatemode_function_full(GstPad * pad,GstPadActivateModeFunction activatemode,gpointer user_data,GDestroyNotify notify)1759 gst_pad_set_activatemode_function_full (GstPad * pad,
1760     GstPadActivateModeFunction activatemode, gpointer user_data,
1761     GDestroyNotify notify)
1762 {
1763   g_return_if_fail (GST_IS_PAD (pad));
1764 
1765   if (pad->activatemodenotify)
1766     pad->activatemodenotify (pad->activatemodedata);
1767   GST_PAD_ACTIVATEMODEFUNC (pad) = activatemode;
1768   pad->activatemodedata = user_data;
1769   pad->activatemodenotify = notify;
1770 
1771   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatemodefunc set to %s",
1772       GST_DEBUG_FUNCPTR_NAME (activatemode));
1773 }
1774 
1775 /**
1776  * gst_pad_set_chain_function:
1777  * @p: a sink #GstPad.
1778  * @f: the #GstPadChainFunction to set.
1779  *
1780  * Calls gst_pad_set_chain_function_full() with %NULL for the user_data and
1781  * notify.
1782  */
1783 /**
1784  * gst_pad_set_chain_function_full:
1785  * @pad: a sink #GstPad.
1786  * @chain: the #GstPadChainFunction to set.
1787  * @user_data: user_data passed to @notify
1788  * @notify: notify called when @chain will not be used anymore.
1789  *
1790  * Sets the given chain function for the pad. The chain function is called to
1791  * process a #GstBuffer input buffer. see #GstPadChainFunction for more details.
1792  */
1793 void
gst_pad_set_chain_function_full(GstPad * pad,GstPadChainFunction chain,gpointer user_data,GDestroyNotify notify)1794 gst_pad_set_chain_function_full (GstPad * pad, GstPadChainFunction chain,
1795     gpointer user_data, GDestroyNotify notify)
1796 {
1797   g_return_if_fail (GST_IS_PAD (pad));
1798   g_return_if_fail (GST_PAD_IS_SINK (pad));
1799 
1800   if (pad->chainnotify)
1801     pad->chainnotify (pad->chaindata);
1802   GST_PAD_CHAINFUNC (pad) = chain;
1803   pad->chaindata = user_data;
1804   pad->chainnotify = notify;
1805 
1806   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s",
1807       GST_DEBUG_FUNCPTR_NAME (chain));
1808 }
1809 
1810 /**
1811  * gst_pad_set_chain_list_function:
1812  * @p: a sink #GstPad.
1813  * @f: the #GstPadChainListFunction to set.
1814  *
1815  * Calls gst_pad_set_chain_list_function_full() with %NULL for the user_data and
1816  * notify.
1817  */
1818 /**
1819  * gst_pad_set_chain_list_function_full:
1820  * @pad: a sink #GstPad.
1821  * @chainlist: the #GstPadChainListFunction to set.
1822  * @user_data: user_data passed to @notify
1823  * @notify: notify called when @chainlist will not be used anymore.
1824  *
1825  * Sets the given chain list function for the pad. The chainlist function is
1826  * called to process a #GstBufferList input buffer list. See
1827  * #GstPadChainListFunction for more details.
1828  */
1829 void
gst_pad_set_chain_list_function_full(GstPad * pad,GstPadChainListFunction chainlist,gpointer user_data,GDestroyNotify notify)1830 gst_pad_set_chain_list_function_full (GstPad * pad,
1831     GstPadChainListFunction chainlist, gpointer user_data,
1832     GDestroyNotify notify)
1833 {
1834   g_return_if_fail (GST_IS_PAD (pad));
1835   g_return_if_fail (GST_PAD_IS_SINK (pad));
1836 
1837   if (pad->chainlistnotify)
1838     pad->chainlistnotify (pad->chainlistdata);
1839   GST_PAD_CHAINLISTFUNC (pad) = chainlist;
1840   pad->chainlistdata = user_data;
1841   pad->chainlistnotify = notify;
1842 
1843   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
1844       GST_DEBUG_FUNCPTR_NAME (chainlist));
1845 }
1846 
1847 /**
1848  * gst_pad_set_getrange_function:
1849  * @p: a source #GstPad.
1850  * @f: the #GstPadGetRangeFunction to set.
1851  *
1852  * Calls gst_pad_set_getrange_function_full() with %NULL for the user_data and
1853  * notify.
1854  */
1855 /**
1856  * gst_pad_set_getrange_function_full:
1857  * @pad: a source #GstPad.
1858  * @get: the #GstPadGetRangeFunction to set.
1859  * @user_data: user_data passed to @notify
1860  * @notify: notify called when @get will not be used anymore.
1861  *
1862  * Sets the given getrange function for the pad. The getrange function is
1863  * called to produce a new #GstBuffer to start the processing pipeline. see
1864  * #GstPadGetRangeFunction for a description of the getrange function.
1865  */
1866 void
gst_pad_set_getrange_function_full(GstPad * pad,GstPadGetRangeFunction get,gpointer user_data,GDestroyNotify notify)1867 gst_pad_set_getrange_function_full (GstPad * pad, GstPadGetRangeFunction get,
1868     gpointer user_data, GDestroyNotify notify)
1869 {
1870   g_return_if_fail (GST_IS_PAD (pad));
1871   g_return_if_fail (GST_PAD_IS_SRC (pad));
1872 
1873   if (pad->getrangenotify)
1874     pad->getrangenotify (pad->getrangedata);
1875   GST_PAD_GETRANGEFUNC (pad) = get;
1876   pad->getrangedata = user_data;
1877   pad->getrangenotify = notify;
1878 
1879   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s",
1880       GST_DEBUG_FUNCPTR_NAME (get));
1881 }
1882 
1883 /**
1884  * gst_pad_set_event_function:
1885  * @p: a #GstPad of either direction.
1886  * @f: the #GstPadEventFunction to set.
1887  *
1888  * Calls gst_pad_set_event_function_full() with %NULL for the user_data and
1889  * notify.
1890  */
1891 /**
1892  * gst_pad_set_event_function_full:
1893  * @pad: a #GstPad of either direction.
1894  * @event: the #GstPadEventFunction to set.
1895  * @user_data: user_data passed to @notify
1896  * @notify: notify called when @event will not be used anymore.
1897  *
1898  * Sets the given event handler for the pad.
1899  */
1900 void
gst_pad_set_event_function_full(GstPad * pad,GstPadEventFunction event,gpointer user_data,GDestroyNotify notify)1901 gst_pad_set_event_function_full (GstPad * pad, GstPadEventFunction event,
1902     gpointer user_data, GDestroyNotify notify)
1903 {
1904   g_return_if_fail (GST_IS_PAD (pad));
1905 
1906   if (pad->eventnotify)
1907     pad->eventnotify (pad->eventdata);
1908   GST_PAD_EVENTFUNC (pad) = event;
1909   pad->eventdata = user_data;
1910   pad->eventnotify = notify;
1911 
1912   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfunc for set to %s",
1913       GST_DEBUG_FUNCPTR_NAME (event));
1914 }
1915 
1916 static gboolean
event_wrap(GstPad * pad,GstObject * object,GstEvent * event)1917 event_wrap (GstPad * pad, GstObject * object, GstEvent * event)
1918 {
1919   GstFlowReturn ret;
1920 
1921   ret = GST_PAD_EVENTFULLFUNC (pad) (pad, object, event);
1922   if (ret == GST_FLOW_OK)
1923     return TRUE;
1924   return FALSE;
1925 }
1926 
1927 /**
1928  * gst_pad_set_event_full_function:
1929  * @p: a #GstPad of either direction.
1930  * @f: the #GstPadEventFullFunction to set.
1931  *
1932  * Calls gst_pad_set_event_full_function_full() with %NULL for the user_data and
1933  * notify.
1934  */
1935 /**
1936  * gst_pad_set_event_full_function_full:
1937  * @pad: a #GstPad of either direction.
1938  * @event: the #GstPadEventFullFunction to set.
1939  * @user_data: user_data passed to @notify
1940  * @notify: notify called when @event will not be used anymore.
1941  *
1942  * Sets the given event handler for the pad.
1943  *
1944  * Since: 1.8
1945  */
1946 void
gst_pad_set_event_full_function_full(GstPad * pad,GstPadEventFullFunction event,gpointer user_data,GDestroyNotify notify)1947 gst_pad_set_event_full_function_full (GstPad * pad,
1948     GstPadEventFullFunction event, gpointer user_data, GDestroyNotify notify)
1949 {
1950   g_return_if_fail (GST_IS_PAD (pad));
1951 
1952   if (pad->eventnotify)
1953     pad->eventnotify (pad->eventdata);
1954   GST_PAD_EVENTFULLFUNC (pad) = event;
1955   GST_PAD_EVENTFUNC (pad) = event_wrap;
1956   pad->eventdata = user_data;
1957   pad->eventnotify = notify;
1958 
1959   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfullfunc for set to %s",
1960       GST_DEBUG_FUNCPTR_NAME (event));
1961 }
1962 
1963 /**
1964  * gst_pad_set_query_function:
1965  * @p: a #GstPad of either direction.
1966  * @f: the #GstPadQueryFunction to set.
1967  *
1968  * Calls gst_pad_set_query_function_full() with %NULL for the user_data and
1969  * notify.
1970  */
1971 /**
1972  * gst_pad_set_query_function_full:
1973  * @pad: a #GstPad of either direction.
1974  * @query: the #GstPadQueryFunction to set.
1975  * @user_data: user_data passed to @notify
1976  * @notify: notify called when @query will not be used anymore.
1977  *
1978  * Set the given query function for the pad.
1979  */
1980 void
gst_pad_set_query_function_full(GstPad * pad,GstPadQueryFunction query,gpointer user_data,GDestroyNotify notify)1981 gst_pad_set_query_function_full (GstPad * pad, GstPadQueryFunction query,
1982     gpointer user_data, GDestroyNotify notify)
1983 {
1984   g_return_if_fail (GST_IS_PAD (pad));
1985 
1986   if (pad->querynotify)
1987     pad->querynotify (pad->querydata);
1988   GST_PAD_QUERYFUNC (pad) = query;
1989   pad->querydata = user_data;
1990   pad->querynotify = notify;
1991 
1992   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "queryfunc set to %s",
1993       GST_DEBUG_FUNCPTR_NAME (query));
1994 }
1995 
1996 /**
1997  * gst_pad_set_iterate_internal_links_function:
1998  * @p: a #GstPad of either direction.
1999  * @f: the #GstPadIterIntLinkFunction to set.
2000  *
2001  * Calls gst_pad_set_iterate_internal_links_function_full() with %NULL
2002  * for the user_data and notify.
2003  */
2004 /**
2005  * gst_pad_set_iterate_internal_links_function_full:
2006  * @pad: a #GstPad of either direction.
2007  * @iterintlink: the #GstPadIterIntLinkFunction to set.
2008  * @user_data: user_data passed to @notify
2009  * @notify: notify called when @iterintlink will not be used anymore.
2010  *
2011  * Sets the given internal link iterator function for the pad.
2012  */
2013 void
gst_pad_set_iterate_internal_links_function_full(GstPad * pad,GstPadIterIntLinkFunction iterintlink,gpointer user_data,GDestroyNotify notify)2014 gst_pad_set_iterate_internal_links_function_full (GstPad * pad,
2015     GstPadIterIntLinkFunction iterintlink, gpointer user_data,
2016     GDestroyNotify notify)
2017 {
2018   g_return_if_fail (GST_IS_PAD (pad));
2019 
2020   if (pad->iterintlinknotify)
2021     pad->iterintlinknotify (pad->iterintlinkdata);
2022   GST_PAD_ITERINTLINKFUNC (pad) = iterintlink;
2023   pad->iterintlinkdata = user_data;
2024   pad->iterintlinknotify = notify;
2025 
2026   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s",
2027       GST_DEBUG_FUNCPTR_NAME (iterintlink));
2028 }
2029 
2030 /**
2031  * gst_pad_set_link_function:
2032  * @p: a #GstPad.
2033  * @f: the #GstPadLinkFunction to set.
2034  *
2035  * Calls gst_pad_set_link_function_full() with %NULL
2036  * for the user_data and notify.
2037  */
2038 /**
2039  * gst_pad_set_link_function_full:
2040  * @pad: a #GstPad.
2041  * @link: the #GstPadLinkFunction to set.
2042  * @user_data: user_data passed to @notify
2043  * @notify: notify called when @link will not be used anymore.
2044  *
2045  * Sets the given link function for the pad. It will be called when
2046  * the pad is linked with another pad.
2047  *
2048  * The return value #GST_PAD_LINK_OK should be used when the connection can be
2049  * made.
2050  *
2051  * The return value #GST_PAD_LINK_REFUSED should be used when the connection
2052  * cannot be made for some reason.
2053  *
2054  * If @link is installed on a source pad, it should call the #GstPadLinkFunction
2055  * of the peer sink pad, if present.
2056  */
2057 void
gst_pad_set_link_function_full(GstPad * pad,GstPadLinkFunction link,gpointer user_data,GDestroyNotify notify)2058 gst_pad_set_link_function_full (GstPad * pad, GstPadLinkFunction link,
2059     gpointer user_data, GDestroyNotify notify)
2060 {
2061   g_return_if_fail (GST_IS_PAD (pad));
2062 
2063   if (pad->linknotify)
2064     pad->linknotify (pad->linkdata);
2065   GST_PAD_LINKFUNC (pad) = link;
2066   pad->linkdata = user_data;
2067   pad->linknotify = notify;
2068 
2069   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "linkfunc set to %s",
2070       GST_DEBUG_FUNCPTR_NAME (link));
2071 }
2072 
2073 /**
2074  * gst_pad_set_unlink_function:
2075  * @p: a #GstPad.
2076  * @f: the #GstPadUnlinkFunction to set.
2077  *
2078  * Calls gst_pad_set_unlink_function_full() with %NULL
2079  * for the user_data and notify.
2080  */
2081 /**
2082  * gst_pad_set_unlink_function_full:
2083  * @pad: a #GstPad.
2084  * @unlink: the #GstPadUnlinkFunction to set.
2085  * @user_data: user_data passed to @notify
2086  * @notify: notify called when @unlink will not be used anymore.
2087  *
2088  * Sets the given unlink function for the pad. It will be called
2089  * when the pad is unlinked.
2090  *
2091  * Note that the pad's lock is already held when the unlink
2092  * function is called, so most pad functions cannot be called
2093  * from within the callback.
2094  */
2095 void
gst_pad_set_unlink_function_full(GstPad * pad,GstPadUnlinkFunction unlink,gpointer user_data,GDestroyNotify notify)2096 gst_pad_set_unlink_function_full (GstPad * pad, GstPadUnlinkFunction unlink,
2097     gpointer user_data, GDestroyNotify notify)
2098 {
2099   g_return_if_fail (GST_IS_PAD (pad));
2100 
2101   if (pad->unlinknotify)
2102     pad->unlinknotify (pad->unlinkdata);
2103   GST_PAD_UNLINKFUNC (pad) = unlink;
2104   pad->unlinkdata = user_data;
2105   pad->unlinknotify = notify;
2106 
2107   GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "unlinkfunc set to %s",
2108       GST_DEBUG_FUNCPTR_NAME (unlink));
2109 }
2110 
2111 /**
2112  * gst_pad_unlink:
2113  * @srcpad: the source #GstPad to unlink.
2114  * @sinkpad: the sink #GstPad to unlink.
2115  *
2116  * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked
2117  * signal on both pads.
2118  *
2119  * Returns: %TRUE if the pads were unlinked. This function returns %FALSE if
2120  * the pads were not linked together.
2121  *
2122  * MT safe.
2123  */
2124 gboolean
gst_pad_unlink(GstPad * srcpad,GstPad * sinkpad)2125 gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
2126 {
2127   gboolean result = FALSE;
2128   GstElement *parent = NULL;
2129 
2130   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
2131   g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE);
2132   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
2133   g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE);
2134 
2135   GST_TRACER_PAD_UNLINK_PRE (srcpad, sinkpad);
2136 
2137   GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)",
2138       GST_DEBUG_PAD_NAME (srcpad), srcpad,
2139       GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
2140 
2141   /* We need to notify the parent before taking any pad locks as the bin in
2142    * question might be waiting for a lock on the pad while holding its lock
2143    * that our message will try to take. */
2144   if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
2145     if (GST_IS_ELEMENT (parent)) {
2146       gst_element_post_message (parent,
2147           gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
2148               GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, TRUE));
2149     } else {
2150       gst_object_unref (parent);
2151       parent = NULL;
2152     }
2153   }
2154 
2155   GST_OBJECT_LOCK (srcpad);
2156   GST_OBJECT_LOCK (sinkpad);
2157 
2158   if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad))
2159     goto not_linked_together;
2160 
2161   if (GST_PAD_UNLINKFUNC (srcpad)) {
2162     GstObject *tmpparent;
2163 
2164     ACQUIRE_PARENT (srcpad, tmpparent, no_src_parent);
2165 
2166     GST_PAD_UNLINKFUNC (srcpad) (srcpad, tmpparent);
2167     RELEASE_PARENT (tmpparent);
2168   }
2169 no_src_parent:
2170   if (GST_PAD_UNLINKFUNC (sinkpad)) {
2171     GstObject *tmpparent;
2172 
2173     ACQUIRE_PARENT (sinkpad, tmpparent, no_sink_parent);
2174 
2175     GST_PAD_UNLINKFUNC (sinkpad) (sinkpad, tmpparent);
2176     RELEASE_PARENT (tmpparent);
2177   }
2178 no_sink_parent:
2179 
2180   /* first clear peers */
2181   GST_PAD_PEER (srcpad) = NULL;
2182   GST_PAD_PEER (sinkpad) = NULL;
2183 
2184   GST_OBJECT_UNLOCK (sinkpad);
2185   GST_OBJECT_UNLOCK (srcpad);
2186 
2187   /* fire off a signal to each of the pads telling them
2188    * that they've been unlinked */
2189   g_signal_emit (srcpad, gst_pad_signals[PAD_UNLINKED], 0, sinkpad);
2190   g_signal_emit (sinkpad, gst_pad_signals[PAD_UNLINKED], 0, srcpad);
2191 
2192   GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s",
2193       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2194 
2195   result = TRUE;
2196 
2197 done:
2198   if (parent != NULL) {
2199     gst_element_post_message (parent,
2200         gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
2201             GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE));
2202     gst_object_unref (parent);
2203   }
2204   GST_TRACER_PAD_UNLINK_POST (srcpad, sinkpad, result);
2205   return result;
2206 
2207   /* ERRORS */
2208 not_linked_together:
2209   {
2210     /* we do not emit a warning in this case because unlinking cannot
2211      * be made MT safe.*/
2212     GST_OBJECT_UNLOCK (sinkpad);
2213     GST_OBJECT_UNLOCK (srcpad);
2214     goto done;
2215   }
2216 }
2217 
2218 /**
2219  * gst_pad_is_linked:
2220  * @pad: pad to check
2221  *
2222  * Checks if a @pad is linked to another pad or not.
2223  *
2224  * Returns: %TRUE if the pad is linked, %FALSE otherwise.
2225  *
2226  * MT safe.
2227  */
2228 gboolean
gst_pad_is_linked(GstPad * pad)2229 gst_pad_is_linked (GstPad * pad)
2230 {
2231   gboolean result;
2232 
2233   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2234 
2235   GST_OBJECT_LOCK (pad);
2236   result = (GST_PAD_PEER (pad) != NULL);
2237   GST_OBJECT_UNLOCK (pad);
2238 
2239   return result;
2240 }
2241 
2242 /* get the caps from both pads and see if the intersection
2243  * is not empty.
2244  *
2245  * This function should be called with the pad LOCK on both
2246  * pads
2247  */
2248 static gboolean
gst_pad_link_check_compatible_unlocked(GstPad * src,GstPad * sink,GstPadLinkCheck flags)2249 gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink,
2250     GstPadLinkCheck flags)
2251 {
2252   GstCaps *srccaps = NULL;
2253   GstCaps *sinkcaps = NULL;
2254   gboolean compatible = FALSE;
2255 
2256   if (!(flags & (GST_PAD_LINK_CHECK_CAPS | GST_PAD_LINK_CHECK_TEMPLATE_CAPS)))
2257     return TRUE;
2258 
2259   /* Doing the expensive caps checking takes priority over only checking the template caps */
2260   if (flags & GST_PAD_LINK_CHECK_CAPS) {
2261     GST_OBJECT_UNLOCK (sink);
2262     GST_OBJECT_UNLOCK (src);
2263 
2264     srccaps = gst_pad_query_caps (src, NULL);
2265     sinkcaps = gst_pad_query_caps (sink, NULL);
2266 
2267     GST_OBJECT_LOCK (src);
2268     GST_OBJECT_LOCK (sink);
2269   } else {
2270     /* If one of the two pads doesn't have a template, consider the intersection
2271      * as valid.*/
2272     if (G_UNLIKELY ((GST_PAD_PAD_TEMPLATE (src) == NULL)
2273             || (GST_PAD_PAD_TEMPLATE (sink) == NULL))) {
2274       compatible = TRUE;
2275       goto done;
2276     }
2277     srccaps = gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (src)));
2278     sinkcaps =
2279         gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (sink)));
2280   }
2281 
2282   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, src, "src caps %" GST_PTR_FORMAT,
2283       srccaps);
2284   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, sink, "sink caps %" GST_PTR_FORMAT,
2285       sinkcaps);
2286 
2287   /* if we have caps on both pads we can check the intersection. If one
2288    * of the caps is %NULL, we return %TRUE. */
2289   if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) {
2290     if (srccaps)
2291       gst_caps_unref (srccaps);
2292     if (sinkcaps)
2293       gst_caps_unref (sinkcaps);
2294     goto done;
2295   }
2296 
2297   compatible = gst_caps_can_intersect (srccaps, sinkcaps);
2298   gst_caps_unref (srccaps);
2299   gst_caps_unref (sinkcaps);
2300 
2301 done:
2302   GST_CAT_DEBUG (GST_CAT_CAPS, "caps are %scompatible",
2303       (compatible ? "" : "not "));
2304 
2305   return compatible;
2306 }
2307 
2308 /* check if the grandparents of both pads are the same.
2309  * This check is required so that we don't try to link
2310  * pads from elements in different bins without ghostpads.
2311  *
2312  * The LOCK should be held on both pads
2313  */
2314 static gboolean
gst_pad_link_check_hierarchy(GstPad * src,GstPad * sink)2315 gst_pad_link_check_hierarchy (GstPad * src, GstPad * sink)
2316 {
2317   GstObject *psrc, *psink;
2318 
2319   psrc = GST_OBJECT_PARENT (src);
2320   psink = GST_OBJECT_PARENT (sink);
2321 
2322   /* if one of the pads has no parent, we allow the link */
2323   if (G_UNLIKELY (psrc == NULL || psink == NULL))
2324     goto no_parent;
2325 
2326   /* only care about parents that are elements */
2327   if (G_UNLIKELY (!GST_IS_ELEMENT (psrc) || !GST_IS_ELEMENT (psink)))
2328     goto no_element_parent;
2329 
2330   /* if the parents are the same, we have a loop */
2331   if (G_UNLIKELY (psrc == psink))
2332     goto same_parents;
2333 
2334   /* if they both have a parent, we check the grandparents. We can not lock
2335    * the parent because we hold on the child (pad) and the locking order is
2336    * parent >> child. */
2337   psrc = GST_OBJECT_PARENT (psrc);
2338   psink = GST_OBJECT_PARENT (psink);
2339 
2340   /* if they have grandparents but they are not the same */
2341   if (G_UNLIKELY (psrc != psink))
2342     goto wrong_grandparents;
2343 
2344   return TRUE;
2345 
2346   /* ERRORS */
2347 no_parent:
2348   {
2349     GST_CAT_DEBUG (GST_CAT_CAPS,
2350         "one of the pads has no parent %" GST_PTR_FORMAT " and %"
2351         GST_PTR_FORMAT, psrc, psink);
2352     return TRUE;
2353   }
2354 no_element_parent:
2355   {
2356     GST_CAT_DEBUG (GST_CAT_CAPS,
2357         "one of the pads has no element parent %" GST_PTR_FORMAT " and %"
2358         GST_PTR_FORMAT, psrc, psink);
2359     return TRUE;
2360   }
2361 same_parents:
2362   {
2363     GST_CAT_DEBUG (GST_CAT_CAPS, "pads have same parent %" GST_PTR_FORMAT,
2364         psrc);
2365     return FALSE;
2366   }
2367 wrong_grandparents:
2368   {
2369     GST_CAT_DEBUG (GST_CAT_CAPS,
2370         "pads have different grandparents %" GST_PTR_FORMAT " and %"
2371         GST_PTR_FORMAT, psrc, psink);
2372     return FALSE;
2373   }
2374 }
2375 
2376 /* FIXME leftover from an attempt at refactoring... */
2377 /* call with the two pads unlocked, when this function returns GST_PAD_LINK_OK,
2378  * the two pads will be locked in the srcpad, sinkpad order. */
2379 static GstPadLinkReturn
gst_pad_link_prepare(GstPad * srcpad,GstPad * sinkpad,GstPadLinkCheck flags)2380 gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
2381 {
2382   GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
2383       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2384 
2385   GST_OBJECT_LOCK (srcpad);
2386 
2387   if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL))
2388     goto src_was_linked;
2389 
2390   GST_OBJECT_LOCK (sinkpad);
2391 
2392   if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL))
2393     goto sink_was_linked;
2394 
2395   /* check hierarchy, pads can only be linked if the grandparents
2396    * are the same. */
2397   if ((flags & GST_PAD_LINK_CHECK_HIERARCHY)
2398       && !gst_pad_link_check_hierarchy (srcpad, sinkpad))
2399     goto wrong_hierarchy;
2400 
2401   /* check pad caps for non-empty intersection */
2402   if (!gst_pad_link_check_compatible_unlocked (srcpad, sinkpad, flags))
2403     goto no_format;
2404 
2405   /* FIXME check pad scheduling for non-empty intersection */
2406 
2407   return GST_PAD_LINK_OK;
2408 
2409 src_was_linked:
2410   {
2411     GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s",
2412         GST_DEBUG_PAD_NAME (srcpad),
2413         GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad)));
2414     /* we do not emit a warning in this case because unlinking cannot
2415      * be made MT safe.*/
2416     GST_OBJECT_UNLOCK (srcpad);
2417     return GST_PAD_LINK_WAS_LINKED;
2418   }
2419 sink_was_linked:
2420   {
2421     GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s",
2422         GST_DEBUG_PAD_NAME (sinkpad),
2423         GST_DEBUG_PAD_NAME (GST_PAD_PEER (sinkpad)));
2424     /* we do not emit a warning in this case because unlinking cannot
2425      * be made MT safe.*/
2426     GST_OBJECT_UNLOCK (sinkpad);
2427     GST_OBJECT_UNLOCK (srcpad);
2428     return GST_PAD_LINK_WAS_LINKED;
2429   }
2430 wrong_hierarchy:
2431   {
2432     GST_CAT_INFO (GST_CAT_PADS, "pads have wrong hierarchy");
2433     GST_OBJECT_UNLOCK (sinkpad);
2434     GST_OBJECT_UNLOCK (srcpad);
2435     return GST_PAD_LINK_WRONG_HIERARCHY;
2436   }
2437 no_format:
2438   {
2439     GST_CAT_INFO (GST_CAT_PADS, "caps are incompatible");
2440     GST_OBJECT_UNLOCK (sinkpad);
2441     GST_OBJECT_UNLOCK (srcpad);
2442     return GST_PAD_LINK_NOFORMAT;
2443   }
2444 }
2445 
2446 /**
2447  * gst_pad_can_link:
2448  * @srcpad: the source #GstPad.
2449  * @sinkpad: the sink #GstPad.
2450  *
2451  * Checks if the source pad and the sink pad are compatible so they can be
2452  * linked.
2453  *
2454  * Returns: %TRUE if the pads can be linked.
2455  */
2456 gboolean
gst_pad_can_link(GstPad * srcpad,GstPad * sinkpad)2457 gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
2458 {
2459   GstPadLinkReturn result;
2460 
2461   /* generic checks */
2462   g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
2463   g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
2464 
2465   GST_CAT_INFO (GST_CAT_PADS, "check if %s:%s can link with %s:%s",
2466       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2467 
2468   /* gst_pad_link_prepare does everything for us, we only release the locks
2469    * on the pads that it gets us. If this function returns !OK the locks are not
2470    * taken anymore. */
2471   result = gst_pad_link_prepare (srcpad, sinkpad, GST_PAD_LINK_CHECK_DEFAULT);
2472   if (result != GST_PAD_LINK_OK)
2473     goto done;
2474 
2475   GST_OBJECT_UNLOCK (srcpad);
2476   GST_OBJECT_UNLOCK (sinkpad);
2477 
2478 done:
2479   return result == GST_PAD_LINK_OK;
2480 }
2481 
2482 /**
2483  * gst_pad_link_full:
2484  * @srcpad: the source #GstPad to link.
2485  * @sinkpad: the sink #GstPad to link.
2486  * @flags: the checks to validate when linking
2487  *
2488  * Links the source pad and the sink pad.
2489  *
2490  * This variant of #gst_pad_link provides a more granular control on the
2491  * checks being done when linking. While providing some considerable speedups
2492  * the caller of this method must be aware that wrong usage of those flags
2493  * can cause severe issues. Refer to the documentation of #GstPadLinkCheck
2494  * for more information.
2495  *
2496  * MT Safe.
2497  *
2498  * Returns: A result code indicating if the connection worked or
2499  *          what went wrong.
2500  */
2501 GstPadLinkReturn
gst_pad_link_full(GstPad * srcpad,GstPad * sinkpad,GstPadLinkCheck flags)2502 gst_pad_link_full (GstPad * srcpad, GstPad * sinkpad, GstPadLinkCheck flags)
2503 {
2504   GstPadLinkReturn result;
2505   GstElement *parent;
2506   GstPadLinkFunction srcfunc, sinkfunc;
2507 
2508   g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
2509   g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
2510   g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
2511   g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad),
2512       GST_PAD_LINK_WRONG_DIRECTION);
2513 
2514   GST_TRACER_PAD_LINK_PRE (srcpad, sinkpad);
2515 
2516   /* Notify the parent early. See gst_pad_unlink for details. */
2517   if (G_LIKELY ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad))))) {
2518     if (G_LIKELY (GST_IS_ELEMENT (parent))) {
2519       gst_element_post_message (parent,
2520           gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
2521               GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
2522     } else {
2523       gst_object_unref (parent);
2524       parent = NULL;
2525     }
2526   }
2527 
2528   /* prepare will also lock the two pads */
2529   result = gst_pad_link_prepare (srcpad, sinkpad, flags);
2530 
2531   if (G_UNLIKELY (result != GST_PAD_LINK_OK)) {
2532     GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s",
2533         GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
2534         gst_pad_link_get_name (result));
2535     goto done;
2536   }
2537 
2538   /* must set peers before calling the link function */
2539   GST_PAD_PEER (srcpad) = sinkpad;
2540   GST_PAD_PEER (sinkpad) = srcpad;
2541 
2542   /* check events, when something is different, mark pending */
2543   schedule_events (srcpad, sinkpad);
2544 
2545   /* get the link functions */
2546   srcfunc = GST_PAD_LINKFUNC (srcpad);
2547   sinkfunc = GST_PAD_LINKFUNC (sinkpad);
2548 
2549   if (G_UNLIKELY (srcfunc || sinkfunc)) {
2550     /* custom link functions, execute them */
2551     GST_OBJECT_UNLOCK (sinkpad);
2552     GST_OBJECT_UNLOCK (srcpad);
2553 
2554     if (srcfunc) {
2555       GstObject *tmpparent;
2556 
2557       ACQUIRE_PARENT (srcpad, tmpparent, no_parent);
2558       /* this one will call the peer link function */
2559       result = srcfunc (srcpad, tmpparent, sinkpad);
2560       RELEASE_PARENT (tmpparent);
2561     } else if (sinkfunc) {
2562       GstObject *tmpparent;
2563 
2564       ACQUIRE_PARENT (sinkpad, tmpparent, no_parent);
2565       /* if no source link function, we need to call the sink link
2566        * function ourselves. */
2567       result = sinkfunc (sinkpad, tmpparent, srcpad);
2568       RELEASE_PARENT (tmpparent);
2569     }
2570   no_parent:
2571 
2572     GST_OBJECT_LOCK (srcpad);
2573     GST_OBJECT_LOCK (sinkpad);
2574 
2575     /* we released the lock, check if the same pads are linked still */
2576     if (GST_PAD_PEER (srcpad) != sinkpad || GST_PAD_PEER (sinkpad) != srcpad)
2577       goto concurrent_link;
2578 
2579     if (G_UNLIKELY (result != GST_PAD_LINK_OK))
2580       goto link_failed;
2581   }
2582   GST_OBJECT_UNLOCK (sinkpad);
2583   GST_OBJECT_UNLOCK (srcpad);
2584 
2585   /* fire off a signal to each of the pads telling them
2586    * that they've been linked */
2587   g_signal_emit (srcpad, gst_pad_signals[PAD_LINKED], 0, sinkpad);
2588   g_signal_emit (sinkpad, gst_pad_signals[PAD_LINKED], 0, srcpad);
2589 
2590   GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
2591       GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2592 
2593   if (!(flags & GST_PAD_LINK_CHECK_NO_RECONFIGURE))
2594     gst_pad_send_event (srcpad, gst_event_new_reconfigure ());
2595 
2596 done:
2597   if (G_LIKELY (parent)) {
2598     gst_element_post_message (parent,
2599         gst_message_new_structure_change (GST_OBJECT_CAST (sinkpad),
2600             GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
2601     gst_object_unref (parent);
2602   }
2603 
2604   GST_TRACER_PAD_LINK_POST (srcpad, sinkpad, result);
2605   return result;
2606 
2607   /* ERRORS */
2608 concurrent_link:
2609   {
2610     GST_CAT_INFO (GST_CAT_PADS, "concurrent link between %s:%s and %s:%s",
2611         GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
2612     GST_OBJECT_UNLOCK (sinkpad);
2613     GST_OBJECT_UNLOCK (srcpad);
2614 
2615     /* The other link operation succeeded first */
2616     result = GST_PAD_LINK_WAS_LINKED;
2617     goto done;
2618   }
2619 link_failed:
2620   {
2621     GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed: %s",
2622         GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
2623         gst_pad_link_get_name (result));
2624 
2625     GST_PAD_PEER (srcpad) = NULL;
2626     GST_PAD_PEER (sinkpad) = NULL;
2627 
2628     GST_OBJECT_UNLOCK (sinkpad);
2629     GST_OBJECT_UNLOCK (srcpad);
2630 
2631     goto done;
2632   }
2633 }
2634 
2635 /**
2636  * gst_pad_link:
2637  * @srcpad: the source #GstPad to link.
2638  * @sinkpad: the sink #GstPad to link.
2639  *
2640  * Links the source pad and the sink pad.
2641  *
2642  * Returns: A result code indicating if the connection worked or
2643  *          what went wrong.
2644  *
2645  * MT Safe.
2646  */
2647 GstPadLinkReturn
gst_pad_link(GstPad * srcpad,GstPad * sinkpad)2648 gst_pad_link (GstPad * srcpad, GstPad * sinkpad)
2649 {
2650   return gst_pad_link_full (srcpad, sinkpad, GST_PAD_LINK_CHECK_DEFAULT);
2651 }
2652 
2653 static void
gst_pad_set_pad_template(GstPad * pad,GstPadTemplate * templ)2654 gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ)
2655 {
2656   GstPadTemplate **template_p;
2657 
2658   /* this function would need checks if it weren't static */
2659 
2660   GST_OBJECT_LOCK (pad);
2661   template_p = &pad->padtemplate;
2662   gst_object_replace ((GstObject **) template_p, (GstObject *) templ);
2663   GST_OBJECT_UNLOCK (pad);
2664 
2665   if (templ)
2666     gst_pad_template_pad_created (templ, pad);
2667 }
2668 
2669 /**
2670  * gst_pad_get_pad_template:
2671  * @pad: a #GstPad.
2672  *
2673  * Gets the template for @pad.
2674  *
2675  * Returns: (transfer full) (nullable): the #GstPadTemplate from which
2676  *     this pad was instantiated, or %NULL if this pad has no
2677  *     template. Unref after usage.
2678  */
2679 GstPadTemplate *
gst_pad_get_pad_template(GstPad * pad)2680 gst_pad_get_pad_template (GstPad * pad)
2681 {
2682   GstPadTemplate *templ;
2683 
2684   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2685 
2686   templ = GST_PAD_PAD_TEMPLATE (pad);
2687 
2688   return (templ ? gst_object_ref (templ) : NULL);
2689 }
2690 
2691 /**
2692  * gst_pad_has_current_caps:
2693  * @pad: a  #GstPad to check
2694  *
2695  * Check if @pad has caps set on it with a #GST_EVENT_CAPS event.
2696  *
2697  * Returns: %TRUE when @pad has caps associated with it.
2698  */
2699 gboolean
gst_pad_has_current_caps(GstPad * pad)2700 gst_pad_has_current_caps (GstPad * pad)
2701 {
2702   gboolean result;
2703   GstCaps *caps;
2704 
2705   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
2706 
2707   GST_OBJECT_LOCK (pad);
2708   caps = get_pad_caps (pad);
2709   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
2710       "check current pad caps %" GST_PTR_FORMAT, caps);
2711   result = (caps != NULL);
2712   GST_OBJECT_UNLOCK (pad);
2713 
2714   return result;
2715 }
2716 
2717 /**
2718  * gst_pad_get_current_caps:
2719  * @pad: a  #GstPad to get the current capabilities of.
2720  *
2721  * Gets the capabilities currently configured on @pad with the last
2722  * #GST_EVENT_CAPS event.
2723  *
2724  * Returns: (transfer full) (nullable): the current caps of the pad with
2725  * incremented ref-count or %NULL when pad has no caps. Unref after usage.
2726  */
2727 GstCaps *
gst_pad_get_current_caps(GstPad * pad)2728 gst_pad_get_current_caps (GstPad * pad)
2729 {
2730   GstCaps *result;
2731 
2732   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2733 
2734   GST_OBJECT_LOCK (pad);
2735   if ((result = get_pad_caps (pad)))
2736     gst_caps_ref (result);
2737   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
2738       "get current pad caps %" GST_PTR_FORMAT, result);
2739   GST_OBJECT_UNLOCK (pad);
2740 
2741   return result;
2742 }
2743 
2744 /**
2745  * gst_pad_get_pad_template_caps:
2746  * @pad: a #GstPad to get the template capabilities from.
2747  *
2748  * Gets the capabilities for @pad's template.
2749  *
2750  * Returns: (transfer full): the #GstCaps of this pad template.
2751  * Unref after usage.
2752  */
2753 GstCaps *
gst_pad_get_pad_template_caps(GstPad * pad)2754 gst_pad_get_pad_template_caps (GstPad * pad)
2755 {
2756   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2757 
2758   if (GST_PAD_PAD_TEMPLATE (pad))
2759     return gst_pad_template_get_caps (GST_PAD_PAD_TEMPLATE (pad));
2760 
2761   return gst_caps_ref (GST_CAPS_ANY);
2762 }
2763 
2764 /**
2765  * gst_pad_get_peer:
2766  * @pad: a #GstPad to get the peer of.
2767  *
2768  * Gets the peer of @pad. This function refs the peer pad so
2769  * you need to unref it after use.
2770  *
2771  * Returns: (transfer full) (nullable): the peer #GstPad. Unref after usage.
2772  *
2773  * MT safe.
2774  */
2775 GstPad *
gst_pad_get_peer(GstPad * pad)2776 gst_pad_get_peer (GstPad * pad)
2777 {
2778   GstPad *result;
2779 
2780   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2781 
2782   GST_OBJECT_LOCK (pad);
2783   result = GST_PAD_PEER (pad);
2784   if (result)
2785     gst_object_ref (result);
2786   GST_OBJECT_UNLOCK (pad);
2787 
2788   return result;
2789 }
2790 
2791 /**
2792  * gst_pad_get_allowed_caps:
2793  * @pad: a #GstPad.
2794  *
2795  * Gets the capabilities of the allowed media types that can flow through
2796  * @pad and its peer.
2797  *
2798  * The allowed capabilities is calculated as the intersection of the results of
2799  * calling gst_pad_query_caps() on @pad and its peer. The caller owns a reference
2800  * on the resulting caps.
2801  *
2802  * Returns: (transfer full) (nullable): the allowed #GstCaps of the
2803  *     pad link. Unref the caps when you no longer need it. This
2804  *     function returns %NULL when @pad has no peer.
2805  *
2806  * MT safe.
2807  */
2808 GstCaps *
gst_pad_get_allowed_caps(GstPad * pad)2809 gst_pad_get_allowed_caps (GstPad * pad)
2810 {
2811   GstCaps *mycaps;
2812   GstCaps *caps = NULL;
2813   GstQuery *query;
2814 
2815   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2816 
2817   GST_OBJECT_LOCK (pad);
2818   if (G_UNLIKELY (GST_PAD_PEER (pad) == NULL))
2819     goto no_peer;
2820   GST_OBJECT_UNLOCK (pad);
2821 
2822   GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting allowed caps");
2823 
2824   mycaps = gst_pad_query_caps (pad, NULL);
2825 
2826   /* Query peer caps */
2827   query = gst_query_new_caps (mycaps);
2828   if (!gst_pad_peer_query (pad, query)) {
2829     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "Caps query failed");
2830     goto end;
2831   }
2832 
2833   gst_query_parse_caps_result (query, &caps);
2834   if (caps == NULL) {
2835     g_warn_if_fail (caps != NULL);
2836     goto end;
2837   }
2838   gst_caps_ref (caps);
2839 
2840   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT,
2841       caps);
2842 
2843 end:
2844   gst_query_unref (query);
2845   gst_caps_unref (mycaps);
2846 
2847   return caps;
2848 
2849 no_peer:
2850   {
2851     GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer");
2852     GST_OBJECT_UNLOCK (pad);
2853 
2854     return NULL;
2855   }
2856 }
2857 
2858 /**
2859  * gst_pad_get_single_internal_link:
2860  * @pad: the #GstPad to get the internal link of.
2861  *
2862  * If there is a single internal link of the given pad, this function will
2863  * return it. Otherwise, it will return NULL.
2864  *
2865  * Returns: (transfer full) (nullable): a #GstPad, or %NULL if @pad has none
2866  * or more than one internal links. Unref returned pad with
2867  * gst_object_unref().
2868  *
2869  * Since: 1.18
2870  */
2871 GstPad *
gst_pad_get_single_internal_link(GstPad * pad)2872 gst_pad_get_single_internal_link (GstPad * pad)
2873 {
2874   GstIterator *iter;
2875   gboolean done = FALSE;
2876   GValue item = { 0, };
2877   GstPad *ret = NULL;
2878 
2879   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2880 
2881   iter = gst_pad_iterate_internal_links (pad);
2882 
2883   if (!iter)
2884     return NULL;
2885 
2886   while (!done) {
2887     switch (gst_iterator_next (iter, &item)) {
2888       case GST_ITERATOR_OK:
2889       {
2890         if (ret == NULL) {
2891           ret = g_value_dup_object (&item);
2892         } else {
2893           /* More than one internal link found - don't bother reffing */
2894           gst_clear_object (&ret);
2895           GST_DEBUG_OBJECT (pad,
2896               "Requested single internally linked pad, multiple found");
2897           done = TRUE;
2898         }
2899         g_value_reset (&item);
2900         break;
2901       }
2902       case GST_ITERATOR_RESYNC:
2903         gst_clear_object (&ret);
2904         gst_iterator_resync (iter);
2905         break;
2906       case GST_ITERATOR_ERROR:
2907         GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
2908         return NULL;
2909       case GST_ITERATOR_DONE:
2910         if (ret == NULL) {
2911           GST_DEBUG_OBJECT (pad,
2912               "Requested single internally linked pad, none found");
2913         }
2914         done = TRUE;
2915         break;
2916     }
2917   }
2918   g_value_unset (&item);
2919   gst_iterator_free (iter);
2920 
2921   return ret;
2922 }
2923 
2924 /**
2925  * gst_pad_iterate_internal_links_default:
2926  * @pad: the #GstPad to get the internal links of.
2927  * @parent: (allow-none): the parent of @pad or %NULL
2928  *
2929  * Iterate the list of pads to which the given pad is linked to inside of
2930  * the parent element.
2931  * This is the default handler, and thus returns an iterator of all of the
2932  * pads inside the parent element with opposite direction.
2933  *
2934  * The caller must free this iterator after use with gst_iterator_free().
2935  *
2936  * Returns: (nullable): a #GstIterator of #GstPad, or %NULL if @pad
2937  * has no parent. Unref each returned pad with gst_object_unref().
2938  */
2939 GstIterator *
gst_pad_iterate_internal_links_default(GstPad * pad,GstObject * parent)2940 gst_pad_iterate_internal_links_default (GstPad * pad, GstObject * parent)
2941 {
2942   GstIterator *res;
2943   GList **padlist;
2944   guint32 *cookie;
2945   GMutex *lock;
2946   gpointer owner;
2947   GstElement *eparent;
2948 
2949   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
2950 
2951   if (parent != NULL && GST_IS_ELEMENT (parent)) {
2952     eparent = GST_ELEMENT_CAST (gst_object_ref (parent));
2953   } else {
2954     GST_OBJECT_LOCK (pad);
2955     eparent = GST_PAD_PARENT (pad);
2956     if (!eparent || !GST_IS_ELEMENT (eparent))
2957       goto no_parent;
2958 
2959     gst_object_ref (eparent);
2960     GST_OBJECT_UNLOCK (pad);
2961   }
2962 
2963   if (pad->direction == GST_PAD_SRC)
2964     padlist = &eparent->sinkpads;
2965   else
2966     padlist = &eparent->srcpads;
2967 
2968   GST_DEBUG_OBJECT (pad, "Making iterator");
2969 
2970   cookie = &eparent->pads_cookie;
2971   owner = eparent;
2972   lock = GST_OBJECT_GET_LOCK (eparent);
2973 
2974   res = gst_iterator_new_list (GST_TYPE_PAD,
2975       lock, cookie, padlist, (GObject *) owner, NULL);
2976 
2977   gst_object_unref (owner);
2978 
2979   return res;
2980 
2981   /* ERRORS */
2982 no_parent:
2983   {
2984     GST_OBJECT_UNLOCK (pad);
2985     GST_DEBUG_OBJECT (pad, "no parent element");
2986     return NULL;
2987   }
2988 }
2989 
2990 /**
2991  * gst_pad_iterate_internal_links:
2992  * @pad: the GstPad to get the internal links of.
2993  *
2994  * Gets an iterator for the pads to which the given pad is linked to inside
2995  * of the parent element.
2996  *
2997  * Each #GstPad element yielded by the iterator will have its refcount increased,
2998  * so unref after use.
2999  *
3000  * Free-function: gst_iterator_free
3001  *
3002  * Returns: (transfer full) (nullable): a new #GstIterator of #GstPad
3003  *     or %NULL when the pad does not have an iterator function
3004  *     configured. Use gst_iterator_free() after usage.
3005  */
3006 GstIterator *
gst_pad_iterate_internal_links(GstPad * pad)3007 gst_pad_iterate_internal_links (GstPad * pad)
3008 {
3009   GstIterator *res = NULL;
3010   GstObject *parent;
3011 
3012   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
3013 
3014   GST_OBJECT_LOCK (pad);
3015   ACQUIRE_PARENT (pad, parent, no_parent);
3016   GST_OBJECT_UNLOCK (pad);
3017 
3018   if (GST_PAD_ITERINTLINKFUNC (pad))
3019     res = GST_PAD_ITERINTLINKFUNC (pad) (pad, parent);
3020 
3021   RELEASE_PARENT (parent);
3022 
3023   return res;
3024 
3025   /* ERRORS */
3026 no_parent:
3027   {
3028     GST_DEBUG_OBJECT (pad, "no parent");
3029     GST_OBJECT_UNLOCK (pad);
3030     return NULL;
3031   }
3032 }
3033 
3034 /**
3035  * gst_pad_forward:
3036  * @pad: a #GstPad
3037  * @forward: (scope call): a #GstPadForwardFunction
3038  * @user_data: user data passed to @forward
3039  *
3040  * Calls @forward for all internally linked pads of @pad. This function deals with
3041  * dynamically changing internal pads and will make sure that the @forward
3042  * function is only called once for each pad.
3043  *
3044  * When @forward returns %TRUE, no further pads will be processed.
3045  *
3046  * Returns: %TRUE if one of the dispatcher functions returned %TRUE.
3047  */
3048 gboolean
gst_pad_forward(GstPad * pad,GstPadForwardFunction forward,gpointer user_data)3049 gst_pad_forward (GstPad * pad, GstPadForwardFunction forward,
3050     gpointer user_data)
3051 {
3052   gboolean result = FALSE;
3053   GstIterator *iter;
3054   gboolean done = FALSE;
3055   GValue item = { 0, };
3056   GList *pushed_pads = NULL;
3057 
3058   iter = gst_pad_iterate_internal_links (pad);
3059 
3060   if (!iter)
3061     goto no_iter;
3062 
3063   while (!done) {
3064     switch (gst_iterator_next (iter, &item)) {
3065       case GST_ITERATOR_OK:
3066       {
3067         GstPad *intpad;
3068 
3069         intpad = g_value_get_object (&item);
3070 
3071         /* if already pushed, skip. FIXME, find something faster to tag pads */
3072         if (intpad == NULL || g_list_find (pushed_pads, intpad)) {
3073           g_value_reset (&item);
3074           break;
3075         }
3076 
3077         GST_LOG_OBJECT (pad, "calling forward function on pad %s:%s",
3078             GST_DEBUG_PAD_NAME (intpad));
3079         done = result = forward (intpad, user_data);
3080 
3081         pushed_pads = g_list_prepend (pushed_pads, intpad);
3082 
3083         g_value_reset (&item);
3084         break;
3085       }
3086       case GST_ITERATOR_RESYNC:
3087         /* We don't reset the result here because we don't push the event
3088          * again on pads that got the event already and because we need
3089          * to consider the result of the previous pushes */
3090         gst_iterator_resync (iter);
3091         break;
3092       case GST_ITERATOR_ERROR:
3093         GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
3094         done = TRUE;
3095         break;
3096       case GST_ITERATOR_DONE:
3097         done = TRUE;
3098         break;
3099     }
3100   }
3101   g_value_unset (&item);
3102   gst_iterator_free (iter);
3103 
3104   g_list_free (pushed_pads);
3105 
3106 no_iter:
3107   return result;
3108 }
3109 
3110 typedef struct
3111 {
3112   GstEvent *event;
3113   gboolean result;
3114   gboolean dispatched;
3115 } EventData;
3116 
3117 static gboolean
event_forward_func(GstPad * pad,EventData * data)3118 event_forward_func (GstPad * pad, EventData * data)
3119 {
3120   /* for each pad we send to, we should ref the event; it's up
3121    * to downstream to unref again when handled. */
3122   GST_LOG_OBJECT (pad, "Reffing and pushing event %p (%s) to %s:%s",
3123       data->event, GST_EVENT_TYPE_NAME (data->event), GST_DEBUG_PAD_NAME (pad));
3124 
3125   data->result |= gst_pad_push_event (pad, gst_event_ref (data->event));
3126 
3127   data->dispatched = TRUE;
3128 
3129   /* don't stop */
3130   return FALSE;
3131 }
3132 
3133 /**
3134  * gst_pad_event_default:
3135  * @pad: a #GstPad to call the default event handler on.
3136  * @parent: (allow-none): the parent of @pad or %NULL
3137  * @event: (transfer full): the #GstEvent to handle.
3138  *
3139  * Invokes the default event handler for the given pad.
3140  *
3141  * The EOS event will pause the task associated with @pad before it is forwarded
3142  * to all internally linked pads,
3143  *
3144  * The event is sent to all pads internally linked to @pad. This function
3145  * takes ownership of @event.
3146  *
3147  * Returns: %TRUE if the event was sent successfully.
3148  */
3149 gboolean
gst_pad_event_default(GstPad * pad,GstObject * parent,GstEvent * event)3150 gst_pad_event_default (GstPad * pad, GstObject * parent, GstEvent * event)
3151 {
3152   gboolean result, forward = TRUE;
3153 
3154   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
3155   g_return_val_if_fail (event != NULL, FALSE);
3156 
3157   GST_LOG_OBJECT (pad, "default event handler for event %" GST_PTR_FORMAT,
3158       event);
3159 
3160   switch (GST_EVENT_TYPE (event)) {
3161     case GST_EVENT_CAPS:
3162       forward = GST_PAD_IS_PROXY_CAPS (pad);
3163       result = TRUE;
3164       break;
3165     default:
3166       break;
3167   }
3168 
3169   if (forward) {
3170     EventData data;
3171 
3172     data.event = event;
3173     data.dispatched = FALSE;
3174     data.result = FALSE;
3175 
3176     gst_pad_forward (pad, (GstPadForwardFunction) event_forward_func, &data);
3177 
3178     /* for sinkpads without a parent element or without internal links, nothing
3179      * will be dispatched but we still want to return TRUE. */
3180     if (data.dispatched)
3181       result = data.result;
3182     else
3183       result = TRUE;
3184   }
3185 
3186   gst_event_unref (event);
3187 
3188   return result;
3189 }
3190 
3191 /* Default accept caps implementation just checks against
3192  * the allowed caps for the pad */
3193 static gboolean
gst_pad_query_accept_caps_default(GstPad * pad,GstQuery * query)3194 gst_pad_query_accept_caps_default (GstPad * pad, GstQuery * query)
3195 {
3196   /* get the caps and see if it intersects to something not empty */
3197   GstCaps *caps, *allowed = NULL;
3198   gboolean result;
3199 
3200   GST_DEBUG_OBJECT (pad, "query accept-caps %" GST_PTR_FORMAT, query);
3201 
3202   /* first forward the query to internally linked pads when we are dealing with
3203    * a PROXY CAPS */
3204   if (GST_PAD_IS_PROXY_CAPS (pad)) {
3205     result = gst_pad_proxy_query_accept_caps (pad, query);
3206     if (result)
3207       allowed = gst_pad_get_pad_template_caps (pad);
3208     else
3209       goto done;
3210   }
3211 
3212   gst_query_parse_accept_caps (query, &caps);
3213   if (!allowed) {
3214     if (GST_PAD_IS_ACCEPT_TEMPLATE (pad)) {
3215       allowed = gst_pad_get_pad_template_caps (pad);
3216     } else {
3217       GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, pad,
3218           "fallback ACCEPT_CAPS query, consider implementing a specialized version");
3219       allowed = gst_pad_query_caps (pad, caps);
3220     }
3221   }
3222 
3223   if (allowed) {
3224     if (GST_PAD_IS_ACCEPT_INTERSECT (pad)) {
3225       GST_DEBUG_OBJECT (pad,
3226           "allowed caps intersect %" GST_PTR_FORMAT ", caps %" GST_PTR_FORMAT,
3227           allowed, caps);
3228       result = gst_caps_can_intersect (caps, allowed);
3229     } else {
3230       GST_DEBUG_OBJECT (pad, "allowed caps subset %" GST_PTR_FORMAT ", caps %"
3231           GST_PTR_FORMAT, allowed, caps);
3232       result = gst_caps_is_subset (caps, allowed);
3233     }
3234     if (!result) {
3235       GST_CAT_WARNING_OBJECT (GST_CAT_CAPS, pad, "caps: %" GST_PTR_FORMAT
3236           " were not compatible with: %" GST_PTR_FORMAT, caps, allowed);
3237     }
3238     gst_caps_unref (allowed);
3239   } else {
3240     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3241         "no compatible caps allowed on the pad");
3242     result = FALSE;
3243   }
3244 
3245   gst_query_set_accept_caps_result (query, result);
3246 
3247 done:
3248   return TRUE;
3249 }
3250 
3251 /* Default caps implementation */
3252 static gboolean
gst_pad_query_caps_default(GstPad * pad,GstQuery * query)3253 gst_pad_query_caps_default (GstPad * pad, GstQuery * query)
3254 {
3255   GstCaps *result = NULL, *filter;
3256   GstPadTemplate *templ;
3257   gboolean fixed_caps;
3258 
3259   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "query caps %" GST_PTR_FORMAT,
3260       query);
3261 
3262   /* first try to proxy if we must */
3263   if (GST_PAD_IS_PROXY_CAPS (pad)) {
3264     if ((gst_pad_proxy_query_caps (pad, query))) {
3265       goto done;
3266     }
3267   }
3268 
3269   gst_query_parse_caps (query, &filter);
3270 
3271   /* no proxy or it failed, do default handling */
3272   fixed_caps = GST_PAD_IS_FIXED_CAPS (pad);
3273 
3274   GST_OBJECT_LOCK (pad);
3275   if (fixed_caps) {
3276     /* fixed caps, try the negotiated caps first */
3277     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "fixed pad caps: trying pad caps");
3278     if ((result = get_pad_caps (pad)))
3279       goto filter_done_unlock;
3280   }
3281 
3282   if ((templ = GST_PAD_PAD_TEMPLATE (pad))) {
3283     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "trying pad template caps");
3284     if ((result = GST_PAD_TEMPLATE_CAPS (templ)))
3285       goto filter_done_unlock;
3286   }
3287 
3288   if (!fixed_caps) {
3289     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3290         "non-fixed pad caps: trying pad caps");
3291     /* non fixed caps, try the negotiated caps */
3292     if ((result = get_pad_caps (pad)))
3293       goto filter_done_unlock;
3294   }
3295 
3296   /* this almost never happens */
3297   GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps");
3298   result = GST_CAPS_ANY;
3299 
3300 filter_done_unlock:
3301   GST_OBJECT_UNLOCK (pad);
3302 
3303   /* run the filter on the result */
3304   if (filter) {
3305     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3306         "using caps %p %" GST_PTR_FORMAT " with filter %p %"
3307         GST_PTR_FORMAT, result, result, filter, filter);
3308     result = gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
3309     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "result %p %" GST_PTR_FORMAT,
3310         result, result);
3311   } else {
3312     GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad,
3313         "using caps %p %" GST_PTR_FORMAT, result, result);
3314     result = gst_caps_ref (result);
3315   }
3316   gst_query_set_caps_result (query, result);
3317   gst_caps_unref (result);
3318 
3319 done:
3320   return TRUE;
3321 }
3322 
3323 /* Default latency implementation */
3324 typedef struct
3325 {
3326   gboolean live;
3327   GstClockTime min, max;
3328 } LatencyFoldData;
3329 
3330 static gboolean
query_latency_default_fold(const GValue * item,GValue * ret,gpointer user_data)3331 query_latency_default_fold (const GValue * item, GValue * ret,
3332     gpointer user_data)
3333 {
3334   GstPad *pad = g_value_get_object (item), *peer;
3335   LatencyFoldData *fold_data = user_data;
3336   GstQuery *query;
3337   gboolean res = FALSE;
3338 
3339   query = gst_query_new_latency ();
3340 
3341   peer = gst_pad_get_peer (pad);
3342   if (peer) {
3343     res = gst_pad_peer_query (pad, query);
3344   } else {
3345     GST_LOG_OBJECT (pad, "No peer pad found, ignoring this pad");
3346   }
3347 
3348   if (res) {
3349     gboolean live;
3350     GstClockTime min, max;
3351 
3352     gst_query_parse_latency (query, &live, &min, &max);
3353 
3354     GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT
3355         " max:%" G_GINT64_FORMAT, live ? "true" : "false", min, max);
3356 
3357     if (live) {
3358       if (min > fold_data->min)
3359         fold_data->min = min;
3360 
3361       if (fold_data->max == GST_CLOCK_TIME_NONE)
3362         fold_data->max = max;
3363       else if (max < fold_data->max)
3364         fold_data->max = max;
3365 
3366       fold_data->live = TRUE;
3367     }
3368   } else if (peer) {
3369     GST_DEBUG_OBJECT (pad, "latency query failed");
3370     g_value_set_boolean (ret, FALSE);
3371   }
3372 
3373   gst_query_unref (query);
3374   if (peer)
3375     gst_object_unref (peer);
3376 
3377   return TRUE;
3378 }
3379 
3380 static gboolean
gst_pad_query_latency_default(GstPad * pad,GstQuery * query)3381 gst_pad_query_latency_default (GstPad * pad, GstQuery * query)
3382 {
3383   GstIterator *it;
3384   GstIteratorResult res;
3385   GValue ret = G_VALUE_INIT;
3386   gboolean query_ret;
3387   LatencyFoldData fold_data;
3388 
3389   it = gst_pad_iterate_internal_links (pad);
3390   if (!it) {
3391     GST_DEBUG_OBJECT (pad, "Can't iterate internal links");
3392     return FALSE;
3393   }
3394 
3395   g_value_init (&ret, G_TYPE_BOOLEAN);
3396 
3397 retry:
3398   fold_data.live = FALSE;
3399   fold_data.min = 0;
3400   fold_data.max = GST_CLOCK_TIME_NONE;
3401 
3402   g_value_set_boolean (&ret, TRUE);
3403   res = gst_iterator_fold (it, query_latency_default_fold, &ret, &fold_data);
3404   switch (res) {
3405     case GST_ITERATOR_OK:
3406       g_assert_not_reached ();
3407       break;
3408     case GST_ITERATOR_DONE:
3409       break;
3410     case GST_ITERATOR_ERROR:
3411       g_value_set_boolean (&ret, FALSE);
3412       break;
3413     case GST_ITERATOR_RESYNC:
3414       gst_iterator_resync (it);
3415       goto retry;
3416     default:
3417       g_assert_not_reached ();
3418       break;
3419   }
3420   gst_iterator_free (it);
3421 
3422   query_ret = g_value_get_boolean (&ret);
3423   if (query_ret) {
3424     GST_LOG_OBJECT (pad, "got latency live:%s min:%" G_GINT64_FORMAT
3425         " max:%" G_GINT64_FORMAT, fold_data.live ? "true" : "false",
3426         fold_data.min, fold_data.max);
3427 
3428     if (fold_data.min > fold_data.max) {
3429       GST_ERROR_OBJECT (pad, "minimum latency bigger than maximum latency");
3430     }
3431 
3432     gst_query_set_latency (query, fold_data.live, fold_data.min, fold_data.max);
3433   } else {
3434     GST_LOG_OBJECT (pad, "latency query failed");
3435   }
3436 
3437   return query_ret;
3438 }
3439 
3440 typedef struct
3441 {
3442   GstQuery *query;
3443   gboolean result;
3444   gboolean dispatched;
3445 } QueryData;
3446 
3447 static gboolean
query_forward_func(GstPad * pad,QueryData * data)3448 query_forward_func (GstPad * pad, QueryData * data)
3449 {
3450   GST_LOG_OBJECT (pad, "query peer %p (%s) of %s:%s",
3451       data->query, GST_QUERY_TYPE_NAME (data->query), GST_DEBUG_PAD_NAME (pad));
3452 
3453   data->result |= gst_pad_peer_query (pad, data->query);
3454 
3455   data->dispatched = TRUE;
3456 
3457   /* stop on first successful reply */
3458   return data->result;
3459 }
3460 
3461 /**
3462  * gst_pad_query_default:
3463  * @pad: a #GstPad to call the default query handler on.
3464  * @parent: (allow-none): the parent of @pad or %NULL
3465  * @query: (transfer none): the #GstQuery to handle.
3466  *
3467  * Invokes the default query handler for the given pad.
3468  * The query is sent to all pads internally linked to @pad. Note that
3469  * if there are many possible sink pads that are internally linked to
3470  * @pad, only one will be sent the query.
3471  * Multi-sinkpad elements should implement custom query handlers.
3472  *
3473  * Returns: %TRUE if the query was performed successfully.
3474  */
3475 gboolean
gst_pad_query_default(GstPad * pad,GstObject * parent,GstQuery * query)3476 gst_pad_query_default (GstPad * pad, GstObject * parent, GstQuery * query)
3477 {
3478   gboolean forward, ret = FALSE;
3479 
3480   switch (GST_QUERY_TYPE (query)) {
3481     case GST_QUERY_SCHEDULING:
3482       forward = GST_PAD_IS_PROXY_SCHEDULING (pad);
3483       break;
3484     case GST_QUERY_ALLOCATION:
3485       forward = GST_PAD_IS_PROXY_ALLOCATION (pad);
3486       break;
3487     case GST_QUERY_ACCEPT_CAPS:
3488       ret = gst_pad_query_accept_caps_default (pad, query);
3489       forward = FALSE;
3490       break;
3491     case GST_QUERY_CAPS:
3492       ret = gst_pad_query_caps_default (pad, query);
3493       forward = FALSE;
3494       break;
3495     case GST_QUERY_LATENCY:
3496       ret = gst_pad_query_latency_default (pad, query);
3497       forward = FALSE;
3498       break;
3499     case GST_QUERY_BITRATE:
3500       /* FIXME: better default handling */
3501       forward = TRUE;
3502       break;
3503     case GST_QUERY_POSITION:
3504     case GST_QUERY_SEEKING:
3505     case GST_QUERY_FORMATS:
3506     case GST_QUERY_JITTER:
3507     case GST_QUERY_RATE:
3508     case GST_QUERY_CONVERT:
3509     default:
3510       forward = TRUE;
3511       break;
3512   }
3513 
3514   GST_DEBUG_OBJECT (pad, "%sforwarding %p (%s) query", (forward ? "" : "not "),
3515       query, GST_QUERY_TYPE_NAME (query));
3516 
3517   if (forward) {
3518     QueryData data;
3519 
3520     data.query = query;
3521     data.dispatched = FALSE;
3522     data.result = FALSE;
3523 
3524     gst_pad_forward (pad, (GstPadForwardFunction) query_forward_func, &data);
3525 
3526     if (data.dispatched) {
3527       ret = data.result;
3528     } else {
3529       /* nothing dispatched, assume drained */
3530       if (GST_QUERY_TYPE (query) == GST_QUERY_DRAIN)
3531         ret = TRUE;
3532       else
3533         ret = FALSE;
3534     }
3535   }
3536   return ret;
3537 }
3538 
3539 #define N_STACK_ALLOCATE_PROBES (16)
3540 
3541 /* A helper that checks if a probe was already
3542  * in the called_probes list, and adds it if
3543  * not. Used to avoid calling probes a 2nd time when
3544  * looping again after probe removal */
3545 static gboolean
check_probe_already_called(GHook * hook,ProbeMarshall * data)3546 check_probe_already_called (GHook * hook, ProbeMarshall * data)
3547 {
3548   guint i;
3549 
3550   /* if we have called this callback, do nothing. But only check
3551    * if we're actually calling probes a second time */
3552   if (data->retry) {
3553     for (i = 0; i < data->n_called_probes; i++) {
3554       if (data->called_probes[i] == hook->hook_id) {
3555         return TRUE;
3556       }
3557     }
3558   }
3559 
3560   /* reallocate on the heap if we had more than 16 probes */
3561   if (data->n_called_probes == data->called_probes_size) {
3562     if (data->called_probes_size > N_STACK_ALLOCATE_PROBES) {
3563       data->called_probes_size *= 2;
3564       data->called_probes =
3565           g_renew (gulong, data->called_probes, data->called_probes_size);
3566     } else {
3567       gulong *tmp = data->called_probes;
3568 
3569       data->called_probes_size *= 2;
3570       data->called_probes = g_new (gulong, data->called_probes_size);
3571       memcpy (data->called_probes, tmp,
3572           N_STACK_ALLOCATE_PROBES * sizeof (gulong));
3573     }
3574   }
3575   data->called_probes[data->n_called_probes++] = hook->hook_id;
3576 
3577   /* This probe was not alraedy called */
3578   return FALSE;
3579 }
3580 
3581 static void
probe_hook_marshal(GHook * hook,ProbeMarshall * data)3582 probe_hook_marshal (GHook * hook, ProbeMarshall * data)
3583 {
3584   GstPad *pad = data->pad;
3585   GstPadProbeInfo *info = data->info;
3586   GstPadProbeType type, flags;
3587   GstPadProbeCallback callback;
3588   GstPadProbeReturn ret;
3589   gpointer original_data;
3590 
3591   flags = hook->flags >> G_HOOK_FLAG_USER_SHIFT;
3592   type = info->type;
3593   original_data = info->data;
3594 
3595   /* one of the scheduling types */
3596   if ((flags & GST_PAD_PROBE_TYPE_SCHEDULING & type) == 0)
3597     goto no_match;
3598 
3599   if (G_UNLIKELY (data->handled)) {
3600     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3601         "probe previously returned HANDLED, not calling again");
3602     goto no_match;
3603   } else if (G_UNLIKELY (data->dropped)) {
3604     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3605         "probe previously returned DROPPED, not calling again");
3606     goto no_match;
3607   }
3608 
3609   if (type & GST_PAD_PROBE_TYPE_PUSH) {
3610     /* one of the data types for non-idle probes */
3611     if ((type & GST_PAD_PROBE_TYPE_IDLE) == 0
3612         && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0)
3613       goto no_match;
3614   } else if (type & GST_PAD_PROBE_TYPE_PULL) {
3615     /* one of the data types for non-idle probes */
3616     if ((type & GST_PAD_PROBE_TYPE_BLOCKING) == 0
3617         && (flags & _PAD_PROBE_TYPE_ALL_BOTH_AND_FLUSH & type) == 0)
3618       goto no_match;
3619   } else {
3620     /* Type must have PULL or PUSH probe types */
3621     g_assert_not_reached ();
3622   }
3623 
3624   /* one of the blocking types must match */
3625   if ((type & GST_PAD_PROBE_TYPE_BLOCKING) &&
3626       (flags & GST_PAD_PROBE_TYPE_BLOCKING & type) == 0)
3627     goto no_match;
3628   if ((type & GST_PAD_PROBE_TYPE_BLOCKING) == 0 &&
3629       (flags & GST_PAD_PROBE_TYPE_BLOCKING))
3630     goto no_match;
3631   /* only probes that have GST_PAD_PROBE_TYPE_EVENT_FLUSH set */
3632   if ((type & GST_PAD_PROBE_TYPE_EVENT_FLUSH) &&
3633       (flags & GST_PAD_PROBE_TYPE_EVENT_FLUSH & type) == 0)
3634     goto no_match;
3635 
3636   if (check_probe_already_called (hook, data)) {
3637     /* Reset marshalled = TRUE here, because the probe
3638      * was already called and set it the first time around,
3639      * and we may want to keep blocking on it.
3640      *
3641      * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
3642      */
3643     data->marshalled = TRUE;
3644     goto already_called;
3645   }
3646 
3647   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3648       "hook %lu with flags 0x%08x matches", hook->hook_id, flags);
3649 
3650   callback = (GstPadProbeCallback) hook->func;
3651   if (callback == NULL) {
3652     /* No callback is equivalent to just returning GST_PAD_PROBE_OK */
3653     data->marshalled = TRUE;
3654     return;
3655   }
3656 
3657   info->id = hook->hook_id;
3658 
3659   if ((flags & GST_PAD_PROBE_TYPE_IDLE))
3660     pad->priv->idle_running++;
3661 
3662   GST_OBJECT_UNLOCK (pad);
3663 
3664   ret = callback (pad, info, hook->data);
3665 
3666   GST_OBJECT_LOCK (pad);
3667 
3668   /* If the probe callback asked for the
3669    * probe to be removed, don't set the marshalled flag
3670    * otherwise, you can get a case where you return
3671    * GST_PAD_PROBE_REMOVE from a buffer probe and
3672    * then the pad blocks anyway if there's any other
3673    * blocking probes installed.
3674    *
3675    * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/658
3676    */
3677   if (ret != GST_PAD_PROBE_REMOVE)
3678     data->marshalled = TRUE;
3679 
3680   if ((flags & GST_PAD_PROBE_TYPE_IDLE))
3681     pad->priv->idle_running--;
3682 
3683   if (ret != GST_PAD_PROBE_HANDLED && original_data != NULL
3684       && info->data == NULL) {
3685     GST_DEBUG_OBJECT (pad, "data item in pad probe info was dropped");
3686     info->type = GST_PAD_PROBE_TYPE_INVALID;
3687     data->dropped = TRUE;
3688   }
3689 
3690   switch (ret) {
3691     case GST_PAD_PROBE_REMOVE:
3692       /* remove the probe */
3693       GST_DEBUG_OBJECT (pad, "asked to remove hook");
3694       cleanup_hook (pad, hook);
3695       break;
3696     case GST_PAD_PROBE_DROP:
3697       /* need to drop the data, make sure other probes don't get called
3698        * anymore */
3699       GST_DEBUG_OBJECT (pad, "asked to drop item");
3700       info->type = GST_PAD_PROBE_TYPE_INVALID;
3701       data->dropped = TRUE;
3702       break;
3703     case GST_PAD_PROBE_HANDLED:
3704       GST_DEBUG_OBJECT (pad, "probe handled data");
3705       data->handled = TRUE;
3706       break;
3707     case GST_PAD_PROBE_PASS:
3708       /* inform the pad block to let things pass */
3709       GST_DEBUG_OBJECT (pad, "asked to pass item");
3710       data->pass = TRUE;
3711       break;
3712     case GST_PAD_PROBE_OK:
3713       GST_DEBUG_OBJECT (pad, "probe returned OK");
3714       break;
3715     default:
3716       GST_DEBUG_OBJECT (pad, "probe returned %d", ret);
3717       break;
3718   }
3719   return;
3720 
3721 no_match:
3722   {
3723     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3724         "hook %lu with flags 0x%08x does not match %08x",
3725         hook->hook_id, flags, info->type);
3726     return;
3727   }
3728 already_called:
3729   {
3730     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3731         "hook %lu already called", hook->hook_id);
3732     return;
3733   }
3734 }
3735 
3736 /* a probe that does not take or return any data */
3737 #define PROBE_NO_DATA(pad,mask,label,defaultval)                \
3738   G_STMT_START {						\
3739     if (G_UNLIKELY (pad->num_probes)) {				\
3740       GstFlowReturn pval = defaultval;				\
3741       /* pass NULL as the data item */                          \
3742       GstPadProbeInfo info = { mask, 0, NULL, 0, 0 };		\
3743       info.ABI.abi.flow_ret = defaultval;			\
3744       ret = do_probe_callbacks (pad, &info, defaultval);	\
3745       if (G_UNLIKELY (ret != pval && ret != GST_FLOW_OK))	\
3746         goto label;						\
3747     }								\
3748   } G_STMT_END
3749 
3750 #define PROBE_FULL(pad,mask,data,offs,size,label,handleable,handle_label) \
3751   G_STMT_START {							\
3752     if (G_UNLIKELY (pad->num_probes)) {					\
3753       /* pass the data item */						\
3754       GstPadProbeInfo info = { mask, 0, data, offs, size };		\
3755       info.ABI.abi.flow_ret = GST_FLOW_OK;				\
3756       ret = do_probe_callbacks (pad, &info, GST_FLOW_OK);		\
3757       /* store the possibly updated data item */			\
3758       data = GST_PAD_PROBE_INFO_DATA (&info);				\
3759       /* if something went wrong, exit */				\
3760       if (G_UNLIKELY (ret != GST_FLOW_OK)) {				\
3761 	if (handleable && ret == GST_FLOW_CUSTOM_SUCCESS_1) {		\
3762 	  ret = info.ABI.abi.flow_ret;						\
3763 	  goto handle_label;						\
3764 	}								\
3765 	goto label;							\
3766       }									\
3767     }									\
3768   } G_STMT_END
3769 
3770 #define PROBE_PUSH(pad,mask,data,label)		\
3771   PROBE_FULL(pad, mask, data, -1, -1, label, FALSE, label);
3772 #define PROBE_HANDLE(pad,mask,data,label,handle_label)	\
3773   PROBE_FULL(pad, mask, data, -1, -1, label, TRUE, handle_label);
3774 #define PROBE_PULL(pad,mask,data,offs,size,label)		\
3775   PROBE_FULL(pad, mask, data, offs, size, label, FALSE, label);
3776 
3777 static GstFlowReturn
do_pad_idle_probe_wait(GstPad * pad)3778 do_pad_idle_probe_wait (GstPad * pad)
3779 {
3780   while (GST_PAD_IS_RUNNING_IDLE_PROBE (pad)) {
3781     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3782         "waiting idle probe to be removed");
3783     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING);
3784     GST_PAD_BLOCK_WAIT (pad);
3785     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING);
3786     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked");
3787 
3788     if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
3789       return GST_FLOW_FLUSHING;
3790   }
3791   return GST_FLOW_OK;
3792 }
3793 
3794 #define PROBE_TYPE_IS_SERIALIZED(i) \
3795     ( \
3796       ( \
3797         (((i)->type & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | \
3798         GST_PAD_PROBE_TYPE_EVENT_FLUSH)) && \
3799         GST_EVENT_IS_SERIALIZED ((i)->data)) \
3800       ) || ( \
3801         (((i)->type & GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM) && \
3802         GST_QUERY_IS_SERIALIZED ((i)->data)) \
3803       ) || ( \
3804         ((i)->type & (GST_PAD_PROBE_TYPE_BUFFER | \
3805         GST_PAD_PROBE_TYPE_BUFFER_LIST))  \
3806       ) \
3807     )
3808 
3809 static GstFlowReturn
do_probe_callbacks(GstPad * pad,GstPadProbeInfo * info,GstFlowReturn defaultval)3810 do_probe_callbacks (GstPad * pad, GstPadProbeInfo * info,
3811     GstFlowReturn defaultval)
3812 {
3813   ProbeMarshall data;
3814   guint cookie;
3815   gboolean is_block;
3816   gulong called_probes[N_STACK_ALLOCATE_PROBES];
3817 
3818   data.pad = pad;
3819   data.info = info;
3820   data.pass = FALSE;
3821   data.handled = FALSE;
3822   data.dropped = FALSE;
3823 
3824   /* We stack-allocate for N_STACK_ALLOCATE_PROBES hooks as a first step. If more are needed,
3825    * we will re-allocate with g_malloc(). This should usually never be needed
3826    */
3827   data.called_probes = called_probes;
3828   data.n_called_probes = 0;
3829   data.called_probes_size = N_STACK_ALLOCATE_PROBES;
3830   data.retry = FALSE;
3831 
3832   is_block =
3833       (info->type & GST_PAD_PROBE_TYPE_BLOCK) == GST_PAD_PROBE_TYPE_BLOCK;
3834 
3835   if (is_block && PROBE_TYPE_IS_SERIALIZED (info)) {
3836     if (do_pad_idle_probe_wait (pad) == GST_FLOW_FLUSHING)
3837       goto flushing;
3838   }
3839 
3840 again:
3841   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "do probes");
3842   cookie = pad->priv->probe_list_cookie;
3843 
3844   /* Clear the marshalled flag before doing callbacks. Only if
3845    * there are matching callbacks still will it get set */
3846   data.marshalled = FALSE;
3847 
3848   g_hook_list_marshal (&pad->probes, TRUE,
3849       (GHookMarshaller) probe_hook_marshal, &data);
3850 
3851   /* if the list changed, call the new callbacks (they will not be in
3852    * called_probes yet) */
3853   if (cookie != pad->priv->probe_list_cookie) {
3854     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3855         "probe list changed, restarting");
3856     data.retry = TRUE;
3857     goto again;
3858   }
3859 
3860   /* the first item that dropped will stop the hooks and then we drop here */
3861   if (data.dropped)
3862     goto dropped;
3863 
3864   /* If one handler took care of it, let the the item pass */
3865   if (data.handled) {
3866     goto handled;
3867   }
3868 
3869   /* if no handler matched and we are blocking, let the item pass */
3870   if (!data.marshalled && is_block)
3871     goto passed;
3872 
3873   /* At this point, all handlers returned either OK or PASS. If one handler
3874    * returned PASS, let the item pass */
3875   if (data.pass)
3876     goto passed;
3877 
3878   if (is_block) {
3879     while (GST_PAD_IS_BLOCKED (pad)) {
3880       GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3881           "we are blocked %d times", pad->num_blocked);
3882 
3883       /* we might have released the lock */
3884       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
3885         goto flushing;
3886 
3887       /* now we block the streaming thread. It can be unlocked when we
3888        * deactivate the pad (which will also set the FLUSHING flag) or
3889        * when the pad is unblocked. A flushing event will also unblock
3890        * the pad after setting the FLUSHING flag. */
3891       GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3892           "Waiting to be unblocked or set flushing");
3893       GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_BLOCKING);
3894       GST_PAD_BLOCK_WAIT (pad);
3895       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_BLOCKING);
3896       GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "We got unblocked");
3897 
3898       /* if the list changed, call the new callbacks (they will not be in
3899        * called_probes yet) */
3900       if (cookie != pad->priv->probe_list_cookie) {
3901         GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
3902             "probe list changed, restarting");
3903         data.retry = TRUE;
3904         goto again;
3905       }
3906 
3907       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
3908         goto flushing;
3909     }
3910   }
3911 
3912   if (data.called_probes_size > N_STACK_ALLOCATE_PROBES)
3913     g_free (data.called_probes);
3914 
3915   return defaultval;
3916 
3917   /* ERRORS */
3918 flushing:
3919   {
3920     GST_DEBUG_OBJECT (pad, "pad is flushing");
3921     if (data.called_probes_size > N_STACK_ALLOCATE_PROBES)
3922       g_free (data.called_probes);
3923     return GST_FLOW_FLUSHING;
3924   }
3925 dropped:
3926   {
3927     GST_DEBUG_OBJECT (pad, "data is dropped");
3928     if (data.called_probes_size > N_STACK_ALLOCATE_PROBES)
3929       g_free (data.called_probes);
3930     return GST_FLOW_CUSTOM_SUCCESS;
3931   }
3932 passed:
3933   {
3934     /* FIXME : Should we return FLOW_OK or the defaultval ?? */
3935     GST_DEBUG_OBJECT (pad, "data is passed");
3936     if (data.called_probes_size > N_STACK_ALLOCATE_PROBES)
3937       g_free (data.called_probes);
3938     return GST_FLOW_OK;
3939   }
3940 handled:
3941   {
3942     GST_DEBUG_OBJECT (pad, "data was handled");
3943     if (data.called_probes_size > N_STACK_ALLOCATE_PROBES)
3944       g_free (data.called_probes);
3945     return GST_FLOW_CUSTOM_SUCCESS_1;
3946   }
3947 }
3948 
3949 /* pad offsets */
3950 
3951 /**
3952  * gst_pad_get_offset:
3953  * @pad: a #GstPad
3954  *
3955  * Get the offset applied to the running time of @pad. @pad has to be a source
3956  * pad.
3957  *
3958  * Returns: the offset.
3959  */
3960 gint64
gst_pad_get_offset(GstPad * pad)3961 gst_pad_get_offset (GstPad * pad)
3962 {
3963   gint64 result;
3964 
3965   g_return_val_if_fail (GST_IS_PAD (pad), 0);
3966 
3967   GST_OBJECT_LOCK (pad);
3968   result = pad->offset;
3969   GST_OBJECT_UNLOCK (pad);
3970 
3971   return result;
3972 }
3973 
3974 static gboolean
mark_event_not_received(GstPad * pad,PadEvent * ev,gpointer user_data)3975 mark_event_not_received (GstPad * pad, PadEvent * ev, gpointer user_data)
3976 {
3977   ev->received = FALSE;
3978   return TRUE;
3979 }
3980 
3981 /**
3982  * gst_pad_set_offset:
3983  * @pad: a #GstPad
3984  * @offset: the offset
3985  *
3986  * Set the offset that will be applied to the running time of @pad.
3987  */
3988 void
gst_pad_set_offset(GstPad * pad,gint64 offset)3989 gst_pad_set_offset (GstPad * pad, gint64 offset)
3990 {
3991   g_return_if_fail (GST_IS_PAD (pad));
3992 
3993   GST_OBJECT_LOCK (pad);
3994   /* if nothing changed, do nothing */
3995   if (pad->offset == offset)
3996     goto done;
3997 
3998   pad->offset = offset;
3999   GST_DEBUG_OBJECT (pad, "changed offset to %" GST_STIME_FORMAT,
4000       GST_STIME_ARGS (offset));
4001 
4002   /* resend all sticky events with updated offset on next buffer push */
4003   events_foreach (pad, mark_event_not_received, NULL);
4004   GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
4005 
4006 done:
4007   GST_OBJECT_UNLOCK (pad);
4008 }
4009 
4010 typedef struct
4011 {
4012   GstFlowReturn ret;
4013 
4014   /* If TRUE and ret is not OK this means
4015    * that pushing the EOS event failed
4016    */
4017   gboolean was_eos;
4018 
4019   /* If called for an event this is
4020    * the event that would be pushed
4021    * next. Don't forward sticky events
4022    * that would come after that */
4023   GstEvent *event;
4024 } PushStickyData;
4025 
4026 /* should be called with pad LOCK */
4027 static gboolean
push_sticky(GstPad * pad,PadEvent * ev,gpointer user_data)4028 push_sticky (GstPad * pad, PadEvent * ev, gpointer user_data)
4029 {
4030   PushStickyData *data = user_data;
4031   GstEvent *event = ev->event;
4032 
4033   if (ev->received) {
4034     GST_DEBUG_OBJECT (pad, "event %s was already received",
4035         GST_EVENT_TYPE_NAME (event));
4036     return TRUE;
4037   }
4038 
4039   /* If we're called because of an sticky event, only forward
4040    * events that would come before this new event and the
4041    * event itself */
4042   if (data->event && GST_EVENT_IS_STICKY (data->event) &&
4043       GST_EVENT_TYPE (data->event) <= GST_EVENT_SEGMENT &&
4044       GST_EVENT_TYPE (data->event) < GST_EVENT_TYPE (event)) {
4045     data->ret = GST_FLOW_CUSTOM_SUCCESS_1;
4046   } else {
4047     data->ret = gst_pad_push_event_unchecked (pad, gst_event_ref (event),
4048         GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
4049     if (data->ret == GST_FLOW_CUSTOM_SUCCESS_1)
4050       data->ret = GST_FLOW_OK;
4051   }
4052 
4053   switch (data->ret) {
4054     case GST_FLOW_OK:
4055       ev->received = TRUE;
4056       GST_DEBUG_OBJECT (pad, "event %s marked received",
4057           GST_EVENT_TYPE_NAME (event));
4058       break;
4059     case GST_FLOW_CUSTOM_SUCCESS:
4060       /* we can't assume the event is received when it was dropped */
4061       GST_DEBUG_OBJECT (pad, "event %s was dropped, mark pending",
4062           GST_EVENT_TYPE_NAME (event));
4063       GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
4064       data->ret = GST_FLOW_OK;
4065       break;
4066     case GST_FLOW_CUSTOM_SUCCESS_1:
4067       /* event was ignored and should be sent later */
4068       GST_DEBUG_OBJECT (pad, "event %s was ignored, mark pending",
4069           GST_EVENT_TYPE_NAME (event));
4070       GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
4071       data->ret = GST_FLOW_OK;
4072       break;
4073     case GST_FLOW_NOT_LINKED:
4074       /* not linked is not a problem, we are sticky so the event will be
4075        * rescheduled to be sent later on re-link, but only for non-EOS events */
4076       GST_DEBUG_OBJECT (pad, "pad was not linked, mark pending");
4077       if (GST_EVENT_TYPE (event) != GST_EVENT_EOS) {
4078         data->ret = GST_FLOW_OK;
4079         ev->received = TRUE;
4080       }
4081       break;
4082     default:
4083       GST_DEBUG_OBJECT (pad, "result %s, mark pending events",
4084           gst_flow_get_name (data->ret));
4085       GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
4086       break;
4087   }
4088 
4089   if (data->ret != GST_FLOW_OK && GST_EVENT_TYPE (event) == GST_EVENT_EOS)
4090     data->was_eos = TRUE;
4091 
4092   return data->ret == GST_FLOW_OK;
4093 }
4094 
4095 /* check sticky events and push them when needed. should be called
4096  * with pad LOCK */
4097 static inline GstFlowReturn
check_sticky(GstPad * pad,GstEvent * event)4098 check_sticky (GstPad * pad, GstEvent * event)
4099 {
4100   PushStickyData data = { GST_FLOW_OK, FALSE, event };
4101 
4102   if (G_UNLIKELY (GST_PAD_HAS_PENDING_EVENTS (pad))) {
4103     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
4104 
4105     GST_DEBUG_OBJECT (pad, "pushing all sticky events");
4106     events_foreach (pad, push_sticky, &data);
4107 
4108     /* If there's an EOS event we must push it downstream
4109      * even if sending a previous sticky event failed.
4110      * Otherwise the pipeline might wait forever for EOS.
4111      *
4112      * Only do this if pushing another event than the EOS
4113      * event failed.
4114      */
4115     if (data.ret != GST_FLOW_OK && !data.was_eos) {
4116       PadEvent *ev = find_event_by_type (pad, GST_EVENT_EOS, 0);
4117 
4118       if (ev && !ev->received) {
4119         data.ret = gst_pad_push_event_unchecked (pad, gst_event_ref (ev->event),
4120             GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM);
4121         /* the event could have been dropped. Because this can only
4122          * happen if the user asked for it, it's not an error */
4123         if (data.ret == GST_FLOW_CUSTOM_SUCCESS)
4124           data.ret = GST_FLOW_OK;
4125       }
4126     }
4127   }
4128   return data.ret;
4129 }
4130 
4131 
4132 /**
4133  * gst_pad_query:
4134  * @pad: a #GstPad to invoke the default query on.
4135  * @query: (transfer none): the #GstQuery to perform.
4136  *
4137  * Dispatches a query to a pad. The query should have been allocated by the
4138  * caller via one of the type-specific allocation functions. The element that
4139  * the pad belongs to is responsible for filling the query with an appropriate
4140  * response, which should then be parsed with a type-specific query parsing
4141  * function.
4142  *
4143  * Again, the caller is responsible for both the allocation and deallocation of
4144  * the query structure.
4145  *
4146  * Please also note that some queries might need a running pipeline to work.
4147  *
4148  * Returns: %TRUE if the query could be performed.
4149  */
4150 gboolean
gst_pad_query(GstPad * pad,GstQuery * query)4151 gst_pad_query (GstPad * pad, GstQuery * query)
4152 {
4153   GstObject *parent;
4154   gboolean res, serialized;
4155   GstPadQueryFunction func;
4156   GstPadProbeType type;
4157   GstFlowReturn ret;
4158 
4159   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
4160   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
4161 
4162   if (GST_PAD_IS_SRC (pad)) {
4163     if (G_UNLIKELY (!GST_QUERY_IS_UPSTREAM (query)))
4164       goto wrong_direction;
4165     type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM;
4166   } else if (GST_PAD_IS_SINK (pad)) {
4167     if (G_UNLIKELY (!GST_QUERY_IS_DOWNSTREAM (query)))
4168       goto wrong_direction;
4169     type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM;
4170   } else
4171     goto unknown_direction;
4172 
4173   GST_DEBUG_OBJECT (pad, "doing query %p (%s)", query,
4174       GST_QUERY_TYPE_NAME (query));
4175   GST_TRACER_PAD_QUERY_PRE (pad, query);
4176 
4177   serialized = GST_QUERY_IS_SERIALIZED (query);
4178   if (G_UNLIKELY (serialized))
4179     GST_PAD_STREAM_LOCK (pad);
4180 
4181   GST_OBJECT_LOCK (pad);
4182   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
4183       GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
4184   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
4185 
4186   ACQUIRE_PARENT (pad, parent, no_parent);
4187   GST_OBJECT_UNLOCK (pad);
4188 
4189   if ((func = GST_PAD_QUERYFUNC (pad)) == NULL)
4190     goto no_func;
4191 
4192   res = func (pad, parent, query);
4193 
4194   RELEASE_PARENT (parent);
4195 
4196   GST_DEBUG_OBJECT (pad, "sent query %p (%s), result %d", query,
4197       GST_QUERY_TYPE_NAME (query), res);
4198   GST_TRACER_PAD_QUERY_POST (pad, query, res);
4199 
4200   if (res != TRUE)
4201     goto query_failed;
4202 
4203   GST_OBJECT_LOCK (pad);
4204   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped);
4205   GST_OBJECT_UNLOCK (pad);
4206 
4207   if (G_UNLIKELY (serialized))
4208     GST_PAD_STREAM_UNLOCK (pad);
4209 
4210   return res;
4211 
4212   /* ERRORS */
4213 wrong_direction:
4214   {
4215     g_warning ("pad %s:%s query %s in wrong direction",
4216         GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query));
4217     return FALSE;
4218   }
4219 unknown_direction:
4220   {
4221     g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
4222     return FALSE;
4223   }
4224 no_parent:
4225   {
4226     GST_DEBUG_OBJECT (pad, "had no parent");
4227     GST_OBJECT_UNLOCK (pad);
4228     if (G_UNLIKELY (serialized))
4229       GST_PAD_STREAM_UNLOCK (pad);
4230     return FALSE;
4231   }
4232 no_func:
4233   {
4234     GST_DEBUG_OBJECT (pad, "had no query function");
4235     RELEASE_PARENT (parent);
4236     if (G_UNLIKELY (serialized))
4237       GST_PAD_STREAM_UNLOCK (pad);
4238     return FALSE;
4239   }
4240 query_failed:
4241   {
4242     GST_DEBUG_OBJECT (pad, "query failed");
4243     if (G_UNLIKELY (serialized))
4244       GST_PAD_STREAM_UNLOCK (pad);
4245     return FALSE;
4246   }
4247 probe_stopped:
4248   {
4249     GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret));
4250     GST_OBJECT_UNLOCK (pad);
4251     if (G_UNLIKELY (serialized))
4252       GST_PAD_STREAM_UNLOCK (pad);
4253 
4254     /* if a probe dropped without handling, we don't sent it further but assume
4255      * that the probe did not answer the query and return FALSE */
4256     if (ret != GST_FLOW_CUSTOM_SUCCESS_1)
4257       res = FALSE;
4258     else
4259       res = TRUE;
4260 
4261     return res;
4262   }
4263 }
4264 
4265 /**
4266  * gst_pad_peer_query:
4267  * @pad: a #GstPad to invoke the peer query on.
4268  * @query: (transfer none): the #GstQuery to perform.
4269  *
4270  * Performs gst_pad_query() on the peer of @pad.
4271  *
4272  * The caller is responsible for both the allocation and deallocation of
4273  * the query structure.
4274  *
4275  * Returns: %TRUE if the query could be performed. This function returns %FALSE
4276  * if @pad has no peer.
4277  */
4278 gboolean
gst_pad_peer_query(GstPad * pad,GstQuery * query)4279 gst_pad_peer_query (GstPad * pad, GstQuery * query)
4280 {
4281   GstPad *peerpad;
4282   GstPadProbeType type;
4283   gboolean res, serialized;
4284   GstFlowReturn ret;
4285 
4286   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
4287   g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
4288 
4289   if (GST_PAD_IS_SRC (pad)) {
4290     if (G_UNLIKELY (!GST_QUERY_IS_DOWNSTREAM (query)))
4291       goto wrong_direction;
4292     type = GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM;
4293   } else if (GST_PAD_IS_SINK (pad)) {
4294     if (G_UNLIKELY (!GST_QUERY_IS_UPSTREAM (query)))
4295       goto wrong_direction;
4296     type = GST_PAD_PROBE_TYPE_QUERY_UPSTREAM;
4297   } else
4298     goto unknown_direction;
4299 
4300   GST_DEBUG_OBJECT (pad, "peer query %p (%s)", query,
4301       GST_QUERY_TYPE_NAME (query));
4302 
4303   serialized = GST_QUERY_IS_SERIALIZED (query);
4304 
4305   GST_OBJECT_LOCK (pad);
4306   if (GST_PAD_IS_SRC (pad) && serialized) {
4307     /* all serialized queries on the srcpad trigger push of
4308      * sticky events */
4309     if (check_sticky (pad, NULL) != GST_FLOW_OK)
4310       goto sticky_failed;
4311   }
4312 
4313   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
4314       GST_PAD_PROBE_TYPE_BLOCK, query, probe_stopped);
4315   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, query, probe_stopped);
4316 
4317   peerpad = GST_PAD_PEER (pad);
4318   if (G_UNLIKELY (peerpad == NULL))
4319     goto no_peer;
4320 
4321   gst_object_ref (peerpad);
4322   GST_OBJECT_UNLOCK (pad);
4323 
4324   res = gst_pad_query (peerpad, query);
4325 
4326   gst_object_unref (peerpad);
4327 
4328   if (res != TRUE)
4329     goto query_failed;
4330 
4331   GST_OBJECT_LOCK (pad);
4332   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PULL, query, probe_stopped);
4333   GST_OBJECT_UNLOCK (pad);
4334 
4335   return res;
4336 
4337   /* ERRORS */
4338 wrong_direction:
4339   {
4340     g_warning ("pad %s:%s query %s in wrong direction",
4341         GST_DEBUG_PAD_NAME (pad), GST_QUERY_TYPE_NAME (query));
4342     return FALSE;
4343   }
4344 unknown_direction:
4345   {
4346     g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
4347     return FALSE;
4348   }
4349 sticky_failed:
4350   {
4351     GST_WARNING_OBJECT (pad, "could not send sticky events");
4352     GST_OBJECT_UNLOCK (pad);
4353     return FALSE;
4354   }
4355 no_peer:
4356   {
4357     GST_INFO_OBJECT (pad, "pad has no peer");
4358     GST_OBJECT_UNLOCK (pad);
4359     return FALSE;
4360   }
4361 query_failed:
4362   {
4363     GST_DEBUG_OBJECT (pad, "query failed");
4364     return FALSE;
4365   }
4366 probe_stopped:
4367   {
4368     GST_DEBUG_OBJECT (pad, "probe stopped: %s", gst_flow_get_name (ret));
4369     GST_OBJECT_UNLOCK (pad);
4370 
4371     /* if a probe dropped without handling, we don't sent it further but
4372      * assume that the probe did not answer the query and return FALSE */
4373     if (ret != GST_FLOW_CUSTOM_SUCCESS_1)
4374       res = FALSE;
4375     else
4376       res = TRUE;
4377 
4378     return res;
4379   }
4380 }
4381 
4382 /**********************************************************************
4383  * Data passing functions
4384  */
4385 
4386 /* this is the chain function that does not perform the additional argument
4387  * checking for that little extra speed.
4388  */
4389 static inline GstFlowReturn
gst_pad_chain_data_unchecked(GstPad * pad,GstPadProbeType type,void * data)4390 gst_pad_chain_data_unchecked (GstPad * pad, GstPadProbeType type, void *data)
4391 {
4392   GstFlowReturn ret;
4393   GstObject *parent;
4394   gboolean handled = FALSE;
4395 
4396   GST_PAD_STREAM_LOCK (pad);
4397 
4398   GST_OBJECT_LOCK (pad);
4399   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
4400     goto flushing;
4401 
4402   if (G_UNLIKELY (GST_PAD_IS_EOS (pad)))
4403     goto eos;
4404 
4405   if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH))
4406     goto wrong_mode;
4407 
4408 #ifdef GST_ENABLE_EXTRA_CHECKS
4409   if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) {
4410     if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) {
4411       g_warning (G_STRLOC
4412           ":%s:<%s:%s> Got data flow before stream-start event",
4413           G_STRFUNC, GST_DEBUG_PAD_NAME (pad));
4414     }
4415     if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) {
4416       g_warning (G_STRLOC
4417           ":%s:<%s:%s> Got data flow before segment event",
4418           G_STRFUNC, GST_DEBUG_PAD_NAME (pad));
4419     }
4420     pad->priv->last_cookie = pad->priv->events_cookie;
4421   }
4422 #endif
4423 
4424   PROBE_HANDLE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped,
4425       probe_handled);
4426 
4427   PROBE_HANDLE (pad, type, data, probe_stopped, probe_handled);
4428 
4429   ACQUIRE_PARENT (pad, parent, no_parent);
4430   GST_OBJECT_UNLOCK (pad);
4431 
4432   /* NOTE: we read the chainfunc unlocked.
4433    * we cannot hold the lock for the pad so we might send
4434    * the data to the wrong function. This is not really a
4435    * problem since functions are assigned at creation time
4436    * and don't change that often... */
4437   if (G_LIKELY (type & GST_PAD_PROBE_TYPE_BUFFER)) {
4438     GstPadChainFunction chainfunc;
4439 
4440     if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
4441       goto no_function;
4442 
4443     GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
4444         "calling chainfunction &%s with buffer %" GST_PTR_FORMAT,
4445         GST_DEBUG_FUNCPTR_NAME (chainfunc), GST_BUFFER (data));
4446 
4447     ret = chainfunc (pad, parent, GST_BUFFER_CAST (data));
4448 
4449     GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
4450         "called chainfunction &%s with buffer %p, returned %s",
4451         GST_DEBUG_FUNCPTR_NAME (chainfunc), data, gst_flow_get_name (ret));
4452   } else {
4453     GstPadChainListFunction chainlistfunc;
4454 
4455     if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL))
4456       goto no_function;
4457 
4458     GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
4459         "calling chainlistfunction &%s",
4460         GST_DEBUG_FUNCPTR_NAME (chainlistfunc));
4461 
4462     ret = chainlistfunc (pad, parent, GST_BUFFER_LIST_CAST (data));
4463 
4464     GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
4465         "called chainlistfunction &%s, returned %s",
4466         GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret));
4467   }
4468 
4469   pad->ABI.abi.last_flowret = ret;
4470 
4471   RELEASE_PARENT (parent);
4472 
4473   GST_PAD_STREAM_UNLOCK (pad);
4474 
4475   return ret;
4476 
4477   /* ERRORS */
4478 flushing:
4479   {
4480     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4481         "chaining, but pad was flushing");
4482     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
4483     GST_OBJECT_UNLOCK (pad);
4484     GST_PAD_STREAM_UNLOCK (pad);
4485     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4486     return GST_FLOW_FLUSHING;
4487   }
4488 eos:
4489   {
4490     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "chaining, but pad was EOS");
4491     pad->ABI.abi.last_flowret = GST_FLOW_EOS;
4492     GST_OBJECT_UNLOCK (pad);
4493     GST_PAD_STREAM_UNLOCK (pad);
4494     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4495     return GST_FLOW_EOS;
4496   }
4497 wrong_mode:
4498   {
4499     g_critical ("chain on pad %s:%s but it was not in push mode",
4500         GST_DEBUG_PAD_NAME (pad));
4501     pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
4502     GST_OBJECT_UNLOCK (pad);
4503     GST_PAD_STREAM_UNLOCK (pad);
4504     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4505     return GST_FLOW_ERROR;
4506   }
4507 probe_handled:
4508   handled = TRUE;
4509   /* PASSTHROUGH */
4510 probe_stopped:
4511   {
4512     /* We unref the buffer, except if the probe handled it (CUSTOM_SUCCESS_1) */
4513     if (!handled)
4514       gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4515 
4516     switch (ret) {
4517       case GST_FLOW_CUSTOM_SUCCESS:
4518       case GST_FLOW_CUSTOM_SUCCESS_1:
4519         GST_DEBUG_OBJECT (pad, "dropped or handled buffer");
4520         ret = GST_FLOW_OK;
4521         break;
4522       default:
4523         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
4524         break;
4525     }
4526     pad->ABI.abi.last_flowret = ret;
4527     GST_OBJECT_UNLOCK (pad);
4528     GST_PAD_STREAM_UNLOCK (pad);
4529     return ret;
4530   }
4531 no_parent:
4532   {
4533     GST_DEBUG_OBJECT (pad, "No parent when chaining %" GST_PTR_FORMAT, data);
4534     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
4535     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4536     GST_OBJECT_UNLOCK (pad);
4537     GST_PAD_STREAM_UNLOCK (pad);
4538     return GST_FLOW_FLUSHING;
4539   }
4540 no_function:
4541   {
4542     pad->ABI.abi.last_flowret = GST_FLOW_NOT_SUPPORTED;
4543     RELEASE_PARENT (parent);
4544     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4545     g_critical ("chain on pad %s:%s but it has no chainfunction",
4546         GST_DEBUG_PAD_NAME (pad));
4547     GST_PAD_STREAM_UNLOCK (pad);
4548     return GST_FLOW_NOT_SUPPORTED;
4549   }
4550 }
4551 
4552 /**
4553  * gst_pad_chain:
4554  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
4555  * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
4556  *     if not.
4557  *
4558  * Chain a buffer to @pad.
4559  *
4560  * The function returns #GST_FLOW_FLUSHING if the pad was flushing.
4561  *
4562  * If the buffer type is not acceptable for @pad (as negotiated with a
4563  * preceding GST_EVENT_CAPS event), this function returns
4564  * #GST_FLOW_NOT_NEGOTIATED.
4565  *
4566  * The function proceeds calling the chain function installed on @pad (see
4567  * gst_pad_set_chain_function()) and the return value of that function is
4568  * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no
4569  * chain function.
4570  *
4571  * In all cases, success or failure, the caller loses its reference to @buffer
4572  * after calling this function.
4573  *
4574  * Returns: a #GstFlowReturn from the pad.
4575  *
4576  * MT safe.
4577  */
4578 GstFlowReturn
gst_pad_chain(GstPad * pad,GstBuffer * buffer)4579 gst_pad_chain (GstPad * pad, GstBuffer * buffer)
4580 {
4581   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
4582   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
4583   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
4584 
4585   return gst_pad_chain_data_unchecked (pad,
4586       GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
4587 }
4588 
4589 static GstFlowReturn
gst_pad_chain_list_default(GstPad * pad,GstObject * parent,GstBufferList * list)4590 gst_pad_chain_list_default (GstPad * pad, GstObject * parent,
4591     GstBufferList * list)
4592 {
4593   guint i, len;
4594   GstBuffer *buffer;
4595   GstFlowReturn ret;
4596 
4597   GST_LOG_OBJECT (pad, "chaining each buffer in list individually");
4598 
4599   len = gst_buffer_list_length (list);
4600 
4601   ret = GST_FLOW_OK;
4602   for (i = 0; i < len; i++) {
4603     buffer = gst_buffer_list_get (list, i);
4604     ret =
4605         gst_pad_chain_data_unchecked (pad,
4606         GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH,
4607         gst_buffer_ref (buffer));
4608     if (ret != GST_FLOW_OK)
4609       break;
4610   }
4611   gst_buffer_list_unref (list);
4612 
4613   return ret;
4614 }
4615 
4616 /**
4617  * gst_pad_chain_list:
4618  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
4619  * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
4620  *     if not.
4621  *
4622  * Chain a bufferlist to @pad.
4623  *
4624  * The function returns #GST_FLOW_FLUSHING if the pad was flushing.
4625  *
4626  * If @pad was not negotiated properly with a CAPS event, this function
4627  * returns #GST_FLOW_NOT_NEGOTIATED.
4628  *
4629  * The function proceeds calling the chainlist function installed on @pad (see
4630  * gst_pad_set_chain_list_function()) and the return value of that function is
4631  * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no
4632  * chainlist function.
4633  *
4634  * In all cases, success or failure, the caller loses its reference to @list
4635  * after calling this function.
4636  *
4637  * MT safe.
4638  *
4639  * Returns: a #GstFlowReturn from the pad.
4640  */
4641 GstFlowReturn
gst_pad_chain_list(GstPad * pad,GstBufferList * list)4642 gst_pad_chain_list (GstPad * pad, GstBufferList * list)
4643 {
4644   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
4645   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
4646   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
4647 
4648   return gst_pad_chain_data_unchecked (pad,
4649       GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list);
4650 }
4651 
4652 static GstFlowReturn
gst_pad_push_data(GstPad * pad,GstPadProbeType type,void * data)4653 gst_pad_push_data (GstPad * pad, GstPadProbeType type, void *data)
4654 {
4655   GstPad *peer;
4656   GstFlowReturn ret;
4657   gboolean handled = FALSE;
4658 
4659   GST_OBJECT_LOCK (pad);
4660   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
4661     goto flushing;
4662 
4663   if (G_UNLIKELY (GST_PAD_IS_EOS (pad)))
4664     goto eos;
4665 
4666   if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PUSH))
4667     goto wrong_mode;
4668 
4669 #ifdef GST_ENABLE_EXTRA_CHECKS
4670   if (G_UNLIKELY (pad->priv->last_cookie != pad->priv->events_cookie)) {
4671     if (!find_event_by_type (pad, GST_EVENT_STREAM_START, 0)) {
4672       g_warning (G_STRLOC
4673           ":%s:<%s:%s> Got data flow before stream-start event",
4674           G_STRFUNC, GST_DEBUG_PAD_NAME (pad));
4675     }
4676     if (!find_event_by_type (pad, GST_EVENT_SEGMENT, 0)) {
4677       g_warning (G_STRLOC
4678           ":%s:<%s:%s> Got data flow before segment event",
4679           G_STRFUNC, GST_DEBUG_PAD_NAME (pad));
4680     }
4681     pad->priv->last_cookie = pad->priv->events_cookie;
4682   }
4683 #endif
4684 
4685   if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK)
4686     goto events_error;
4687 
4688   /* do block probes */
4689   PROBE_HANDLE (pad, type | GST_PAD_PROBE_TYPE_BLOCK, data, probe_stopped,
4690       probe_handled);
4691 
4692   /* recheck sticky events because the probe might have cause a relink */
4693   if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK)
4694     goto events_error;
4695 
4696   /* do post-blocking probes */
4697   PROBE_HANDLE (pad, type, data, probe_stopped, probe_handled);
4698 
4699   /* recheck sticky events because the probe might have cause a relink */
4700   if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK)
4701     goto events_error;
4702 
4703   if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
4704     goto not_linked;
4705 
4706   /* take ref to peer pad before releasing the lock */
4707   gst_object_ref (peer);
4708   pad->priv->using++;
4709   GST_OBJECT_UNLOCK (pad);
4710 
4711   ret = gst_pad_chain_data_unchecked (peer, type, data);
4712   data = NULL;
4713 
4714   gst_object_unref (peer);
4715 
4716   GST_OBJECT_LOCK (pad);
4717   pad->ABI.abi.last_flowret = ret;
4718   pad->priv->using--;
4719   if (pad->priv->using == 0) {
4720     /* pad is not active anymore, trigger idle callbacks */
4721     PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
4722         probe_stopped, ret);
4723   }
4724   GST_OBJECT_UNLOCK (pad);
4725 
4726   return ret;
4727 
4728   /* ERROR recovery here */
4729   /* ERRORS */
4730 flushing:
4731   {
4732     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4733         "pushing, but pad was flushing");
4734     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
4735     GST_OBJECT_UNLOCK (pad);
4736     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4737     return GST_FLOW_FLUSHING;
4738   }
4739 eos:
4740   {
4741     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pushing, but pad was EOS");
4742     pad->ABI.abi.last_flowret = GST_FLOW_EOS;
4743     GST_OBJECT_UNLOCK (pad);
4744     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4745     return GST_FLOW_EOS;
4746   }
4747 wrong_mode:
4748   {
4749     g_critical ("pushing on pad %s:%s but it was not activated in push mode",
4750         GST_DEBUG_PAD_NAME (pad));
4751     pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
4752     GST_OBJECT_UNLOCK (pad);
4753     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4754     return GST_FLOW_ERROR;
4755   }
4756 events_error:
4757   {
4758     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4759         "error pushing events, return %s", gst_flow_get_name (ret));
4760     pad->ABI.abi.last_flowret = ret;
4761     GST_OBJECT_UNLOCK (pad);
4762     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4763     return ret;
4764   }
4765 probe_handled:
4766   handled = TRUE;
4767   /* PASSTHROUGH */
4768 probe_stopped:
4769   {
4770     GST_OBJECT_UNLOCK (pad);
4771     if (data != NULL && !handled)
4772       gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4773 
4774     switch (ret) {
4775       case GST_FLOW_CUSTOM_SUCCESS:
4776       case GST_FLOW_CUSTOM_SUCCESS_1:
4777         GST_DEBUG_OBJECT (pad, "dropped or handled buffer");
4778         ret = GST_FLOW_OK;
4779         break;
4780       default:
4781         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
4782         break;
4783     }
4784     pad->ABI.abi.last_flowret = ret;
4785     return ret;
4786   }
4787 not_linked:
4788   {
4789     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4790         "pushing, but it was not linked");
4791     pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED;
4792     GST_OBJECT_UNLOCK (pad);
4793     gst_mini_object_unref (GST_MINI_OBJECT_CAST (data));
4794     return GST_FLOW_NOT_LINKED;
4795   }
4796 }
4797 
4798 /**
4799  * gst_pad_push:
4800  * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
4801  * @buffer: (transfer full): the #GstBuffer to push returns GST_FLOW_ERROR
4802  *     if not.
4803  *
4804  * Pushes a buffer to the peer of @pad.
4805  *
4806  * This function will call installed block probes before triggering any
4807  * installed data probes.
4808  *
4809  * The function proceeds calling gst_pad_chain() on the peer pad and returns
4810  * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
4811  * be returned.
4812  *
4813  * In all cases, success or failure, the caller loses its reference to @buffer
4814  * after calling this function.
4815  *
4816  * Returns: a #GstFlowReturn from the peer pad.
4817  *
4818  * MT safe.
4819  */
4820 GstFlowReturn
gst_pad_push(GstPad * pad,GstBuffer * buffer)4821 gst_pad_push (GstPad * pad, GstBuffer * buffer)
4822 {
4823   GstFlowReturn res;
4824 
4825   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
4826   g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
4827   g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
4828 
4829   GST_TRACER_PAD_PUSH_PRE (pad, buffer);
4830   res = gst_pad_push_data (pad,
4831       GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH, buffer);
4832   GST_TRACER_PAD_PUSH_POST (pad, res);
4833   return res;
4834 }
4835 
4836 /**
4837  * gst_pad_push_list:
4838  * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
4839  * @list: (transfer full): the #GstBufferList to push returns GST_FLOW_ERROR
4840  *     if not.
4841  *
4842  * Pushes a buffer list to the peer of @pad.
4843  *
4844  * This function will call installed block probes before triggering any
4845  * installed data probes.
4846  *
4847  * The function proceeds calling the chain function on the peer pad and returns
4848  * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
4849  * be returned. If the peer pad does not have any installed chainlist function
4850  * every group buffer of the list will be merged into a normal #GstBuffer and
4851  * chained via gst_pad_chain().
4852  *
4853  * In all cases, success or failure, the caller loses its reference to @list
4854  * after calling this function.
4855  *
4856  * Returns: a #GstFlowReturn from the peer pad.
4857  *
4858  * MT safe.
4859  */
4860 GstFlowReturn
gst_pad_push_list(GstPad * pad,GstBufferList * list)4861 gst_pad_push_list (GstPad * pad, GstBufferList * list)
4862 {
4863   GstFlowReturn res;
4864 
4865   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
4866   g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
4867   g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
4868 
4869   GST_TRACER_PAD_PUSH_LIST_PRE (pad, list);
4870   res = gst_pad_push_data (pad,
4871       GST_PAD_PROBE_TYPE_BUFFER_LIST | GST_PAD_PROBE_TYPE_PUSH, list);
4872   GST_TRACER_PAD_PUSH_LIST_POST (pad, res);
4873   return res;
4874 }
4875 
4876 static GstFlowReturn
gst_pad_get_range_unchecked(GstPad * pad,guint64 offset,guint size,GstBuffer ** buffer)4877 gst_pad_get_range_unchecked (GstPad * pad, guint64 offset, guint size,
4878     GstBuffer ** buffer)
4879 {
4880   GstFlowReturn ret;
4881   GstPadGetRangeFunction getrangefunc;
4882   GstObject *parent;
4883   GstBuffer *res_buf;
4884 
4885   GST_PAD_STREAM_LOCK (pad);
4886 
4887   GST_OBJECT_LOCK (pad);
4888   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
4889     goto flushing;
4890 
4891   if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
4892     goto wrong_mode;
4893 
4894   if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK)
4895     goto events_error;
4896 
4897   res_buf = *buffer;
4898 
4899   /* when one of the probes returns DROPPED, probe_stopped will be called
4900    * and we skip calling the getrange function, res_buf should then contain a
4901    * valid result buffer */
4902   PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
4903       res_buf, offset, size, probe_stopped);
4904 
4905   /* recheck sticky events because the probe might have cause a relink */
4906   if (G_UNLIKELY ((ret = check_sticky (pad, NULL))) != GST_FLOW_OK)
4907     goto events_error;
4908 
4909   ACQUIRE_PARENT (pad, parent, no_parent);
4910   GST_OBJECT_UNLOCK (pad);
4911 
4912   if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL))
4913     goto no_function;
4914 
4915   GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4916       "calling getrangefunc %s, offset %"
4917       G_GUINT64_FORMAT ", size %u",
4918       GST_DEBUG_FUNCPTR_NAME (getrangefunc), offset, size);
4919 
4920   ret = getrangefunc (pad, parent, offset, size, &res_buf);
4921 
4922   RELEASE_PARENT (parent);
4923 
4924   GST_OBJECT_LOCK (pad);
4925   if (G_UNLIKELY (ret != GST_FLOW_OK))
4926     goto get_range_failed;
4927 
4928   /* can only fire the signal if we have a valid buffer */
4929 probed_data:
4930   PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
4931       res_buf, offset, size, probe_stopped_unref);
4932   pad->ABI.abi.last_flowret = ret;
4933   GST_OBJECT_UNLOCK (pad);
4934 
4935   GST_PAD_STREAM_UNLOCK (pad);
4936 
4937   /* If the caller provided a buffer it must be filled by the getrange
4938    * function instead of it returning a new buffer */
4939   g_return_val_if_fail (!*buffer || res_buf == *buffer, GST_FLOW_ERROR);
4940 
4941   *buffer = res_buf;
4942 
4943   return ret;
4944 
4945   /* ERRORS */
4946 flushing:
4947   {
4948     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4949         "getrange, but pad was flushing");
4950     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
4951     GST_OBJECT_UNLOCK (pad);
4952     GST_PAD_STREAM_UNLOCK (pad);
4953     return GST_FLOW_FLUSHING;
4954   }
4955 wrong_mode:
4956   {
4957     g_critical ("getrange on pad %s:%s but it was not activated in pull mode",
4958         GST_DEBUG_PAD_NAME (pad));
4959     pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
4960     GST_OBJECT_UNLOCK (pad);
4961     GST_PAD_STREAM_UNLOCK (pad);
4962     return GST_FLOW_ERROR;
4963   }
4964 events_error:
4965   {
4966     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "error pushing events");
4967     pad->ABI.abi.last_flowret = ret;
4968     GST_OBJECT_UNLOCK (pad);
4969     GST_PAD_STREAM_UNLOCK (pad);
4970     return ret;
4971   }
4972 no_parent:
4973   {
4974     GST_DEBUG_OBJECT (pad, "no parent");
4975     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
4976     GST_OBJECT_UNLOCK (pad);
4977     GST_PAD_STREAM_UNLOCK (pad);
4978     return GST_FLOW_FLUSHING;
4979   }
4980 no_function:
4981   {
4982     g_critical ("getrange on pad %s:%s but it has no getrangefunction",
4983         GST_DEBUG_PAD_NAME (pad));
4984     RELEASE_PARENT (parent);
4985     GST_PAD_STREAM_UNLOCK (pad);
4986     return GST_FLOW_NOT_SUPPORTED;
4987   }
4988 probe_stopped:
4989   {
4990     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
4991         "probe returned %s", gst_flow_get_name (ret));
4992     if (ret == GST_FLOW_CUSTOM_SUCCESS) {
4993       if (res_buf) {
4994         /* the probe filled the buffer and asks us to not call the getrange
4995          * anymore, we continue with the post probes then. */
4996         GST_DEBUG_OBJECT (pad, "handled buffer");
4997         ret = GST_FLOW_OK;
4998         goto probed_data;
4999       } else {
5000         /* no buffer, we are EOS */
5001         GST_DEBUG_OBJECT (pad, "no buffer, return EOS");
5002         ret = GST_FLOW_EOS;
5003       }
5004     }
5005     pad->ABI.abi.last_flowret = ret;
5006     GST_OBJECT_UNLOCK (pad);
5007     GST_PAD_STREAM_UNLOCK (pad);
5008 
5009     return ret;
5010   }
5011 probe_stopped_unref:
5012   {
5013     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
5014         "probe returned %s", gst_flow_get_name (ret));
5015     /* if we drop here, it signals EOS */
5016     if (ret == GST_FLOW_CUSTOM_SUCCESS)
5017       ret = GST_FLOW_EOS;
5018     pad->ABI.abi.last_flowret = ret;
5019     GST_OBJECT_UNLOCK (pad);
5020     GST_PAD_STREAM_UNLOCK (pad);
5021     if (*buffer == NULL)
5022       gst_buffer_unref (res_buf);
5023     return ret;
5024   }
5025 get_range_failed:
5026   {
5027     pad->ABI.abi.last_flowret = ret;
5028     GST_OBJECT_UNLOCK (pad);
5029     GST_PAD_STREAM_UNLOCK (pad);
5030     GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
5031         (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
5032         pad, "getrange failed, flow: %s", gst_flow_get_name (ret));
5033     return ret;
5034   }
5035 }
5036 
5037 /**
5038  * gst_pad_get_range:
5039  * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
5040  * @offset: The start offset of the buffer
5041  * @size: The length of the buffer
5042  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
5043  *     returns #GST_FLOW_ERROR if %NULL.
5044  *
5045  * When @pad is flushing this function returns #GST_FLOW_FLUSHING
5046  * immediately and @buffer is %NULL.
5047  *
5048  * Calls the getrange function of @pad, see #GstPadGetRangeFunction for a
5049  * description of a getrange function. If @pad has no getrange function
5050  * installed (see gst_pad_set_getrange_function()) this function returns
5051  * #GST_FLOW_NOT_SUPPORTED.
5052  *
5053  * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be
5054  * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer
5055  * must be freed with gst_buffer_unref() after usage.
5056  *
5057  * When @buffer points to a variable that points to a valid #GstBuffer, the
5058  * buffer will be filled with the result data when this function returns
5059  * #GST_FLOW_OK. If the provided buffer is larger than @size, only
5060  * @size bytes will be filled in the result buffer and its size will be updated
5061  * accordingly.
5062  *
5063  * Note that less than @size bytes can be returned in @buffer when, for example,
5064  * an EOS condition is near or when @buffer is not large enough to hold @size
5065  * bytes. The caller should check the result buffer size to get the result size.
5066  *
5067  * When this function returns any other result value than #GST_FLOW_OK, @buffer
5068  * will be unchanged.
5069  *
5070  * This is a lowlevel function. Usually gst_pad_pull_range() is used.
5071  *
5072  * Returns: a #GstFlowReturn from the pad.
5073  *
5074  * MT safe.
5075  */
5076 GstFlowReturn
gst_pad_get_range(GstPad * pad,guint64 offset,guint size,GstBuffer ** buffer)5077 gst_pad_get_range (GstPad * pad, guint64 offset, guint size,
5078     GstBuffer ** buffer)
5079 {
5080   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
5081   g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
5082   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
5083   g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer)
5084           && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR);
5085 
5086   return gst_pad_get_range_unchecked (pad, offset, size, buffer);
5087 }
5088 
5089 /**
5090  * gst_pad_pull_range:
5091  * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
5092  * @offset: The start offset of the buffer
5093  * @size: The length of the buffer
5094  * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer, returns
5095  *     GST_FLOW_ERROR if %NULL.
5096  *
5097  * Pulls a @buffer from the peer pad or fills up a provided buffer.
5098  *
5099  * This function will first trigger the pad block signal if it was
5100  * installed.
5101  *
5102  * When @pad is not linked #GST_FLOW_NOT_LINKED is returned else this
5103  * function returns the result of gst_pad_get_range() on the peer pad.
5104  * See gst_pad_get_range() for a list of return values and for the
5105  * semantics of the arguments of this function.
5106  *
5107  * If @buffer points to a variable holding %NULL, a valid new #GstBuffer will be
5108  * placed in @buffer when this function returns #GST_FLOW_OK. The new buffer
5109  * must be freed with gst_buffer_unref() after usage. When this function
5110  * returns any other result value, @buffer will still point to %NULL.
5111  *
5112  * When @buffer points to a variable that points to a valid #GstBuffer, the
5113  * buffer will be filled with the result data when this function returns
5114  * #GST_FLOW_OK. When this function returns any other result value,
5115  * @buffer will be unchanged. If the provided buffer is larger than @size, only
5116  * @size bytes will be filled in the result buffer and its size will be updated
5117  * accordingly.
5118  *
5119  * Note that less than @size bytes can be returned in @buffer when, for example,
5120  * an EOS condition is near or when @buffer is not large enough to hold @size
5121  * bytes. The caller should check the result buffer size to get the result size.
5122  *
5123  * Returns: a #GstFlowReturn from the peer pad.
5124  *
5125  * MT safe.
5126  */
5127 GstFlowReturn
gst_pad_pull_range(GstPad * pad,guint64 offset,guint size,GstBuffer ** buffer)5128 gst_pad_pull_range (GstPad * pad, guint64 offset, guint size,
5129     GstBuffer ** buffer)
5130 {
5131   GstPad *peer;
5132   GstFlowReturn ret;
5133   GstBuffer *res_buf;
5134 
5135   g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
5136   g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
5137   g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
5138   g_return_val_if_fail (*buffer == NULL || (GST_IS_BUFFER (*buffer)
5139           && gst_buffer_get_size (*buffer) >= size), GST_FLOW_ERROR);
5140 
5141   GST_TRACER_PAD_PULL_RANGE_PRE (pad, offset, size);
5142 
5143   GST_OBJECT_LOCK (pad);
5144   if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5145     goto flushing;
5146 
5147   if (G_UNLIKELY (GST_PAD_MODE (pad) != GST_PAD_MODE_PULL))
5148     goto wrong_mode;
5149 
5150   res_buf = *buffer;
5151 
5152   /* when one of the probes returns DROPPED, probe_stopped will be
5153    * called and we skip calling the peer getrange function. *buffer should then
5154    * contain a valid buffer */
5155   PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BLOCK,
5156       res_buf, offset, size, probe_stopped);
5157 
5158   if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
5159     goto not_linked;
5160 
5161   gst_object_ref (peer);
5162   pad->priv->using++;
5163   GST_OBJECT_UNLOCK (pad);
5164 
5165   ret = gst_pad_get_range_unchecked (peer, offset, size, &res_buf);
5166 
5167   gst_object_unref (peer);
5168 
5169   GST_OBJECT_LOCK (pad);
5170   pad->priv->using--;
5171   pad->ABI.abi.last_flowret = ret;
5172   if (pad->priv->using == 0) {
5173     /* pad is not active anymore, trigger idle callbacks */
5174     PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_IDLE,
5175         probe_stopped_unref, ret);
5176   }
5177 
5178   if (G_UNLIKELY (ret != GST_FLOW_OK))
5179     goto pull_range_failed;
5180 
5181 probed_data:
5182   PROBE_PULL (pad, GST_PAD_PROBE_TYPE_PULL | GST_PAD_PROBE_TYPE_BUFFER,
5183       res_buf, offset, size, probe_stopped_unref);
5184 
5185   GST_OBJECT_UNLOCK (pad);
5186 
5187   *buffer = res_buf;
5188 
5189   GST_TRACER_PAD_PULL_RANGE_POST (pad, *buffer, ret);
5190   return ret;
5191 
5192   /* ERROR recovery here */
5193 flushing:
5194   {
5195     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
5196         "pullrange, but pad was flushing");
5197     pad->ABI.abi.last_flowret = GST_FLOW_FLUSHING;
5198     GST_OBJECT_UNLOCK (pad);
5199     ret = GST_FLOW_FLUSHING;
5200     goto done;
5201   }
5202 wrong_mode:
5203   {
5204     g_critical ("pullrange on pad %s:%s but it was not activated in pull mode",
5205         GST_DEBUG_PAD_NAME (pad));
5206     pad->ABI.abi.last_flowret = GST_FLOW_ERROR;
5207     GST_OBJECT_UNLOCK (pad);
5208     ret = GST_FLOW_ERROR;
5209     goto done;
5210   }
5211 probe_stopped:
5212   {
5213     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pre probe returned %s",
5214         gst_flow_get_name (ret));
5215     if (ret == GST_FLOW_CUSTOM_SUCCESS) {
5216       if (res_buf) {
5217         /* the probe filled the buffer and asks us to not forward to the peer
5218          * anymore, we continue with the post probes then */
5219         GST_DEBUG_OBJECT (pad, "handled buffer");
5220         ret = GST_FLOW_OK;
5221         goto probed_data;
5222       } else {
5223         /* no buffer, we are EOS then */
5224         GST_DEBUG_OBJECT (pad, "no buffer, return EOS");
5225         ret = GST_FLOW_EOS;
5226       }
5227     }
5228     pad->ABI.abi.last_flowret = ret;
5229     GST_OBJECT_UNLOCK (pad);
5230     goto done;
5231   }
5232 not_linked:
5233   {
5234     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
5235         "pulling range, but it was not linked");
5236     pad->ABI.abi.last_flowret = GST_FLOW_NOT_LINKED;
5237     GST_OBJECT_UNLOCK (pad);
5238     ret = GST_FLOW_NOT_LINKED;
5239     goto done;
5240   }
5241 pull_range_failed:
5242   {
5243     pad->ABI.abi.last_flowret = ret;
5244     GST_OBJECT_UNLOCK (pad);
5245     GST_CAT_LEVEL_LOG (GST_CAT_SCHEDULING,
5246         (ret >= GST_FLOW_EOS) ? GST_LEVEL_INFO : GST_LEVEL_WARNING,
5247         pad, "pullrange failed, flow: %s", gst_flow_get_name (ret));
5248     goto done;
5249   }
5250 probe_stopped_unref:
5251   {
5252     GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
5253         "post probe returned %s", gst_flow_get_name (ret));
5254 
5255     /* if we drop here, it signals EOS */
5256     if (ret == GST_FLOW_CUSTOM_SUCCESS)
5257       ret = GST_FLOW_EOS;
5258 
5259     pad->ABI.abi.last_flowret = ret;
5260     GST_OBJECT_UNLOCK (pad);
5261 
5262     if (*buffer == NULL)
5263       gst_buffer_unref (res_buf);
5264     goto done;
5265   }
5266 done:
5267   GST_TRACER_PAD_PULL_RANGE_POST (pad, NULL, ret);
5268   return ret;
5269 }
5270 
5271 /* must be called with pad object lock */
5272 static GstFlowReturn
store_sticky_event(GstPad * pad,GstEvent * event)5273 store_sticky_event (GstPad * pad, GstEvent * event)
5274 {
5275   guint i, len;
5276   GstEventType type;
5277   GArray *events;
5278   gboolean res = FALSE;
5279   GQuark name_id = 0;
5280   gboolean insert = TRUE;
5281 
5282   type = GST_EVENT_TYPE (event);
5283 
5284   /* Store all sticky events except SEGMENT/EOS when we're flushing,
5285    * otherwise they can be dropped and nothing would ever resend them.
5286    * Only do that for activated pads though, everything else is a bug!
5287    */
5288   if (G_UNLIKELY (GST_PAD_MODE (pad) == GST_PAD_MODE_NONE
5289           || (GST_PAD_IS_FLUSHING (pad) && (type == GST_EVENT_SEGMENT
5290                   || type == GST_EVENT_EOS))))
5291     goto flushed;
5292 
5293   /* Unset the EOS flag when received STREAM_START event, so pad can
5294    * store sticky event and then push it later */
5295   if (type == GST_EVENT_STREAM_START) {
5296     GST_LOG_OBJECT (pad, "Removing pending EOS, StreamGroupDone, TAG events");
5297     remove_event_by_type (pad, GST_EVENT_EOS);
5298     remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
5299     remove_event_by_type (pad, GST_EVENT_TAG);
5300     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
5301   }
5302 
5303   if (G_UNLIKELY (GST_PAD_IS_EOS (pad)))
5304     goto eos;
5305 
5306   if (type & GST_EVENT_TYPE_STICKY_MULTI)
5307     name_id = gst_structure_get_name_id (gst_event_get_structure (event));
5308 
5309   events = pad->priv->events;
5310   len = events->len;
5311 
5312   for (i = 0; i < len; i++) {
5313     PadEvent *ev = &g_array_index (events, PadEvent, i);
5314 
5315     if (ev->event == NULL)
5316       continue;
5317 
5318     if (type == GST_EVENT_TYPE (ev->event)) {
5319       /* matching types, check matching name if needed */
5320       if (name_id && !gst_event_has_name_id (ev->event, name_id))
5321         continue;
5322 
5323       /* overwrite */
5324       if ((res = gst_event_replace (&ev->event, event)))
5325         ev->received = FALSE;
5326 
5327       insert = FALSE;
5328       break;
5329     }
5330 
5331     if (type < GST_EVENT_TYPE (ev->event) || (type != GST_EVENT_TYPE (ev->event)
5332             && GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS)) {
5333       /* STREAM_START, CAPS and SEGMENT must be delivered in this order. By
5334        * storing the sticky ordered we can check that this is respected. */
5335       if (G_UNLIKELY (GST_EVENT_TYPE (ev->event) <= GST_EVENT_SEGMENT
5336               || GST_EVENT_TYPE (ev->event) == GST_EVENT_EOS))
5337         g_warning (G_STRLOC
5338             ":%s:<%s:%s> Sticky event misordering, got '%s' before '%s'",
5339             G_STRFUNC, GST_DEBUG_PAD_NAME (pad),
5340             gst_event_type_get_name (GST_EVENT_TYPE (ev->event)),
5341             gst_event_type_get_name (type));
5342       break;
5343     }
5344   }
5345   if (insert) {
5346     PadEvent ev;
5347     ev.event = gst_event_ref (event);
5348     ev.received = FALSE;
5349     g_array_insert_val (events, i, ev);
5350     res = TRUE;
5351   }
5352 
5353   if (res) {
5354     pad->priv->events_cookie++;
5355     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
5356 
5357     GST_LOG_OBJECT (pad, "stored sticky event %s", GST_EVENT_TYPE_NAME (event));
5358 
5359     switch (GST_EVENT_TYPE (event)) {
5360       case GST_EVENT_CAPS:
5361         GST_OBJECT_UNLOCK (pad);
5362 
5363         GST_DEBUG_OBJECT (pad, "notify caps");
5364         g_object_notify_by_pspec ((GObject *) pad, pspec_caps);
5365 
5366         GST_OBJECT_LOCK (pad);
5367         break;
5368       default:
5369         break;
5370     }
5371   }
5372   if (type == GST_EVENT_EOS) {
5373     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_EOS);
5374     pad->ABI.abi.last_flowret = GST_FLOW_EOS;
5375   }
5376 
5377   return GST_PAD_IS_FLUSHING (pad) ? GST_FLOW_FLUSHING : GST_FLOW_OK;
5378 
5379   /* ERRORS */
5380 flushed:
5381   {
5382     GST_DEBUG_OBJECT (pad, "pad is flushing");
5383     return GST_FLOW_FLUSHING;
5384   }
5385 eos:
5386   {
5387     GST_DEBUG_OBJECT (pad, "pad is EOS");
5388     return GST_FLOW_EOS;
5389   }
5390 }
5391 
5392 /**
5393  * gst_pad_store_sticky_event:
5394  * @pad: a #GstPad
5395  * @event: (transfer none): a #GstEvent
5396  *
5397  * Store the sticky @event on @pad
5398  *
5399  * Returns: #GST_FLOW_OK on success, #GST_FLOW_FLUSHING when the pad
5400  * was flushing or #GST_FLOW_EOS when the pad was EOS.
5401  *
5402  * Since: 1.2
5403  */
5404 GstFlowReturn
gst_pad_store_sticky_event(GstPad * pad,GstEvent * event)5405 gst_pad_store_sticky_event (GstPad * pad, GstEvent * event)
5406 {
5407   GstFlowReturn ret;
5408 
5409   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
5410   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
5411 
5412   GST_OBJECT_LOCK (pad);
5413   ret = store_sticky_event (pad, event);
5414   GST_OBJECT_UNLOCK (pad);
5415 
5416   return ret;
5417 }
5418 
5419 static gboolean
sticky_changed(GstPad * pad,PadEvent * ev,gpointer user_data)5420 sticky_changed (GstPad * pad, PadEvent * ev, gpointer user_data)
5421 {
5422   PushStickyData *data = user_data;
5423 
5424   /* Forward all sticky events before our current one that are pending */
5425   if (ev->event != data->event
5426       && GST_EVENT_TYPE (ev->event) < GST_EVENT_TYPE (data->event))
5427     return push_sticky (pad, ev, data);
5428 
5429   return TRUE;
5430 }
5431 
5432 /* should be called with pad LOCK */
5433 static GstFlowReturn
gst_pad_push_event_unchecked(GstPad * pad,GstEvent * event,GstPadProbeType type)5434 gst_pad_push_event_unchecked (GstPad * pad, GstEvent * event,
5435     GstPadProbeType type)
5436 {
5437   GstFlowReturn ret;
5438   GstPad *peerpad;
5439   GstEventType event_type;
5440   gint64 old_pad_offset = pad->offset;
5441 
5442   /* pass the adjusted event on. We need to do this even if
5443    * there is no peer pad because of the probes. */
5444   event = apply_pad_offset (pad, event, GST_PAD_IS_SINK (pad));
5445 
5446   /* Two checks to be made:
5447    * . (un)set the FLUSHING flag for flushing events,
5448    * . handle pad blocking */
5449   event_type = GST_EVENT_TYPE (event);
5450   switch (event_type) {
5451     case GST_EVENT_FLUSH_START:
5452       GST_PAD_SET_FLUSHING (pad);
5453 
5454       GST_PAD_BLOCK_BROADCAST (pad);
5455       type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
5456       break;
5457     case GST_EVENT_FLUSH_STOP:
5458       if (G_UNLIKELY (!GST_PAD_IS_ACTIVE (pad)))
5459         goto inactive;
5460 
5461       GST_PAD_UNSET_FLUSHING (pad);
5462 
5463       /* Remove sticky EOS events */
5464       GST_LOG_OBJECT (pad, "Removing pending EOS events");
5465       remove_event_by_type (pad, GST_EVENT_EOS);
5466       remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
5467       remove_event_by_type (pad, GST_EVENT_SEGMENT);
5468       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
5469       pad->ABI.abi.last_flowret = GST_FLOW_OK;
5470 
5471       type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
5472       break;
5473     default:
5474     {
5475       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5476         goto flushed;
5477 
5478       /* No need to check for EOS here as either the caller (gst_pad_push_event())
5479        * checked already or this is called as part of pushing sticky events,
5480        * in which case we still want to forward the EOS event downstream.
5481        */
5482 
5483       switch (GST_EVENT_TYPE (event)) {
5484         case GST_EVENT_RECONFIGURE:
5485           if (GST_PAD_IS_SINK (pad))
5486             GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
5487           break;
5488         default:
5489           break;
5490       }
5491       PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH |
5492           GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
5493       /* recheck sticky events because the probe might have cause a relink */
5494       if (GST_PAD_HAS_PENDING_EVENTS (pad) && GST_PAD_IS_SRC (pad)
5495           && (GST_EVENT_IS_SERIALIZED (event)
5496               || GST_EVENT_IS_STICKY (event))) {
5497         PushStickyData data = { GST_FLOW_OK, FALSE, event };
5498         GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
5499 
5500         /* Push all sticky events before our current one
5501          * that have changed */
5502         events_foreach (pad, sticky_changed, &data);
5503       }
5504       break;
5505     }
5506   }
5507 
5508   /* send probes after modifying the events above */
5509   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
5510 
5511   /* recheck sticky events because the probe might have cause a relink */
5512   if (GST_PAD_HAS_PENDING_EVENTS (pad) && GST_PAD_IS_SRC (pad)
5513       && (GST_EVENT_IS_SERIALIZED (event)
5514           || GST_EVENT_IS_STICKY (event))) {
5515     PushStickyData data = { GST_FLOW_OK, FALSE, event };
5516     GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_PENDING_EVENTS);
5517 
5518     /* Push all sticky events before our current one
5519      * that have changed */
5520     events_foreach (pad, sticky_changed, &data);
5521   }
5522 
5523   /* the pad offset might've been changed by any of the probes above. It
5524    * would've been taken into account when repushing any of the sticky events
5525    * above but not for our current event here */
5526   if (G_UNLIKELY (old_pad_offset != pad->offset)) {
5527     event =
5528         _apply_pad_offset (pad, event, GST_PAD_IS_SINK (pad),
5529         pad->offset - old_pad_offset);
5530   }
5531 
5532   /* now check the peer pad */
5533   peerpad = GST_PAD_PEER (pad);
5534   if (peerpad == NULL)
5535     goto not_linked;
5536 
5537   gst_object_ref (peerpad);
5538   pad->priv->using++;
5539   GST_OBJECT_UNLOCK (pad);
5540 
5541   GST_LOG_OBJECT (pad, "sending event %p (%s) to peerpad %" GST_PTR_FORMAT,
5542       event, gst_event_type_get_name (event_type), peerpad);
5543 
5544   ret = gst_pad_send_event_unchecked (peerpad, event, type);
5545 
5546   /* Note: we gave away ownership of the event at this point but we can still
5547    * print the old pointer */
5548   GST_LOG_OBJECT (pad,
5549       "sent event %p (%s) to peerpad %" GST_PTR_FORMAT ", ret %s", event,
5550       gst_event_type_get_name (event_type), peerpad, gst_flow_get_name (ret));
5551 
5552   gst_object_unref (peerpad);
5553 
5554   GST_OBJECT_LOCK (pad);
5555   pad->priv->using--;
5556   if (pad->priv->using == 0) {
5557     /* pad is not active anymore, trigger idle callbacks */
5558     PROBE_NO_DATA (pad, GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_IDLE,
5559         idle_probe_stopped, ret);
5560   }
5561   return ret;
5562 
5563   /* ERROR handling */
5564 flushed:
5565   {
5566     GST_DEBUG_OBJECT (pad, "We're flushing");
5567     gst_event_unref (event);
5568     return GST_FLOW_FLUSHING;
5569   }
5570 inactive:
5571   {
5572     GST_DEBUG_OBJECT (pad, "flush-stop on inactive pad");
5573     gst_event_unref (event);
5574     return GST_FLOW_FLUSHING;
5575   }
5576 probe_stopped:
5577   {
5578     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
5579     if (ret != GST_FLOW_CUSTOM_SUCCESS_1)
5580       gst_event_unref (event);
5581 
5582     switch (ret) {
5583       case GST_FLOW_CUSTOM_SUCCESS_1:
5584         GST_DEBUG_OBJECT (pad, "handled event");
5585         break;
5586       case GST_FLOW_CUSTOM_SUCCESS:
5587         GST_DEBUG_OBJECT (pad, "dropped event");
5588         break;
5589       default:
5590         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
5591         break;
5592     }
5593     return ret;
5594   }
5595 not_linked:
5596   {
5597     GST_DEBUG_OBJECT (pad, "Dropping event %s because pad is not linked",
5598         gst_event_type_get_name (GST_EVENT_TYPE (event)));
5599     GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_PENDING_EVENTS);
5600     gst_event_unref (event);
5601 
5602     /* unlinked pads should not influence latency configuration */
5603     if (event_type == GST_EVENT_LATENCY)
5604       return GST_FLOW_OK;
5605 
5606     return GST_FLOW_NOT_LINKED;
5607   }
5608 idle_probe_stopped:
5609   {
5610     GST_DEBUG_OBJECT (pad, "Idle probe returned %s", gst_flow_get_name (ret));
5611     return ret;
5612   }
5613 }
5614 
5615 /**
5616  * gst_pad_push_event:
5617  * @pad: a #GstPad to push the event to.
5618  * @event: (transfer full): the #GstEvent to send to the pad.
5619  *
5620  * Sends the event to the peer of the given pad. This function is
5621  * mainly used by elements to send events to their peer
5622  * elements.
5623  *
5624  * This function takes ownership of the provided event so you should
5625  * gst_event_ref() it if you want to reuse the event after this call.
5626  *
5627  * Returns: %TRUE if the event was handled.
5628  *
5629  * MT safe.
5630  */
5631 gboolean
gst_pad_push_event(GstPad * pad,GstEvent * event)5632 gst_pad_push_event (GstPad * pad, GstEvent * event)
5633 {
5634   gboolean res = FALSE;
5635   GstPadProbeType type;
5636   gboolean sticky, serialized;
5637 
5638   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
5639   g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
5640 
5641   GST_TRACER_PAD_PUSH_EVENT_PRE (pad, event);
5642 
5643   if (GST_PAD_IS_SRC (pad)) {
5644     if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
5645       goto wrong_direction;
5646     type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
5647   } else if (GST_PAD_IS_SINK (pad)) {
5648     if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
5649       goto wrong_direction;
5650     /* events pushed on sinkpad never are sticky */
5651     type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
5652   } else
5653     goto unknown_direction;
5654 
5655   GST_OBJECT_LOCK (pad);
5656   sticky = GST_EVENT_IS_STICKY (event);
5657   serialized = GST_EVENT_IS_SERIALIZED (event);
5658 
5659   if (sticky) {
5660     /* srcpad sticky events are stored immediately, the received flag is set
5661      * to FALSE and will be set to TRUE when we can successfully push the
5662      * event to the peer pad */
5663     switch (store_sticky_event (pad, event)) {
5664       case GST_FLOW_FLUSHING:
5665         goto flushed;
5666       case GST_FLOW_EOS:
5667         goto eos;
5668       default:
5669         break;
5670     }
5671   }
5672   if (GST_PAD_IS_SRC (pad) && (serialized || sticky)) {
5673     /* all serialized or sticky events on the srcpad trigger push of
5674      * sticky events */
5675     res = (check_sticky (pad, event) == GST_FLOW_OK);
5676   }
5677   if (!sticky) {
5678     GstFlowReturn ret;
5679 
5680     /* other events are pushed right away */
5681     ret = gst_pad_push_event_unchecked (pad, event, type);
5682     /* dropped events by a probe are not an error */
5683     res = (ret == GST_FLOW_OK || ret == GST_FLOW_CUSTOM_SUCCESS
5684         || ret == GST_FLOW_CUSTOM_SUCCESS_1);
5685   } else {
5686     /* Errors in sticky event pushing are no problem and ignored here
5687      * as they will cause more meaningful errors during data flow.
5688      * For EOS events, that are not followed by data flow, we still
5689      * return FALSE here though.
5690      */
5691     if (GST_EVENT_TYPE (event) != GST_EVENT_EOS)
5692       res = TRUE;
5693     gst_event_unref (event);
5694   }
5695   GST_OBJECT_UNLOCK (pad);
5696 
5697   GST_TRACER_PAD_PUSH_EVENT_POST (pad, res);
5698   return res;
5699 
5700   /* ERROR handling */
5701 wrong_direction:
5702   {
5703     g_warning ("pad %s:%s pushing %s event in wrong direction",
5704         GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
5705     gst_event_unref (event);
5706     goto done;
5707   }
5708 unknown_direction:
5709   {
5710     g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
5711     gst_event_unref (event);
5712     goto done;
5713   }
5714 flushed:
5715   {
5716     GST_DEBUG_OBJECT (pad, "We're flushing");
5717     GST_OBJECT_UNLOCK (pad);
5718     gst_event_unref (event);
5719     goto done;
5720   }
5721 eos:
5722   {
5723     GST_DEBUG_OBJECT (pad, "We're EOS");
5724     GST_OBJECT_UNLOCK (pad);
5725     gst_event_unref (event);
5726     goto done;
5727   }
5728 done:
5729   GST_TRACER_PAD_PUSH_EVENT_POST (pad, FALSE);
5730   return FALSE;
5731 }
5732 
5733 /* Check if we can call the event function with the given event */
5734 static GstFlowReturn
pre_eventfunc_check(GstPad * pad,GstEvent * event)5735 pre_eventfunc_check (GstPad * pad, GstEvent * event)
5736 {
5737   GstCaps *caps;
5738 
5739   switch (GST_EVENT_TYPE (event)) {
5740     case GST_EVENT_CAPS:
5741     {
5742       /* backwards compatibility mode for caps */
5743       gst_event_parse_caps (event, &caps);
5744 
5745       if (!gst_pad_query_accept_caps (pad, caps))
5746         goto not_accepted;
5747       break;
5748     }
5749     default:
5750       break;
5751   }
5752   return GST_FLOW_OK;
5753 
5754   /* ERRORS */
5755 not_accepted:
5756   {
5757     GST_CAT_WARNING_OBJECT (GST_CAT_CAPS, pad,
5758         "caps %" GST_PTR_FORMAT " not accepted", caps);
5759     return GST_FLOW_NOT_NEGOTIATED;
5760   }
5761 }
5762 
5763 static GstFlowReturn
gst_pad_send_event_unchecked(GstPad * pad,GstEvent * event,GstPadProbeType type)5764 gst_pad_send_event_unchecked (GstPad * pad, GstEvent * event,
5765     GstPadProbeType type)
5766 {
5767   GstFlowReturn ret;
5768   GstEventType event_type;
5769   gboolean serialized, need_unlock = FALSE, sticky;
5770   GstPadEventFunction eventfunc;
5771   GstPadEventFullFunction eventfullfunc = NULL;
5772   GstObject *parent;
5773   gint64 old_pad_offset;
5774 
5775   GST_OBJECT_LOCK (pad);
5776 
5777   old_pad_offset = pad->offset;
5778   event = apply_pad_offset (pad, event, GST_PAD_IS_SRC (pad));
5779 
5780   if (GST_PAD_IS_SINK (pad))
5781     serialized = GST_EVENT_IS_SERIALIZED (event);
5782   else
5783     serialized = FALSE;
5784   sticky = GST_EVENT_IS_STICKY (event);
5785   event_type = GST_EVENT_TYPE (event);
5786   switch (event_type) {
5787     case GST_EVENT_FLUSH_START:
5788       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
5789           "have event type %d (FLUSH_START)", GST_EVENT_TYPE (event));
5790 
5791       /* can't even accept a flush begin event when flushing */
5792       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5793         goto flushing;
5794 
5795       GST_PAD_SET_FLUSHING (pad);
5796       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "set flush flag");
5797       GST_PAD_BLOCK_BROADCAST (pad);
5798       type |= GST_PAD_PROBE_TYPE_EVENT_FLUSH;
5799       break;
5800     case GST_EVENT_FLUSH_STOP:
5801       /* we can't accept flush-stop on inactive pads else the flushing flag
5802        * would be cleared and it would look like the pad can accept data.
5803        * Also, some elements restart a streaming thread in flush-stop which we
5804        * can't allow on inactive pads */
5805       if (G_UNLIKELY (!GST_PAD_IS_ACTIVE (pad)))
5806         goto inactive;
5807 
5808       GST_PAD_UNSET_FLUSHING (pad);
5809       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "cleared flush flag");
5810       /* Remove pending EOS events */
5811       GST_LOG_OBJECT (pad, "Removing pending EOS and SEGMENT events");
5812       remove_event_by_type (pad, GST_EVENT_EOS);
5813       remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
5814       remove_event_by_type (pad, GST_EVENT_SEGMENT);
5815       GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
5816       pad->ABI.abi.last_flowret = GST_FLOW_OK;
5817 
5818       GST_OBJECT_UNLOCK (pad);
5819       /* grab stream lock */
5820       GST_PAD_STREAM_LOCK (pad);
5821       need_unlock = TRUE;
5822       GST_OBJECT_LOCK (pad);
5823       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5824         goto flushing;
5825       break;
5826     case GST_EVENT_RECONFIGURE:
5827       if (GST_PAD_IS_SRC (pad))
5828         GST_OBJECT_FLAG_SET (pad, GST_PAD_FLAG_NEED_RECONFIGURE);
5829     default:
5830       GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad,
5831           "have event type %" GST_PTR_FORMAT, event);
5832 
5833       if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5834         goto flushing;
5835 
5836       switch (event_type) {
5837         case GST_EVENT_STREAM_START:
5838           /* Remove sticky EOS events */
5839           GST_LOG_OBJECT (pad, "Removing pending EOS events");
5840           remove_event_by_type (pad, GST_EVENT_EOS);
5841           remove_event_by_type (pad, GST_EVENT_STREAM_GROUP_DONE);
5842           remove_event_by_type (pad, GST_EVENT_TAG);
5843           GST_OBJECT_FLAG_UNSET (pad, GST_PAD_FLAG_EOS);
5844           break;
5845         default:
5846           break;
5847       }
5848 
5849       if (serialized) {
5850         if (G_UNLIKELY (GST_PAD_IS_EOS (pad)))
5851           goto eos;
5852 
5853         /* lock order: STREAM_LOCK, LOCK, recheck flushing. */
5854         GST_OBJECT_UNLOCK (pad);
5855         GST_PAD_STREAM_LOCK (pad);
5856         need_unlock = TRUE;
5857         GST_OBJECT_LOCK (pad);
5858         if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
5859           goto flushing;
5860 
5861         if (G_UNLIKELY (GST_PAD_IS_EOS (pad)))
5862           goto eos;
5863       }
5864       break;
5865   }
5866 
5867   /* now do the probe */
5868   PROBE_PUSH (pad,
5869       type | GST_PAD_PROBE_TYPE_PUSH |
5870       GST_PAD_PROBE_TYPE_BLOCK, event, probe_stopped);
5871 
5872   PROBE_PUSH (pad, type | GST_PAD_PROBE_TYPE_PUSH, event, probe_stopped);
5873 
5874   /* the pad offset might've been changed by any of the probes above. It
5875    * would've been taken into account when repushing any of the sticky events
5876    * above but not for our current event here */
5877   if (G_UNLIKELY (old_pad_offset != pad->offset)) {
5878     event =
5879         _apply_pad_offset (pad, event, GST_PAD_IS_SRC (pad),
5880         pad->offset - old_pad_offset);
5881   }
5882 
5883   eventfullfunc = GST_PAD_EVENTFULLFUNC (pad);
5884   eventfunc = GST_PAD_EVENTFUNC (pad);
5885   if (G_UNLIKELY (eventfunc == NULL && eventfullfunc == NULL))
5886     goto no_function;
5887 
5888   ACQUIRE_PARENT (pad, parent, no_parent);
5889   GST_OBJECT_UNLOCK (pad);
5890 
5891   ret = pre_eventfunc_check (pad, event);
5892   if (G_UNLIKELY (ret != GST_FLOW_OK))
5893     goto precheck_failed;
5894 
5895   if (sticky)
5896     gst_event_ref (event);
5897 
5898   if (eventfullfunc) {
5899     ret = eventfullfunc (pad, parent, event);
5900   } else if (eventfunc (pad, parent, event)) {
5901     ret = GST_FLOW_OK;
5902   } else {
5903     /* something went wrong */
5904     switch (event_type) {
5905       case GST_EVENT_CAPS:
5906         ret = GST_FLOW_NOT_NEGOTIATED;
5907         break;
5908       default:
5909         ret = GST_FLOW_ERROR;
5910         break;
5911     }
5912   }
5913   RELEASE_PARENT (parent);
5914 
5915   GST_DEBUG_OBJECT (pad, "sent event, ret %s", gst_flow_get_name (ret));
5916 
5917   if (sticky) {
5918     if (ret == GST_FLOW_OK) {
5919       GST_OBJECT_LOCK (pad);
5920       /* after the event function accepted the event, we can store the sticky
5921        * event on the pad */
5922       switch (store_sticky_event (pad, event)) {
5923         case GST_FLOW_FLUSHING:
5924           goto flushing;
5925         case GST_FLOW_EOS:
5926           goto eos;
5927         default:
5928           break;
5929       }
5930       GST_OBJECT_UNLOCK (pad);
5931     }
5932     gst_event_unref (event);
5933   }
5934 
5935   if (need_unlock)
5936     GST_PAD_STREAM_UNLOCK (pad);
5937 
5938   return ret;
5939 
5940   /* ERROR handling */
5941 flushing:
5942   {
5943     GST_OBJECT_UNLOCK (pad);
5944     if (need_unlock)
5945       GST_PAD_STREAM_UNLOCK (pad);
5946     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
5947         "Received event on flushing pad. Discarding");
5948     gst_event_unref (event);
5949     return GST_FLOW_FLUSHING;
5950   }
5951 inactive:
5952   {
5953     GST_OBJECT_UNLOCK (pad);
5954     if (need_unlock)
5955       GST_PAD_STREAM_UNLOCK (pad);
5956     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
5957         "Received flush-stop on inactive pad. Discarding");
5958     gst_event_unref (event);
5959     return GST_FLOW_FLUSHING;
5960   }
5961 eos:
5962   {
5963     GST_OBJECT_UNLOCK (pad);
5964     if (need_unlock)
5965       GST_PAD_STREAM_UNLOCK (pad);
5966     GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad,
5967         "Received event on EOS pad. Discarding");
5968     gst_event_unref (event);
5969     return GST_FLOW_EOS;
5970   }
5971 probe_stopped:
5972   {
5973     GST_OBJECT_UNLOCK (pad);
5974     if (need_unlock)
5975       GST_PAD_STREAM_UNLOCK (pad);
5976     /* Only unref if unhandled */
5977     if (ret != GST_FLOW_CUSTOM_SUCCESS_1)
5978       gst_event_unref (event);
5979 
5980     switch (ret) {
5981       case GST_FLOW_CUSTOM_SUCCESS_1:
5982       case GST_FLOW_CUSTOM_SUCCESS:
5983         GST_DEBUG_OBJECT (pad, "dropped or handled event");
5984         ret = GST_FLOW_OK;
5985         break;
5986       default:
5987         GST_DEBUG_OBJECT (pad, "an error occurred %s", gst_flow_get_name (ret));
5988         break;
5989     }
5990     return ret;
5991   }
5992 no_function:
5993   {
5994     g_warning ("pad %s:%s has no event handler, file a bug.",
5995         GST_DEBUG_PAD_NAME (pad));
5996     GST_OBJECT_UNLOCK (pad);
5997     if (need_unlock)
5998       GST_PAD_STREAM_UNLOCK (pad);
5999     gst_event_unref (event);
6000     return GST_FLOW_NOT_SUPPORTED;
6001   }
6002 no_parent:
6003   {
6004     GST_DEBUG_OBJECT (pad, "no parent");
6005     GST_OBJECT_UNLOCK (pad);
6006     if (need_unlock)
6007       GST_PAD_STREAM_UNLOCK (pad);
6008     gst_event_unref (event);
6009     return GST_FLOW_FLUSHING;
6010   }
6011 precheck_failed:
6012   {
6013     GST_DEBUG_OBJECT (pad, "pre event check failed");
6014     RELEASE_PARENT (parent);
6015     if (need_unlock)
6016       GST_PAD_STREAM_UNLOCK (pad);
6017     gst_event_unref (event);
6018     return ret;
6019   }
6020 }
6021 
6022 /**
6023  * gst_pad_send_event:
6024  * @pad: a #GstPad to send the event to.
6025  * @event: (transfer full): the #GstEvent to send to the pad.
6026  *
6027  * Sends the event to the pad. This function can be used
6028  * by applications to send events in the pipeline.
6029  *
6030  * If @pad is a source pad, @event should be an upstream event. If @pad is a
6031  * sink pad, @event should be a downstream event. For example, you would not
6032  * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream.
6033  * Furthermore, some downstream events have to be serialized with data flow,
6034  * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If
6035  * the event needs to be serialized with data flow, this function will take the
6036  * pad's stream lock while calling its event function.
6037  *
6038  * To find out whether an event type is upstream, downstream, or downstream and
6039  * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(),
6040  * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and
6041  * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or
6042  * plugin doesn't need to bother itself with this information; the core handles
6043  * all necessary locks and checks.
6044  *
6045  * This function takes ownership of the provided event so you should
6046  * gst_event_ref() it if you want to reuse the event after this call.
6047  *
6048  * Returns: %TRUE if the event was handled.
6049  */
6050 gboolean
gst_pad_send_event(GstPad * pad,GstEvent * event)6051 gst_pad_send_event (GstPad * pad, GstEvent * event)
6052 {
6053   gboolean result;
6054   GstPadProbeType type;
6055 
6056   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
6057   g_return_val_if_fail (event != NULL, FALSE);
6058 
6059   if (GST_PAD_IS_SINK (pad)) {
6060     if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event)))
6061       goto wrong_direction;
6062     type = GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM;
6063   } else if (GST_PAD_IS_SRC (pad)) {
6064     if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event)))
6065       goto wrong_direction;
6066     type = GST_PAD_PROBE_TYPE_EVENT_UPSTREAM;
6067   } else
6068     goto unknown_direction;
6069 
6070   if (gst_pad_send_event_unchecked (pad, event, type) != GST_FLOW_OK)
6071     result = FALSE;
6072   else
6073     result = TRUE;
6074 
6075   return result;
6076 
6077   /* ERROR handling */
6078 wrong_direction:
6079   {
6080     g_warning ("pad %s:%s sending %s event in wrong direction",
6081         GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event));
6082     gst_event_unref (event);
6083     return FALSE;
6084   }
6085 unknown_direction:
6086   {
6087     g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad));
6088     gst_event_unref (event);
6089     return FALSE;
6090   }
6091 }
6092 
6093 /**
6094  * gst_pad_set_element_private:
6095  * @pad: the #GstPad to set the private data of.
6096  * @priv: The private data to attach to the pad.
6097  *
6098  * Set the given private data gpointer on the pad.
6099  * This function can only be used by the element that owns the pad.
6100  * No locking is performed in this function.
6101  */
6102 void
gst_pad_set_element_private(GstPad * pad,gpointer priv)6103 gst_pad_set_element_private (GstPad * pad, gpointer priv)
6104 {
6105   pad->element_private = priv;
6106 }
6107 
6108 /**
6109  * gst_pad_get_element_private:
6110  * @pad: the #GstPad to get the private data of.
6111  *
6112  * Gets the private data of a pad.
6113  * No locking is performed in this function.
6114  *
6115  * Returns: (transfer none) (nullable): a #gpointer to the private data.
6116  */
6117 gpointer
gst_pad_get_element_private(GstPad * pad)6118 gst_pad_get_element_private (GstPad * pad)
6119 {
6120   return pad->element_private;
6121 }
6122 
6123 /**
6124  * gst_pad_get_sticky_event:
6125  * @pad: the #GstPad to get the event from.
6126  * @event_type: the #GstEventType that should be retrieved.
6127  * @idx: the index of the event
6128  *
6129  * Returns a new reference of the sticky event of type @event_type
6130  * from the event.
6131  *
6132  * Returns: (transfer full) (nullable): a #GstEvent of type
6133  * @event_type or %NULL when no event of @event_type was on
6134  * @pad. Unref after usage.
6135  */
6136 GstEvent *
gst_pad_get_sticky_event(GstPad * pad,GstEventType event_type,guint idx)6137 gst_pad_get_sticky_event (GstPad * pad, GstEventType event_type, guint idx)
6138 {
6139   GstEvent *event = NULL;
6140   PadEvent *ev;
6141 
6142   g_return_val_if_fail (GST_IS_PAD (pad), NULL);
6143   g_return_val_if_fail ((event_type & GST_EVENT_TYPE_STICKY) != 0, NULL);
6144 
6145   GST_OBJECT_LOCK (pad);
6146   ev = find_event_by_type (pad, event_type, idx);
6147   if (ev && (event = ev->event))
6148     gst_event_ref (event);
6149   GST_OBJECT_UNLOCK (pad);
6150 
6151   return event;
6152 }
6153 
6154 typedef struct
6155 {
6156   GstPadStickyEventsForeachFunction func;
6157   gpointer user_data;
6158 } ForeachDispatch;
6159 
6160 static gboolean
foreach_dispatch_function(GstPad * pad,PadEvent * ev,gpointer user_data)6161 foreach_dispatch_function (GstPad * pad, PadEvent * ev, gpointer user_data)
6162 {
6163   ForeachDispatch *data = user_data;
6164   gboolean ret = TRUE;
6165 
6166   if (ev->event) {
6167     GST_OBJECT_UNLOCK (pad);
6168 
6169     ret = data->func (pad, &ev->event, data->user_data);
6170 
6171     GST_OBJECT_LOCK (pad);
6172   }
6173 
6174   return ret;
6175 }
6176 
6177 /**
6178  * gst_pad_sticky_events_foreach:
6179  * @pad: the #GstPad that should be used for iteration.
6180  * @foreach_func: (scope call): the #GstPadStickyEventsForeachFunction that
6181  *                should be called for every event.
6182  * @user_data: (closure): the optional user data.
6183  *
6184  * Iterates all sticky events on @pad and calls @foreach_func for every
6185  * event. If @foreach_func returns %FALSE the iteration is immediately stopped.
6186  */
6187 void
gst_pad_sticky_events_foreach(GstPad * pad,GstPadStickyEventsForeachFunction foreach_func,gpointer user_data)6188 gst_pad_sticky_events_foreach (GstPad * pad,
6189     GstPadStickyEventsForeachFunction foreach_func, gpointer user_data)
6190 {
6191   ForeachDispatch data;
6192 
6193   g_return_if_fail (GST_IS_PAD (pad));
6194   g_return_if_fail (foreach_func != NULL);
6195 
6196   data.func = foreach_func;
6197   data.user_data = user_data;
6198 
6199   GST_OBJECT_LOCK (pad);
6200   events_foreach (pad, foreach_dispatch_function, &data);
6201   GST_OBJECT_UNLOCK (pad);
6202 }
6203 
6204 static void
do_stream_status(GstPad * pad,GstStreamStatusType type,GThread * thread,GstTask * task)6205 do_stream_status (GstPad * pad, GstStreamStatusType type,
6206     GThread * thread, GstTask * task)
6207 {
6208   GstElement *parent;
6209 
6210   GST_DEBUG_OBJECT (pad, "doing stream-status %d", type);
6211 
6212   if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (pad)))) {
6213     if (GST_IS_ELEMENT (parent)) {
6214       GstMessage *message;
6215       GValue value = { 0 };
6216 
6217       if (type == GST_STREAM_STATUS_TYPE_ENTER) {
6218         gchar *tname;
6219 
6220         /* create a good task name (we can directly grab the parent and pad
6221          * names since they both exist at this point, and changing the name of
6222          * parent and pad when a pad is activating is a big no-no). */
6223         tname = g_strdup_printf ("%s:%s", GST_DEBUG_PAD_NAME (pad));
6224 
6225         gst_object_set_name (GST_OBJECT_CAST (task), tname);
6226         g_free (tname);
6227       }
6228 
6229       message = gst_message_new_stream_status (GST_OBJECT_CAST (pad),
6230           type, parent);
6231 
6232       g_value_init (&value, GST_TYPE_TASK);
6233       g_value_set_object (&value, task);
6234       gst_message_set_stream_status_object (message, &value);
6235       g_value_unset (&value);
6236 
6237       GST_DEBUG_OBJECT (pad, "posting stream-status %d", type);
6238       gst_element_post_message (parent, message);
6239     }
6240     gst_object_unref (parent);
6241   }
6242 }
6243 
6244 static void
pad_enter_thread(GstTask * task,GThread * thread,gpointer user_data)6245 pad_enter_thread (GstTask * task, GThread * thread, gpointer user_data)
6246 {
6247   do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_ENTER,
6248       thread, task);
6249 }
6250 
6251 static void
pad_leave_thread(GstTask * task,GThread * thread,gpointer user_data)6252 pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data)
6253 {
6254   do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_LEAVE,
6255       thread, task);
6256 }
6257 
6258 /**
6259  * gst_pad_start_task:
6260  * @pad: the #GstPad to start the task of
6261  * @func: the task function to call
6262  * @user_data: user data passed to the task function
6263  * @notify: called when @user_data is no longer referenced
6264  *
6265  * Starts a task that repeatedly calls @func with @user_data. This function
6266  * is mostly used in pad activation functions to start the dataflow.
6267  * The #GST_PAD_STREAM_LOCK of @pad will automatically be acquired
6268  * before @func is called.
6269  *
6270  * Returns: a %TRUE if the task could be started.
6271  */
6272 gboolean
gst_pad_start_task(GstPad * pad,GstTaskFunction func,gpointer user_data,GDestroyNotify notify)6273 gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer user_data,
6274     GDestroyNotify notify)
6275 {
6276   GstTask *task;
6277   gboolean res;
6278 
6279   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
6280   g_return_val_if_fail (func != NULL, FALSE);
6281 
6282   GST_DEBUG_OBJECT (pad, "start task");
6283 
6284   GST_OBJECT_LOCK (pad);
6285   task = GST_PAD_TASK (pad);
6286   if (task == NULL) {
6287     task = gst_task_new (func, user_data, notify);
6288     gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad));
6289     gst_task_set_enter_callback (task, pad_enter_thread, pad, NULL);
6290     gst_task_set_leave_callback (task, pad_leave_thread, pad, NULL);
6291     GST_INFO_OBJECT (pad, "created task %p", task);
6292     GST_PAD_TASK (pad) = task;
6293     gst_object_ref (task);
6294     /* release lock to post the message */
6295     GST_OBJECT_UNLOCK (pad);
6296 
6297     do_stream_status (pad, GST_STREAM_STATUS_TYPE_CREATE, NULL, task);
6298 
6299     gst_object_unref (task);
6300 
6301     GST_OBJECT_LOCK (pad);
6302     /* nobody else is supposed to have changed the pad now */
6303     if (GST_PAD_TASK (pad) != task)
6304       goto concurrent_stop;
6305   }
6306   res = gst_task_set_state (task, GST_TASK_STARTED);
6307   GST_OBJECT_UNLOCK (pad);
6308 
6309   return res;
6310 
6311   /* ERRORS */
6312 concurrent_stop:
6313   {
6314     GST_OBJECT_UNLOCK (pad);
6315     return TRUE;
6316   }
6317 }
6318 
6319 /**
6320  * gst_pad_pause_task:
6321  * @pad: the #GstPad to pause the task of
6322  *
6323  * Pause the task of @pad. This function will also wait until the
6324  * function executed by the task is finished if this function is not
6325  * called from the task function.
6326  *
6327  * Returns: a %TRUE if the task could be paused or %FALSE when the pad
6328  * has no task.
6329  */
6330 gboolean
gst_pad_pause_task(GstPad * pad)6331 gst_pad_pause_task (GstPad * pad)
6332 {
6333   GstTask *task;
6334   gboolean res;
6335 
6336   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
6337 
6338   GST_DEBUG_OBJECT (pad, "pause task");
6339 
6340   GST_OBJECT_LOCK (pad);
6341   task = GST_PAD_TASK (pad);
6342   if (task == NULL)
6343     goto no_task;
6344   res = gst_task_set_state (task, GST_TASK_PAUSED);
6345   /* unblock activation waits if any */
6346   pad->priv->in_activation = FALSE;
6347   g_cond_broadcast (&pad->priv->activation_cond);
6348   GST_OBJECT_UNLOCK (pad);
6349 
6350   /* wait for task function to finish, this lock is recursive so it does nothing
6351    * when the pause is called from the task itself */
6352   GST_PAD_STREAM_LOCK (pad);
6353   GST_PAD_STREAM_UNLOCK (pad);
6354 
6355   return res;
6356 
6357 no_task:
6358   {
6359     GST_DEBUG_OBJECT (pad, "pad has no task");
6360     GST_OBJECT_UNLOCK (pad);
6361     return FALSE;
6362   }
6363 }
6364 
6365 /**
6366  * gst_pad_get_task_state:
6367  * @pad: the #GstPad to get task state from
6368  *
6369  * Get @pad task state. If no task is currently
6370  * set, #GST_TASK_STOPPED is returned.
6371  *
6372  * Returns: The current state of @pad's task.
6373  *
6374  * Since: 1.12
6375  */
6376 GstTaskState
gst_pad_get_task_state(GstPad * pad)6377 gst_pad_get_task_state (GstPad * pad)
6378 {
6379   GstTask *task;
6380   GstTaskState res;
6381 
6382   g_return_val_if_fail (GST_IS_PAD (pad), GST_TASK_STOPPED);
6383 
6384   GST_OBJECT_LOCK (pad);
6385   task = GST_PAD_TASK (pad);
6386   if (task == NULL)
6387     goto no_task;
6388   res = gst_task_get_state (task);
6389   GST_OBJECT_UNLOCK (pad);
6390 
6391   return res;
6392 
6393 no_task:
6394   {
6395     GST_DEBUG_OBJECT (pad, "pad has no task");
6396     GST_OBJECT_UNLOCK (pad);
6397     return GST_TASK_STOPPED;
6398   }
6399 }
6400 
6401 /**
6402  * gst_pad_stop_task:
6403  * @pad: the #GstPad to stop the task of
6404  *
6405  * Stop the task of @pad. This function will also make sure that the
6406  * function executed by the task will effectively stop if not called
6407  * from the GstTaskFunction.
6408  *
6409  * This function will deadlock if called from the GstTaskFunction of
6410  * the task. Use gst_task_pause() instead.
6411  *
6412  * Regardless of whether the pad has a task, the stream lock is acquired and
6413  * released so as to ensure that streaming through this pad has finished.
6414  *
6415  * Returns: a %TRUE if the task could be stopped or %FALSE on error.
6416  */
6417 gboolean
gst_pad_stop_task(GstPad * pad)6418 gst_pad_stop_task (GstPad * pad)
6419 {
6420   GstTask *task;
6421   gboolean res;
6422 
6423   g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
6424 
6425   GST_DEBUG_OBJECT (pad, "stop task");
6426 
6427   GST_OBJECT_LOCK (pad);
6428   task = GST_PAD_TASK (pad);
6429   if (task == NULL)
6430     goto no_task;
6431   GST_PAD_TASK (pad) = NULL;
6432   res = gst_task_set_state (task, GST_TASK_STOPPED);
6433   /* unblock activation waits if any */
6434   pad->priv->in_activation = FALSE;
6435   g_cond_broadcast (&pad->priv->activation_cond);
6436   GST_OBJECT_UNLOCK (pad);
6437 
6438   GST_PAD_STREAM_LOCK (pad);
6439   GST_PAD_STREAM_UNLOCK (pad);
6440 
6441   if (!gst_task_join (task))
6442     goto join_failed;
6443 
6444   gst_object_unref (task);
6445 
6446   return res;
6447 
6448 no_task:
6449   {
6450     GST_DEBUG_OBJECT (pad, "no task");
6451     GST_OBJECT_UNLOCK (pad);
6452 
6453     GST_PAD_STREAM_LOCK (pad);
6454     GST_PAD_STREAM_UNLOCK (pad);
6455 
6456     /* this is not an error */
6457     return TRUE;
6458   }
6459 join_failed:
6460   {
6461     /* this is bad, possibly the application tried to join the task from
6462      * the task's thread. We install the task again so that it will be stopped
6463      * again from the right thread next time hopefully. */
6464     GST_OBJECT_LOCK (pad);
6465     GST_DEBUG_OBJECT (pad, "join failed");
6466     /* we can only install this task if there was no other task */
6467     if (GST_PAD_TASK (pad) == NULL)
6468       GST_PAD_TASK (pad) = task;
6469     GST_OBJECT_UNLOCK (pad);
6470 
6471     return FALSE;
6472   }
6473 }
6474 
6475 /**
6476  * gst_pad_probe_info_get_event:
6477  * @info: a #GstPadProbeInfo
6478  *
6479  * Returns: (transfer none) (nullable): The #GstEvent from the probe
6480  */
6481 
6482 GstEvent *
gst_pad_probe_info_get_event(GstPadProbeInfo * info)6483 gst_pad_probe_info_get_event (GstPadProbeInfo * info)
6484 {
6485   g_return_val_if_fail (info->type & (GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM |
6486           GST_PAD_PROBE_TYPE_EVENT_UPSTREAM), NULL);
6487 
6488   return GST_PAD_PROBE_INFO_EVENT (info);
6489 }
6490 
6491 
6492 /**
6493  * gst_pad_probe_info_get_query:
6494  * @info: a #GstPadProbeInfo
6495  *
6496  * Returns: (transfer none) (nullable): The #GstQuery from the probe
6497  */
6498 
6499 GstQuery *
gst_pad_probe_info_get_query(GstPadProbeInfo * info)6500 gst_pad_probe_info_get_query (GstPadProbeInfo * info)
6501 {
6502   g_return_val_if_fail (info->type & (GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM |
6503           GST_PAD_PROBE_TYPE_QUERY_UPSTREAM), NULL);
6504 
6505   return GST_PAD_PROBE_INFO_QUERY (info);
6506 }
6507 
6508 /**
6509  * gst_pad_probe_info_get_buffer:
6510  * @info: a #GstPadProbeInfo
6511  *
6512  * Returns: (transfer none) (nullable): The #GstBuffer from the probe
6513  */
6514 
6515 GstBuffer *
gst_pad_probe_info_get_buffer(GstPadProbeInfo * info)6516 gst_pad_probe_info_get_buffer (GstPadProbeInfo * info)
6517 {
6518   g_return_val_if_fail (info->type & GST_PAD_PROBE_TYPE_BUFFER, NULL);
6519 
6520   return GST_PAD_PROBE_INFO_BUFFER (info);
6521 }
6522 
6523 /**
6524  * gst_pad_probe_info_get_buffer_list:
6525  * @info: a #GstPadProbeInfo
6526  *
6527  * Returns: (transfer none) (nullable): The #GstBufferList from the probe
6528  */
6529 
6530 GstBufferList *
gst_pad_probe_info_get_buffer_list(GstPadProbeInfo * info)6531 gst_pad_probe_info_get_buffer_list (GstPadProbeInfo * info)
6532 {
6533   g_return_val_if_fail (info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST, NULL);
6534 
6535   return GST_PAD_PROBE_INFO_BUFFER_LIST (info);
6536 }
6537 
6538 /**
6539  * gst_pad_get_last_flow_return:
6540  * @pad: the #GstPad
6541  *
6542  * Gets the #GstFlowReturn return from the last data passed by this pad.
6543  *
6544  * Since: 1.4
6545  */
6546 GstFlowReturn
gst_pad_get_last_flow_return(GstPad * pad)6547 gst_pad_get_last_flow_return (GstPad * pad)
6548 {
6549   GstFlowReturn ret;
6550 
6551   GST_OBJECT_LOCK (pad);
6552   ret = GST_PAD_LAST_FLOW_RETURN (pad);
6553   GST_OBJECT_UNLOCK (pad);
6554 
6555   return ret;
6556 }
6557