|
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., 59 Temple Place - Suite 330, |
|
20 * Boston, MA 02111-1307, USA. |
|
21 */ |
|
22 /** |
|
23 * SECTION:gstpad |
|
24 * @short_description: Object contained by elements that allows links to |
|
25 * other elements |
|
26 * @see_also: #GstPadTemplate, #GstElement, #GstEvent |
|
27 * |
|
28 * A #GstElement is linked to other elements via "pads", which are extremely |
|
29 * light-weight generic link points. |
|
30 * After two pads are retrieved from an element with gst_element_get_pad(), |
|
31 * the pads can be link with gst_pad_link(). (For quick links, |
|
32 * you can also use gst_element_link(), which will make the obvious |
|
33 * link for you if it's straightforward.) |
|
34 * |
|
35 * Pads are typically created from a #GstPadTemplate with |
|
36 * gst_pad_new_from_template(). |
|
37 * |
|
38 * Pads have #GstCaps attached to it to describe the media type they are |
|
39 * capable of dealing with. gst_pad_get_caps() and gst_pad_set_caps() are |
|
40 * used to manipulate the caps of the pads. |
|
41 * Pads created from a pad template cannot set capabilities that are |
|
42 * incompatible with the pad template capabilities. |
|
43 * |
|
44 * Pads without pad templates can be created with gst_pad_new(), |
|
45 * which takes a direction and a name as an argument. If the name is NULL, |
|
46 * then a guaranteed unique name will be assigned to it. |
|
47 * |
|
48 * gst_pad_get_parent() will retrieve the #GstElement that owns the pad. |
|
49 * |
|
50 * A #GstElement creating a pad will typically use the various |
|
51 * gst_pad_set_*_function() calls to register callbacks for various events |
|
52 * on the pads. |
|
53 * |
|
54 * GstElements will use gst_pad_push() and gst_pad_pull_range() to push out |
|
55 * or pull in a buffer. |
|
56 * |
|
57 * To send a #GstEvent on a pad, use gst_pad_send_event() and |
|
58 * gst_pad_push_event(). |
|
59 * |
|
60 * Last reviewed on 2006-07-06 (0.10.9) |
|
61 */ |
|
62 |
|
63 #include "gst_private.h" |
|
64 |
|
65 #include "gstpad.h" |
|
66 #include "gstpadtemplate.h" |
|
67 #include "gstenumtypes.h" |
|
68 #include "gstmarshal.h" |
|
69 #include "gstutils.h" |
|
70 #include "gstinfo.h" |
|
71 #include "gsterror.h" |
|
72 #include "gstvalue.h" |
|
73 #include "glib-compat-private.h" |
|
74 |
|
75 #ifdef __SYMBIAN32__ |
|
76 #include <glib_global.h> |
|
77 #endif |
|
78 |
|
79 GST_DEBUG_CATEGORY_STATIC (debug_dataflow); |
|
80 #define GST_CAT_DEFAULT GST_CAT_PADS |
|
81 |
|
82 /* Pad signals and args */ |
|
83 enum |
|
84 { |
|
85 PAD_LINKED, |
|
86 PAD_UNLINKED, |
|
87 PAD_REQUEST_LINK, |
|
88 PAD_HAVE_DATA, |
|
89 /* FILL ME */ |
|
90 LAST_SIGNAL |
|
91 }; |
|
92 |
|
93 enum |
|
94 { |
|
95 PAD_PROP_0, |
|
96 PAD_PROP_CAPS, |
|
97 PAD_PROP_DIRECTION, |
|
98 PAD_PROP_TEMPLATE, |
|
99 /* FILL ME */ |
|
100 }; |
|
101 |
|
102 static void gst_pad_class_init (GstPadClass * klass); |
|
103 static void gst_pad_init (GstPad * pad); |
|
104 static void gst_pad_dispose (GObject * object); |
|
105 static void gst_pad_finalize (GObject * object); |
|
106 static void gst_pad_set_property (GObject * object, guint prop_id, |
|
107 const GValue * value, GParamSpec * pspec); |
|
108 static void gst_pad_get_property (GObject * object, guint prop_id, |
|
109 GValue * value, GParamSpec * pspec); |
|
110 |
|
111 static GstFlowReturn handle_pad_block (GstPad * pad); |
|
112 static GstCaps *gst_pad_get_caps_unlocked (GstPad * pad); |
|
113 static void gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ); |
|
114 static gboolean gst_pad_activate_default (GstPad * pad); |
|
115 static gboolean gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps); |
|
116 |
|
117 #ifndef GST_DISABLE_LOADSAVE |
|
118 static xmlNodePtr gst_pad_save_thyself (GstObject * object, xmlNodePtr parent); |
|
119 #endif |
|
120 |
|
121 static GstObjectClass *parent_class = NULL; |
|
122 static guint gst_pad_signals[LAST_SIGNAL] = { 0 }; |
|
123 |
|
124 /* quarks for probe signals */ |
|
125 static GQuark buffer_quark; |
|
126 static GQuark event_quark; |
|
127 |
|
128 typedef struct |
|
129 { |
|
130 const gint ret; |
|
131 const gchar *name; |
|
132 GQuark quark; |
|
133 } GstFlowQuarks; |
|
134 |
|
135 static GstFlowQuarks flow_quarks[] = { |
|
136 {GST_FLOW_CUSTOM_SUCCESS, "custom-success", 0}, |
|
137 {GST_FLOW_RESEND, "resend", 0}, |
|
138 {GST_FLOW_OK, "ok", 0}, |
|
139 {GST_FLOW_NOT_LINKED, "not-linked", 0}, |
|
140 {GST_FLOW_WRONG_STATE, "wrong-state", 0}, |
|
141 {GST_FLOW_UNEXPECTED, "unexpected", 0}, |
|
142 {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0}, |
|
143 {GST_FLOW_ERROR, "error", 0}, |
|
144 {GST_FLOW_NOT_SUPPORTED, "not-supported", 0}, |
|
145 {GST_FLOW_CUSTOM_ERROR, "custom-error", 0}, |
|
146 |
|
147 {0, NULL, 0} |
|
148 }; |
|
149 |
|
150 /** |
|
151 * gst_flow_get_name: |
|
152 * @ret: a #GstFlowReturn to get the name of. |
|
153 * |
|
154 * Gets a string representing the given flow return. |
|
155 * |
|
156 * Returns: a static string with the name of the flow return. |
|
157 */ |
|
158 #ifdef __SYMBIAN32__ |
|
159 EXPORT_C |
|
160 #endif |
|
161 |
|
162 G_CONST_RETURN gchar * |
|
163 gst_flow_get_name (GstFlowReturn ret) |
|
164 { |
|
165 gint i; |
|
166 |
|
167 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
|
168 |
|
169 for (i = 0; flow_quarks[i].name; i++) { |
|
170 if (ret == flow_quarks[i].ret) |
|
171 return flow_quarks[i].name; |
|
172 } |
|
173 return "unknown"; |
|
174 } |
|
175 |
|
176 /** |
|
177 * gst_flow_to_quark: |
|
178 * @ret: a #GstFlowReturn to get the quark of. |
|
179 * |
|
180 * Get the unique quark for the given GstFlowReturn. |
|
181 * |
|
182 * Returns: the quark associated with the flow return or 0 if an |
|
183 * invalid return was specified. |
|
184 */ |
|
185 #ifdef __SYMBIAN32__ |
|
186 EXPORT_C |
|
187 #endif |
|
188 |
|
189 GQuark |
|
190 gst_flow_to_quark (GstFlowReturn ret) |
|
191 { |
|
192 gint i; |
|
193 |
|
194 ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS); |
|
195 |
|
196 for (i = 0; flow_quarks[i].name; i++) { |
|
197 if (ret == flow_quarks[i].ret) |
|
198 return flow_quarks[i].quark; |
|
199 } |
|
200 return 0; |
|
201 } |
|
202 #ifdef __SYMBIAN32__ |
|
203 EXPORT_C |
|
204 #endif |
|
205 |
|
206 |
|
207 GType |
|
208 gst_pad_get_type (void) |
|
209 { |
|
210 static GType gst_pad_type = 0; |
|
211 |
|
212 if (G_UNLIKELY (gst_pad_type == 0)) { |
|
213 static const GTypeInfo pad_info = { |
|
214 sizeof (GstPadClass), NULL, NULL, |
|
215 (GClassInitFunc) gst_pad_class_init, NULL, NULL, |
|
216 sizeof (GstPad), |
|
217 0, |
|
218 (GInstanceInitFunc) gst_pad_init, NULL |
|
219 }; |
|
220 gint i; |
|
221 |
|
222 gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad", |
|
223 &pad_info, 0); |
|
224 |
|
225 buffer_quark = g_quark_from_static_string ("buffer"); |
|
226 event_quark = g_quark_from_static_string ("event"); |
|
227 |
|
228 for (i = 0; flow_quarks[i].name; i++) { |
|
229 flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); |
|
230 } |
|
231 |
|
232 GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", |
|
233 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); |
|
234 } |
|
235 return gst_pad_type; |
|
236 } |
|
237 |
|
238 static gboolean |
|
239 _gst_do_pass_data_accumulator (GSignalInvocationHint * ihint, |
|
240 GValue * return_accu, const GValue * handler_return, gpointer dummy) |
|
241 { |
|
242 gboolean ret = g_value_get_boolean (handler_return); |
|
243 |
|
244 GST_DEBUG ("accumulated %d", ret); |
|
245 g_value_set_boolean (return_accu, ret); |
|
246 |
|
247 return ret; |
|
248 } |
|
249 |
|
250 static gboolean |
|
251 default_have_data (GstPad * pad, GstMiniObject * o) |
|
252 { |
|
253 return TRUE; |
|
254 } |
|
255 |
|
256 static void |
|
257 gst_pad_class_init (GstPadClass * klass) |
|
258 { |
|
259 GObjectClass *gobject_class; |
|
260 GstObjectClass *gstobject_class; |
|
261 |
|
262 gobject_class = G_OBJECT_CLASS (klass); |
|
263 gstobject_class = GST_OBJECT_CLASS (klass); |
|
264 |
|
265 parent_class = g_type_class_peek_parent (klass); |
|
266 |
|
267 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pad_dispose); |
|
268 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_pad_finalize); |
|
269 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pad_set_property); |
|
270 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pad_get_property); |
|
271 |
|
272 /** |
|
273 * GstPad::linked: |
|
274 * @pad: the pad that emitted the signal |
|
275 * @peer: the peer pad that has been connected |
|
276 * |
|
277 * Signals that a pad has been linked to the peer pad. |
|
278 */ |
|
279 gst_pad_signals[PAD_LINKED] = |
|
280 g_signal_new ("linked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, |
|
281 G_STRUCT_OFFSET (GstPadClass, linked), NULL, NULL, |
|
282 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
|
283 /** |
|
284 * GstPad::unlinked: |
|
285 * @pad: the pad that emitted the signal |
|
286 * @peer: the peer pad that has been disconnected |
|
287 * |
|
288 * Signals that a pad has been unlinked from the peer pad. |
|
289 */ |
|
290 gst_pad_signals[PAD_UNLINKED] = |
|
291 g_signal_new ("unlinked", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, |
|
292 G_STRUCT_OFFSET (GstPadClass, unlinked), NULL, NULL, |
|
293 gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); |
|
294 /** |
|
295 * GstPad::request-link: |
|
296 * @pad: the pad that emitted the signal |
|
297 * @peer: the peer pad for which a connection is requested |
|
298 * |
|
299 * Signals that a pad connection has been requested. |
|
300 */ |
|
301 gst_pad_signals[PAD_REQUEST_LINK] = |
|
302 g_signal_new ("request-link", G_TYPE_FROM_CLASS (klass), |
|
303 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPadClass, request_link), NULL, |
|
304 NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 0); |
|
305 |
|
306 /** |
|
307 * GstPad::have-data: |
|
308 * @pad: the pad that emitted the signal |
|
309 * @mini_obj: new data |
|
310 * |
|
311 * Signals that new data is available on the pad. This signal is used |
|
312 * internally for implementing pad probes. |
|
313 * See gst_pad_add_*_probe functions. |
|
314 * |
|
315 * Returns: %TRUE to keep the data, %FALSE to drop it |
|
316 */ |
|
317 gst_pad_signals[PAD_HAVE_DATA] = |
|
318 g_signal_new ("have-data", G_TYPE_FROM_CLASS (klass), |
|
319 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
320 G_STRUCT_OFFSET (GstPadClass, have_data), |
|
321 _gst_do_pass_data_accumulator, |
|
322 NULL, gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, |
|
323 GST_TYPE_MINI_OBJECT); |
|
324 |
|
325 g_object_class_install_property (gobject_class, PAD_PROP_CAPS, |
|
326 g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad", |
|
327 GST_TYPE_CAPS, G_PARAM_READABLE)); |
|
328 g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION, |
|
329 g_param_spec_enum ("direction", "Direction", "The direction of the pad", |
|
330 GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN, |
|
331 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); |
|
332 /* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */ |
|
333 g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE, |
|
334 g_param_spec_object ("template", "Template", |
|
335 "The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE, |
|
336 G_PARAM_READWRITE)); |
|
337 |
|
338 #ifndef GST_DISABLE_LOADSAVE |
|
339 gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself); |
|
340 #endif |
|
341 gstobject_class->path_string_separator = "."; |
|
342 |
|
343 klass->have_data = default_have_data; |
|
344 } |
|
345 |
|
346 static void |
|
347 gst_pad_init (GstPad * pad) |
|
348 { |
|
349 GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN; |
|
350 GST_PAD_PEER (pad) = NULL; |
|
351 |
|
352 GST_PAD_CHAINFUNC (pad) = NULL; |
|
353 |
|
354 GST_PAD_LINKFUNC (pad) = NULL; |
|
355 |
|
356 GST_PAD_CAPS (pad) = NULL; |
|
357 GST_PAD_GETCAPSFUNC (pad) = NULL; |
|
358 |
|
359 GST_PAD_ACTIVATEFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_activate_default); |
|
360 GST_PAD_EVENTFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_event_default); |
|
361 GST_PAD_QUERYTYPEFUNC (pad) = |
|
362 GST_DEBUG_FUNCPTR (gst_pad_get_query_types_default); |
|
363 GST_PAD_QUERYFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_query_default); |
|
364 GST_PAD_INTLINKFUNC (pad) = |
|
365 GST_DEBUG_FUNCPTR (gst_pad_get_internal_links_default); |
|
366 GST_PAD_ACCEPTCAPSFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_acceptcaps_default); |
|
367 |
|
368 pad->do_buffer_signals = 0; |
|
369 pad->do_event_signals = 0; |
|
370 |
|
371 GST_PAD_SET_FLUSHING (pad); |
|
372 |
|
373 pad->preroll_lock = g_mutex_new (); |
|
374 pad->preroll_cond = g_cond_new (); |
|
375 |
|
376 pad->stream_rec_lock = g_new (GStaticRecMutex, 1); |
|
377 g_static_rec_mutex_init (pad->stream_rec_lock); |
|
378 |
|
379 pad->block_cond = g_cond_new (); |
|
380 } |
|
381 |
|
382 static void |
|
383 gst_pad_dispose (GObject * object) |
|
384 { |
|
385 GstPad *pad = GST_PAD (object); |
|
386 GstPad *peer; |
|
387 |
|
388 GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, pad, "dispose"); |
|
389 |
|
390 /* unlink the peer pad */ |
|
391 if ((peer = gst_pad_get_peer (pad))) { |
|
392 /* window for MT unsafeness, someone else could unlink here |
|
393 * and then we call unlink with wrong pads. The unlink |
|
394 * function would catch this and safely return failed. */ |
|
395 if (GST_PAD_IS_SRC (pad)) |
|
396 gst_pad_unlink (pad, peer); |
|
397 else |
|
398 gst_pad_unlink (peer, pad); |
|
399 |
|
400 gst_object_unref (peer); |
|
401 } |
|
402 |
|
403 /* clear the caps */ |
|
404 gst_caps_replace (&GST_PAD_CAPS (pad), NULL); |
|
405 |
|
406 gst_pad_set_pad_template (pad, NULL); |
|
407 |
|
408 G_OBJECT_CLASS (parent_class)->dispose (object); |
|
409 } |
|
410 |
|
411 static void |
|
412 gst_pad_finalize (GObject * object) |
|
413 { |
|
414 GstPad *pad = GST_PAD (object); |
|
415 GstTask *task; |
|
416 |
|
417 /* in case the task is still around, clean it up */ |
|
418 if ((task = GST_PAD_TASK (pad))) { |
|
419 gst_task_join (task); |
|
420 GST_PAD_TASK (pad) = NULL; |
|
421 gst_object_unref (task); |
|
422 } |
|
423 |
|
424 if (pad->stream_rec_lock) { |
|
425 g_static_rec_mutex_free (pad->stream_rec_lock); |
|
426 g_free (pad->stream_rec_lock); |
|
427 pad->stream_rec_lock = NULL; |
|
428 } |
|
429 if (pad->preroll_lock) { |
|
430 g_mutex_free (pad->preroll_lock); |
|
431 g_cond_free (pad->preroll_cond); |
|
432 pad->preroll_lock = NULL; |
|
433 pad->preroll_cond = NULL; |
|
434 } |
|
435 if (pad->block_cond) { |
|
436 g_cond_free (pad->block_cond); |
|
437 pad->block_cond = NULL; |
|
438 } |
|
439 |
|
440 G_OBJECT_CLASS (parent_class)->finalize (object); |
|
441 } |
|
442 |
|
443 static void |
|
444 gst_pad_set_property (GObject * object, guint prop_id, |
|
445 const GValue * value, GParamSpec * pspec) |
|
446 { |
|
447 g_return_if_fail (GST_IS_PAD (object)); |
|
448 |
|
449 switch (prop_id) { |
|
450 case PAD_PROP_DIRECTION: |
|
451 GST_PAD_DIRECTION (object) = g_value_get_enum (value); |
|
452 break; |
|
453 case PAD_PROP_TEMPLATE: |
|
454 gst_pad_set_pad_template (GST_PAD_CAST (object), |
|
455 (GstPadTemplate *) g_value_get_object (value)); |
|
456 break; |
|
457 default: |
|
458 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
459 break; |
|
460 } |
|
461 } |
|
462 |
|
463 static void |
|
464 gst_pad_get_property (GObject * object, guint prop_id, |
|
465 GValue * value, GParamSpec * pspec) |
|
466 { |
|
467 g_return_if_fail (GST_IS_PAD (object)); |
|
468 |
|
469 switch (prop_id) { |
|
470 case PAD_PROP_CAPS: |
|
471 GST_OBJECT_LOCK (object); |
|
472 g_value_set_boxed (value, GST_PAD_CAPS (object)); |
|
473 GST_OBJECT_UNLOCK (object); |
|
474 break; |
|
475 case PAD_PROP_DIRECTION: |
|
476 g_value_set_enum (value, GST_PAD_DIRECTION (object)); |
|
477 break; |
|
478 case PAD_PROP_TEMPLATE: |
|
479 g_value_set_object (value, GST_PAD_PAD_TEMPLATE (object)); |
|
480 break; |
|
481 default: |
|
482 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
483 break; |
|
484 } |
|
485 } |
|
486 |
|
487 /** |
|
488 * gst_pad_new: |
|
489 * @name: the name of the new pad. |
|
490 * @direction: the #GstPadDirection of the pad. |
|
491 * |
|
492 * Creates a new pad with the given name in the given direction. |
|
493 * If name is NULL, a guaranteed unique name (across all pads) |
|
494 * will be assigned. |
|
495 * This function makes a copy of the name so you can safely free the name. |
|
496 * |
|
497 * Returns: a new #GstPad, or NULL in case of an error. |
|
498 * |
|
499 * MT safe. |
|
500 */ |
|
501 #ifdef __SYMBIAN32__ |
|
502 EXPORT_C |
|
503 #endif |
|
504 |
|
505 GstPad * |
|
506 gst_pad_new (const gchar * name, GstPadDirection direction) |
|
507 { |
|
508 return g_object_new (GST_TYPE_PAD, |
|
509 "name", name, "direction", direction, NULL); |
|
510 } |
|
511 |
|
512 /** |
|
513 * gst_pad_new_from_template: |
|
514 * @templ: the pad template to use |
|
515 * @name: the name of the element |
|
516 * |
|
517 * Creates a new pad with the given name from the given template. |
|
518 * If name is NULL, a guaranteed unique name (across all pads) |
|
519 * will be assigned. |
|
520 * This function makes a copy of the name so you can safely free the name. |
|
521 * |
|
522 * Returns: a new #GstPad, or NULL in case of an error. |
|
523 */ |
|
524 #ifdef __SYMBIAN32__ |
|
525 EXPORT_C |
|
526 #endif |
|
527 |
|
528 GstPad * |
|
529 gst_pad_new_from_template (GstPadTemplate * templ, const gchar * name) |
|
530 { |
|
531 g_return_val_if_fail (GST_IS_PAD_TEMPLATE (templ), NULL); |
|
532 |
|
533 return g_object_new (GST_TYPE_PAD, |
|
534 "name", name, "direction", templ->direction, "template", templ, NULL); |
|
535 } |
|
536 |
|
537 /** |
|
538 * gst_pad_new_from_static_template: |
|
539 * @templ: the #GstStaticPadTemplate to use |
|
540 * @name: the name of the element |
|
541 * |
|
542 * Creates a new pad with the given name from the given static template. |
|
543 * If name is NULL, a guaranteed unique name (across all pads) |
|
544 * will be assigned. |
|
545 * This function makes a copy of the name so you can safely free the name. |
|
546 * |
|
547 * Returns: a new #GstPad, or NULL in case of an error. |
|
548 */ |
|
549 #ifdef __SYMBIAN32__ |
|
550 EXPORT_C |
|
551 #endif |
|
552 |
|
553 GstPad * |
|
554 gst_pad_new_from_static_template (GstStaticPadTemplate * templ, |
|
555 const gchar * name) |
|
556 { |
|
557 GstPad *pad; |
|
558 GstPadTemplate *template; |
|
559 |
|
560 template = gst_static_pad_template_get (templ); |
|
561 pad = gst_pad_new_from_template (template, name); |
|
562 gst_object_unref (template); |
|
563 return pad; |
|
564 } |
|
565 |
|
566 /** |
|
567 * gst_pad_get_direction: |
|
568 * @pad: a #GstPad to get the direction of. |
|
569 * |
|
570 * Gets the direction of the pad. The direction of the pad is |
|
571 * decided at construction time so this function does not take |
|
572 * the LOCK. |
|
573 * |
|
574 * Returns: the #GstPadDirection of the pad. |
|
575 * |
|
576 * MT safe. |
|
577 */ |
|
578 #ifdef __SYMBIAN32__ |
|
579 EXPORT_C |
|
580 #endif |
|
581 |
|
582 GstPadDirection |
|
583 gst_pad_get_direction (GstPad * pad) |
|
584 { |
|
585 GstPadDirection result; |
|
586 |
|
587 /* PAD_UNKNOWN is a little silly but we need some sort of |
|
588 * error return value */ |
|
589 g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN); |
|
590 |
|
591 GST_OBJECT_LOCK (pad); |
|
592 result = GST_PAD_DIRECTION (pad); |
|
593 GST_OBJECT_UNLOCK (pad); |
|
594 |
|
595 return result; |
|
596 } |
|
597 |
|
598 static gboolean |
|
599 gst_pad_activate_default (GstPad * pad) |
|
600 { |
|
601 return gst_pad_activate_push (pad, TRUE); |
|
602 } |
|
603 |
|
604 static void |
|
605 pre_activate (GstPad * pad, GstActivateMode new_mode) |
|
606 { |
|
607 switch (new_mode) { |
|
608 case GST_ACTIVATE_PUSH: |
|
609 case GST_ACTIVATE_PULL: |
|
610 GST_OBJECT_LOCK (pad); |
|
611 GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE %d, unset flushing", |
|
612 new_mode); |
|
613 GST_PAD_UNSET_FLUSHING (pad); |
|
614 GST_PAD_ACTIVATE_MODE (pad) = new_mode; |
|
615 GST_OBJECT_UNLOCK (pad); |
|
616 break; |
|
617 case GST_ACTIVATE_NONE: |
|
618 GST_OBJECT_LOCK (pad); |
|
619 GST_DEBUG_OBJECT (pad, "setting ACTIVATE_MODE NONE, set flushing"); |
|
620 GST_PAD_SET_FLUSHING (pad); |
|
621 GST_PAD_ACTIVATE_MODE (pad) = new_mode; |
|
622 /* unlock blocked pads so element can resume and stop */ |
|
623 GST_PAD_BLOCK_BROADCAST (pad); |
|
624 GST_OBJECT_UNLOCK (pad); |
|
625 break; |
|
626 } |
|
627 } |
|
628 |
|
629 static void |
|
630 post_activate (GstPad * pad, GstActivateMode new_mode) |
|
631 { |
|
632 switch (new_mode) { |
|
633 case GST_ACTIVATE_PUSH: |
|
634 case GST_ACTIVATE_PULL: |
|
635 /* nop */ |
|
636 break; |
|
637 case GST_ACTIVATE_NONE: |
|
638 /* ensures that streaming stops */ |
|
639 GST_PAD_STREAM_LOCK (pad); |
|
640 GST_DEBUG_OBJECT (pad, "stopped streaming"); |
|
641 GST_PAD_STREAM_UNLOCK (pad); |
|
642 break; |
|
643 } |
|
644 } |
|
645 |
|
646 /** |
|
647 * gst_pad_set_active: |
|
648 * @pad: the #GstPad to activate or deactivate. |
|
649 * @active: whether or not the pad should be active. |
|
650 * |
|
651 * Activates or deactivates the given pad. |
|
652 * Normally called from within core state change functions. |
|
653 * |
|
654 * If @active, makes sure the pad is active. If it is already active, either in |
|
655 * push or pull mode, just return. Otherwise dispatches to the pad's activate |
|
656 * function to perform the actual activation. |
|
657 * |
|
658 * If not @active, checks the pad's current mode and calls |
|
659 * gst_pad_activate_push() or gst_pad_activate_pull(), as appropriate, with a |
|
660 * FALSE argument. |
|
661 * |
|
662 * Returns: #TRUE if the operation was successful. |
|
663 * |
|
664 * MT safe. |
|
665 */ |
|
666 #ifdef __SYMBIAN32__ |
|
667 EXPORT_C |
|
668 #endif |
|
669 |
|
670 gboolean |
|
671 gst_pad_set_active (GstPad * pad, gboolean active) |
|
672 { |
|
673 GstActivateMode old; |
|
674 gboolean ret = FALSE; |
|
675 |
|
676 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
677 |
|
678 GST_OBJECT_LOCK (pad); |
|
679 old = GST_PAD_ACTIVATE_MODE (pad); |
|
680 GST_OBJECT_UNLOCK (pad); |
|
681 |
|
682 if (active) { |
|
683 switch (old) { |
|
684 case GST_ACTIVATE_PUSH: |
|
685 GST_DEBUG_OBJECT (pad, "activating pad from push"); |
|
686 ret = TRUE; |
|
687 break; |
|
688 case GST_ACTIVATE_PULL: |
|
689 GST_DEBUG_OBJECT (pad, "activating pad from pull"); |
|
690 ret = TRUE; |
|
691 break; |
|
692 case GST_ACTIVATE_NONE: |
|
693 GST_DEBUG_OBJECT (pad, "activating pad from none"); |
|
694 ret = (GST_PAD_ACTIVATEFUNC (pad)) (pad); |
|
695 break; |
|
696 } |
|
697 } else { |
|
698 switch (old) { |
|
699 case GST_ACTIVATE_PUSH: |
|
700 GST_DEBUG_OBJECT (pad, "deactivating pad from push"); |
|
701 ret = gst_pad_activate_push (pad, FALSE); |
|
702 break; |
|
703 case GST_ACTIVATE_PULL: |
|
704 GST_DEBUG_OBJECT (pad, "deactivating pad from pull"); |
|
705 ret = gst_pad_activate_pull (pad, FALSE); |
|
706 break; |
|
707 case GST_ACTIVATE_NONE: |
|
708 GST_DEBUG_OBJECT (pad, "deactivating pad from none"); |
|
709 ret = TRUE; |
|
710 break; |
|
711 } |
|
712 } |
|
713 |
|
714 if (!ret) { |
|
715 GST_OBJECT_LOCK (pad); |
|
716 if (!active) { |
|
717 g_critical ("Failed to deactivate pad %s:%s, very bad", |
|
718 GST_DEBUG_PAD_NAME (pad)); |
|
719 } else { |
|
720 GST_WARNING_OBJECT (pad, "Failed to activate pad"); |
|
721 } |
|
722 GST_OBJECT_UNLOCK (pad); |
|
723 } |
|
724 |
|
725 return ret; |
|
726 } |
|
727 |
|
728 /** |
|
729 * gst_pad_activate_pull: |
|
730 * @pad: the #GstPad to activate or deactivate. |
|
731 * @active: whether or not the pad should be active. |
|
732 * |
|
733 * Activates or deactivates the given pad in pull mode via dispatching to the |
|
734 * pad's activatepullfunc. For use from within pad activation functions only. |
|
735 * When called on sink pads, will first proxy the call to the peer pad, which |
|
736 * is expected to activate its internally linked pads from within its |
|
737 * activate_pull function. |
|
738 * |
|
739 * If you don't know what this is, you probably don't want to call it. |
|
740 * |
|
741 * Returns: TRUE if the operation was successful. |
|
742 * |
|
743 * MT safe. |
|
744 */ |
|
745 #ifdef __SYMBIAN32__ |
|
746 EXPORT_C |
|
747 #endif |
|
748 |
|
749 gboolean |
|
750 gst_pad_activate_pull (GstPad * pad, gboolean active) |
|
751 { |
|
752 GstActivateMode old, new; |
|
753 GstPad *peer; |
|
754 |
|
755 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
756 |
|
757 GST_OBJECT_LOCK (pad); |
|
758 old = GST_PAD_ACTIVATE_MODE (pad); |
|
759 GST_OBJECT_UNLOCK (pad); |
|
760 |
|
761 if (active) { |
|
762 switch (old) { |
|
763 case GST_ACTIVATE_PULL: |
|
764 GST_DEBUG_OBJECT (pad, "activating pad from pull, was ok"); |
|
765 goto was_ok; |
|
766 case GST_ACTIVATE_PUSH: |
|
767 GST_DEBUG_OBJECT (pad, |
|
768 "activating pad from push, deactivate push first"); |
|
769 /* pad was activate in the wrong direction, deactivate it |
|
770 * and reactivate it in pull mode */ |
|
771 if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE))) |
|
772 goto deactivate_failed; |
|
773 /* fallthrough, pad is deactivated now. */ |
|
774 case GST_ACTIVATE_NONE: |
|
775 GST_DEBUG_OBJECT (pad, "activating pad from none"); |
|
776 break; |
|
777 } |
|
778 } else { |
|
779 switch (old) { |
|
780 case GST_ACTIVATE_NONE: |
|
781 GST_DEBUG_OBJECT (pad, "deactivating pad from none, was ok"); |
|
782 goto was_ok; |
|
783 case GST_ACTIVATE_PUSH: |
|
784 GST_DEBUG_OBJECT (pad, "deactivating pad from push, weird"); |
|
785 /* pad was activated in the other direction, deactivate it |
|
786 * in push mode, this should not happen... */ |
|
787 if (G_UNLIKELY (!gst_pad_activate_push (pad, FALSE))) |
|
788 goto deactivate_failed; |
|
789 /* everything is fine now */ |
|
790 goto was_ok; |
|
791 case GST_ACTIVATE_PULL: |
|
792 GST_DEBUG_OBJECT (pad, "deactivating pad from pull"); |
|
793 break; |
|
794 } |
|
795 } |
|
796 |
|
797 if (gst_pad_get_direction (pad) == GST_PAD_SINK) { |
|
798 if ((peer = gst_pad_get_peer (pad))) { |
|
799 GST_DEBUG_OBJECT (pad, "calling peer"); |
|
800 if (G_UNLIKELY (!gst_pad_activate_pull (peer, active))) |
|
801 goto peer_failed; |
|
802 gst_object_unref (peer); |
|
803 } else { |
|
804 goto not_linked; |
|
805 } |
|
806 } else { |
|
807 if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL)) |
|
808 goto failure; /* Can't activate pull on a src without a |
|
809 getrange function */ |
|
810 } |
|
811 |
|
812 new = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE; |
|
813 pre_activate (pad, new); |
|
814 |
|
815 if (GST_PAD_ACTIVATEPULLFUNC (pad)) { |
|
816 if (G_UNLIKELY (!GST_PAD_ACTIVATEPULLFUNC (pad) (pad, active))) |
|
817 goto failure; |
|
818 } else { |
|
819 /* can happen for sinks of passthrough elements */ |
|
820 } |
|
821 |
|
822 post_activate (pad, new); |
|
823 |
|
824 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in pull mode", |
|
825 active ? "activated" : "deactivated"); |
|
826 |
|
827 return TRUE; |
|
828 |
|
829 was_ok: |
|
830 { |
|
831 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in pull mode", |
|
832 active ? "activated" : "deactivated"); |
|
833 return TRUE; |
|
834 } |
|
835 deactivate_failed: |
|
836 { |
|
837 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
838 "failed to %s in switch to pull from mode %d", |
|
839 (active ? "activate" : "deactivate"), old); |
|
840 return FALSE; |
|
841 } |
|
842 peer_failed: |
|
843 { |
|
844 GST_OBJECT_LOCK (peer); |
|
845 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
846 "activate_pull on peer (%s:%s) failed", GST_DEBUG_PAD_NAME (peer)); |
|
847 GST_OBJECT_UNLOCK (peer); |
|
848 gst_object_unref (peer); |
|
849 return FALSE; |
|
850 } |
|
851 not_linked: |
|
852 { |
|
853 GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "can't activate unlinked sink " |
|
854 "pad in pull mode"); |
|
855 return FALSE; |
|
856 } |
|
857 failure: |
|
858 { |
|
859 GST_OBJECT_LOCK (pad); |
|
860 GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in pull mode", |
|
861 active ? "activate" : "deactivate"); |
|
862 GST_PAD_SET_FLUSHING (pad); |
|
863 GST_PAD_ACTIVATE_MODE (pad) = old; |
|
864 GST_OBJECT_UNLOCK (pad); |
|
865 return FALSE; |
|
866 } |
|
867 } |
|
868 |
|
869 /** |
|
870 * gst_pad_activate_push: |
|
871 * @pad: the #GstPad to activate or deactivate. |
|
872 * @active: whether the pad should be active or not. |
|
873 * |
|
874 * Activates or deactivates the given pad in push mode via dispatching to the |
|
875 * pad's activatepushfunc. For use from within pad activation functions only. |
|
876 * |
|
877 * If you don't know what this is, you probably don't want to call it. |
|
878 * |
|
879 * Returns: %TRUE if the operation was successful. |
|
880 * |
|
881 * MT safe. |
|
882 */ |
|
883 #ifdef __SYMBIAN32__ |
|
884 EXPORT_C |
|
885 #endif |
|
886 |
|
887 gboolean |
|
888 gst_pad_activate_push (GstPad * pad, gboolean active) |
|
889 { |
|
890 GstActivateMode old, new; |
|
891 |
|
892 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
893 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "trying to set %s in push mode", |
|
894 active ? "activated" : "deactivated"); |
|
895 |
|
896 GST_OBJECT_LOCK (pad); |
|
897 old = GST_PAD_ACTIVATE_MODE (pad); |
|
898 GST_OBJECT_UNLOCK (pad); |
|
899 |
|
900 if (active) { |
|
901 switch (old) { |
|
902 case GST_ACTIVATE_PUSH: |
|
903 GST_DEBUG_OBJECT (pad, "activating pad from push, was ok"); |
|
904 goto was_ok; |
|
905 case GST_ACTIVATE_PULL: |
|
906 GST_DEBUG_OBJECT (pad, |
|
907 "activating pad from push, deactivating pull first"); |
|
908 /* pad was activate in the wrong direction, deactivate it |
|
909 * an reactivate it in push mode */ |
|
910 if (G_UNLIKELY (!gst_pad_activate_pull (pad, FALSE))) |
|
911 goto deactivate_failed; |
|
912 /* fallthrough, pad is deactivated now. */ |
|
913 case GST_ACTIVATE_NONE: |
|
914 GST_DEBUG_OBJECT (pad, "activating pad from none"); |
|
915 break; |
|
916 } |
|
917 } else { |
|
918 switch (old) { |
|
919 case GST_ACTIVATE_NONE: |
|
920 GST_DEBUG_OBJECT (pad, "deactivating pad from none, was ok"); |
|
921 goto was_ok; |
|
922 case GST_ACTIVATE_PULL: |
|
923 GST_DEBUG_OBJECT (pad, "deactivating pad from pull, weird"); |
|
924 /* pad was activated in the other direction, deactivate it |
|
925 * in pull mode, this should not happen... */ |
|
926 if (G_UNLIKELY (!gst_pad_activate_pull (pad, FALSE))) |
|
927 goto deactivate_failed; |
|
928 /* everything is fine now */ |
|
929 goto was_ok; |
|
930 case GST_ACTIVATE_PUSH: |
|
931 GST_DEBUG_OBJECT (pad, "deactivating pad from push"); |
|
932 break; |
|
933 } |
|
934 } |
|
935 |
|
936 new = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE; |
|
937 pre_activate (pad, new); |
|
938 |
|
939 if (GST_PAD_ACTIVATEPUSHFUNC (pad)) { |
|
940 if (G_UNLIKELY (!GST_PAD_ACTIVATEPUSHFUNC (pad) (pad, active))) { |
|
941 goto failure; |
|
942 } |
|
943 } else { |
|
944 /* quite ok, element relies on state change func to prepare itself */ |
|
945 } |
|
946 |
|
947 post_activate (pad, new); |
|
948 |
|
949 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "%s in push mode", |
|
950 active ? "activated" : "deactivated"); |
|
951 return TRUE; |
|
952 |
|
953 was_ok: |
|
954 { |
|
955 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "already %s in push mode", |
|
956 active ? "activated" : "deactivated"); |
|
957 return TRUE; |
|
958 } |
|
959 deactivate_failed: |
|
960 { |
|
961 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
962 "failed to %s in switch to push from mode %d", |
|
963 (active ? "activate" : "deactivate"), old); |
|
964 return FALSE; |
|
965 } |
|
966 failure: |
|
967 { |
|
968 GST_OBJECT_LOCK (pad); |
|
969 GST_CAT_INFO_OBJECT (GST_CAT_PADS, pad, "failed to %s in push mode", |
|
970 active ? "activate" : "deactivate"); |
|
971 GST_PAD_SET_FLUSHING (pad); |
|
972 GST_PAD_ACTIVATE_MODE (pad) = old; |
|
973 GST_OBJECT_UNLOCK (pad); |
|
974 return FALSE; |
|
975 } |
|
976 } |
|
977 |
|
978 /** |
|
979 * gst_pad_is_active: |
|
980 * @pad: the #GstPad to query |
|
981 * |
|
982 * Query if a pad is active |
|
983 * |
|
984 * Returns: TRUE if the pad is active. |
|
985 * |
|
986 * MT safe. |
|
987 */ |
|
988 #ifdef __SYMBIAN32__ |
|
989 EXPORT_C |
|
990 #endif |
|
991 |
|
992 gboolean |
|
993 gst_pad_is_active (GstPad * pad) |
|
994 { |
|
995 gboolean result = FALSE; |
|
996 |
|
997 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
998 |
|
999 GST_OBJECT_LOCK (pad); |
|
1000 result = GST_PAD_MODE_ACTIVATE (GST_PAD_ACTIVATE_MODE (pad)); |
|
1001 GST_OBJECT_UNLOCK (pad); |
|
1002 |
|
1003 return result; |
|
1004 } |
|
1005 |
|
1006 /** |
|
1007 * gst_pad_set_blocked_async: |
|
1008 * @pad: the #GstPad to block or unblock |
|
1009 * @blocked: boolean indicating whether the pad should be blocked or unblocked |
|
1010 * @callback: #GstPadBlockCallback that will be called when the |
|
1011 * operation succeeds |
|
1012 * @user_data: user data passed to the callback |
|
1013 * |
|
1014 * Blocks or unblocks the dataflow on a pad. The provided callback |
|
1015 * is called when the operation succeeds; this happens right before the next |
|
1016 * attempt at pushing a buffer on the pad. |
|
1017 * |
|
1018 * This can take a while as the pad can only become blocked when real dataflow |
|
1019 * is happening. |
|
1020 * When the pipeline is stalled, for example in PAUSED, this can |
|
1021 * take an indeterminate amount of time. |
|
1022 * You can pass NULL as the callback to make this call block. Be careful with |
|
1023 * this blocking call as it might not return for reasons stated above. |
|
1024 * |
|
1025 * Returns: TRUE if the pad could be blocked. This function can fail if the |
|
1026 * wrong parameters were passed or the pad was already in the requested state. |
|
1027 * |
|
1028 * MT safe. |
|
1029 */ |
|
1030 #ifdef __SYMBIAN32__ |
|
1031 EXPORT_C |
|
1032 #endif |
|
1033 |
|
1034 gboolean |
|
1035 gst_pad_set_blocked_async (GstPad * pad, gboolean blocked, |
|
1036 GstPadBlockCallback callback, gpointer user_data) |
|
1037 { |
|
1038 gboolean was_blocked = FALSE; |
|
1039 |
|
1040 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
1041 |
|
1042 GST_OBJECT_LOCK (pad); |
|
1043 |
|
1044 was_blocked = GST_PAD_IS_BLOCKED (pad); |
|
1045 |
|
1046 if (G_UNLIKELY (was_blocked == blocked)) |
|
1047 goto had_right_state; |
|
1048 |
|
1049 if (blocked) { |
|
1050 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad"); |
|
1051 |
|
1052 GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED); |
|
1053 pad->block_callback = callback; |
|
1054 pad->block_data = user_data; |
|
1055 if (!callback) { |
|
1056 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block"); |
|
1057 GST_PAD_BLOCK_WAIT (pad); |
|
1058 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked"); |
|
1059 } |
|
1060 } else { |
|
1061 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad"); |
|
1062 |
|
1063 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED); |
|
1064 |
|
1065 pad->block_callback = callback; |
|
1066 pad->block_data = user_data; |
|
1067 |
|
1068 GST_PAD_BLOCK_BROADCAST (pad); |
|
1069 if (!callback) { |
|
1070 /* no callback, wait for the unblock to happen */ |
|
1071 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock"); |
|
1072 GST_PAD_BLOCK_WAIT (pad); |
|
1073 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked"); |
|
1074 } |
|
1075 } |
|
1076 GST_OBJECT_UNLOCK (pad); |
|
1077 |
|
1078 return TRUE; |
|
1079 |
|
1080 had_right_state: |
|
1081 { |
|
1082 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
1083 "pad was in right state (%d)", was_blocked); |
|
1084 GST_OBJECT_UNLOCK (pad); |
|
1085 |
|
1086 return FALSE; |
|
1087 } |
|
1088 } |
|
1089 |
|
1090 /** |
|
1091 * gst_pad_set_blocked: |
|
1092 * @pad: the #GstPad to block or unblock |
|
1093 * @blocked: boolean indicating we should block or unblock |
|
1094 * |
|
1095 * Blocks or unblocks the dataflow on a pad. This function is |
|
1096 * a shortcut for gst_pad_set_blocked_async() with a NULL |
|
1097 * callback. |
|
1098 * |
|
1099 * Returns: TRUE if the pad could be blocked. This function can fail if the |
|
1100 * wrong parameters were passed or the pad was already in the requested state. |
|
1101 * |
|
1102 * MT safe. |
|
1103 */ |
|
1104 #ifdef __SYMBIAN32__ |
|
1105 EXPORT_C |
|
1106 #endif |
|
1107 |
|
1108 gboolean |
|
1109 gst_pad_set_blocked (GstPad * pad, gboolean blocked) |
|
1110 { |
|
1111 return gst_pad_set_blocked_async (pad, blocked, NULL, NULL); |
|
1112 } |
|
1113 |
|
1114 /** |
|
1115 * gst_pad_is_blocked: |
|
1116 * @pad: the #GstPad to query |
|
1117 * |
|
1118 * Checks if the pad is blocked or not. This function returns the |
|
1119 * last requested state of the pad. It is not certain that the pad |
|
1120 * is actually blocking at this point (see gst_pad_is_blocking()). |
|
1121 * |
|
1122 * Returns: TRUE if the pad is blocked. |
|
1123 * |
|
1124 * MT safe. |
|
1125 */ |
|
1126 #ifdef __SYMBIAN32__ |
|
1127 EXPORT_C |
|
1128 #endif |
|
1129 |
|
1130 gboolean |
|
1131 gst_pad_is_blocked (GstPad * pad) |
|
1132 { |
|
1133 gboolean result = FALSE; |
|
1134 |
|
1135 g_return_val_if_fail (GST_IS_PAD (pad), result); |
|
1136 |
|
1137 GST_OBJECT_LOCK (pad); |
|
1138 result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED); |
|
1139 GST_OBJECT_UNLOCK (pad); |
|
1140 |
|
1141 return result; |
|
1142 } |
|
1143 |
|
1144 /** |
|
1145 * gst_pad_is_blocking: |
|
1146 * @pad: the #GstPad to query |
|
1147 * |
|
1148 * Checks if the pad is blocking or not. This is a guaranteed state |
|
1149 * of whether the pad is actually blocking on a #GstBuffer or a #GstEvent. |
|
1150 * |
|
1151 * Returns: TRUE if the pad is blocking. |
|
1152 * |
|
1153 * MT safe. |
|
1154 * |
|
1155 * Since: 0.10.11 |
|
1156 */ |
|
1157 #ifdef __SYMBIAN32__ |
|
1158 EXPORT_C |
|
1159 #endif |
|
1160 |
|
1161 gboolean |
|
1162 gst_pad_is_blocking (GstPad * pad) |
|
1163 { |
|
1164 gboolean result = FALSE; |
|
1165 |
|
1166 g_return_val_if_fail (GST_IS_PAD (pad), result); |
|
1167 |
|
1168 GST_OBJECT_LOCK (pad); |
|
1169 /* the blocking flag is only valid if the pad is not flushing */ |
|
1170 result = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) && |
|
1171 !GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING); |
|
1172 GST_OBJECT_UNLOCK (pad); |
|
1173 |
|
1174 return result; |
|
1175 } |
|
1176 |
|
1177 /** |
|
1178 * gst_pad_set_activate_function: |
|
1179 * @pad: a #GstPad. |
|
1180 * @activate: the #GstPadActivateFunction to set. |
|
1181 * |
|
1182 * Sets the given activate function for @pad. The activate function will |
|
1183 * dispatch to gst_pad_activate_push() or gst_pad_activate_pull() to perform |
|
1184 * the actual activation. Only makes sense to set on sink pads. |
|
1185 * |
|
1186 * Call this function if your sink pad can start a pull-based task. |
|
1187 */ |
|
1188 #ifdef __SYMBIAN32__ |
|
1189 EXPORT_C |
|
1190 #endif |
|
1191 |
|
1192 void |
|
1193 gst_pad_set_activate_function (GstPad * pad, GstPadActivateFunction activate) |
|
1194 { |
|
1195 g_return_if_fail (GST_IS_PAD (pad)); |
|
1196 |
|
1197 GST_PAD_ACTIVATEFUNC (pad) = activate; |
|
1198 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatefunc set to %s", |
|
1199 GST_DEBUG_FUNCPTR_NAME (activate)); |
|
1200 } |
|
1201 |
|
1202 /** |
|
1203 * gst_pad_set_activatepull_function: |
|
1204 * @pad: a #GstPad. |
|
1205 * @activatepull: the #GstPadActivateModeFunction to set. |
|
1206 * |
|
1207 * Sets the given activate_pull function for the pad. An activate_pull function |
|
1208 * prepares the element and any upstream connections for pulling. See XXX |
|
1209 * part-activation.txt for details. |
|
1210 */ |
|
1211 #ifdef __SYMBIAN32__ |
|
1212 EXPORT_C |
|
1213 #endif |
|
1214 |
|
1215 void |
|
1216 gst_pad_set_activatepull_function (GstPad * pad, |
|
1217 GstPadActivateModeFunction activatepull) |
|
1218 { |
|
1219 g_return_if_fail (GST_IS_PAD (pad)); |
|
1220 |
|
1221 GST_PAD_ACTIVATEPULLFUNC (pad) = activatepull; |
|
1222 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatepullfunc set to %s", |
|
1223 GST_DEBUG_FUNCPTR_NAME (activatepull)); |
|
1224 } |
|
1225 |
|
1226 /** |
|
1227 * gst_pad_set_activatepush_function: |
|
1228 * @pad: a #GstPad. |
|
1229 * @activatepush: the #GstPadActivateModeFunction to set. |
|
1230 * |
|
1231 * Sets the given activate_push function for the pad. An activate_push function |
|
1232 * prepares the element for pushing. See XXX part-activation.txt for details. |
|
1233 */ |
|
1234 #ifdef __SYMBIAN32__ |
|
1235 EXPORT_C |
|
1236 #endif |
|
1237 |
|
1238 void |
|
1239 gst_pad_set_activatepush_function (GstPad * pad, |
|
1240 GstPadActivateModeFunction activatepush) |
|
1241 { |
|
1242 g_return_if_fail (GST_IS_PAD (pad)); |
|
1243 |
|
1244 GST_PAD_ACTIVATEPUSHFUNC (pad) = activatepush; |
|
1245 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "activatepushfunc set to %s", |
|
1246 GST_DEBUG_FUNCPTR_NAME (activatepush)); |
|
1247 } |
|
1248 |
|
1249 /** |
|
1250 * gst_pad_set_chain_function: |
|
1251 * @pad: a sink #GstPad. |
|
1252 * @chain: the #GstPadChainFunction to set. |
|
1253 * |
|
1254 * Sets the given chain function for the pad. The chain function is called to |
|
1255 * process a #GstBuffer input buffer. see #GstPadChainFunction for more details. |
|
1256 */ |
|
1257 #ifdef __SYMBIAN32__ |
|
1258 EXPORT_C |
|
1259 #endif |
|
1260 |
|
1261 void |
|
1262 gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain) |
|
1263 { |
|
1264 g_return_if_fail (GST_IS_PAD (pad)); |
|
1265 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); |
|
1266 |
|
1267 GST_PAD_CHAINFUNC (pad) = chain; |
|
1268 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s", |
|
1269 GST_DEBUG_FUNCPTR_NAME (chain)); |
|
1270 } |
|
1271 |
|
1272 /** |
|
1273 * gst_pad_set_getrange_function: |
|
1274 * @pad: a source #GstPad. |
|
1275 * @get: the #GstPadGetRangeFunction to set. |
|
1276 * |
|
1277 * Sets the given getrange function for the pad. The getrange function is |
|
1278 * called to produce a new #GstBuffer to start the processing pipeline. see |
|
1279 * #GstPadGetRangeFunction for a description of the getrange function. |
|
1280 */ |
|
1281 #ifdef __SYMBIAN32__ |
|
1282 EXPORT_C |
|
1283 #endif |
|
1284 |
|
1285 void |
|
1286 gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get) |
|
1287 { |
|
1288 g_return_if_fail (GST_IS_PAD (pad)); |
|
1289 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC); |
|
1290 |
|
1291 GST_PAD_GETRANGEFUNC (pad) = get; |
|
1292 |
|
1293 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getrangefunc set to %s", |
|
1294 GST_DEBUG_FUNCPTR_NAME (get)); |
|
1295 } |
|
1296 |
|
1297 /** |
|
1298 * gst_pad_set_checkgetrange_function: |
|
1299 * @pad: a source #GstPad. |
|
1300 * @check: the #GstPadCheckGetRangeFunction to set. |
|
1301 * |
|
1302 * Sets the given checkgetrange function for the pad. Implement this function |
|
1303 * on a pad if you dynamically support getrange based scheduling on the pad. |
|
1304 */ |
|
1305 #ifdef __SYMBIAN32__ |
|
1306 EXPORT_C |
|
1307 #endif |
|
1308 |
|
1309 void |
|
1310 gst_pad_set_checkgetrange_function (GstPad * pad, |
|
1311 GstPadCheckGetRangeFunction check) |
|
1312 { |
|
1313 g_return_if_fail (GST_IS_PAD (pad)); |
|
1314 g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC); |
|
1315 |
|
1316 GST_PAD_CHECKGETRANGEFUNC (pad) = check; |
|
1317 |
|
1318 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "checkgetrangefunc set to %s", |
|
1319 GST_DEBUG_FUNCPTR_NAME (check)); |
|
1320 } |
|
1321 |
|
1322 /** |
|
1323 * gst_pad_set_event_function: |
|
1324 * @pad: a #GstPad of either direction. |
|
1325 * @event: the #GstPadEventFunction to set. |
|
1326 * |
|
1327 * Sets the given event handler for the pad. |
|
1328 */ |
|
1329 #ifdef __SYMBIAN32__ |
|
1330 EXPORT_C |
|
1331 #endif |
|
1332 |
|
1333 void |
|
1334 gst_pad_set_event_function (GstPad * pad, GstPadEventFunction event) |
|
1335 { |
|
1336 g_return_if_fail (GST_IS_PAD (pad)); |
|
1337 |
|
1338 GST_PAD_EVENTFUNC (pad) = event; |
|
1339 |
|
1340 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "eventfunc for set to %s", |
|
1341 GST_DEBUG_FUNCPTR_NAME (event)); |
|
1342 } |
|
1343 |
|
1344 /** |
|
1345 * gst_pad_set_query_function: |
|
1346 * @pad: a #GstPad of either direction. |
|
1347 * @query: the #GstPadQueryFunction to set. |
|
1348 * |
|
1349 * Set the given query function for the pad. |
|
1350 */ |
|
1351 #ifdef __SYMBIAN32__ |
|
1352 EXPORT_C |
|
1353 #endif |
|
1354 |
|
1355 void |
|
1356 gst_pad_set_query_function (GstPad * pad, GstPadQueryFunction query) |
|
1357 { |
|
1358 g_return_if_fail (GST_IS_PAD (pad)); |
|
1359 |
|
1360 GST_PAD_QUERYFUNC (pad) = query; |
|
1361 |
|
1362 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "queryfunc set to %s", |
|
1363 GST_DEBUG_FUNCPTR_NAME (query)); |
|
1364 } |
|
1365 |
|
1366 /** |
|
1367 * gst_pad_set_query_type_function: |
|
1368 * @pad: a #GstPad of either direction. |
|
1369 * @type_func: the #GstPadQueryTypeFunction to set. |
|
1370 * |
|
1371 * Set the given query type function for the pad. |
|
1372 */ |
|
1373 #ifdef __SYMBIAN32__ |
|
1374 EXPORT_C |
|
1375 #endif |
|
1376 |
|
1377 void |
|
1378 gst_pad_set_query_type_function (GstPad * pad, |
|
1379 GstPadQueryTypeFunction type_func) |
|
1380 { |
|
1381 g_return_if_fail (GST_IS_PAD (pad)); |
|
1382 |
|
1383 GST_PAD_QUERYTYPEFUNC (pad) = type_func; |
|
1384 |
|
1385 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "querytypefunc set to %s", |
|
1386 GST_DEBUG_FUNCPTR_NAME (type_func)); |
|
1387 } |
|
1388 |
|
1389 /** |
|
1390 * gst_pad_get_query_types: |
|
1391 * @pad: a #GstPad. |
|
1392 * |
|
1393 * Get an array of supported queries that can be performed |
|
1394 * on this pad. |
|
1395 * |
|
1396 * Returns: a zero-terminated array of #GstQueryType. |
|
1397 */ |
|
1398 #ifdef __SYMBIAN32__ |
|
1399 EXPORT_C |
|
1400 #endif |
|
1401 |
|
1402 const GstQueryType * |
|
1403 gst_pad_get_query_types (GstPad * pad) |
|
1404 { |
|
1405 GstPadQueryTypeFunction func; |
|
1406 |
|
1407 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
1408 |
|
1409 if (G_UNLIKELY ((func = GST_PAD_QUERYTYPEFUNC (pad)) == NULL)) |
|
1410 goto no_func; |
|
1411 |
|
1412 return func (pad); |
|
1413 |
|
1414 no_func: |
|
1415 { |
|
1416 return NULL; |
|
1417 } |
|
1418 } |
|
1419 |
|
1420 static gboolean |
|
1421 gst_pad_get_query_types_dispatcher (GstPad * pad, const GstQueryType ** data) |
|
1422 { |
|
1423 *data = gst_pad_get_query_types (pad); |
|
1424 |
|
1425 return TRUE; |
|
1426 } |
|
1427 |
|
1428 /** |
|
1429 * gst_pad_get_query_types_default: |
|
1430 * @pad: a #GstPad. |
|
1431 * |
|
1432 * Invoke the default dispatcher for the query types on |
|
1433 * the pad. |
|
1434 * |
|
1435 * Returns: an zero-terminated array of #GstQueryType, or NULL if none of the |
|
1436 * internally-linked pads has a query types function. |
|
1437 */ |
|
1438 #ifdef __SYMBIAN32__ |
|
1439 EXPORT_C |
|
1440 #endif |
|
1441 |
|
1442 const GstQueryType * |
|
1443 gst_pad_get_query_types_default (GstPad * pad) |
|
1444 { |
|
1445 GstQueryType *result = NULL; |
|
1446 |
|
1447 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
1448 |
|
1449 gst_pad_dispatcher (pad, (GstPadDispatcherFunction) |
|
1450 gst_pad_get_query_types_dispatcher, &result); |
|
1451 |
|
1452 return result; |
|
1453 } |
|
1454 |
|
1455 /** |
|
1456 * gst_pad_set_internal_link_function: |
|
1457 * @pad: a #GstPad of either direction. |
|
1458 * @intlink: the #GstPadIntLinkFunction to set. |
|
1459 * |
|
1460 * Sets the given internal link function for the pad. |
|
1461 */ |
|
1462 #ifdef __SYMBIAN32__ |
|
1463 EXPORT_C |
|
1464 #endif |
|
1465 |
|
1466 void |
|
1467 gst_pad_set_internal_link_function (GstPad * pad, GstPadIntLinkFunction intlink) |
|
1468 { |
|
1469 g_return_if_fail (GST_IS_PAD (pad)); |
|
1470 |
|
1471 GST_PAD_INTLINKFUNC (pad) = intlink; |
|
1472 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s", |
|
1473 GST_DEBUG_FUNCPTR_NAME (intlink)); |
|
1474 } |
|
1475 |
|
1476 /** |
|
1477 * gst_pad_set_link_function: |
|
1478 * @pad: a #GstPad. |
|
1479 * @link: the #GstPadLinkFunction to set. |
|
1480 * |
|
1481 * Sets the given link function for the pad. It will be called when |
|
1482 * the pad is linked with another pad. |
|
1483 * |
|
1484 * The return value #GST_PAD_LINK_OK should be used when the connection can be |
|
1485 * made. |
|
1486 * |
|
1487 * The return value #GST_PAD_LINK_REFUSED should be used when the connection |
|
1488 * cannot be made for some reason. |
|
1489 * |
|
1490 * If @link is installed on a source pad, it should call the #GstPadLinkFunction |
|
1491 * of the peer sink pad, if present. |
|
1492 */ |
|
1493 #ifdef __SYMBIAN32__ |
|
1494 EXPORT_C |
|
1495 #endif |
|
1496 |
|
1497 void |
|
1498 gst_pad_set_link_function (GstPad * pad, GstPadLinkFunction link) |
|
1499 { |
|
1500 g_return_if_fail (GST_IS_PAD (pad)); |
|
1501 |
|
1502 GST_PAD_LINKFUNC (pad) = link; |
|
1503 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "linkfunc set to %s", |
|
1504 GST_DEBUG_FUNCPTR_NAME (link)); |
|
1505 } |
|
1506 |
|
1507 /** |
|
1508 * gst_pad_set_unlink_function: |
|
1509 * @pad: a #GstPad. |
|
1510 * @unlink: the #GstPadUnlinkFunction to set. |
|
1511 * |
|
1512 * Sets the given unlink function for the pad. It will be called |
|
1513 * when the pad is unlinked. |
|
1514 */ |
|
1515 #ifdef __SYMBIAN32__ |
|
1516 EXPORT_C |
|
1517 #endif |
|
1518 |
|
1519 void |
|
1520 gst_pad_set_unlink_function (GstPad * pad, GstPadUnlinkFunction unlink) |
|
1521 { |
|
1522 g_return_if_fail (GST_IS_PAD (pad)); |
|
1523 |
|
1524 GST_PAD_UNLINKFUNC (pad) = unlink; |
|
1525 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "unlinkfunc set to %s", |
|
1526 GST_DEBUG_FUNCPTR_NAME (unlink)); |
|
1527 } |
|
1528 |
|
1529 /** |
|
1530 * gst_pad_set_getcaps_function: |
|
1531 * @pad: a #GstPad. |
|
1532 * @getcaps: the #GstPadGetCapsFunction to set. |
|
1533 * |
|
1534 * Sets the given getcaps function for the pad. @getcaps should return the |
|
1535 * allowable caps for a pad in the context of the element's state, its link to |
|
1536 * other elements, and the devices or files it has opened. These caps must be a |
|
1537 * subset of the pad template caps. In the NULL state with no links, @getcaps |
|
1538 * should ideally return the same caps as the pad template. In rare |
|
1539 * circumstances, an object property can affect the caps returned by @getcaps, |
|
1540 * but this is discouraged. |
|
1541 * |
|
1542 * You do not need to call this function if @pad's allowed caps are always the |
|
1543 * same as the pad template caps. This can only be true if the padtemplate |
|
1544 * has fixed simple caps. |
|
1545 * |
|
1546 * For most filters, the caps returned by @getcaps is directly affected by the |
|
1547 * allowed caps on other pads. For demuxers and decoders, the caps returned by |
|
1548 * the srcpad's getcaps function is directly related to the stream data. Again, |
|
1549 * @getcaps should return the most specific caps it reasonably can, since this |
|
1550 * helps with autoplugging. |
|
1551 * |
|
1552 * Note that the return value from @getcaps is owned by the caller, so the |
|
1553 * caller should unref the caps after usage. |
|
1554 */ |
|
1555 #ifdef __SYMBIAN32__ |
|
1556 EXPORT_C |
|
1557 #endif |
|
1558 |
|
1559 void |
|
1560 gst_pad_set_getcaps_function (GstPad * pad, GstPadGetCapsFunction getcaps) |
|
1561 { |
|
1562 g_return_if_fail (GST_IS_PAD (pad)); |
|
1563 |
|
1564 GST_PAD_GETCAPSFUNC (pad) = getcaps; |
|
1565 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "getcapsfunc set to %s", |
|
1566 GST_DEBUG_FUNCPTR_NAME (getcaps)); |
|
1567 } |
|
1568 |
|
1569 /** |
|
1570 * gst_pad_set_acceptcaps_function: |
|
1571 * @pad: a #GstPad. |
|
1572 * @acceptcaps: the #GstPadAcceptCapsFunction to set. |
|
1573 * |
|
1574 * Sets the given acceptcaps function for the pad. The acceptcaps function |
|
1575 * will be called to check if the pad can accept the given caps. Setting the |
|
1576 * acceptcaps function to NULL restores the default behaviour of allowing |
|
1577 * any caps that matches the caps from gst_pad_get_caps. |
|
1578 */ |
|
1579 #ifdef __SYMBIAN32__ |
|
1580 EXPORT_C |
|
1581 #endif |
|
1582 |
|
1583 void |
|
1584 gst_pad_set_acceptcaps_function (GstPad * pad, |
|
1585 GstPadAcceptCapsFunction acceptcaps) |
|
1586 { |
|
1587 g_return_if_fail (GST_IS_PAD (pad)); |
|
1588 |
|
1589 GST_PAD_ACCEPTCAPSFUNC (pad) = acceptcaps; |
|
1590 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "acceptcapsfunc set to %s", |
|
1591 GST_DEBUG_FUNCPTR_NAME (acceptcaps)); |
|
1592 } |
|
1593 |
|
1594 /** |
|
1595 * gst_pad_set_fixatecaps_function: |
|
1596 * @pad: a #GstPad. |
|
1597 * @fixatecaps: the #GstPadFixateCapsFunction to set. |
|
1598 * |
|
1599 * Sets the given fixatecaps function for the pad. The fixatecaps function |
|
1600 * will be called whenever the default values for a GstCaps needs to be |
|
1601 * filled in. |
|
1602 */ |
|
1603 #ifdef __SYMBIAN32__ |
|
1604 EXPORT_C |
|
1605 #endif |
|
1606 |
|
1607 void |
|
1608 gst_pad_set_fixatecaps_function (GstPad * pad, |
|
1609 GstPadFixateCapsFunction fixatecaps) |
|
1610 { |
|
1611 g_return_if_fail (GST_IS_PAD (pad)); |
|
1612 |
|
1613 GST_PAD_FIXATECAPSFUNC (pad) = fixatecaps; |
|
1614 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fixatecapsfunc set to %s", |
|
1615 GST_DEBUG_FUNCPTR_NAME (fixatecaps)); |
|
1616 } |
|
1617 |
|
1618 /** |
|
1619 * gst_pad_set_setcaps_function: |
|
1620 * @pad: a #GstPad. |
|
1621 * @setcaps: the #GstPadSetCapsFunction to set. |
|
1622 * |
|
1623 * Sets the given setcaps function for the pad. The setcaps function |
|
1624 * will be called whenever a buffer with a new media type is pushed or |
|
1625 * pulled from the pad. The pad/element needs to update its internal |
|
1626 * structures to process the new media type. If this new type is not |
|
1627 * acceptable, the setcaps function should return FALSE. |
|
1628 */ |
|
1629 #ifdef __SYMBIAN32__ |
|
1630 EXPORT_C |
|
1631 #endif |
|
1632 |
|
1633 void |
|
1634 gst_pad_set_setcaps_function (GstPad * pad, GstPadSetCapsFunction setcaps) |
|
1635 { |
|
1636 g_return_if_fail (GST_IS_PAD (pad)); |
|
1637 |
|
1638 GST_PAD_SETCAPSFUNC (pad) = setcaps; |
|
1639 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "setcapsfunc set to %s", |
|
1640 GST_DEBUG_FUNCPTR_NAME (setcaps)); |
|
1641 } |
|
1642 |
|
1643 /** |
|
1644 * gst_pad_set_bufferalloc_function: |
|
1645 * @pad: a sink #GstPad. |
|
1646 * @bufalloc: the #GstPadBufferAllocFunction to set. |
|
1647 * |
|
1648 * Sets the given bufferalloc function for the pad. Note that the |
|
1649 * bufferalloc function can only be set on sinkpads. |
|
1650 */ |
|
1651 #ifdef __SYMBIAN32__ |
|
1652 EXPORT_C |
|
1653 #endif |
|
1654 |
|
1655 void |
|
1656 gst_pad_set_bufferalloc_function (GstPad * pad, |
|
1657 GstPadBufferAllocFunction bufalloc) |
|
1658 { |
|
1659 g_return_if_fail (GST_IS_PAD (pad)); |
|
1660 g_return_if_fail (GST_PAD_IS_SINK (pad)); |
|
1661 |
|
1662 GST_PAD_BUFFERALLOCFUNC (pad) = bufalloc; |
|
1663 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "bufferallocfunc set to %s", |
|
1664 GST_DEBUG_FUNCPTR_NAME (bufalloc)); |
|
1665 } |
|
1666 |
|
1667 /** |
|
1668 * gst_pad_unlink: |
|
1669 * @srcpad: the source #GstPad to unlink. |
|
1670 * @sinkpad: the sink #GstPad to unlink. |
|
1671 * |
|
1672 * Unlinks the source pad from the sink pad. Will emit the #GstPad::unlinked |
|
1673 * signal on both pads. |
|
1674 * |
|
1675 * Returns: TRUE if the pads were unlinked. This function returns FALSE if |
|
1676 * the pads were not linked together. |
|
1677 * |
|
1678 * MT safe. |
|
1679 */ |
|
1680 #ifdef __SYMBIAN32__ |
|
1681 EXPORT_C |
|
1682 #endif |
|
1683 |
|
1684 gboolean |
|
1685 gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad) |
|
1686 { |
|
1687 g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE); |
|
1688 g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE); |
|
1689 |
|
1690 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)", |
|
1691 GST_DEBUG_PAD_NAME (srcpad), srcpad, |
|
1692 GST_DEBUG_PAD_NAME (sinkpad), sinkpad); |
|
1693 |
|
1694 GST_OBJECT_LOCK (srcpad); |
|
1695 |
|
1696 if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC)) |
|
1697 goto not_srcpad; |
|
1698 |
|
1699 GST_OBJECT_LOCK (sinkpad); |
|
1700 |
|
1701 if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK)) |
|
1702 goto not_sinkpad; |
|
1703 |
|
1704 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad)) |
|
1705 goto not_linked_together; |
|
1706 |
|
1707 if (GST_PAD_UNLINKFUNC (srcpad)) { |
|
1708 GST_PAD_UNLINKFUNC (srcpad) (srcpad); |
|
1709 } |
|
1710 if (GST_PAD_UNLINKFUNC (sinkpad)) { |
|
1711 GST_PAD_UNLINKFUNC (sinkpad) (sinkpad); |
|
1712 } |
|
1713 |
|
1714 /* first clear peers */ |
|
1715 GST_PAD_PEER (srcpad) = NULL; |
|
1716 GST_PAD_PEER (sinkpad) = NULL; |
|
1717 |
|
1718 GST_OBJECT_UNLOCK (sinkpad); |
|
1719 GST_OBJECT_UNLOCK (srcpad); |
|
1720 |
|
1721 /* fire off a signal to each of the pads telling them |
|
1722 * that they've been unlinked */ |
|
1723 g_signal_emit (G_OBJECT (srcpad), gst_pad_signals[PAD_UNLINKED], 0, sinkpad); |
|
1724 g_signal_emit (G_OBJECT (sinkpad), gst_pad_signals[PAD_UNLINKED], 0, srcpad); |
|
1725 |
|
1726 GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s", |
|
1727 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
1728 |
|
1729 return TRUE; |
|
1730 |
|
1731 not_srcpad: |
|
1732 { |
|
1733 g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad)); |
|
1734 GST_OBJECT_UNLOCK (srcpad); |
|
1735 return FALSE; |
|
1736 } |
|
1737 not_sinkpad: |
|
1738 { |
|
1739 g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad)); |
|
1740 GST_OBJECT_UNLOCK (sinkpad); |
|
1741 GST_OBJECT_UNLOCK (srcpad); |
|
1742 return FALSE; |
|
1743 } |
|
1744 not_linked_together: |
|
1745 { |
|
1746 /* we do not emit a warning in this case because unlinking cannot |
|
1747 * be made MT safe.*/ |
|
1748 GST_OBJECT_UNLOCK (sinkpad); |
|
1749 GST_OBJECT_UNLOCK (srcpad); |
|
1750 return FALSE; |
|
1751 } |
|
1752 } |
|
1753 |
|
1754 /** |
|
1755 * gst_pad_is_linked: |
|
1756 * @pad: pad to check |
|
1757 * |
|
1758 * Checks if a @pad is linked to another pad or not. |
|
1759 * |
|
1760 * Returns: TRUE if the pad is linked, FALSE otherwise. |
|
1761 * |
|
1762 * MT safe. |
|
1763 */ |
|
1764 #ifdef __SYMBIAN32__ |
|
1765 EXPORT_C |
|
1766 #endif |
|
1767 |
|
1768 gboolean |
|
1769 gst_pad_is_linked (GstPad * pad) |
|
1770 { |
|
1771 gboolean result; |
|
1772 |
|
1773 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
1774 |
|
1775 GST_OBJECT_LOCK (pad); |
|
1776 result = (GST_PAD_PEER (pad) != NULL); |
|
1777 GST_OBJECT_UNLOCK (pad); |
|
1778 |
|
1779 return result; |
|
1780 } |
|
1781 |
|
1782 /* get the caps from both pads and see if the intersection |
|
1783 * is not empty. |
|
1784 * |
|
1785 * This function should be called with the pad LOCK on both |
|
1786 * pads |
|
1787 */ |
|
1788 static gboolean |
|
1789 gst_pad_link_check_compatible_unlocked (GstPad * src, GstPad * sink) |
|
1790 { |
|
1791 GstCaps *srccaps; |
|
1792 GstCaps *sinkcaps; |
|
1793 GstCaps *icaps; |
|
1794 |
|
1795 srccaps = gst_pad_get_caps_unlocked (src); |
|
1796 sinkcaps = gst_pad_get_caps_unlocked (sink); |
|
1797 |
|
1798 GST_CAT_DEBUG (GST_CAT_CAPS, "src caps %" GST_PTR_FORMAT, srccaps); |
|
1799 GST_CAT_DEBUG (GST_CAT_CAPS, "sink caps %" GST_PTR_FORMAT, sinkcaps); |
|
1800 |
|
1801 /* if we have caps on both pads we can check the intersection. If one |
|
1802 * of the caps is NULL, we return TRUE. */ |
|
1803 if (srccaps == NULL || sinkcaps == NULL) |
|
1804 goto done; |
|
1805 |
|
1806 icaps = gst_caps_intersect (srccaps, sinkcaps); |
|
1807 gst_caps_unref (srccaps); |
|
1808 gst_caps_unref (sinkcaps); |
|
1809 |
|
1810 if (icaps == NULL) |
|
1811 goto was_null; |
|
1812 |
|
1813 GST_CAT_DEBUG (GST_CAT_CAPS, |
|
1814 "intersection caps %p %" GST_PTR_FORMAT, icaps, icaps); |
|
1815 |
|
1816 if (gst_caps_is_empty (icaps)) |
|
1817 goto was_empty; |
|
1818 |
|
1819 gst_caps_unref (icaps); |
|
1820 |
|
1821 done: |
|
1822 return TRUE; |
|
1823 |
|
1824 /* incompatible cases */ |
|
1825 was_null: |
|
1826 { |
|
1827 GST_CAT_DEBUG (GST_CAT_CAPS, "intersection gave NULL"); |
|
1828 return FALSE; |
|
1829 } |
|
1830 was_empty: |
|
1831 { |
|
1832 GST_CAT_DEBUG (GST_CAT_CAPS, "intersection is EMPTY"); |
|
1833 gst_caps_unref (icaps); |
|
1834 return FALSE; |
|
1835 } |
|
1836 } |
|
1837 |
|
1838 /* check if the grandparents of both pads are the same. |
|
1839 * This check is required so that we don't try to link |
|
1840 * pads from elements in different bins without ghostpads. |
|
1841 * |
|
1842 * The LOCK should be held on both pads |
|
1843 */ |
|
1844 static gboolean |
|
1845 gst_pad_link_check_hierarchy (GstPad * src, GstPad * sink) |
|
1846 { |
|
1847 GstObject *psrc, *psink; |
|
1848 |
|
1849 psrc = GST_OBJECT_PARENT (src); |
|
1850 psink = GST_OBJECT_PARENT (sink); |
|
1851 |
|
1852 /* if one of the pads has no parent, we allow the link */ |
|
1853 if (G_UNLIKELY (psrc == NULL || psink == NULL)) |
|
1854 goto no_parent; |
|
1855 |
|
1856 /* only care about parents that are elements */ |
|
1857 if (G_UNLIKELY (!GST_IS_ELEMENT (psrc) || !GST_IS_ELEMENT (psink))) |
|
1858 goto no_element_parent; |
|
1859 |
|
1860 /* if the parents are the same, we have a loop */ |
|
1861 if (G_UNLIKELY (psrc == psink)) |
|
1862 goto same_parents; |
|
1863 |
|
1864 /* if they both have a parent, we check the grandparents. We can not lock |
|
1865 * the parent because we hold on the child (pad) and the locking order is |
|
1866 * parent >> child. */ |
|
1867 psrc = GST_OBJECT_PARENT (psrc); |
|
1868 psink = GST_OBJECT_PARENT (psink); |
|
1869 |
|
1870 /* if they have grandparents but they are not the same */ |
|
1871 if (G_UNLIKELY (psrc != psink)) |
|
1872 goto wrong_grandparents; |
|
1873 |
|
1874 return TRUE; |
|
1875 |
|
1876 /* ERRORS */ |
|
1877 no_parent: |
|
1878 { |
|
1879 GST_CAT_DEBUG (GST_CAT_CAPS, |
|
1880 "one of the pads has no parent %" GST_PTR_FORMAT " and %" |
|
1881 GST_PTR_FORMAT, psrc, psink); |
|
1882 return TRUE; |
|
1883 } |
|
1884 no_element_parent: |
|
1885 { |
|
1886 GST_CAT_DEBUG (GST_CAT_CAPS, |
|
1887 "one of the pads has no element parent %" GST_PTR_FORMAT " and %" |
|
1888 GST_PTR_FORMAT, psrc, psink); |
|
1889 return TRUE; |
|
1890 } |
|
1891 same_parents: |
|
1892 { |
|
1893 GST_CAT_DEBUG (GST_CAT_CAPS, "pads have same parent %" GST_PTR_FORMAT, |
|
1894 psrc); |
|
1895 return FALSE; |
|
1896 } |
|
1897 wrong_grandparents: |
|
1898 { |
|
1899 GST_CAT_DEBUG (GST_CAT_CAPS, |
|
1900 "pads have different grandparents %" GST_PTR_FORMAT " and %" |
|
1901 GST_PTR_FORMAT, psrc, psink); |
|
1902 return FALSE; |
|
1903 } |
|
1904 } |
|
1905 |
|
1906 /* FIXME leftover from an attempt at refactoring... */ |
|
1907 /* call with the two pads unlocked, when this function returns GST_PAD_LINK_OK, |
|
1908 * the two pads will be locked in the srcpad, sinkpad order. */ |
|
1909 static GstPadLinkReturn |
|
1910 gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad) |
|
1911 { |
|
1912 /* generic checks */ |
|
1913 g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED); |
|
1914 g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED); |
|
1915 |
|
1916 GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s", |
|
1917 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
1918 |
|
1919 GST_OBJECT_LOCK (srcpad); |
|
1920 |
|
1921 if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC)) |
|
1922 goto not_srcpad; |
|
1923 |
|
1924 if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL)) |
|
1925 goto src_was_linked; |
|
1926 |
|
1927 GST_OBJECT_LOCK (sinkpad); |
|
1928 |
|
1929 if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK)) |
|
1930 goto not_sinkpad; |
|
1931 |
|
1932 if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL)) |
|
1933 goto sink_was_linked; |
|
1934 |
|
1935 /* check hierarchy, pads can only be linked if the grandparents |
|
1936 * are the same. */ |
|
1937 if (!gst_pad_link_check_hierarchy (srcpad, sinkpad)) |
|
1938 goto wrong_hierarchy; |
|
1939 |
|
1940 /* check pad caps for non-empty intersection */ |
|
1941 if (!gst_pad_link_check_compatible_unlocked (srcpad, sinkpad)) |
|
1942 goto no_format; |
|
1943 |
|
1944 /* FIXME check pad scheduling for non-empty intersection */ |
|
1945 |
|
1946 return GST_PAD_LINK_OK; |
|
1947 |
|
1948 not_srcpad: |
|
1949 { |
|
1950 g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad)); |
|
1951 GST_OBJECT_UNLOCK (srcpad); |
|
1952 return GST_PAD_LINK_WRONG_DIRECTION; |
|
1953 } |
|
1954 src_was_linked: |
|
1955 { |
|
1956 GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s", |
|
1957 GST_DEBUG_PAD_NAME (srcpad), |
|
1958 GST_DEBUG_PAD_NAME (GST_PAD_PEER (srcpad))); |
|
1959 /* we do not emit a warning in this case because unlinking cannot |
|
1960 * be made MT safe.*/ |
|
1961 GST_OBJECT_UNLOCK (srcpad); |
|
1962 return GST_PAD_LINK_WAS_LINKED; |
|
1963 } |
|
1964 not_sinkpad: |
|
1965 { |
|
1966 g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad)); |
|
1967 GST_OBJECT_UNLOCK (sinkpad); |
|
1968 GST_OBJECT_UNLOCK (srcpad); |
|
1969 return GST_PAD_LINK_WRONG_DIRECTION; |
|
1970 } |
|
1971 sink_was_linked: |
|
1972 { |
|
1973 GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s", |
|
1974 GST_DEBUG_PAD_NAME (sinkpad), |
|
1975 GST_DEBUG_PAD_NAME (GST_PAD_PEER (sinkpad))); |
|
1976 /* we do not emit a warning in this case because unlinking cannot |
|
1977 * be made MT safe.*/ |
|
1978 GST_OBJECT_UNLOCK (sinkpad); |
|
1979 GST_OBJECT_UNLOCK (srcpad); |
|
1980 return GST_PAD_LINK_WAS_LINKED; |
|
1981 } |
|
1982 wrong_hierarchy: |
|
1983 { |
|
1984 GST_CAT_INFO (GST_CAT_PADS, "pads have wrong hierarchy"); |
|
1985 GST_OBJECT_UNLOCK (sinkpad); |
|
1986 GST_OBJECT_UNLOCK (srcpad); |
|
1987 return GST_PAD_LINK_WRONG_HIERARCHY; |
|
1988 } |
|
1989 no_format: |
|
1990 { |
|
1991 GST_CAT_INFO (GST_CAT_PADS, "caps are incompatible"); |
|
1992 GST_OBJECT_UNLOCK (sinkpad); |
|
1993 GST_OBJECT_UNLOCK (srcpad); |
|
1994 return GST_PAD_LINK_NOFORMAT; |
|
1995 } |
|
1996 } |
|
1997 |
|
1998 /** |
|
1999 * gst_pad_link: |
|
2000 * @srcpad: the source #GstPad to link. |
|
2001 * @sinkpad: the sink #GstPad to link. |
|
2002 * |
|
2003 * Links the source pad and the sink pad. |
|
2004 * |
|
2005 * Returns: A result code indicating if the connection worked or |
|
2006 * what went wrong. |
|
2007 * |
|
2008 * MT Safe. |
|
2009 */ |
|
2010 #ifdef __SYMBIAN32__ |
|
2011 EXPORT_C |
|
2012 #endif |
|
2013 |
|
2014 GstPadLinkReturn |
|
2015 gst_pad_link (GstPad * srcpad, GstPad * sinkpad) |
|
2016 { |
|
2017 GstPadLinkReturn result; |
|
2018 |
|
2019 /* prepare will also lock the two pads */ |
|
2020 result = gst_pad_link_prepare (srcpad, sinkpad); |
|
2021 |
|
2022 if (result != GST_PAD_LINK_OK) |
|
2023 goto prepare_failed; |
|
2024 |
|
2025 /* must set peers before calling the link function */ |
|
2026 GST_PAD_PEER (srcpad) = sinkpad; |
|
2027 GST_PAD_PEER (sinkpad) = srcpad; |
|
2028 |
|
2029 GST_OBJECT_UNLOCK (sinkpad); |
|
2030 GST_OBJECT_UNLOCK (srcpad); |
|
2031 |
|
2032 /* FIXME released the locks here, concurrent thread might link |
|
2033 * something else. */ |
|
2034 if (GST_PAD_LINKFUNC (srcpad)) { |
|
2035 /* this one will call the peer link function */ |
|
2036 result = GST_PAD_LINKFUNC (srcpad) (srcpad, sinkpad); |
|
2037 } else if (GST_PAD_LINKFUNC (sinkpad)) { |
|
2038 /* if no source link function, we need to call the sink link |
|
2039 * function ourselves. */ |
|
2040 result = GST_PAD_LINKFUNC (sinkpad) (sinkpad, srcpad); |
|
2041 } else { |
|
2042 result = GST_PAD_LINK_OK; |
|
2043 } |
|
2044 |
|
2045 GST_OBJECT_LOCK (srcpad); |
|
2046 GST_OBJECT_LOCK (sinkpad); |
|
2047 |
|
2048 if (result == GST_PAD_LINK_OK) { |
|
2049 GST_OBJECT_UNLOCK (sinkpad); |
|
2050 GST_OBJECT_UNLOCK (srcpad); |
|
2051 |
|
2052 /* fire off a signal to each of the pads telling them |
|
2053 * that they've been linked */ |
|
2054 g_signal_emit (G_OBJECT (srcpad), gst_pad_signals[PAD_LINKED], 0, sinkpad); |
|
2055 g_signal_emit (G_OBJECT (sinkpad), gst_pad_signals[PAD_LINKED], 0, srcpad); |
|
2056 |
|
2057 GST_CAT_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful", |
|
2058 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
2059 } else { |
|
2060 GST_CAT_INFO (GST_CAT_PADS, "link between %s:%s and %s:%s failed", |
|
2061 GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad)); |
|
2062 |
|
2063 GST_PAD_PEER (srcpad) = NULL; |
|
2064 GST_PAD_PEER (sinkpad) = NULL; |
|
2065 |
|
2066 GST_OBJECT_UNLOCK (sinkpad); |
|
2067 GST_OBJECT_UNLOCK (srcpad); |
|
2068 } |
|
2069 return result; |
|
2070 |
|
2071 prepare_failed: |
|
2072 { |
|
2073 return result; |
|
2074 } |
|
2075 } |
|
2076 |
|
2077 static void |
|
2078 gst_pad_set_pad_template (GstPad * pad, GstPadTemplate * templ) |
|
2079 { |
|
2080 GstPadTemplate **template_p; |
|
2081 |
|
2082 /* this function would need checks if it weren't static */ |
|
2083 |
|
2084 GST_OBJECT_LOCK (pad); |
|
2085 template_p = &pad->padtemplate; |
|
2086 gst_object_replace ((GstObject **) template_p, (GstObject *) templ); |
|
2087 GST_OBJECT_UNLOCK (pad); |
|
2088 |
|
2089 if (templ) |
|
2090 gst_pad_template_pad_created (templ, pad); |
|
2091 } |
|
2092 |
|
2093 /** |
|
2094 * gst_pad_get_pad_template: |
|
2095 * @pad: a #GstPad. |
|
2096 * |
|
2097 * Gets the template for @pad. |
|
2098 * |
|
2099 * Returns: the #GstPadTemplate from which this pad was instantiated, or %NULL |
|
2100 * if this pad has no template. |
|
2101 * |
|
2102 * FIXME: currently returns an unrefcounted padtemplate. |
|
2103 */ |
|
2104 #ifdef __SYMBIAN32__ |
|
2105 EXPORT_C |
|
2106 #endif |
|
2107 |
|
2108 GstPadTemplate * |
|
2109 gst_pad_get_pad_template (GstPad * pad) |
|
2110 { |
|
2111 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2112 |
|
2113 return GST_PAD_PAD_TEMPLATE (pad); |
|
2114 } |
|
2115 |
|
2116 |
|
2117 /* should be called with the pad LOCK held */ |
|
2118 /* refs the caps, so caller is responsible for getting it unreffed */ |
|
2119 static GstCaps * |
|
2120 gst_pad_get_caps_unlocked (GstPad * pad) |
|
2121 { |
|
2122 GstCaps *result = NULL; |
|
2123 GstPadTemplate *templ; |
|
2124 |
|
2125 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps"); |
|
2126 |
|
2127 if (GST_PAD_GETCAPSFUNC (pad)) { |
|
2128 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2129 "dispatching to pad getcaps function"); |
|
2130 |
|
2131 GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_GETCAPS); |
|
2132 GST_OBJECT_UNLOCK (pad); |
|
2133 result = GST_PAD_GETCAPSFUNC (pad) (pad); |
|
2134 GST_OBJECT_LOCK (pad); |
|
2135 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_GETCAPS); |
|
2136 |
|
2137 if (result == NULL) { |
|
2138 g_critical ("pad %s:%s returned NULL caps from getcaps function", |
|
2139 GST_DEBUG_PAD_NAME (pad)); |
|
2140 } else { |
|
2141 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2142 "pad getcaps returned %" GST_PTR_FORMAT, result); |
|
2143 #ifndef G_DISABLE_ASSERT |
|
2144 /* check that the returned caps are a real subset of the template caps */ |
|
2145 if (GST_PAD_PAD_TEMPLATE (pad)) { |
|
2146 const GstCaps *templ_caps = |
|
2147 GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)); |
|
2148 if (!gst_caps_is_subset (result, templ_caps)) { |
|
2149 GstCaps *temp; |
|
2150 |
|
2151 GST_CAT_ERROR_OBJECT (GST_CAT_CAPS, pad, |
|
2152 "pad returned caps %" GST_PTR_FORMAT |
|
2153 " which are not a real subset of its template caps %" |
|
2154 GST_PTR_FORMAT, result, templ_caps); |
|
2155 g_warning |
|
2156 ("pad %s:%s returned caps which are not a real " |
|
2157 "subset of its template caps", GST_DEBUG_PAD_NAME (pad)); |
|
2158 temp = gst_caps_intersect (templ_caps, result); |
|
2159 gst_caps_unref (result); |
|
2160 result = temp; |
|
2161 } |
|
2162 } |
|
2163 #endif |
|
2164 goto done; |
|
2165 } |
|
2166 } |
|
2167 if ((templ = GST_PAD_PAD_TEMPLATE (pad))) { |
|
2168 result = GST_PAD_TEMPLATE_CAPS (templ); |
|
2169 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2170 "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, result, |
|
2171 result); |
|
2172 |
|
2173 result = gst_caps_ref (result); |
|
2174 goto done; |
|
2175 } |
|
2176 if ((result = GST_PAD_CAPS (pad))) { |
|
2177 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2178 "using pad caps %p %" GST_PTR_FORMAT, result, result); |
|
2179 |
|
2180 result = gst_caps_ref (result); |
|
2181 goto done; |
|
2182 } |
|
2183 |
|
2184 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad has no caps"); |
|
2185 result = gst_caps_new_empty (); |
|
2186 |
|
2187 done: |
|
2188 return result; |
|
2189 } |
|
2190 |
|
2191 /** |
|
2192 * gst_pad_get_caps: |
|
2193 * @pad: a #GstPad to get the capabilities of. |
|
2194 * |
|
2195 * Gets the capabilities this pad can produce or consume. |
|
2196 * Note that this method doesn't necessarily return the caps set by |
|
2197 * gst_pad_set_caps() - use #GST_PAD_CAPS for that instead. |
|
2198 * gst_pad_get_caps returns all possible caps a pad can operate with, using |
|
2199 * the pad's get_caps function; |
|
2200 * this returns the pad template caps if not explicitly set. |
|
2201 * |
|
2202 * Returns: a newly allocated copy of the #GstCaps of this pad. |
|
2203 * |
|
2204 * MT safe. |
|
2205 */ |
|
2206 #ifdef __SYMBIAN32__ |
|
2207 EXPORT_C |
|
2208 #endif |
|
2209 |
|
2210 GstCaps * |
|
2211 gst_pad_get_caps (GstPad * pad) |
|
2212 { |
|
2213 GstCaps *result = NULL; |
|
2214 |
|
2215 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2216 |
|
2217 GST_OBJECT_LOCK (pad); |
|
2218 |
|
2219 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get pad caps"); |
|
2220 |
|
2221 result = gst_pad_get_caps_unlocked (pad); |
|
2222 |
|
2223 /* be sure that we have a copy */ |
|
2224 if (result) |
|
2225 result = gst_caps_make_writable (result); |
|
2226 |
|
2227 GST_OBJECT_UNLOCK (pad); |
|
2228 |
|
2229 return result; |
|
2230 } |
|
2231 |
|
2232 /** |
|
2233 * gst_pad_peer_get_caps: |
|
2234 * @pad: a #GstPad to get the peer capabilities of. |
|
2235 * |
|
2236 * Gets the capabilities of the peer connected to this pad. |
|
2237 * |
|
2238 * Returns: the #GstCaps of the peer pad. This function returns a new caps, so |
|
2239 * use gst_caps_unref to get rid of it. this function returns NULL if there is |
|
2240 * no peer pad. |
|
2241 */ |
|
2242 #ifdef __SYMBIAN32__ |
|
2243 EXPORT_C |
|
2244 #endif |
|
2245 |
|
2246 GstCaps * |
|
2247 gst_pad_peer_get_caps (GstPad * pad) |
|
2248 { |
|
2249 GstPad *peerpad; |
|
2250 GstCaps *result = NULL; |
|
2251 |
|
2252 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2253 |
|
2254 GST_OBJECT_LOCK (pad); |
|
2255 |
|
2256 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "get peer caps"); |
|
2257 |
|
2258 peerpad = GST_PAD_PEER (pad); |
|
2259 if (G_UNLIKELY (peerpad == NULL)) |
|
2260 goto no_peer; |
|
2261 |
|
2262 gst_object_ref (peerpad); |
|
2263 GST_OBJECT_UNLOCK (pad); |
|
2264 |
|
2265 result = gst_pad_get_caps (peerpad); |
|
2266 |
|
2267 gst_object_unref (peerpad); |
|
2268 |
|
2269 return result; |
|
2270 |
|
2271 no_peer: |
|
2272 { |
|
2273 GST_OBJECT_UNLOCK (pad); |
|
2274 return NULL; |
|
2275 } |
|
2276 } |
|
2277 |
|
2278 static gboolean |
|
2279 fixate_value (GValue * dest, const GValue * src) |
|
2280 { |
|
2281 if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) { |
|
2282 g_value_init (dest, G_TYPE_INT); |
|
2283 g_value_set_int (dest, gst_value_get_int_range_min (src)); |
|
2284 } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) { |
|
2285 g_value_init (dest, G_TYPE_DOUBLE); |
|
2286 g_value_set_double (dest, gst_value_get_double_range_min (src)); |
|
2287 } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) { |
|
2288 gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src)); |
|
2289 } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) { |
|
2290 GValue temp = { 0 }; |
|
2291 |
|
2292 /* list could be empty */ |
|
2293 if (gst_value_list_get_size (src) <= 0) |
|
2294 return FALSE; |
|
2295 |
|
2296 gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0)); |
|
2297 |
|
2298 if (!fixate_value (dest, &temp)) |
|
2299 gst_value_init_and_copy (dest, &temp); |
|
2300 g_value_unset (&temp); |
|
2301 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) { |
|
2302 gboolean res = FALSE; |
|
2303 guint n; |
|
2304 |
|
2305 g_value_init (dest, GST_TYPE_ARRAY); |
|
2306 for (n = 0; n < gst_value_array_get_size (src); n++) { |
|
2307 GValue kid = { 0 }; |
|
2308 const GValue *orig_kid = gst_value_array_get_value (src, n); |
|
2309 |
|
2310 if (!fixate_value (&kid, orig_kid)) |
|
2311 gst_value_init_and_copy (&kid, orig_kid); |
|
2312 else |
|
2313 res = TRUE; |
|
2314 gst_value_array_append_value (dest, &kid); |
|
2315 g_value_unset (&kid); |
|
2316 } |
|
2317 |
|
2318 if (!res) |
|
2319 g_value_unset (dest); |
|
2320 |
|
2321 return res; |
|
2322 } else { |
|
2323 return FALSE; |
|
2324 } |
|
2325 |
|
2326 return TRUE; |
|
2327 } |
|
2328 |
|
2329 static gboolean |
|
2330 gst_pad_default_fixate (GQuark field_id, const GValue * value, gpointer data) |
|
2331 { |
|
2332 GstStructure *s = data; |
|
2333 GValue v = { 0 }; |
|
2334 |
|
2335 if (fixate_value (&v, value)) { |
|
2336 gst_structure_id_set_value (s, field_id, &v); |
|
2337 g_value_unset (&v); |
|
2338 } |
|
2339 |
|
2340 return TRUE; |
|
2341 } |
|
2342 |
|
2343 /** |
|
2344 * gst_pad_fixate_caps: |
|
2345 * @pad: a #GstPad to fixate |
|
2346 * @caps: the #GstCaps to fixate |
|
2347 * |
|
2348 * Fixate a caps on the given pad. Modifies the caps in place, so you should |
|
2349 * make sure that the caps are actually writable (see gst_caps_make_writable()). |
|
2350 */ |
|
2351 #ifdef __SYMBIAN32__ |
|
2352 EXPORT_C |
|
2353 #endif |
|
2354 |
|
2355 void |
|
2356 gst_pad_fixate_caps (GstPad * pad, GstCaps * caps) |
|
2357 { |
|
2358 GstPadFixateCapsFunction fixatefunc; |
|
2359 guint n; |
|
2360 |
|
2361 g_return_if_fail (GST_IS_PAD (pad)); |
|
2362 g_return_if_fail (caps != NULL); |
|
2363 |
|
2364 if (gst_caps_is_fixed (caps)) |
|
2365 return; |
|
2366 |
|
2367 fixatefunc = GST_PAD_FIXATECAPSFUNC (pad); |
|
2368 if (fixatefunc) { |
|
2369 fixatefunc (pad, caps); |
|
2370 } |
|
2371 |
|
2372 /* default fixation */ |
|
2373 for (n = 0; n < gst_caps_get_size (caps); n++) { |
|
2374 GstStructure *s = gst_caps_get_structure (caps, n); |
|
2375 |
|
2376 gst_structure_foreach (s, gst_pad_default_fixate, s); |
|
2377 } |
|
2378 } |
|
2379 |
|
2380 /* Default accept caps implementation just checks against |
|
2381 * against the allowed caps for the pad */ |
|
2382 static gboolean |
|
2383 gst_pad_acceptcaps_default (GstPad * pad, GstCaps * caps) |
|
2384 { |
|
2385 /* get the caps and see if it intersects to something |
|
2386 * not empty */ |
|
2387 GstCaps *intersect; |
|
2388 GstCaps *allowed; |
|
2389 gboolean result = FALSE; |
|
2390 |
|
2391 GST_DEBUG_OBJECT (pad, "caps %" GST_PTR_FORMAT, caps); |
|
2392 |
|
2393 allowed = gst_pad_get_caps (pad); |
|
2394 if (!allowed) |
|
2395 goto nothing_allowed; |
|
2396 |
|
2397 GST_DEBUG_OBJECT (pad, "allowed caps %" GST_PTR_FORMAT, allowed); |
|
2398 |
|
2399 intersect = gst_caps_intersect (allowed, caps); |
|
2400 |
|
2401 GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect); |
|
2402 |
|
2403 result = !gst_caps_is_empty (intersect); |
|
2404 if (!result) |
|
2405 GST_DEBUG_OBJECT (pad, "intersection gave empty caps"); |
|
2406 |
|
2407 gst_caps_unref (allowed); |
|
2408 gst_caps_unref (intersect); |
|
2409 |
|
2410 return result; |
|
2411 |
|
2412 /* ERRORS */ |
|
2413 nothing_allowed: |
|
2414 { |
|
2415 GST_DEBUG_OBJECT (pad, "no caps allowed on the pad"); |
|
2416 return FALSE; |
|
2417 } |
|
2418 } |
|
2419 |
|
2420 /** |
|
2421 * gst_pad_accept_caps: |
|
2422 * @pad: a #GstPad to check |
|
2423 * @caps: a #GstCaps to check on the pad |
|
2424 * |
|
2425 * Check if the given pad accepts the caps. |
|
2426 * |
|
2427 * Returns: TRUE if the pad can accept the caps. |
|
2428 */ |
|
2429 #ifdef __SYMBIAN32__ |
|
2430 EXPORT_C |
|
2431 #endif |
|
2432 |
|
2433 gboolean |
|
2434 gst_pad_accept_caps (GstPad * pad, GstCaps * caps) |
|
2435 { |
|
2436 gboolean result; |
|
2437 GstPadAcceptCapsFunction acceptfunc; |
|
2438 GstCaps *existing = NULL; |
|
2439 |
|
2440 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
2441 |
|
2442 /* any pad can be unnegotiated */ |
|
2443 if (caps == NULL) |
|
2444 return TRUE; |
|
2445 |
|
2446 /* lock for checking the existing caps */ |
|
2447 GST_OBJECT_LOCK (pad); |
|
2448 acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad); |
|
2449 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps); |
|
2450 /* The current caps on a pad are trivially acceptable */ |
|
2451 if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) { |
|
2452 if (caps == existing || gst_caps_is_equal (caps, existing)) |
|
2453 goto is_same_caps; |
|
2454 } |
|
2455 GST_OBJECT_UNLOCK (pad); |
|
2456 |
|
2457 if (G_LIKELY (acceptfunc)) { |
|
2458 /* we can call the function */ |
|
2459 result = acceptfunc (pad, caps); |
|
2460 GST_DEBUG_OBJECT (pad, "acceptfunc returned %d", result); |
|
2461 } else { |
|
2462 /* Only null if the element explicitly unset it */ |
|
2463 result = gst_pad_acceptcaps_default (pad, caps); |
|
2464 GST_DEBUG_OBJECT (pad, "default acceptcaps returned %d", result); |
|
2465 } |
|
2466 return result; |
|
2467 |
|
2468 is_same_caps: |
|
2469 { |
|
2470 GST_DEBUG_OBJECT (pad, "pad had same caps"); |
|
2471 GST_OBJECT_UNLOCK (pad); |
|
2472 return TRUE; |
|
2473 } |
|
2474 } |
|
2475 |
|
2476 /** |
|
2477 * gst_pad_peer_accept_caps: |
|
2478 * @pad: a #GstPad to check the peer of |
|
2479 * @caps: a #GstCaps to check on the pad |
|
2480 * |
|
2481 * Check if the peer of @pad accepts @caps. If @pad has no peer, this function |
|
2482 * returns TRUE. |
|
2483 * |
|
2484 * Returns: TRUE if the peer of @pad can accept the caps or @pad has no peer. |
|
2485 */ |
|
2486 #ifdef __SYMBIAN32__ |
|
2487 EXPORT_C |
|
2488 #endif |
|
2489 |
|
2490 gboolean |
|
2491 gst_pad_peer_accept_caps (GstPad * pad, GstCaps * caps) |
|
2492 { |
|
2493 GstPad *peerpad; |
|
2494 gboolean result; |
|
2495 |
|
2496 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
2497 |
|
2498 GST_OBJECT_LOCK (pad); |
|
2499 |
|
2500 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "peer accept caps of (%p)", pad); |
|
2501 |
|
2502 peerpad = GST_PAD_PEER (pad); |
|
2503 if (G_UNLIKELY (peerpad == NULL)) |
|
2504 goto no_peer; |
|
2505 |
|
2506 result = gst_pad_accept_caps (peerpad, caps); |
|
2507 GST_OBJECT_UNLOCK (pad); |
|
2508 |
|
2509 return result; |
|
2510 |
|
2511 no_peer: |
|
2512 { |
|
2513 GST_OBJECT_UNLOCK (pad); |
|
2514 return TRUE; |
|
2515 } |
|
2516 } |
|
2517 |
|
2518 /** |
|
2519 * gst_pad_set_caps: |
|
2520 * @pad: a #GstPad to set the capabilities of. |
|
2521 * @caps: a #GstCaps to set. |
|
2522 * |
|
2523 * Sets the capabilities of this pad. The caps must be fixed. Any previous |
|
2524 * caps on the pad will be unreffed. This function refs the caps so you should |
|
2525 * unref if as soon as you don't need it anymore. |
|
2526 * It is possible to set NULL caps, which will make the pad unnegotiated |
|
2527 * again. |
|
2528 * |
|
2529 * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed |
|
2530 * or bad parameters were provided to this function. |
|
2531 * |
|
2532 * MT safe. |
|
2533 */ |
|
2534 #ifdef __SYMBIAN32__ |
|
2535 EXPORT_C |
|
2536 #endif |
|
2537 |
|
2538 gboolean |
|
2539 gst_pad_set_caps (GstPad * pad, GstCaps * caps) |
|
2540 { |
|
2541 GstPadSetCapsFunction setcaps; |
|
2542 GstCaps *existing; |
|
2543 |
|
2544 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
2545 g_return_val_if_fail (caps == NULL || gst_caps_is_fixed (caps), FALSE); |
|
2546 |
|
2547 GST_OBJECT_LOCK (pad); |
|
2548 existing = GST_PAD_CAPS (pad); |
|
2549 if (existing == caps) |
|
2550 goto was_ok; |
|
2551 |
|
2552 if (gst_caps_is_equal (caps, existing)) |
|
2553 goto setting_same_caps; |
|
2554 |
|
2555 setcaps = GST_PAD_SETCAPSFUNC (pad); |
|
2556 |
|
2557 /* call setcaps function to configure the pad only if the |
|
2558 * caps is not NULL */ |
|
2559 if (setcaps != NULL && caps) { |
|
2560 if (!GST_PAD_IS_IN_SETCAPS (pad)) { |
|
2561 GST_OBJECT_FLAG_SET (pad, GST_PAD_IN_SETCAPS); |
|
2562 GST_OBJECT_UNLOCK (pad); |
|
2563 if (!setcaps (pad, caps)) |
|
2564 goto could_not_set; |
|
2565 GST_OBJECT_LOCK (pad); |
|
2566 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS); |
|
2567 } else { |
|
2568 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "pad was dispatching"); |
|
2569 } |
|
2570 } |
|
2571 |
|
2572 gst_caps_replace (&GST_PAD_CAPS (pad), caps); |
|
2573 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "caps %" GST_PTR_FORMAT, caps); |
|
2574 GST_OBJECT_UNLOCK (pad); |
|
2575 |
|
2576 g_object_notify (G_OBJECT (pad), "caps"); |
|
2577 |
|
2578 return TRUE; |
|
2579 |
|
2580 was_ok: |
|
2581 { |
|
2582 GST_OBJECT_UNLOCK (pad); |
|
2583 return TRUE; |
|
2584 } |
|
2585 setting_same_caps: |
|
2586 { |
|
2587 gst_caps_replace (&GST_PAD_CAPS (pad), caps); |
|
2588 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2589 "caps %" GST_PTR_FORMAT " same as existing, updating ptr only", caps); |
|
2590 GST_OBJECT_UNLOCK (pad); |
|
2591 return TRUE; |
|
2592 } |
|
2593 |
|
2594 /* ERRORS */ |
|
2595 could_not_set: |
|
2596 { |
|
2597 GST_OBJECT_LOCK (pad); |
|
2598 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_IN_SETCAPS); |
|
2599 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2600 "caps %" GST_PTR_FORMAT " could not be set", caps); |
|
2601 GST_OBJECT_UNLOCK (pad); |
|
2602 |
|
2603 return FALSE; |
|
2604 } |
|
2605 } |
|
2606 |
|
2607 static gboolean |
|
2608 gst_pad_configure_sink (GstPad * pad, GstCaps * caps) |
|
2609 { |
|
2610 gboolean res; |
|
2611 |
|
2612 /* See if pad accepts the caps */ |
|
2613 if (!gst_pad_accept_caps (pad, caps)) |
|
2614 goto not_accepted; |
|
2615 |
|
2616 /* set caps on pad if call succeeds */ |
|
2617 res = gst_pad_set_caps (pad, caps); |
|
2618 /* no need to unref the caps here, set_caps takes a ref and |
|
2619 * our ref goes away when we leave this function. */ |
|
2620 |
|
2621 return res; |
|
2622 |
|
2623 not_accepted: |
|
2624 { |
|
2625 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2626 "caps %" GST_PTR_FORMAT " not accepted", caps); |
|
2627 return FALSE; |
|
2628 } |
|
2629 } |
|
2630 |
|
2631 /* returns TRUE if the src pad could be configured to accept the given caps */ |
|
2632 static gboolean |
|
2633 gst_pad_configure_src (GstPad * pad, GstCaps * caps, gboolean dosetcaps) |
|
2634 { |
|
2635 gboolean res; |
|
2636 |
|
2637 /* See if pad accepts the caps */ |
|
2638 if (!gst_pad_accept_caps (pad, caps)) |
|
2639 goto not_accepted; |
|
2640 |
|
2641 if (dosetcaps) |
|
2642 res = gst_pad_set_caps (pad, caps); |
|
2643 else |
|
2644 res = TRUE; |
|
2645 |
|
2646 return res; |
|
2647 |
|
2648 not_accepted: |
|
2649 { |
|
2650 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, |
|
2651 "caps %" GST_PTR_FORMAT " not accepted", caps); |
|
2652 return FALSE; |
|
2653 } |
|
2654 } |
|
2655 |
|
2656 /** |
|
2657 * gst_pad_get_pad_template_caps: |
|
2658 * @pad: a #GstPad to get the template capabilities from. |
|
2659 * |
|
2660 * Gets the capabilities for @pad's template. |
|
2661 * |
|
2662 * Returns: the #GstCaps of this pad template. If you intend to keep a |
|
2663 * reference on the caps, make a copy (see gst_caps_copy ()). |
|
2664 */ |
|
2665 #ifdef __SYMBIAN32__ |
|
2666 EXPORT_C |
|
2667 #endif |
|
2668 |
|
2669 const GstCaps * |
|
2670 gst_pad_get_pad_template_caps (GstPad * pad) |
|
2671 { |
|
2672 static GstStaticCaps anycaps = GST_STATIC_CAPS ("ANY"); |
|
2673 |
|
2674 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2675 |
|
2676 if (GST_PAD_PAD_TEMPLATE (pad)) |
|
2677 return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)); |
|
2678 |
|
2679 return gst_static_caps_get (&anycaps); |
|
2680 } |
|
2681 |
|
2682 /** |
|
2683 * gst_pad_get_peer: |
|
2684 * @pad: a #GstPad to get the peer of. |
|
2685 * |
|
2686 * Gets the peer of @pad. This function refs the peer pad so |
|
2687 * you need to unref it after use. |
|
2688 * |
|
2689 * Returns: the peer #GstPad. Unref after usage. |
|
2690 * |
|
2691 * MT safe. |
|
2692 */ |
|
2693 #ifdef __SYMBIAN32__ |
|
2694 EXPORT_C |
|
2695 #endif |
|
2696 |
|
2697 GstPad * |
|
2698 gst_pad_get_peer (GstPad * pad) |
|
2699 { |
|
2700 GstPad *result; |
|
2701 |
|
2702 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2703 |
|
2704 GST_OBJECT_LOCK (pad); |
|
2705 result = GST_PAD_PEER (pad); |
|
2706 if (result) |
|
2707 gst_object_ref (result); |
|
2708 GST_OBJECT_UNLOCK (pad); |
|
2709 |
|
2710 return result; |
|
2711 } |
|
2712 |
|
2713 /** |
|
2714 * gst_pad_get_allowed_caps: |
|
2715 * @pad: a #GstPad. |
|
2716 * |
|
2717 * Gets the capabilities of the allowed media types that can flow through |
|
2718 * @pad and its peer. |
|
2719 * |
|
2720 * The allowed capabilities is calculated as the intersection of the results of |
|
2721 * calling gst_pad_get_caps() on @pad and its peer. The caller owns a reference |
|
2722 * on the resulting caps. |
|
2723 * |
|
2724 * Returns: the allowed #GstCaps of the pad link. Unref the caps when you no |
|
2725 * longer need it. This function returns NULL when @pad has no peer. |
|
2726 * |
|
2727 * MT safe. |
|
2728 */ |
|
2729 #ifdef __SYMBIAN32__ |
|
2730 EXPORT_C |
|
2731 #endif |
|
2732 |
|
2733 GstCaps * |
|
2734 gst_pad_get_allowed_caps (GstPad * pad) |
|
2735 { |
|
2736 GstCaps *mycaps; |
|
2737 GstCaps *caps; |
|
2738 GstCaps *peercaps; |
|
2739 GstPad *peer; |
|
2740 |
|
2741 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2742 |
|
2743 GST_OBJECT_LOCK (pad); |
|
2744 |
|
2745 peer = GST_PAD_PEER (pad); |
|
2746 if (G_UNLIKELY (peer == NULL)) |
|
2747 goto no_peer; |
|
2748 |
|
2749 GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting allowed caps"); |
|
2750 |
|
2751 gst_object_ref (peer); |
|
2752 GST_OBJECT_UNLOCK (pad); |
|
2753 mycaps = gst_pad_get_caps (pad); |
|
2754 |
|
2755 peercaps = gst_pad_get_caps (peer); |
|
2756 gst_object_unref (peer); |
|
2757 |
|
2758 caps = gst_caps_intersect (mycaps, peercaps); |
|
2759 gst_caps_unref (peercaps); |
|
2760 gst_caps_unref (mycaps); |
|
2761 |
|
2762 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "allowed caps %" GST_PTR_FORMAT, |
|
2763 caps); |
|
2764 |
|
2765 return caps; |
|
2766 |
|
2767 no_peer: |
|
2768 { |
|
2769 GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer"); |
|
2770 GST_OBJECT_UNLOCK (pad); |
|
2771 |
|
2772 return NULL; |
|
2773 } |
|
2774 } |
|
2775 |
|
2776 /** |
|
2777 * gst_pad_get_negotiated_caps: |
|
2778 * @pad: a #GstPad. |
|
2779 * |
|
2780 * Gets the capabilities of the media type that currently flows through @pad |
|
2781 * and its peer. |
|
2782 * |
|
2783 * This function can be used on both src and sinkpads. Note that srcpads are |
|
2784 * always negotiated before sinkpads so it is possible that the negotiated caps |
|
2785 * on the srcpad do not match the negotiated caps of the peer. |
|
2786 * |
|
2787 * Returns: the negotiated #GstCaps of the pad link. Unref the caps when |
|
2788 * you no longer need it. This function returns NULL when the @pad has no |
|
2789 * peer or is not negotiated yet. |
|
2790 * |
|
2791 * MT safe. |
|
2792 */ |
|
2793 #ifdef __SYMBIAN32__ |
|
2794 EXPORT_C |
|
2795 #endif |
|
2796 |
|
2797 GstCaps * |
|
2798 gst_pad_get_negotiated_caps (GstPad * pad) |
|
2799 { |
|
2800 GstCaps *caps; |
|
2801 GstPad *peer; |
|
2802 |
|
2803 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
2804 |
|
2805 GST_OBJECT_LOCK (pad); |
|
2806 |
|
2807 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
|
2808 goto no_peer; |
|
2809 |
|
2810 GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "getting negotiated caps"); |
|
2811 |
|
2812 caps = GST_PAD_CAPS (pad); |
|
2813 if (caps) |
|
2814 gst_caps_ref (caps); |
|
2815 GST_OBJECT_UNLOCK (pad); |
|
2816 |
|
2817 GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "negotiated caps %" GST_PTR_FORMAT, |
|
2818 caps); |
|
2819 |
|
2820 return caps; |
|
2821 |
|
2822 no_peer: |
|
2823 { |
|
2824 GST_CAT_DEBUG_OBJECT (GST_CAT_PROPERTIES, pad, "no peer"); |
|
2825 GST_OBJECT_UNLOCK (pad); |
|
2826 |
|
2827 return NULL; |
|
2828 } |
|
2829 } |
|
2830 |
|
2831 /* calls the buffer_alloc function on the given pad */ |
|
2832 static GstFlowReturn |
|
2833 gst_pad_buffer_alloc_unchecked (GstPad * pad, guint64 offset, gint size, |
|
2834 GstCaps * caps, GstBuffer ** buf) |
|
2835 { |
|
2836 GstFlowReturn ret; |
|
2837 GstPadBufferAllocFunction bufferallocfunc; |
|
2838 |
|
2839 GST_OBJECT_LOCK (pad); |
|
2840 /* when the pad is flushing we cannot give a buffer */ |
|
2841 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
|
2842 goto flushing; |
|
2843 |
|
2844 bufferallocfunc = pad->bufferallocfunc; |
|
2845 |
|
2846 if (offset == GST_BUFFER_OFFSET_NONE) { |
|
2847 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
2848 "calling bufferallocfunc &%s (@%p) for size %d offset NONE", |
|
2849 GST_DEBUG_FUNCPTR_NAME (bufferallocfunc), bufferallocfunc, size); |
|
2850 } else { |
|
2851 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
2852 "calling bufferallocfunc &%s (@%p) of for size %d offset %" |
|
2853 G_GUINT64_FORMAT, GST_DEBUG_FUNCPTR_NAME (bufferallocfunc), |
|
2854 bufferallocfunc, size, offset); |
|
2855 } |
|
2856 GST_OBJECT_UNLOCK (pad); |
|
2857 |
|
2858 /* G_LIKELY for now since most elements don't implement a buffer alloc |
|
2859 * function and there is no default alloc proxy function as this is usually |
|
2860 * not possible. */ |
|
2861 if (G_LIKELY (bufferallocfunc == NULL)) |
|
2862 goto fallback; |
|
2863 |
|
2864 ret = bufferallocfunc (pad, offset, size, caps, buf); |
|
2865 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
|
2866 goto error; |
|
2867 /* no error, but NULL buffer means fallback to the default */ |
|
2868 if (G_UNLIKELY (*buf == NULL)) |
|
2869 goto fallback; |
|
2870 |
|
2871 /* If the buffer alloc function didn't set up the caps like it should, |
|
2872 * do it for it */ |
|
2873 if (G_UNLIKELY (caps && (GST_BUFFER_CAPS (*buf) == NULL))) { |
|
2874 GST_WARNING_OBJECT (pad, |
|
2875 "Buffer allocation function did not set caps. Setting"); |
|
2876 gst_buffer_set_caps (*buf, caps); |
|
2877 } |
|
2878 return ret; |
|
2879 |
|
2880 flushing: |
|
2881 { |
|
2882 /* pad was flushing */ |
|
2883 GST_OBJECT_UNLOCK (pad); |
|
2884 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad was flushing"); |
|
2885 return GST_FLOW_WRONG_STATE; |
|
2886 } |
|
2887 error: |
|
2888 { |
|
2889 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
2890 "alloc function returned error (%d) %s", ret, gst_flow_get_name (ret)); |
|
2891 return ret; |
|
2892 } |
|
2893 fallback: |
|
2894 { |
|
2895 /* fallback case, allocate a buffer of our own, add pad caps. */ |
|
2896 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc"); |
|
2897 |
|
2898 *buf = gst_buffer_new_and_alloc (size); |
|
2899 GST_BUFFER_OFFSET (*buf) = offset; |
|
2900 gst_buffer_set_caps (*buf, caps); |
|
2901 |
|
2902 return GST_FLOW_OK; |
|
2903 } |
|
2904 } |
|
2905 |
|
2906 static GstFlowReturn |
|
2907 gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size, |
|
2908 GstCaps * caps, GstBuffer ** buf, gboolean setcaps) |
|
2909 { |
|
2910 GstPad *peer; |
|
2911 GstFlowReturn ret; |
|
2912 gboolean caps_changed; |
|
2913 |
|
2914 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
2915 g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR); |
|
2916 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); |
|
2917 |
|
2918 GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d", offset, size); |
|
2919 |
|
2920 GST_OBJECT_LOCK (pad); |
|
2921 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
|
2922 if ((ret = handle_pad_block (pad)) != GST_FLOW_OK) |
|
2923 goto flushed; |
|
2924 |
|
2925 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
|
2926 goto no_peer; |
|
2927 |
|
2928 gst_object_ref (peer); |
|
2929 GST_OBJECT_UNLOCK (pad); |
|
2930 |
|
2931 ret = gst_pad_buffer_alloc_unchecked (peer, offset, size, caps, buf); |
|
2932 gst_object_unref (peer); |
|
2933 |
|
2934 if (G_UNLIKELY (ret != GST_FLOW_OK)) |
|
2935 goto peer_error; |
|
2936 |
|
2937 /* FIXME, move capnego this into a base class? */ |
|
2938 caps = GST_BUFFER_CAPS (*buf); |
|
2939 |
|
2940 /* Lock for checking caps, pretty pointless as the _pad_push() function might |
|
2941 * change it concurrently, one of the problems with automatic caps setting in |
|
2942 * pad_alloc_and_set_caps. Worst case, if does a check too much, but only |
|
2943 * when there is heavy renegotiation going on in both directions. */ |
|
2944 GST_OBJECT_LOCK (pad); |
|
2945 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
2946 GST_OBJECT_UNLOCK (pad); |
|
2947 |
|
2948 /* we got a new datatype on the pad, see if it can handle it */ |
|
2949 if (G_UNLIKELY (caps_changed)) { |
|
2950 GST_DEBUG_OBJECT (pad, |
|
2951 "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT, |
|
2952 GST_PAD_CAPS (pad), caps, caps); |
|
2953 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, setcaps))) |
|
2954 goto not_negotiated; |
|
2955 } |
|
2956 return ret; |
|
2957 |
|
2958 flushed: |
|
2959 { |
|
2960 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "pad block stopped by flush"); |
|
2961 GST_OBJECT_UNLOCK (pad); |
|
2962 return ret; |
|
2963 } |
|
2964 no_peer: |
|
2965 { |
|
2966 /* pad has no peer */ |
|
2967 GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, |
|
2968 "called bufferallocfunc but had no peer"); |
|
2969 GST_OBJECT_UNLOCK (pad); |
|
2970 return GST_FLOW_NOT_LINKED; |
|
2971 } |
|
2972 peer_error: |
|
2973 { |
|
2974 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
2975 "alloc function returned error %s", gst_flow_get_name (ret)); |
|
2976 return ret; |
|
2977 } |
|
2978 not_negotiated: |
|
2979 { |
|
2980 gst_buffer_unref (*buf); |
|
2981 *buf = NULL; |
|
2982 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
2983 "alloc function returned unacceptable buffer"); |
|
2984 return GST_FLOW_NOT_NEGOTIATED; |
|
2985 } |
|
2986 } |
|
2987 |
|
2988 /** |
|
2989 * gst_pad_alloc_buffer: |
|
2990 * @pad: a source #GstPad |
|
2991 * @offset: the offset of the new buffer in the stream |
|
2992 * @size: the size of the new buffer |
|
2993 * @caps: the caps of the new buffer |
|
2994 * @buf: a newly allocated buffer |
|
2995 * |
|
2996 * Allocates a new, empty buffer optimized to push to pad @pad. This |
|
2997 * function only works if @pad is a source pad and has a peer. |
|
2998 * |
|
2999 * A new, empty #GstBuffer will be put in the @buf argument. |
|
3000 * You need to check the caps of the buffer after performing this |
|
3001 * function and renegotiate to the format if needed. |
|
3002 * |
|
3003 * Returns: a result code indicating success of the operation. Any |
|
3004 * result code other than #GST_FLOW_OK is an error and @buf should |
|
3005 * not be used. |
|
3006 * An error can occur if the pad is not connected or when the downstream |
|
3007 * peer elements cannot provide an acceptable buffer. |
|
3008 * |
|
3009 * MT safe. |
|
3010 */ |
|
3011 #ifdef __SYMBIAN32__ |
|
3012 EXPORT_C |
|
3013 #endif |
|
3014 |
|
3015 GstFlowReturn |
|
3016 gst_pad_alloc_buffer (GstPad * pad, guint64 offset, gint size, GstCaps * caps, |
|
3017 GstBuffer ** buf) |
|
3018 { |
|
3019 return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, FALSE); |
|
3020 } |
|
3021 |
|
3022 /** |
|
3023 * gst_pad_alloc_buffer_and_set_caps: |
|
3024 * @pad: a source #GstPad |
|
3025 * @offset: the offset of the new buffer in the stream |
|
3026 * @size: the size of the new buffer |
|
3027 * @caps: the caps of the new buffer |
|
3028 * @buf: a newly allocated buffer |
|
3029 * |
|
3030 * In addition to the function gst_pad_alloc_buffer(), this function |
|
3031 * automatically calls gst_pad_set_caps() when the caps of the |
|
3032 * newly allocated buffer are different from the @pad caps. |
|
3033 * |
|
3034 * Returns: a result code indicating success of the operation. Any |
|
3035 * result code other than #GST_FLOW_OK is an error and @buf should |
|
3036 * not be used. |
|
3037 * An error can occur if the pad is not connected or when the downstream |
|
3038 * peer elements cannot provide an acceptable buffer. |
|
3039 * |
|
3040 * MT safe. |
|
3041 */ |
|
3042 #ifdef __SYMBIAN32__ |
|
3043 EXPORT_C |
|
3044 #endif |
|
3045 |
|
3046 GstFlowReturn |
|
3047 gst_pad_alloc_buffer_and_set_caps (GstPad * pad, guint64 offset, gint size, |
|
3048 GstCaps * caps, GstBuffer ** buf) |
|
3049 { |
|
3050 return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE); |
|
3051 } |
|
3052 |
|
3053 /** |
|
3054 * gst_pad_get_internal_links_default: |
|
3055 * @pad: the #GstPad to get the internal links of. |
|
3056 * |
|
3057 * Gets a list of pads to which the given pad is linked to |
|
3058 * inside of the parent element. |
|
3059 * This is the default handler, and thus returns a list of all of the |
|
3060 * pads inside the parent element with opposite direction. |
|
3061 * The caller must free this list after use. |
|
3062 * |
|
3063 * Returns: a newly allocated #GList of pads, or NULL if the pad has no parent. |
|
3064 * |
|
3065 * Not MT safe. |
|
3066 */ |
|
3067 #ifdef __SYMBIAN32__ |
|
3068 EXPORT_C |
|
3069 #endif |
|
3070 |
|
3071 GList * |
|
3072 gst_pad_get_internal_links_default (GstPad * pad) |
|
3073 { |
|
3074 GList *res = NULL; |
|
3075 GstElement *parent; |
|
3076 GList *parent_pads; |
|
3077 GstPadDirection direction; |
|
3078 |
|
3079 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
3080 |
|
3081 direction = pad->direction; |
|
3082 |
|
3083 parent = GST_PAD_PARENT (pad); |
|
3084 if (!parent) |
|
3085 goto no_parent; |
|
3086 |
|
3087 parent_pads = parent->pads; |
|
3088 |
|
3089 while (parent_pads) { |
|
3090 GstPad *parent_pad = GST_PAD_CAST (parent_pads->data); |
|
3091 |
|
3092 if (parent_pad->direction != direction) { |
|
3093 GST_DEBUG_OBJECT (pad, "adding pad %s:%s", |
|
3094 GST_DEBUG_PAD_NAME (parent_pad)); |
|
3095 res = g_list_prepend (res, parent_pad); |
|
3096 } |
|
3097 parent_pads = g_list_next (parent_pads); |
|
3098 } |
|
3099 return res; |
|
3100 |
|
3101 no_parent: |
|
3102 { |
|
3103 GST_DEBUG_OBJECT (pad, "no parent"); |
|
3104 return NULL; |
|
3105 } |
|
3106 } |
|
3107 |
|
3108 /** |
|
3109 * gst_pad_get_internal_links: |
|
3110 * @pad: the #GstPad to get the internal links of. |
|
3111 * |
|
3112 * Gets a list of pads to which the given pad is linked to |
|
3113 * inside of the parent element. |
|
3114 * The caller must free this list after use. |
|
3115 * |
|
3116 * Returns: a newly allocated #GList of pads. |
|
3117 * |
|
3118 * Not MT safe. |
|
3119 */ |
|
3120 #ifdef __SYMBIAN32__ |
|
3121 EXPORT_C |
|
3122 #endif |
|
3123 |
|
3124 GList * |
|
3125 gst_pad_get_internal_links (GstPad * pad) |
|
3126 { |
|
3127 GList *res = NULL; |
|
3128 |
|
3129 g_return_val_if_fail (GST_IS_PAD (pad), NULL); |
|
3130 |
|
3131 if (GST_PAD_INTLINKFUNC (pad)) |
|
3132 res = GST_PAD_INTLINKFUNC (pad) (pad); |
|
3133 |
|
3134 return res; |
|
3135 } |
|
3136 |
|
3137 |
|
3138 static gboolean |
|
3139 gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event) |
|
3140 { |
|
3141 GList *orig, *pads; |
|
3142 gboolean result; |
|
3143 |
|
3144 GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads", |
|
3145 event, GST_EVENT_TYPE_NAME (event)); |
|
3146 |
|
3147 result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK); |
|
3148 |
|
3149 orig = pads = gst_pad_get_internal_links (pad); |
|
3150 |
|
3151 while (pads) { |
|
3152 GstPad *eventpad = GST_PAD_CAST (pads->data); |
|
3153 |
|
3154 pads = g_list_next (pads); |
|
3155 |
|
3156 if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) { |
|
3157 /* for each pad we send to, we should ref the event; it's up |
|
3158 * to downstream to unref again when handled. */ |
|
3159 GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s", |
|
3160 event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad)); |
|
3161 gst_event_ref (event); |
|
3162 gst_pad_push_event (eventpad, event); |
|
3163 } else { |
|
3164 /* we only send the event on one pad, multi-sinkpad elements |
|
3165 * should implement a handler */ |
|
3166 GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s", |
|
3167 event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad)); |
|
3168 result = gst_pad_push_event (eventpad, event); |
|
3169 goto done; |
|
3170 } |
|
3171 } |
|
3172 /* we handled the incoming event so we unref once */ |
|
3173 GST_LOG_OBJECT (pad, "handled event %p, unreffing", event); |
|
3174 gst_event_unref (event); |
|
3175 |
|
3176 done: |
|
3177 g_list_free (orig); |
|
3178 |
|
3179 return result; |
|
3180 } |
|
3181 |
|
3182 /** |
|
3183 * gst_pad_event_default: |
|
3184 * @pad: a #GstPad to call the default event handler on. |
|
3185 * @event: the #GstEvent to handle. |
|
3186 * |
|
3187 * Invokes the default event handler for the given pad. End-of-stream and |
|
3188 * discontinuity events are handled specially, and then the event is sent to all |
|
3189 * pads internally linked to @pad. Note that if there are many possible sink |
|
3190 * pads that are internally linked to @pad, only one will be sent an event. |
|
3191 * Multi-sinkpad elements should implement custom event handlers. |
|
3192 * |
|
3193 * Returns: TRUE if the event was sent succesfully. |
|
3194 */ |
|
3195 #ifdef __SYMBIAN32__ |
|
3196 EXPORT_C |
|
3197 #endif |
|
3198 |
|
3199 gboolean |
|
3200 gst_pad_event_default (GstPad * pad, GstEvent * event) |
|
3201 { |
|
3202 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
3203 g_return_val_if_fail (event != NULL, FALSE); |
|
3204 |
|
3205 switch (GST_EVENT_TYPE (event)) { |
|
3206 case GST_EVENT_EOS: |
|
3207 { |
|
3208 GST_DEBUG_OBJECT (pad, "pausing task because of eos"); |
|
3209 gst_pad_pause_task (pad); |
|
3210 } |
|
3211 /* fall thru */ |
|
3212 default: |
|
3213 break; |
|
3214 } |
|
3215 |
|
3216 return gst_pad_event_default_dispatch (pad, event); |
|
3217 } |
|
3218 |
|
3219 /** |
|
3220 * gst_pad_dispatcher: |
|
3221 * @pad: a #GstPad to dispatch. |
|
3222 * @dispatch: the #GstDispatcherFunction to call. |
|
3223 * @data: gpointer user data passed to the dispatcher function. |
|
3224 * |
|
3225 * Invokes the given dispatcher function on each respective peer of |
|
3226 * all pads that are internally linked to the given pad. |
|
3227 * The GstPadDispatcherFunction should return TRUE when no further pads |
|
3228 * need to be processed. |
|
3229 * |
|
3230 * Returns: TRUE if one of the dispatcher functions returned TRUE. |
|
3231 */ |
|
3232 #ifdef __SYMBIAN32__ |
|
3233 EXPORT_C |
|
3234 #endif |
|
3235 |
|
3236 gboolean |
|
3237 gst_pad_dispatcher (GstPad * pad, GstPadDispatcherFunction dispatch, |
|
3238 gpointer data) |
|
3239 { |
|
3240 gboolean res = FALSE; |
|
3241 GList *int_pads, *orig; |
|
3242 |
|
3243 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
3244 g_return_val_if_fail (dispatch != NULL, FALSE); |
|
3245 |
|
3246 orig = int_pads = gst_pad_get_internal_links (pad); |
|
3247 |
|
3248 while (int_pads) { |
|
3249 GstPad *int_pad = GST_PAD_CAST (int_pads->data); |
|
3250 GstPad *int_peer = gst_pad_get_peer (int_pad); |
|
3251 |
|
3252 if (int_peer) { |
|
3253 GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s", |
|
3254 GST_DEBUG_PAD_NAME (int_peer)); |
|
3255 res = dispatch (int_peer, data); |
|
3256 gst_object_unref (int_peer); |
|
3257 if (res) |
|
3258 break; |
|
3259 } else { |
|
3260 GST_DEBUG_OBJECT (int_pad, "no peer"); |
|
3261 } |
|
3262 int_pads = g_list_next (int_pads); |
|
3263 } |
|
3264 g_list_free (orig); |
|
3265 GST_DEBUG_OBJECT (pad, "done, result %d", res); |
|
3266 |
|
3267 return res; |
|
3268 } |
|
3269 |
|
3270 /** |
|
3271 * gst_pad_query: |
|
3272 * @pad: a #GstPad to invoke the default query on. |
|
3273 * @query: the #GstQuery to perform. |
|
3274 * |
|
3275 * Dispatches a query to a pad. The query should have been allocated by the |
|
3276 * caller via one of the type-specific allocation functions in gstquery.h. The |
|
3277 * element is responsible for filling the query with an appropriate response, |
|
3278 * which should then be parsed with a type-specific query parsing function. |
|
3279 * |
|
3280 * Again, the caller is responsible for both the allocation and deallocation of |
|
3281 * the query structure. |
|
3282 * |
|
3283 * Returns: TRUE if the query could be performed. |
|
3284 */ |
|
3285 #ifdef __SYMBIAN32__ |
|
3286 EXPORT_C |
|
3287 #endif |
|
3288 |
|
3289 gboolean |
|
3290 gst_pad_query (GstPad * pad, GstQuery * query) |
|
3291 { |
|
3292 GstPadQueryFunction func; |
|
3293 |
|
3294 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
3295 g_return_val_if_fail (GST_IS_QUERY (query), FALSE); |
|
3296 |
|
3297 GST_DEBUG_OBJECT (pad, "sending query %p", query); |
|
3298 |
|
3299 if ((func = GST_PAD_QUERYFUNC (pad)) == NULL) |
|
3300 goto no_func; |
|
3301 |
|
3302 return func (pad, query); |
|
3303 |
|
3304 no_func: |
|
3305 { |
|
3306 GST_DEBUG_OBJECT (pad, "had no query function"); |
|
3307 return FALSE; |
|
3308 } |
|
3309 } |
|
3310 |
|
3311 /** |
|
3312 * gst_pad_peer_query: |
|
3313 * @pad: a #GstPad to invoke the peer query on. |
|
3314 * @query: the #GstQuery to perform. |
|
3315 * |
|
3316 * Performs gst_pad_query() on the peer of @pad. |
|
3317 * |
|
3318 * The caller is responsible for both the allocation and deallocation of |
|
3319 * the query structure. |
|
3320 * |
|
3321 * Returns: TRUE if the query could be performed. This function returns %FALSE |
|
3322 * if @pad has no peer. |
|
3323 * |
|
3324 * Since: 0.10.15 |
|
3325 */ |
|
3326 #ifdef __SYMBIAN32__ |
|
3327 EXPORT_C |
|
3328 #endif |
|
3329 |
|
3330 gboolean |
|
3331 gst_pad_peer_query (GstPad * pad, GstQuery * query) |
|
3332 { |
|
3333 GstPad *peerpad; |
|
3334 gboolean result; |
|
3335 |
|
3336 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
3337 g_return_val_if_fail (GST_IS_QUERY (query), FALSE); |
|
3338 |
|
3339 GST_OBJECT_LOCK (pad); |
|
3340 |
|
3341 GST_DEBUG_OBJECT (pad, "peer query"); |
|
3342 |
|
3343 peerpad = GST_PAD_PEER (pad); |
|
3344 if (G_UNLIKELY (peerpad == NULL)) |
|
3345 goto no_peer; |
|
3346 |
|
3347 gst_object_ref (peerpad); |
|
3348 GST_OBJECT_UNLOCK (pad); |
|
3349 |
|
3350 result = gst_pad_query (peerpad, query); |
|
3351 |
|
3352 gst_object_unref (peerpad); |
|
3353 |
|
3354 return result; |
|
3355 |
|
3356 /* ERRORS */ |
|
3357 no_peer: |
|
3358 { |
|
3359 GST_WARNING_OBJECT (pad, "pad has no peer"); |
|
3360 GST_OBJECT_UNLOCK (pad); |
|
3361 return FALSE; |
|
3362 } |
|
3363 } |
|
3364 |
|
3365 /** |
|
3366 * gst_pad_query_default: |
|
3367 * @pad: a #GstPad to call the default query handler on. |
|
3368 * @query: the #GstQuery to handle. |
|
3369 * |
|
3370 * Invokes the default query handler for the given pad. |
|
3371 * The query is sent to all pads internally linked to @pad. Note that |
|
3372 * if there are many possible sink pads that are internally linked to |
|
3373 * @pad, only one will be sent the query. |
|
3374 * Multi-sinkpad elements should implement custom query handlers. |
|
3375 * |
|
3376 * Returns: TRUE if the query was performed succesfully. |
|
3377 */ |
|
3378 #ifdef __SYMBIAN32__ |
|
3379 EXPORT_C |
|
3380 #endif |
|
3381 |
|
3382 gboolean |
|
3383 gst_pad_query_default (GstPad * pad, GstQuery * query) |
|
3384 { |
|
3385 switch (GST_QUERY_TYPE (query)) { |
|
3386 case GST_QUERY_POSITION: |
|
3387 case GST_QUERY_SEEKING: |
|
3388 case GST_QUERY_FORMATS: |
|
3389 case GST_QUERY_LATENCY: |
|
3390 case GST_QUERY_JITTER: |
|
3391 case GST_QUERY_RATE: |
|
3392 case GST_QUERY_CONVERT: |
|
3393 default: |
|
3394 return gst_pad_dispatcher |
|
3395 (pad, (GstPadDispatcherFunction) gst_pad_query, query); |
|
3396 } |
|
3397 } |
|
3398 |
|
3399 #ifndef GST_DISABLE_LOADSAVE |
|
3400 /* FIXME: why isn't this on a GstElement ? */ |
|
3401 /** |
|
3402 * gst_pad_load_and_link: |
|
3403 * @self: an #xmlNodePtr to read the description from. |
|
3404 * @parent: the #GstObject element that owns the pad. |
|
3405 * |
|
3406 * Reads the pad definition from the XML node and links the given pad |
|
3407 * in the element to a pad of an element up in the hierarchy. |
|
3408 */ |
|
3409 void |
|
3410 gst_pad_load_and_link (xmlNodePtr self, GstObject * parent) |
|
3411 { |
|
3412 xmlNodePtr field = self->xmlChildrenNode; |
|
3413 GstPad *pad = NULL, *targetpad; |
|
3414 gchar *peer = NULL; |
|
3415 gchar **split; |
|
3416 GstElement *target; |
|
3417 GstObject *grandparent; |
|
3418 gchar *name = NULL; |
|
3419 |
|
3420 while (field) { |
|
3421 if (!strcmp ((char *) field->name, "name")) { |
|
3422 name = (gchar *) xmlNodeGetContent (field); |
|
3423 pad = gst_element_get_pad (GST_ELEMENT (parent), name); |
|
3424 g_free (name); |
|
3425 } else if (!strcmp ((char *) field->name, "peer")) { |
|
3426 peer = (gchar *) xmlNodeGetContent (field); |
|
3427 } |
|
3428 field = field->next; |
|
3429 } |
|
3430 g_return_if_fail (pad != NULL); |
|
3431 |
|
3432 if (peer == NULL) |
|
3433 return; |
|
3434 |
|
3435 split = g_strsplit (peer, ".", 2); |
|
3436 |
|
3437 if (split[0] == NULL || split[1] == NULL) { |
|
3438 GST_CAT_DEBUG_OBJECT (GST_CAT_XML, pad, |
|
3439 "Could not parse peer '%s', leaving unlinked", peer); |
|
3440 |
|
3441 g_free (peer); |
|
3442 return; |
|
3443 } |
|
3444 g_free (peer); |
|
3445 |
|
3446 g_return_if_fail (split[0] != NULL); |
|
3447 g_return_if_fail (split[1] != NULL); |
|
3448 |
|
3449 grandparent = gst_object_get_parent (parent); |
|
3450 |
|
3451 if (grandparent && GST_IS_BIN (grandparent)) { |
|
3452 target = gst_bin_get_by_name_recurse_up (GST_BIN (grandparent), split[0]); |
|
3453 } else |
|
3454 goto cleanup; |
|
3455 |
|
3456 if (target == NULL) |
|
3457 goto cleanup; |
|
3458 |
|
3459 targetpad = gst_element_get_pad (target, split[1]); |
|
3460 |
|
3461 if (targetpad == NULL) |
|
3462 goto cleanup; |
|
3463 |
|
3464 gst_pad_link (pad, targetpad); |
|
3465 |
|
3466 cleanup: |
|
3467 g_strfreev (split); |
|
3468 } |
|
3469 |
|
3470 /** |
|
3471 * gst_pad_save_thyself: |
|
3472 * @pad: a #GstPad to save. |
|
3473 * @parent: the parent #xmlNodePtr to save the description in. |
|
3474 * |
|
3475 * Saves the pad into an xml representation. |
|
3476 * |
|
3477 * Returns: the #xmlNodePtr representation of the pad. |
|
3478 */ |
|
3479 static xmlNodePtr |
|
3480 gst_pad_save_thyself (GstObject * object, xmlNodePtr parent) |
|
3481 { |
|
3482 GstPad *pad; |
|
3483 GstPad *peer; |
|
3484 |
|
3485 g_return_val_if_fail (GST_IS_PAD (object), NULL); |
|
3486 |
|
3487 pad = GST_PAD (object); |
|
3488 |
|
3489 xmlNewChild (parent, NULL, (xmlChar *) "name", |
|
3490 (xmlChar *) GST_PAD_NAME (pad)); |
|
3491 |
|
3492 if (GST_PAD_IS_SRC (pad)) { |
|
3493 xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "source"); |
|
3494 } else if (GST_PAD_IS_SINK (pad)) { |
|
3495 xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "sink"); |
|
3496 } else { |
|
3497 xmlNewChild (parent, NULL, (xmlChar *) "direction", (xmlChar *) "unknown"); |
|
3498 } |
|
3499 |
|
3500 if (GST_PAD_PEER (pad) != NULL) { |
|
3501 gchar *content; |
|
3502 |
|
3503 peer = GST_PAD_PEER (pad); |
|
3504 /* first check to see if the peer's parent's parent is the same */ |
|
3505 /* we just save it off */ |
|
3506 content = g_strdup_printf ("%s.%s", |
|
3507 GST_OBJECT_NAME (GST_PAD_PARENT (peer)), GST_PAD_NAME (peer)); |
|
3508 xmlNewChild (parent, NULL, (xmlChar *) "peer", (xmlChar *) content); |
|
3509 g_free (content); |
|
3510 } else |
|
3511 xmlNewChild (parent, NULL, (xmlChar *) "peer", NULL); |
|
3512 |
|
3513 return parent; |
|
3514 } |
|
3515 |
|
3516 #if 0 |
|
3517 /** |
|
3518 * gst_ghost_pad_save_thyself: |
|
3519 * @pad: a ghost #GstPad to save. |
|
3520 * @parent: the parent #xmlNodePtr to save the description in. |
|
3521 * |
|
3522 * Saves the ghost pad into an xml representation. |
|
3523 * |
|
3524 * Returns: the #xmlNodePtr representation of the pad. |
|
3525 */ |
|
3526 xmlNodePtr |
|
3527 gst_ghost_pad_save_thyself (GstPad * pad, xmlNodePtr parent) |
|
3528 { |
|
3529 xmlNodePtr self; |
|
3530 |
|
3531 g_return_val_if_fail (GST_IS_GHOST_PAD (pad), NULL); |
|
3532 |
|
3533 self = xmlNewChild (parent, NULL, (xmlChar *) "ghostpad", NULL); |
|
3534 xmlNewChild (self, NULL, (xmlChar *) "name", (xmlChar *) GST_PAD_NAME (pad)); |
|
3535 xmlNewChild (self, NULL, (xmlChar *) "parent", |
|
3536 (xmlChar *) GST_OBJECT_NAME (GST_PAD_PARENT (pad))); |
|
3537 |
|
3538 /* FIXME FIXME FIXME! */ |
|
3539 |
|
3540 return self; |
|
3541 } |
|
3542 #endif /* 0 */ |
|
3543 #endif /* GST_DISABLE_LOADSAVE */ |
|
3544 |
|
3545 /* |
|
3546 * should be called with pad OBJECT_LOCK and STREAM_LOCK held. |
|
3547 * GST_PAD_IS_BLOCKED (pad) == TRUE when this function is |
|
3548 * called. |
|
3549 * |
|
3550 * This function performs the pad blocking when an event, buffer push |
|
3551 * or buffer_alloc is performed on a _SRC_ pad. It blocks the |
|
3552 * streaming thread after informing the pad has been blocked. |
|
3553 * |
|
3554 * An application can with this method wait and block any streaming |
|
3555 * thread and perform operations such as seeking or linking. |
|
3556 * |
|
3557 * Two methods are available for notifying the application of the |
|
3558 * block: |
|
3559 * - the callback method, which happens in the STREAMING thread with |
|
3560 * the STREAM_LOCK held. With this method, the most useful way of |
|
3561 * dealing with the callback is to post a message to the main thread |
|
3562 * where the pad block can then be handled outside of the streaming |
|
3563 * thread. With the last method one can perform all operations such |
|
3564 * as doing a state change, linking, unblocking, seeking etc on the |
|
3565 * pad. |
|
3566 * - the GCond signal method, which makes any thread unblock when |
|
3567 * the pad block happens. |
|
3568 * |
|
3569 * During the actual blocking state, the GST_PAD_BLOCKING flag is set. |
|
3570 * The GST_PAD_BLOCKING flag is unset when the pad was unblocked. |
|
3571 * |
|
3572 * MT safe. |
|
3573 */ |
|
3574 static GstFlowReturn |
|
3575 handle_pad_block (GstPad * pad) |
|
3576 { |
|
3577 GstPadBlockCallback callback; |
|
3578 gpointer user_data; |
|
3579 GstFlowReturn ret = GST_FLOW_OK; |
|
3580 |
|
3581 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "signal block taken"); |
|
3582 |
|
3583 /* flushing, don't bother trying to block and return WRONG_STATE |
|
3584 * right away */ |
|
3585 if (GST_PAD_IS_FLUSHING (pad)) |
|
3586 goto flushingnonref; |
|
3587 |
|
3588 /* we grab an extra ref for the callbacks, this is probably not |
|
3589 * needed (callback code does not have a ref and cannot unref). I |
|
3590 * think this was done to make it possible to unref the element in |
|
3591 * the callback, which is in the end totally impossible as it |
|
3592 * requires grabbing the STREAM_LOCK and OBJECT_LOCK which are |
|
3593 * all taken when calling this function. */ |
|
3594 gst_object_ref (pad); |
|
3595 |
|
3596 /* we either have a callback installed to notify the block or |
|
3597 * some other thread is doing a GCond wait. */ |
|
3598 callback = pad->block_callback; |
|
3599 if (callback) { |
|
3600 /* there is a callback installed, call it. We release the |
|
3601 * lock so that the callback can do something usefull with the |
|
3602 * pad */ |
|
3603 user_data = pad->block_data; |
|
3604 GST_OBJECT_UNLOCK (pad); |
|
3605 callback (pad, TRUE, user_data); |
|
3606 GST_OBJECT_LOCK (pad); |
|
3607 |
|
3608 /* we released the lock, recheck flushing */ |
|
3609 if (GST_PAD_IS_FLUSHING (pad)) |
|
3610 goto flushing; |
|
3611 } else { |
|
3612 /* no callback, signal the thread that is doing a GCond wait |
|
3613 * if any. */ |
|
3614 GST_PAD_BLOCK_BROADCAST (pad); |
|
3615 } |
|
3616 |
|
3617 /* OBJECT_LOCK could have been released when we did the callback, which |
|
3618 * then could have made the pad unblock so we need to check the blocking |
|
3619 * condition again. */ |
|
3620 while (GST_PAD_IS_BLOCKED (pad)) { |
|
3621 /* now we block the streaming thread. It can be unlocked when we |
|
3622 * deactivate the pad (which will also set the FLUSHING flag) or |
|
3623 * when the pad is unblocked. A flushing event will also unblock |
|
3624 * the pad after setting the FLUSHING flag. */ |
|
3625 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3626 "Waiting to be unblocked or set flushing"); |
|
3627 GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKING); |
|
3628 GST_PAD_BLOCK_WAIT (pad); |
|
3629 GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKING); |
|
3630 |
|
3631 /* see if we got unblocked by a flush or not */ |
|
3632 if (GST_PAD_IS_FLUSHING (pad)) |
|
3633 goto flushing; |
|
3634 } |
|
3635 |
|
3636 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "got unblocked"); |
|
3637 |
|
3638 /* when we get here, the pad is unblocked again and we perform |
|
3639 * the needed unblock code. */ |
|
3640 callback = pad->block_callback; |
|
3641 if (callback) { |
|
3642 /* we need to call the callback */ |
|
3643 user_data = pad->block_data; |
|
3644 GST_OBJECT_UNLOCK (pad); |
|
3645 callback (pad, FALSE, user_data); |
|
3646 GST_OBJECT_LOCK (pad); |
|
3647 } else { |
|
3648 /* we need to signal the thread waiting on the GCond */ |
|
3649 GST_PAD_BLOCK_BROADCAST (pad); |
|
3650 } |
|
3651 |
|
3652 gst_object_unref (pad); |
|
3653 |
|
3654 return ret; |
|
3655 |
|
3656 flushingnonref: |
|
3657 { |
|
3658 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pad was flushing"); |
|
3659 return GST_FLOW_WRONG_STATE; |
|
3660 } |
|
3661 flushing: |
|
3662 { |
|
3663 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "pad became flushing"); |
|
3664 gst_object_unref (pad); |
|
3665 return GST_FLOW_WRONG_STATE; |
|
3666 } |
|
3667 } |
|
3668 |
|
3669 /********************************************************************** |
|
3670 * Data passing functions |
|
3671 */ |
|
3672 |
|
3673 static gboolean |
|
3674 gst_pad_emit_have_data_signal (GstPad * pad, GstMiniObject * obj) |
|
3675 { |
|
3676 GValue ret = { 0 }; |
|
3677 GValue args[2] = { {0}, {0} }; |
|
3678 gboolean res; |
|
3679 GQuark detail; |
|
3680 |
|
3681 /* init */ |
|
3682 g_value_init (&ret, G_TYPE_BOOLEAN); |
|
3683 g_value_set_boolean (&ret, TRUE); |
|
3684 g_value_init (&args[0], GST_TYPE_PAD); |
|
3685 g_value_set_object (&args[0], pad); |
|
3686 g_value_init (&args[1], GST_TYPE_MINI_OBJECT); |
|
3687 gst_value_set_mini_object (&args[1], obj); |
|
3688 |
|
3689 if (GST_IS_EVENT (obj)) |
|
3690 detail = event_quark; |
|
3691 else |
|
3692 detail = buffer_quark; |
|
3693 |
|
3694 /* actually emit */ |
|
3695 g_signal_emitv (args, gst_pad_signals[PAD_HAVE_DATA], detail, &ret); |
|
3696 res = g_value_get_boolean (&ret); |
|
3697 |
|
3698 /* clean up */ |
|
3699 g_value_unset (&ret); |
|
3700 g_value_unset (&args[0]); |
|
3701 g_value_unset (&args[1]); |
|
3702 |
|
3703 return res; |
|
3704 } |
|
3705 |
|
3706 /* this is the chain function that does not perform the additional argument |
|
3707 * checking for that little extra speed. |
|
3708 */ |
|
3709 static inline GstFlowReturn |
|
3710 gst_pad_chain_unchecked (GstPad * pad, GstBuffer * buffer) |
|
3711 { |
|
3712 GstCaps *caps; |
|
3713 gboolean caps_changed; |
|
3714 GstPadChainFunction chainfunc; |
|
3715 GstFlowReturn ret; |
|
3716 gboolean emit_signal; |
|
3717 |
|
3718 GST_PAD_STREAM_LOCK (pad); |
|
3719 |
|
3720 GST_OBJECT_LOCK (pad); |
|
3721 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
|
3722 goto flushing; |
|
3723 |
|
3724 caps = GST_BUFFER_CAPS (buffer); |
|
3725 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
3726 |
|
3727 emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; |
|
3728 GST_OBJECT_UNLOCK (pad); |
|
3729 |
|
3730 /* see if the signal should be emited, we emit before caps nego as |
|
3731 * we might drop the buffer and do capsnego for nothing. */ |
|
3732 if (G_UNLIKELY (emit_signal)) { |
|
3733 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer))) |
|
3734 goto dropping; |
|
3735 } |
|
3736 |
|
3737 /* we got a new datatype on the pad, see if it can handle it */ |
|
3738 if (G_UNLIKELY (caps_changed)) { |
|
3739 GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps); |
|
3740 if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps))) |
|
3741 goto not_negotiated; |
|
3742 } |
|
3743 |
|
3744 /* NOTE: we read the chainfunc unlocked. |
|
3745 * we cannot hold the lock for the pad so we might send |
|
3746 * the data to the wrong function. This is not really a |
|
3747 * problem since functions are assigned at creation time |
|
3748 * and don't change that often... */ |
|
3749 if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL)) |
|
3750 goto no_function; |
|
3751 |
|
3752 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3753 "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc)); |
|
3754 |
|
3755 ret = chainfunc (pad, buffer); |
|
3756 |
|
3757 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3758 "called chainfunction &%s, returned %s", |
|
3759 GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret)); |
|
3760 |
|
3761 GST_PAD_STREAM_UNLOCK (pad); |
|
3762 |
|
3763 return ret; |
|
3764 |
|
3765 /* ERRORS */ |
|
3766 flushing: |
|
3767 { |
|
3768 gst_buffer_unref (buffer); |
|
3769 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3770 "pushing, but pad was flushing"); |
|
3771 GST_OBJECT_UNLOCK (pad); |
|
3772 GST_PAD_STREAM_UNLOCK (pad); |
|
3773 return GST_FLOW_WRONG_STATE; |
|
3774 } |
|
3775 dropping: |
|
3776 { |
|
3777 gst_buffer_unref (buffer); |
|
3778 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
|
3779 GST_PAD_STREAM_UNLOCK (pad); |
|
3780 return GST_FLOW_OK; |
|
3781 } |
|
3782 not_negotiated: |
|
3783 { |
|
3784 gst_buffer_unref (buffer); |
|
3785 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3786 "pushing buffer but pad did not accept"); |
|
3787 GST_PAD_STREAM_UNLOCK (pad); |
|
3788 return GST_FLOW_NOT_NEGOTIATED; |
|
3789 } |
|
3790 no_function: |
|
3791 { |
|
3792 gst_buffer_unref (buffer); |
|
3793 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3794 "pushing, but not chainhandler"); |
|
3795 GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), |
|
3796 ("push on pad %s:%s but it has no chainfunction", |
|
3797 GST_DEBUG_PAD_NAME (pad))); |
|
3798 GST_PAD_STREAM_UNLOCK (pad); |
|
3799 return GST_FLOW_NOT_SUPPORTED; |
|
3800 } |
|
3801 } |
|
3802 |
|
3803 /** |
|
3804 * gst_pad_chain: |
|
3805 * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. |
|
3806 * @buffer: the #GstBuffer to send, return GST_FLOW_ERROR if not. |
|
3807 * |
|
3808 * Chain a buffer to @pad. |
|
3809 * |
|
3810 * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing. |
|
3811 * |
|
3812 * If the caps on @buffer are different from the current caps on @pad, this |
|
3813 * function will call any setcaps function (see gst_pad_set_setcaps_function()) |
|
3814 * installed on @pad. If the new caps are not acceptable for @pad, this |
|
3815 * function returns #GST_FLOW_NOT_NEGOTIATED. |
|
3816 * |
|
3817 * The function proceeds calling the chain function installed on @pad (see |
|
3818 * gst_pad_set_chain_function()) and the return value of that function is |
|
3819 * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no |
|
3820 * chain function. |
|
3821 * |
|
3822 * In all cases, success or failure, the caller loses its reference to @buffer |
|
3823 * after calling this function. |
|
3824 * |
|
3825 * Returns: a #GstFlowReturn from the pad. |
|
3826 * |
|
3827 * MT safe. |
|
3828 */ |
|
3829 #ifdef __SYMBIAN32__ |
|
3830 EXPORT_C |
|
3831 #endif |
|
3832 |
|
3833 GstFlowReturn |
|
3834 gst_pad_chain (GstPad * pad, GstBuffer * buffer) |
|
3835 { |
|
3836 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
3837 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, |
|
3838 GST_FLOW_ERROR); |
|
3839 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
|
3840 |
|
3841 return gst_pad_chain_unchecked (pad, buffer); |
|
3842 } |
|
3843 |
|
3844 /** |
|
3845 * gst_pad_push: |
|
3846 * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not. |
|
3847 * @buffer: the #GstBuffer to push returns GST_FLOW_ERROR if not. |
|
3848 * |
|
3849 * Pushes a buffer to the peer of @pad. |
|
3850 * |
|
3851 * This function will call an installed pad block before triggering any |
|
3852 * installed pad probes. |
|
3853 * |
|
3854 * If the caps on @buffer are different from the currently configured caps on |
|
3855 * @pad, this function will call any installed setcaps function on @pad (see |
|
3856 * gst_pad_set_setcaps_function()). In case of failure to renegotiate the new |
|
3857 * format, this function returns #GST_FLOW_NOT_NEGOTIATED. |
|
3858 * |
|
3859 * The function proceeds calling gst_pad_chain() on the peer pad and returns |
|
3860 * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will |
|
3861 * be returned. |
|
3862 * |
|
3863 * In all cases, success or failure, the caller loses its reference to @buffer |
|
3864 * after calling this function. |
|
3865 * |
|
3866 * Returns: a #GstFlowReturn from the peer pad. |
|
3867 * |
|
3868 * MT safe. |
|
3869 */ |
|
3870 #ifdef __SYMBIAN32__ |
|
3871 EXPORT_C |
|
3872 #endif |
|
3873 GstFlowReturn |
|
3874 gst_pad_push (GstPad * pad, GstBuffer * buffer) |
|
3875 { |
|
3876 GstPad *peer; |
|
3877 GstFlowReturn ret; |
|
3878 |
|
3879 GstCaps *caps; |
|
3880 gboolean caps_changed; |
|
3881 |
|
3882 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
3883 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR); |
|
3884 g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); |
|
3885 |
|
3886 GST_OBJECT_LOCK (pad); |
|
3887 |
|
3888 /* FIXME: this check can go away; pad_set_blocked could be implemented with |
|
3889 * probes completely or probes with an extended pad block. */ |
|
3890 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
|
3891 if ((ret = handle_pad_block (pad)) != GST_FLOW_OK) |
|
3892 goto flushed; |
|
3893 |
|
3894 /* we emit signals on the pad arg, the peer will have a chance to |
|
3895 * emit in the _chain() function */ |
|
3896 if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) { |
|
3897 /* unlock before emitting */ |
|
3898 GST_OBJECT_UNLOCK (pad); |
|
3899 |
|
3900 /* if the signal handler returned FALSE, it means we should just drop the |
|
3901 * buffer */ |
|
3902 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer))) |
|
3903 goto dropped; |
|
3904 |
|
3905 GST_OBJECT_LOCK (pad); |
|
3906 } |
|
3907 |
|
3908 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
|
3909 goto not_linked; |
|
3910 |
|
3911 /* take ref to peer pad before releasing the lock */ |
|
3912 gst_object_ref (peer); |
|
3913 |
|
3914 /* Before pushing the buffer to the peer pad, ensure that caps |
|
3915 * are set on this pad */ |
|
3916 caps = GST_BUFFER_CAPS (buffer); |
|
3917 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
3918 |
|
3919 GST_OBJECT_UNLOCK (pad); |
|
3920 |
|
3921 /* we got a new datatype from the pad, it had better handle it */ |
|
3922 if (G_UNLIKELY (caps_changed)) { |
|
3923 GST_DEBUG_OBJECT (pad, |
|
3924 "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT, |
|
3925 GST_PAD_CAPS (pad), caps, caps); |
|
3926 if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE))) |
|
3927 goto not_negotiated; |
|
3928 } |
|
3929 |
|
3930 ret = gst_pad_chain_unchecked (peer, buffer); |
|
3931 |
|
3932 gst_object_unref (peer); |
|
3933 |
|
3934 return ret; |
|
3935 |
|
3936 /* ERROR recovery here */ |
|
3937 flushed: |
|
3938 { |
|
3939 gst_buffer_unref (buffer); |
|
3940 GST_DEBUG_OBJECT (pad, "pad block stopped by flush"); |
|
3941 GST_OBJECT_UNLOCK (pad); |
|
3942 return ret; |
|
3943 } |
|
3944 dropped: |
|
3945 { |
|
3946 gst_buffer_unref (buffer); |
|
3947 GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); |
|
3948 return GST_FLOW_OK; |
|
3949 } |
|
3950 not_linked: |
|
3951 { |
|
3952 gst_buffer_unref (buffer); |
|
3953 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3954 "pushing, but it was not linked"); |
|
3955 GST_OBJECT_UNLOCK (pad); |
|
3956 return GST_FLOW_NOT_LINKED; |
|
3957 } |
|
3958 not_negotiated: |
|
3959 { |
|
3960 gst_buffer_unref (buffer); |
|
3961 gst_object_unref (peer); |
|
3962 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
3963 "element pushed buffer then refused to accept the caps"); |
|
3964 return GST_FLOW_NOT_NEGOTIATED; |
|
3965 } |
|
3966 } |
|
3967 |
|
3968 /** |
|
3969 * gst_pad_check_pull_range: |
|
3970 * @pad: a sink #GstPad. |
|
3971 * |
|
3972 * Checks if a gst_pad_pull_range() can be performed on the peer |
|
3973 * source pad. This function is used by plugins that want to check |
|
3974 * if they can use random access on the peer source pad. |
|
3975 * |
|
3976 * The peer sourcepad can implement a custom #GstPadCheckGetRangeFunction |
|
3977 * if it needs to perform some logic to determine if pull_range is |
|
3978 * possible. |
|
3979 * |
|
3980 * Returns: a gboolean with the result. |
|
3981 * |
|
3982 * MT safe. |
|
3983 */ |
|
3984 #ifdef __SYMBIAN32__ |
|
3985 EXPORT_C |
|
3986 #endif |
|
3987 |
|
3988 gboolean |
|
3989 gst_pad_check_pull_range (GstPad * pad) |
|
3990 { |
|
3991 GstPad *peer; |
|
3992 gboolean ret; |
|
3993 GstPadCheckGetRangeFunction checkgetrangefunc; |
|
3994 |
|
3995 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
3996 |
|
3997 GST_OBJECT_LOCK (pad); |
|
3998 if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK) |
|
3999 goto wrong_direction; |
|
4000 |
|
4001 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
|
4002 goto not_connected; |
|
4003 |
|
4004 gst_object_ref (peer); |
|
4005 GST_OBJECT_UNLOCK (pad); |
|
4006 |
|
4007 /* see note in above function */ |
|
4008 if (G_LIKELY ((checkgetrangefunc = peer->checkgetrangefunc) == NULL)) { |
|
4009 /* FIXME, kindoff ghetto */ |
|
4010 ret = GST_PAD_GETRANGEFUNC (peer) != NULL; |
|
4011 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4012 "no checkgetrangefunc, assuming %d", ret); |
|
4013 } else { |
|
4014 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4015 "calling checkgetrangefunc %s of peer pad %s:%s", |
|
4016 GST_DEBUG_FUNCPTR_NAME (checkgetrangefunc), GST_DEBUG_PAD_NAME (peer)); |
|
4017 |
|
4018 ret = checkgetrangefunc (peer); |
|
4019 } |
|
4020 |
|
4021 gst_object_unref (peer); |
|
4022 |
|
4023 return ret; |
|
4024 |
|
4025 /* ERROR recovery here */ |
|
4026 wrong_direction: |
|
4027 { |
|
4028 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4029 "checking pull range, but pad must be a sinkpad"); |
|
4030 GST_OBJECT_UNLOCK (pad); |
|
4031 return FALSE; |
|
4032 } |
|
4033 not_connected: |
|
4034 { |
|
4035 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4036 "checking pull range, but it was not linked"); |
|
4037 GST_OBJECT_UNLOCK (pad); |
|
4038 return FALSE; |
|
4039 } |
|
4040 } |
|
4041 |
|
4042 /** |
|
4043 * gst_pad_get_range: |
|
4044 * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not. |
|
4045 * @offset: The start offset of the buffer |
|
4046 * @size: The length of the buffer |
|
4047 * @buffer: a pointer to hold the #GstBuffer, returns #GST_FLOW_ERROR if %NULL. |
|
4048 * |
|
4049 * When @pad is flushing this function returns #GST_FLOW_WRONG_STATE |
|
4050 * immediatly. |
|
4051 * |
|
4052 * Calls the getrange function of @pad, see #GstPadGetRangeFunction for a |
|
4053 * description of a getrange function. If @pad has no getrange function |
|
4054 * installed (see gst_pad_set_getrange_function()) this function returns |
|
4055 * #GST_FLOW_NOT_SUPPORTED. |
|
4056 * |
|
4057 * @buffer's caps must either be unset or the same as what is already |
|
4058 * configured on @pad. Renegotiation within a running pull-mode pipeline is not |
|
4059 * supported. |
|
4060 * |
|
4061 * This is a lowlevel function. Usualy gst_pad_pull_range() is used. |
|
4062 * |
|
4063 * Returns: a #GstFlowReturn from the pad. |
|
4064 * |
|
4065 * MT safe. |
|
4066 */ |
|
4067 #ifdef __SYMBIAN32__ |
|
4068 EXPORT_C |
|
4069 #endif |
|
4070 |
|
4071 GstFlowReturn |
|
4072 gst_pad_get_range (GstPad * pad, guint64 offset, guint size, |
|
4073 GstBuffer ** buffer) |
|
4074 { |
|
4075 GstFlowReturn ret; |
|
4076 GstPadGetRangeFunction getrangefunc; |
|
4077 gboolean emit_signal; |
|
4078 |
|
4079 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
4080 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR); |
|
4081 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
|
4082 |
|
4083 GST_PAD_STREAM_LOCK (pad); |
|
4084 |
|
4085 GST_OBJECT_LOCK (pad); |
|
4086 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
|
4087 goto flushing; |
|
4088 |
|
4089 emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; |
|
4090 GST_OBJECT_UNLOCK (pad); |
|
4091 |
|
4092 if (G_UNLIKELY ((getrangefunc = GST_PAD_GETRANGEFUNC (pad)) == NULL)) |
|
4093 goto no_function; |
|
4094 |
|
4095 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4096 "calling getrangefunc %s, offset %" |
|
4097 G_GUINT64_FORMAT ", size %u", |
|
4098 GST_DEBUG_FUNCPTR_NAME (getrangefunc), offset, size); |
|
4099 |
|
4100 ret = getrangefunc (pad, offset, size, buffer); |
|
4101 |
|
4102 /* can only fire the signal if we have a valid buffer */ |
|
4103 if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) { |
|
4104 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer))) |
|
4105 goto dropping; |
|
4106 } |
|
4107 |
|
4108 GST_PAD_STREAM_UNLOCK (pad); |
|
4109 |
|
4110 if (G_LIKELY (ret == GST_FLOW_OK)) { |
|
4111 GstCaps *caps; |
|
4112 gboolean caps_changed; |
|
4113 |
|
4114 GST_OBJECT_LOCK (pad); |
|
4115 /* Before pushing the buffer to the peer pad, ensure that caps |
|
4116 * are set on this pad */ |
|
4117 caps = GST_BUFFER_CAPS (*buffer); |
|
4118 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
4119 GST_OBJECT_UNLOCK (pad); |
|
4120 |
|
4121 /* we got a new datatype from the pad not supported in a running pull-mode |
|
4122 * pipeline */ |
|
4123 if (G_UNLIKELY (caps_changed)) |
|
4124 goto not_negotiated; |
|
4125 } |
|
4126 |
|
4127 return ret; |
|
4128 |
|
4129 /* ERRORS */ |
|
4130 flushing: |
|
4131 { |
|
4132 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4133 "pulling range, but pad was flushing"); |
|
4134 GST_OBJECT_UNLOCK (pad); |
|
4135 GST_PAD_STREAM_UNLOCK (pad); |
|
4136 return GST_FLOW_WRONG_STATE; |
|
4137 } |
|
4138 no_function: |
|
4139 { |
|
4140 GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL), |
|
4141 ("pullrange on pad %s:%s but it has no getrangefunction", |
|
4142 GST_DEBUG_PAD_NAME (pad))); |
|
4143 GST_PAD_STREAM_UNLOCK (pad); |
|
4144 return GST_FLOW_NOT_SUPPORTED; |
|
4145 } |
|
4146 dropping: |
|
4147 { |
|
4148 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4149 "Dropping data after FALSE probe return"); |
|
4150 GST_PAD_STREAM_UNLOCK (pad); |
|
4151 gst_buffer_unref (*buffer); |
|
4152 *buffer = NULL; |
|
4153 return GST_FLOW_UNEXPECTED; |
|
4154 } |
|
4155 not_negotiated: |
|
4156 { |
|
4157 /* ideally we want to use the commented-out code, but currently demuxers |
|
4158 * and typefind do not follow part-negotiation.txt. When switching into |
|
4159 * pull mode, typefind should probably return the found caps from |
|
4160 * getcaps(), and demuxers should do the setcaps(). */ |
|
4161 |
|
4162 #if 0 |
|
4163 gst_buffer_unref (*buffer); |
|
4164 *buffer = NULL; |
|
4165 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4166 "getrange returned buffer of different caps"); |
|
4167 return GST_FLOW_NOT_NEGOTIATED; |
|
4168 #endif |
|
4169 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4170 "getrange returned buffer of different caps"); |
|
4171 return ret; |
|
4172 } |
|
4173 } |
|
4174 |
|
4175 |
|
4176 /** |
|
4177 * gst_pad_pull_range: |
|
4178 * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not. |
|
4179 * @offset: The start offset of the buffer |
|
4180 * @size: The length of the buffer |
|
4181 * @buffer: a pointer to hold the #GstBuffer, returns GST_FLOW_ERROR if %NULL. |
|
4182 * |
|
4183 * Pulls a @buffer from the peer pad. |
|
4184 * |
|
4185 * This function will first trigger the pad block signal if it was |
|
4186 * installed. |
|
4187 * |
|
4188 * When @pad is not linked #GST_FLOW_NOT_LINKED is returned else this |
|
4189 * function returns the result of gst_pad_get_range() on the peer pad. |
|
4190 * See gst_pad_get_range() for a list of return values and for the |
|
4191 * semantics of the arguments of this function. |
|
4192 * |
|
4193 * @buffer's caps must either be unset or the same as what is already |
|
4194 * configured on @pad. Renegotiation within a running pull-mode pipeline is not |
|
4195 * supported. |
|
4196 * |
|
4197 * Returns: a #GstFlowReturn from the peer pad. |
|
4198 * When this function returns #GST_FLOW_OK, @buffer will contain a valid |
|
4199 * #GstBuffer that should be freed with gst_buffer_unref() after usage. |
|
4200 * @buffer may not be used or freed when any other return value than |
|
4201 * #GST_FLOW_OK is returned. |
|
4202 * |
|
4203 * MT safe. |
|
4204 */ |
|
4205 #ifdef __SYMBIAN32__ |
|
4206 EXPORT_C |
|
4207 #endif |
|
4208 |
|
4209 GstFlowReturn |
|
4210 gst_pad_pull_range (GstPad * pad, guint64 offset, guint size, |
|
4211 GstBuffer ** buffer) |
|
4212 { |
|
4213 GstPad *peer; |
|
4214 GstFlowReturn ret; |
|
4215 gboolean emit_signal; |
|
4216 |
|
4217 g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); |
|
4218 g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK, |
|
4219 GST_FLOW_ERROR); |
|
4220 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); |
|
4221 |
|
4222 GST_OBJECT_LOCK (pad); |
|
4223 |
|
4224 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) |
|
4225 handle_pad_block (pad); |
|
4226 |
|
4227 if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) |
|
4228 goto not_connected; |
|
4229 |
|
4230 /* signal emision for the pad, peer has chance to emit when |
|
4231 * we call _get_range() */ |
|
4232 emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; |
|
4233 |
|
4234 gst_object_ref (peer); |
|
4235 GST_OBJECT_UNLOCK (pad); |
|
4236 |
|
4237 ret = gst_pad_get_range (peer, offset, size, buffer); |
|
4238 |
|
4239 gst_object_unref (peer); |
|
4240 |
|
4241 /* can only fire the signal if we have a valid buffer */ |
|
4242 if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) { |
|
4243 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer))) |
|
4244 goto dropping; |
|
4245 } |
|
4246 |
|
4247 if (G_LIKELY (ret == GST_FLOW_OK)) { |
|
4248 GstCaps *caps; |
|
4249 gboolean caps_changed; |
|
4250 |
|
4251 GST_OBJECT_LOCK (pad); |
|
4252 /* Before pushing the buffer to the peer pad, ensure that caps |
|
4253 * are set on this pad */ |
|
4254 caps = GST_BUFFER_CAPS (*buffer); |
|
4255 caps_changed = caps && caps != GST_PAD_CAPS (pad); |
|
4256 GST_OBJECT_UNLOCK (pad); |
|
4257 |
|
4258 /* we got a new datatype on the pad, see if it can handle it */ |
|
4259 if (G_UNLIKELY (caps_changed)) |
|
4260 goto not_negotiated; |
|
4261 } |
|
4262 |
|
4263 return ret; |
|
4264 |
|
4265 /* ERROR recovery here */ |
|
4266 not_connected: |
|
4267 { |
|
4268 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4269 "pulling range, but it was not linked"); |
|
4270 GST_OBJECT_UNLOCK (pad); |
|
4271 return GST_FLOW_NOT_LINKED; |
|
4272 } |
|
4273 dropping: |
|
4274 { |
|
4275 GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4276 "Dropping data after FALSE probe return"); |
|
4277 gst_buffer_unref (*buffer); |
|
4278 *buffer = NULL; |
|
4279 return GST_FLOW_UNEXPECTED; |
|
4280 } |
|
4281 not_negotiated: |
|
4282 { |
|
4283 /* ideally we want to use the commented-out code, but currently demuxers |
|
4284 * and typefind do not follow part-negotiation.txt. When switching into |
|
4285 * pull mode, typefind should probably return the found caps from |
|
4286 * getcaps(), and demuxers should do the setcaps(). */ |
|
4287 |
|
4288 #if 0 |
|
4289 gst_buffer_unref (*buffer); |
|
4290 *buffer = NULL; |
|
4291 GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4292 "pullrange returned buffer of different caps"); |
|
4293 return GST_FLOW_NOT_NEGOTIATED; |
|
4294 #endif |
|
4295 GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad, |
|
4296 "pullrange returned buffer of different caps"); |
|
4297 return ret; |
|
4298 } |
|
4299 } |
|
4300 |
|
4301 /** |
|
4302 * gst_pad_push_event: |
|
4303 * @pad: a #GstPad to push the event to. |
|
4304 * @event: the #GstEvent to send to the pad. |
|
4305 * |
|
4306 * Sends the event to the peer of the given pad. This function is |
|
4307 * mainly used by elements to send events to their peer |
|
4308 * elements. |
|
4309 * |
|
4310 * This function takes owership of the provided event so you should |
|
4311 * gst_event_ref() it if you want to reuse the event after this call. |
|
4312 * |
|
4313 * Returns: TRUE if the event was handled. |
|
4314 * |
|
4315 * MT safe. |
|
4316 */ |
|
4317 #ifdef __SYMBIAN32__ |
|
4318 EXPORT_C |
|
4319 #endif |
|
4320 |
|
4321 gboolean |
|
4322 gst_pad_push_event (GstPad * pad, GstEvent * event) |
|
4323 { |
|
4324 GstPad *peerpad; |
|
4325 gboolean result; |
|
4326 |
|
4327 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
4328 g_return_val_if_fail (event != NULL, FALSE); |
|
4329 g_return_val_if_fail (GST_IS_EVENT (event), FALSE); |
|
4330 |
|
4331 GST_LOG_OBJECT (pad, "event: %s", GST_EVENT_TYPE_NAME (event)); |
|
4332 |
|
4333 GST_OBJECT_LOCK (pad); |
|
4334 |
|
4335 /* Two checks to be made: |
|
4336 * . (un)set the FLUSHING flag for flushing events, |
|
4337 * . handle pad blocking */ |
|
4338 switch (GST_EVENT_TYPE (event)) { |
|
4339 case GST_EVENT_FLUSH_START: |
|
4340 GST_PAD_SET_FLUSHING (pad); |
|
4341 |
|
4342 if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) { |
|
4343 /* flush start will have set the FLUSHING flag and will then |
|
4344 * unlock all threads doing a GCond wait on the blocking pad. This |
|
4345 * will typically unblock the STREAMING thread blocked on a pad. */ |
|
4346 GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-start, " |
|
4347 "doing block signal."); |
|
4348 GST_PAD_BLOCK_BROADCAST (pad); |
|
4349 goto flushed; |
|
4350 } |
|
4351 break; |
|
4352 case GST_EVENT_FLUSH_STOP: |
|
4353 GST_PAD_UNSET_FLUSHING (pad); |
|
4354 |
|
4355 /* if we are blocked, flush away the FLUSH_STOP event */ |
|
4356 if (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) { |
|
4357 GST_LOG_OBJECT (pad, "Pad is blocked, not forwarding flush-stop"); |
|
4358 goto flushed; |
|
4359 } |
|
4360 break; |
|
4361 default: |
|
4362 while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad))) { |
|
4363 /* block the event as long as the pad is blocked */ |
|
4364 if (handle_pad_block (pad) != GST_FLOW_OK) |
|
4365 goto flushed; |
|
4366 } |
|
4367 break; |
|
4368 } |
|
4369 |
|
4370 if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) { |
|
4371 GST_OBJECT_UNLOCK (pad); |
|
4372 |
|
4373 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event))) |
|
4374 goto dropping; |
|
4375 |
|
4376 GST_OBJECT_LOCK (pad); |
|
4377 } |
|
4378 peerpad = GST_PAD_PEER (pad); |
|
4379 if (peerpad == NULL) |
|
4380 goto not_linked; |
|
4381 |
|
4382 GST_LOG_OBJECT (pad, "sending event %s to peerpad %" GST_PTR_FORMAT, |
|
4383 GST_EVENT_TYPE_NAME (event), peerpad); |
|
4384 gst_object_ref (peerpad); |
|
4385 GST_OBJECT_UNLOCK (pad); |
|
4386 |
|
4387 result = gst_pad_send_event (peerpad, event); |
|
4388 |
|
4389 /* Note: we gave away ownership of the event at this point */ |
|
4390 GST_LOG_OBJECT (pad, "sent event to peerpad %" GST_PTR_FORMAT ", result %d", |
|
4391 peerpad, result); |
|
4392 gst_object_unref (peerpad); |
|
4393 |
|
4394 return result; |
|
4395 |
|
4396 /* ERROR handling */ |
|
4397 dropping: |
|
4398 { |
|
4399 GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return"); |
|
4400 gst_event_unref (event); |
|
4401 return FALSE; |
|
4402 } |
|
4403 not_linked: |
|
4404 { |
|
4405 GST_DEBUG_OBJECT (pad, "Dropping event because pad is not linked"); |
|
4406 gst_event_unref (event); |
|
4407 GST_OBJECT_UNLOCK (pad); |
|
4408 return FALSE; |
|
4409 } |
|
4410 flushed: |
|
4411 { |
|
4412 GST_DEBUG_OBJECT (pad, |
|
4413 "Not forwarding event since we're flushing and blocking"); |
|
4414 gst_event_unref (event); |
|
4415 GST_OBJECT_UNLOCK (pad); |
|
4416 return TRUE; |
|
4417 } |
|
4418 } |
|
4419 |
|
4420 /** |
|
4421 * gst_pad_send_event: |
|
4422 * @pad: a #GstPad to send the event to. |
|
4423 * @event: the #GstEvent to send to the pad. |
|
4424 * |
|
4425 * Sends the event to the pad. This function can be used |
|
4426 * by applications to send events in the pipeline. |
|
4427 * |
|
4428 * If @pad is a source pad, @event should be an upstream event. If @pad is a |
|
4429 * sink pad, @event should be a downstream event. For example, you would not |
|
4430 * send a #GST_EVENT_EOS on a src pad; EOS events only propagate downstream. |
|
4431 * Furthermore, some downstream events have to be serialized with data flow, |
|
4432 * like EOS, while some can travel out-of-band, like #GST_EVENT_FLUSH_START. If |
|
4433 * the event needs to be serialized with data flow, this function will take the |
|
4434 * pad's stream lock while calling its event function. |
|
4435 * |
|
4436 * To find out whether an event type is upstream, downstream, or downstream and |
|
4437 * serialized, see #GstEventTypeFlags, gst_event_type_get_flags(), |
|
4438 * #GST_EVENT_IS_UPSTREAM, #GST_EVENT_IS_DOWNSTREAM, and |
|
4439 * #GST_EVENT_IS_SERIALIZED. Note that in practice that an application or |
|
4440 * plugin doesn't need to bother itself with this information; the core handles |
|
4441 * all necessary locks and checks. |
|
4442 * |
|
4443 * This function takes owership of the provided event so you should |
|
4444 * gst_event_ref() it if you want to reuse the event after this call. |
|
4445 * |
|
4446 * Returns: TRUE if the event was handled. |
|
4447 */ |
|
4448 #ifdef __SYMBIAN32__ |
|
4449 EXPORT_C |
|
4450 #endif |
|
4451 |
|
4452 gboolean |
|
4453 gst_pad_send_event (GstPad * pad, GstEvent * event) |
|
4454 { |
|
4455 gboolean result = FALSE; |
|
4456 GstPadEventFunction eventfunc; |
|
4457 gboolean serialized, need_unlock = FALSE; |
|
4458 |
|
4459 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
4460 g_return_val_if_fail (event != NULL, FALSE); |
|
4461 |
|
4462 GST_OBJECT_LOCK (pad); |
|
4463 if (GST_PAD_IS_SINK (pad)) { |
|
4464 if (G_UNLIKELY (!GST_EVENT_IS_DOWNSTREAM (event))) |
|
4465 goto wrong_direction; |
|
4466 serialized = GST_EVENT_IS_SERIALIZED (event); |
|
4467 } else if (GST_PAD_IS_SRC (pad)) { |
|
4468 if (G_UNLIKELY (!GST_EVENT_IS_UPSTREAM (event))) |
|
4469 goto wrong_direction; |
|
4470 /* events on srcpad never are serialized */ |
|
4471 serialized = FALSE; |
|
4472 } else |
|
4473 goto unknown_direction; |
|
4474 |
|
4475 if (G_UNLIKELY (GST_EVENT_SRC (event) == NULL)) { |
|
4476 GST_LOG_OBJECT (pad, "event had no source, setting pad as event source"); |
|
4477 GST_EVENT_SRC (event) = gst_object_ref (pad); |
|
4478 } |
|
4479 |
|
4480 /* pad signals */ |
|
4481 if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) { |
|
4482 GST_OBJECT_UNLOCK (pad); |
|
4483 |
|
4484 if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT_CAST (event))) |
|
4485 goto dropping; |
|
4486 |
|
4487 GST_OBJECT_LOCK (pad); |
|
4488 } |
|
4489 |
|
4490 switch (GST_EVENT_TYPE (event)) { |
|
4491 case GST_EVENT_FLUSH_START: |
|
4492 GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, |
|
4493 "have event type %d (FLUSH_START)", GST_EVENT_TYPE (event)); |
|
4494 |
|
4495 /* can't even accept a flush begin event when flushing */ |
|
4496 if (GST_PAD_IS_FLUSHING (pad)) |
|
4497 goto flushing; |
|
4498 GST_PAD_SET_FLUSHING (pad); |
|
4499 GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "set flush flag"); |
|
4500 break; |
|
4501 case GST_EVENT_FLUSH_STOP: |
|
4502 GST_PAD_UNSET_FLUSHING (pad); |
|
4503 GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "cleared flush flag"); |
|
4504 GST_OBJECT_UNLOCK (pad); |
|
4505 /* grab stream lock */ |
|
4506 GST_PAD_STREAM_LOCK (pad); |
|
4507 need_unlock = TRUE; |
|
4508 GST_OBJECT_LOCK (pad); |
|
4509 break; |
|
4510 default: |
|
4511 GST_CAT_DEBUG_OBJECT (GST_CAT_EVENT, pad, "have event type %s", |
|
4512 GST_EVENT_TYPE_NAME (event)); |
|
4513 |
|
4514 /* make this a little faster, no point in grabbing the lock |
|
4515 * if the pad is allready flushing. */ |
|
4516 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
|
4517 goto flushing; |
|
4518 |
|
4519 if (serialized) { |
|
4520 /* lock order: STREAM_LOCK, LOCK, recheck flushing. */ |
|
4521 GST_OBJECT_UNLOCK (pad); |
|
4522 GST_PAD_STREAM_LOCK (pad); |
|
4523 need_unlock = TRUE; |
|
4524 GST_OBJECT_LOCK (pad); |
|
4525 if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad))) |
|
4526 goto flushing; |
|
4527 } |
|
4528 break; |
|
4529 } |
|
4530 if (G_UNLIKELY ((eventfunc = GST_PAD_EVENTFUNC (pad)) == NULL)) |
|
4531 goto no_function; |
|
4532 |
|
4533 GST_OBJECT_UNLOCK (pad); |
|
4534 |
|
4535 result = eventfunc (pad, event); |
|
4536 |
|
4537 if (need_unlock) |
|
4538 GST_PAD_STREAM_UNLOCK (pad); |
|
4539 |
|
4540 GST_DEBUG_OBJECT (pad, "sent event, result %d", result); |
|
4541 |
|
4542 return result; |
|
4543 |
|
4544 /* ERROR handling */ |
|
4545 wrong_direction: |
|
4546 { |
|
4547 g_warning ("pad %s:%s sending %s event in wrong direction", |
|
4548 GST_DEBUG_PAD_NAME (pad), GST_EVENT_TYPE_NAME (event)); |
|
4549 GST_OBJECT_UNLOCK (pad); |
|
4550 gst_event_unref (event); |
|
4551 return FALSE; |
|
4552 } |
|
4553 unknown_direction: |
|
4554 { |
|
4555 g_warning ("pad %s:%s has invalid direction", GST_DEBUG_PAD_NAME (pad)); |
|
4556 GST_OBJECT_UNLOCK (pad); |
|
4557 gst_event_unref (event); |
|
4558 return FALSE; |
|
4559 } |
|
4560 no_function: |
|
4561 { |
|
4562 g_warning ("pad %s:%s has no event handler, file a bug.", |
|
4563 GST_DEBUG_PAD_NAME (pad)); |
|
4564 GST_OBJECT_UNLOCK (pad); |
|
4565 if (need_unlock) |
|
4566 GST_PAD_STREAM_UNLOCK (pad); |
|
4567 gst_event_unref (event); |
|
4568 return FALSE; |
|
4569 } |
|
4570 flushing: |
|
4571 { |
|
4572 GST_OBJECT_UNLOCK (pad); |
|
4573 if (need_unlock) |
|
4574 GST_PAD_STREAM_UNLOCK (pad); |
|
4575 GST_CAT_INFO_OBJECT (GST_CAT_EVENT, pad, |
|
4576 "Received event on flushing pad. Discarding"); |
|
4577 gst_event_unref (event); |
|
4578 return FALSE; |
|
4579 } |
|
4580 dropping: |
|
4581 { |
|
4582 GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return"); |
|
4583 gst_event_unref (event); |
|
4584 return FALSE; |
|
4585 } |
|
4586 } |
|
4587 |
|
4588 /** |
|
4589 * gst_pad_set_element_private: |
|
4590 * @pad: the #GstPad to set the private data of. |
|
4591 * @priv: The private data to attach to the pad. |
|
4592 * |
|
4593 * Set the given private data gpointer on the pad. |
|
4594 * This function can only be used by the element that owns the pad. |
|
4595 * No locking is performed in this function. |
|
4596 */ |
|
4597 #ifdef __SYMBIAN32__ |
|
4598 EXPORT_C |
|
4599 #endif |
|
4600 |
|
4601 void |
|
4602 gst_pad_set_element_private (GstPad * pad, gpointer priv) |
|
4603 { |
|
4604 pad->element_private = priv; |
|
4605 } |
|
4606 |
|
4607 /** |
|
4608 * gst_pad_get_element_private: |
|
4609 * @pad: the #GstPad to get the private data of. |
|
4610 * |
|
4611 * Gets the private data of a pad. |
|
4612 * No locking is performed in this function. |
|
4613 * |
|
4614 * Returns: a #gpointer to the private data. |
|
4615 */ |
|
4616 #ifdef __SYMBIAN32__ |
|
4617 EXPORT_C |
|
4618 #endif |
|
4619 |
|
4620 gpointer |
|
4621 gst_pad_get_element_private (GstPad * pad) |
|
4622 { |
|
4623 return pad->element_private; |
|
4624 } |
|
4625 |
|
4626 /** |
|
4627 * gst_pad_start_task: |
|
4628 * @pad: the #GstPad to start the task of |
|
4629 * @func: the task function to call |
|
4630 * @data: data passed to the task function |
|
4631 * |
|
4632 * Starts a task that repeatedly calls @func with @data. This function |
|
4633 * is mostly used in pad activation functions to start the dataflow. |
|
4634 * The #GST_PAD_STREAM_LOCK of @pad will automatically be acquired |
|
4635 * before @func is called. |
|
4636 * |
|
4637 * Returns: a %TRUE if the task could be started. |
|
4638 */ |
|
4639 #ifdef __SYMBIAN32__ |
|
4640 EXPORT_C |
|
4641 #endif |
|
4642 |
|
4643 gboolean |
|
4644 gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data) |
|
4645 { |
|
4646 GstTask *task; |
|
4647 |
|
4648 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
4649 g_return_val_if_fail (func != NULL, FALSE); |
|
4650 |
|
4651 GST_DEBUG_OBJECT (pad, "start task"); |
|
4652 |
|
4653 GST_OBJECT_LOCK (pad); |
|
4654 task = GST_PAD_TASK (pad); |
|
4655 if (task == NULL) { |
|
4656 task = gst_task_create (func, data); |
|
4657 gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad)); |
|
4658 GST_PAD_TASK (pad) = task; |
|
4659 GST_DEBUG_OBJECT (pad, "created task"); |
|
4660 } |
|
4661 gst_task_start (task); |
|
4662 GST_OBJECT_UNLOCK (pad); |
|
4663 |
|
4664 return TRUE; |
|
4665 } |
|
4666 |
|
4667 /** |
|
4668 * gst_pad_pause_task: |
|
4669 * @pad: the #GstPad to pause the task of |
|
4670 * |
|
4671 * Pause the task of @pad. This function will also wait until the |
|
4672 * function executed by the task is finished if this function is not |
|
4673 * called from the task function. |
|
4674 * |
|
4675 * Returns: a TRUE if the task could be paused or FALSE when the pad |
|
4676 * has no task. |
|
4677 */ |
|
4678 #ifdef __SYMBIAN32__ |
|
4679 EXPORT_C |
|
4680 #endif |
|
4681 |
|
4682 gboolean |
|
4683 gst_pad_pause_task (GstPad * pad) |
|
4684 { |
|
4685 GstTask *task; |
|
4686 |
|
4687 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
4688 |
|
4689 GST_DEBUG_OBJECT (pad, "pause task"); |
|
4690 |
|
4691 GST_OBJECT_LOCK (pad); |
|
4692 task = GST_PAD_TASK (pad); |
|
4693 if (task == NULL) |
|
4694 goto no_task; |
|
4695 gst_task_pause (task); |
|
4696 GST_OBJECT_UNLOCK (pad); |
|
4697 |
|
4698 /* wait for task function to finish, this lock is recursive so it does nothing |
|
4699 * when the pause is called from the task itself */ |
|
4700 GST_PAD_STREAM_LOCK (pad); |
|
4701 GST_PAD_STREAM_UNLOCK (pad); |
|
4702 |
|
4703 return TRUE; |
|
4704 |
|
4705 no_task: |
|
4706 { |
|
4707 GST_DEBUG_OBJECT (pad, "pad has no task"); |
|
4708 GST_OBJECT_UNLOCK (pad); |
|
4709 return FALSE; |
|
4710 } |
|
4711 } |
|
4712 |
|
4713 /** |
|
4714 * gst_pad_stop_task: |
|
4715 * @pad: the #GstPad to stop the task of |
|
4716 * |
|
4717 * Stop the task of @pad. This function will also make sure that the |
|
4718 * function executed by the task will effectively stop if not called |
|
4719 * from the GstTaskFunction. |
|
4720 * |
|
4721 * This function will deadlock if called from the GstTaskFunction of |
|
4722 * the task. Use gst_task_pause() instead. |
|
4723 * |
|
4724 * Regardless of whether the pad has a task, the stream lock is acquired and |
|
4725 * released so as to ensure that streaming through this pad has finished. |
|
4726 * |
|
4727 * Returns: a TRUE if the task could be stopped or FALSE on error. |
|
4728 */ |
|
4729 #ifdef __SYMBIAN32__ |
|
4730 EXPORT_C |
|
4731 #endif |
|
4732 |
|
4733 gboolean |
|
4734 gst_pad_stop_task (GstPad * pad) |
|
4735 { |
|
4736 GstTask *task; |
|
4737 |
|
4738 g_return_val_if_fail (GST_IS_PAD (pad), FALSE); |
|
4739 |
|
4740 GST_DEBUG_OBJECT (pad, "stop task"); |
|
4741 |
|
4742 GST_OBJECT_LOCK (pad); |
|
4743 task = GST_PAD_TASK (pad); |
|
4744 if (task == NULL) |
|
4745 goto no_task; |
|
4746 GST_PAD_TASK (pad) = NULL; |
|
4747 gst_task_stop (task); |
|
4748 GST_OBJECT_UNLOCK (pad); |
|
4749 |
|
4750 GST_PAD_STREAM_LOCK (pad); |
|
4751 GST_PAD_STREAM_UNLOCK (pad); |
|
4752 |
|
4753 if (!gst_task_join (task)) |
|
4754 goto join_failed; |
|
4755 |
|
4756 gst_object_unref (task); |
|
4757 |
|
4758 return TRUE; |
|
4759 |
|
4760 no_task: |
|
4761 { |
|
4762 GST_DEBUG_OBJECT (pad, "no task"); |
|
4763 GST_OBJECT_UNLOCK (pad); |
|
4764 |
|
4765 GST_PAD_STREAM_LOCK (pad); |
|
4766 GST_PAD_STREAM_UNLOCK (pad); |
|
4767 |
|
4768 /* this is not an error */ |
|
4769 return TRUE; |
|
4770 } |
|
4771 join_failed: |
|
4772 { |
|
4773 /* this is bad, possibly the application tried to join the task from |
|
4774 * the task's thread. We install the task again so that it will be stopped |
|
4775 * again from the right thread next time hopefully. */ |
|
4776 GST_OBJECT_LOCK (pad); |
|
4777 GST_DEBUG_OBJECT (pad, "join failed"); |
|
4778 /* we can only install this task if there was no other task */ |
|
4779 if (GST_PAD_TASK (pad) == NULL) |
|
4780 GST_PAD_TASK (pad) = task; |
|
4781 GST_OBJECT_UNLOCK (pad); |
|
4782 |
|
4783 return FALSE; |
|
4784 } |
|
4785 } |