--- a/gstreamer_core/gst/gstpad.c Tue Aug 31 15:30:33 2010 +0300
+++ b/gstreamer_core/gst/gstpad.c Wed Sep 01 12:16:41 2010 +0100
@@ -99,16 +99,8 @@
/* FILL ME */
};
-#define GST_PAD_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_PAD, GstPadPrivate))
-
-#define GST_PAD_CHAINLISTFUNC(pad) ((pad)->abidata.ABI.priv->chainlistfunc)
-
-struct _GstPadPrivate
-{
- GstPadChainListFunction chainlistfunc;
-};
-
+static void gst_pad_class_init (GstPadClass * klass);
+static void gst_pad_init (GstPad * pad);
static void gst_pad_dispose (GObject * object);
static void gst_pad_finalize (GObject * object);
static void gst_pad_set_property (GObject * object, guint prop_id,
@@ -150,7 +142,9 @@
{GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0},
{GST_FLOW_ERROR, "error", 0},
{GST_FLOW_NOT_SUPPORTED, "not-supported", 0},
- {GST_FLOW_CUSTOM_ERROR, "custom-error", 0}
+ {GST_FLOW_CUSTOM_ERROR, "custom-error", 0},
+
+ {0, NULL, 0}
};
/**
@@ -172,7 +166,7 @@
ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
- for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
+ for (i = 0; flow_quarks[i].name; i++) {
if (ret == flow_quarks[i].ret)
return flow_quarks[i].name;
}
@@ -199,30 +193,48 @@
ret = CLAMP (ret, GST_FLOW_CUSTOM_ERROR, GST_FLOW_CUSTOM_SUCCESS);
- for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) {
+ for (i = 0; flow_quarks[i].name; i++) {
if (ret == flow_quarks[i].ret)
return flow_quarks[i].quark;
}
return 0;
}
-
-#define _do_init \
-{ \
- gint i; \
- \
- buffer_quark = g_quark_from_static_string ("buffer"); \
- event_quark = g_quark_from_static_string ("event"); \
- \
- for (i = 0; i < G_N_ELEMENTS (flow_quarks); i++) { \
- flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); \
- } \
- \
- GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", \
- GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); \
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+
+GType
+gst_pad_get_type (void)
+{
+ static GType gst_pad_type = 0;
+
+ if (G_UNLIKELY (gst_pad_type == 0)) {
+ static const GTypeInfo pad_info = {
+ sizeof (GstPadClass), NULL, NULL,
+ (GClassInitFunc) gst_pad_class_init, NULL, NULL,
+ sizeof (GstPad),
+ 0,
+ (GInstanceInitFunc) gst_pad_init, NULL
+ };
+ gint i;
+
+ gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad",
+ &pad_info, 0);
+
+ buffer_quark = g_quark_from_static_string ("buffer");
+ event_quark = g_quark_from_static_string ("event");
+
+ for (i = 0; flow_quarks[i].name; i++) {
+ flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name);
+ }
+
+ GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW",
+ GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads");
+ }
+ return gst_pad_type;
}
-G_DEFINE_TYPE_WITH_CODE (GstPad, gst_pad, GST_TYPE_OBJECT, _do_init);
-
static gboolean
_gst_do_pass_data_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer dummy)
@@ -250,8 +262,6 @@
gobject_class = G_OBJECT_CLASS (klass);
gstobject_class = GST_OBJECT_CLASS (klass);
- g_type_class_add_private (klass, sizeof (GstPadPrivate));
-
parent_class = g_type_class_peek_parent (klass);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pad_dispose);
@@ -314,16 +324,16 @@
g_object_class_install_property (gobject_class, PAD_PROP_CAPS,
g_param_spec_boxed ("caps", "Caps", "The capabilities of the pad",
- GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ GST_TYPE_CAPS, G_PARAM_READABLE));
g_object_class_install_property (gobject_class, PAD_PROP_DIRECTION,
g_param_spec_enum ("direction", "Direction", "The direction of the pad",
GST_TYPE_PAD_DIRECTION, GST_PAD_UNKNOWN,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/* FIXME, Make G_PARAM_CONSTRUCT_ONLY when we fix ghostpads. */
g_object_class_install_property (gobject_class, PAD_PROP_TEMPLATE,
g_param_spec_object ("template", "Template",
"The GstPadTemplate of this pad", GST_TYPE_PAD_TEMPLATE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ G_PARAM_READWRITE));
#ifndef GST_DISABLE_LOADSAVE
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_pad_save_thyself);
@@ -336,8 +346,6 @@
static void
gst_pad_init (GstPad * pad)
{
- pad->abidata.ABI.priv = GST_PAD_GET_PRIVATE (pad);
-
GST_PAD_DIRECTION (pad) = GST_PAD_UNKNOWN;
GST_PAD_PEER (pad) = NULL;
@@ -355,9 +363,6 @@
GST_PAD_QUERYFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_query_default);
GST_PAD_INTLINKFUNC (pad) =
GST_DEBUG_FUNCPTR (gst_pad_get_internal_links_default);
- GST_PAD_ITERINTLINKFUNC (pad) =
- GST_DEBUG_FUNCPTR (gst_pad_iterate_internal_links_default);
-
GST_PAD_ACCEPTCAPSFUNC (pad) = GST_DEBUG_FUNCPTR (gst_pad_acceptcaps_default);
pad->do_buffer_signals = 0;
@@ -400,11 +405,6 @@
gst_pad_set_pad_template (pad, NULL);
- if (pad->block_destroy_data && pad->block_data) {
- pad->block_destroy_data (pad->block_data);
- pad->block_data = NULL;
- }
-
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -588,7 +588,9 @@
* error return value */
g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_UNKNOWN);
+ GST_OBJECT_LOCK (pad);
result = GST_PAD_DIRECTION (pad);
+ GST_OBJECT_UNLOCK (pad);
return result;
}
@@ -799,13 +801,7 @@
goto peer_failed;
gst_object_unref (peer);
} else {
- /* there is no peer, this is only fatal when we activate. When we
- * deactivate, we must assume the application has unlinked the peer and
- * will deactivate it eventually. */
- if (active)
- goto not_linked;
- else
- GST_DEBUG_OBJECT (pad, "deactivating unlinked pad");
+ goto not_linked;
}
} else {
if (G_UNLIKELY (GST_PAD_GETRANGEFUNC (pad) == NULL))
@@ -1008,107 +1004,6 @@
}
/**
- * gst_pad_set_blocked_async_full:
- * @pad: the #GstPad to block or unblock
- * @blocked: boolean indicating whether the pad should be blocked or unblocked
- * @callback: #GstPadBlockCallback that will be called when the
- * operation succeeds
- * @user_data: user data passed to the callback
- * @destroy_data: #GDestroyNotify for user_data
- *
- * Blocks or unblocks the dataflow on a pad. The provided callback
- * is called when the operation succeeds; this happens right before the next
- * attempt at pushing a buffer on the pad.
- *
- * This can take a while as the pad can only become blocked when real dataflow
- * is happening.
- * When the pipeline is stalled, for example in PAUSED, this can
- * take an indeterminate amount of time.
- * You can pass NULL as the callback to make this call block. Be careful with
- * this blocking call as it might not return for reasons stated above.
- *
- * Returns: TRUE if the pad could be blocked. This function can fail if the
- * wrong parameters were passed or the pad was already in the requested state.
- *
- * MT safe.
- *
- * Since: 0.10.23
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gboolean
-gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
- GstPadBlockCallback callback, gpointer user_data,
- GDestroyNotify destroy_data)
-{
- gboolean was_blocked = FALSE;
-
- g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-
- GST_OBJECT_LOCK (pad);
-
- was_blocked = GST_PAD_IS_BLOCKED (pad);
-
- if (G_UNLIKELY (was_blocked == blocked))
- goto had_right_state;
-
- if (blocked) {
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad");
-
- GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
-
- if (pad->block_destroy_data && pad->block_data &&
- pad->block_data != user_data)
- pad->block_destroy_data (pad->block_data);
-
- pad->block_callback = callback;
- pad->block_data = user_data;
- pad->block_destroy_data = destroy_data;
- pad->abidata.ABI.block_callback_called = FALSE;
- if (!callback) {
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
- GST_PAD_BLOCK_WAIT (pad);
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked");
- }
- } else {
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
-
- GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
-
- if (pad->block_destroy_data && pad->block_data &&
- pad->block_data != user_data)
- pad->block_destroy_data (pad->block_data);
-
- pad->block_callback = callback;
- pad->block_data = user_data;
- pad->block_destroy_data = destroy_data;
- pad->abidata.ABI.block_callback_called = FALSE;
-
- GST_PAD_BLOCK_BROADCAST (pad);
- if (!callback) {
- /* no callback, wait for the unblock to happen */
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock");
- GST_PAD_BLOCK_WAIT (pad);
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked");
- }
- }
- GST_OBJECT_UNLOCK (pad);
-
- return TRUE;
-
-had_right_state:
- {
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "pad was in right state (%d)", was_blocked);
- GST_OBJECT_UNLOCK (pad);
-
- return FALSE;
- }
-}
-
-/**
* gst_pad_set_blocked_async:
* @pad: the #GstPad to block or unblock
* @blocked: boolean indicating whether the pad should be blocked or unblocked
@@ -1140,8 +1035,56 @@
gst_pad_set_blocked_async (GstPad * pad, gboolean blocked,
GstPadBlockCallback callback, gpointer user_data)
{
- return gst_pad_set_blocked_async_full (pad, blocked,
- callback, user_data, NULL);
+ gboolean was_blocked = FALSE;
+
+ g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+
+ GST_OBJECT_LOCK (pad);
+
+ was_blocked = GST_PAD_IS_BLOCKED (pad);
+
+ if (G_UNLIKELY (was_blocked == blocked))
+ goto had_right_state;
+
+ if (blocked) {
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocking pad");
+
+ GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
+ pad->block_callback = callback;
+ pad->block_data = user_data;
+ if (!callback) {
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for block");
+ GST_PAD_BLOCK_WAIT (pad);
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "blocked");
+ }
+ } else {
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocking pad");
+
+ GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
+
+ pad->block_callback = callback;
+ pad->block_data = user_data;
+
+ GST_PAD_BLOCK_BROADCAST (pad);
+ if (!callback) {
+ /* no callback, wait for the unblock to happen */
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "waiting for unblock");
+ GST_PAD_BLOCK_WAIT (pad);
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad, "unblocked");
+ }
+ }
+ GST_OBJECT_UNLOCK (pad);
+
+ return TRUE;
+
+had_right_state:
+ {
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "pad was in right state (%d)", was_blocked);
+ GST_OBJECT_UNLOCK (pad);
+
+ return FALSE;
+ }
}
/**
@@ -1319,7 +1262,7 @@
gst_pad_set_chain_function (GstPad * pad, GstPadChainFunction chain)
{
g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_PAD_IS_SINK (pad));
+ g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
GST_PAD_CHAINFUNC (pad) = chain;
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainfunc set to %s",
@@ -1327,33 +1270,6 @@
}
/**
- * gst_pad_set_chain_list_function:
- * @pad: a sink #GstPad.
- * @chainlist: the #GstPadChainListFunction to set.
- *
- * Sets the given chain list function for the pad. The chainlist function is
- * called to process a #GstBufferList input buffer list. See
- * #GstPadChainListFunction for more details.
- *
- * Since: 0.10.24
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-gst_pad_set_chain_list_function (GstPad * pad,
- GstPadChainListFunction chainlist)
-{
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_PAD_IS_SINK (pad));
-
- GST_PAD_CHAINLISTFUNC (pad) = chainlist;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "chainlistfunc set to %s",
- GST_DEBUG_FUNCPTR_NAME (chainlist));
-}
-
-/**
* gst_pad_set_getrange_function:
* @pad: a source #GstPad.
* @get: the #GstPadGetRangeFunction to set.
@@ -1370,7 +1286,7 @@
gst_pad_set_getrange_function (GstPad * pad, GstPadGetRangeFunction get)
{
g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_PAD_IS_SRC (pad));
+ g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
GST_PAD_GETRANGEFUNC (pad) = get;
@@ -1395,7 +1311,7 @@
GstPadCheckGetRangeFunction check)
{
g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (GST_PAD_IS_SRC (pad));
+ g_return_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC);
GST_PAD_CHECKGETRANGEFUNC (pad) = check;
@@ -1537,39 +1453,12 @@
}
/**
- * gst_pad_set_iterate_internal_links_function:
- * @pad: a #GstPad of either direction.
- * @iterintlink: the #GstPadIterIntLinkFunction to set.
- *
- * Sets the given internal link iterator function for the pad.
- *
- * Since: 0.10.21
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-void
-gst_pad_set_iterate_internal_links_function (GstPad * pad,
- GstPadIterIntLinkFunction iterintlink)
-{
- g_return_if_fail (GST_IS_PAD (pad));
-
- GST_PAD_ITERINTLINKFUNC (pad) = iterintlink;
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link iterator set to %s",
- GST_DEBUG_FUNCPTR_NAME (iterintlink));
-}
-
-/**
* gst_pad_set_internal_link_function:
* @pad: a #GstPad of either direction.
* @intlink: the #GstPadIntLinkFunction to set.
*
* Sets the given internal link function for the pad.
- *
- * Deprecated: Use the thread-safe gst_pad_set_iterate_internal_links_function()
*/
-#ifndef GST_REMOVE_DEPRECATED
#ifdef __SYMBIAN32__
EXPORT_C
#endif
@@ -1583,7 +1472,6 @@
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "internal link set to %s",
GST_DEBUG_FUNCPTR_NAME (intlink));
}
-#endif /* GST_REMOVE_DEPRECATED */
/**
* gst_pad_set_link_function:
@@ -1796,36 +1684,23 @@
gboolean
gst_pad_unlink (GstPad * srcpad, GstPad * sinkpad)
{
- gboolean result = FALSE;
- GstElement *parent = NULL;
-
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
- g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), FALSE);
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
- g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad), FALSE);
GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinking %s:%s(%p) and %s:%s(%p)",
GST_DEBUG_PAD_NAME (srcpad), srcpad,
GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
- /* We need to notify the parent before taking any pad locks as the bin in
- * question might be waiting for a lock on the pad while holding its lock
- * that our message will try to take. */
- if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
- if (GST_IS_ELEMENT (parent)) {
- gst_element_post_message (parent,
- gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
- GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, TRUE));
- } else {
- gst_object_unref (parent);
- parent = NULL;
- }
- }
-
GST_OBJECT_LOCK (srcpad);
+ if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC))
+ goto not_srcpad;
+
GST_OBJECT_LOCK (sinkpad);
+ if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK))
+ goto not_sinkpad;
+
if (G_UNLIKELY (GST_PAD_PEER (srcpad) != sinkpad))
goto not_linked_together;
@@ -1851,25 +1726,28 @@
GST_CAT_INFO (GST_CAT_ELEMENT_PADS, "unlinked %s:%s and %s:%s",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
- result = TRUE;
-
-done:
- if (parent != NULL) {
- gst_element_post_message (parent,
- gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
- GST_STRUCTURE_CHANGE_TYPE_PAD_UNLINK, parent, FALSE));
- gst_object_unref (parent);
+ return TRUE;
+
+not_srcpad:
+ {
+ g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad));
+ GST_OBJECT_UNLOCK (srcpad);
+ return FALSE;
}
- return result;
-
- /* ERRORS */
+not_sinkpad:
+ {
+ g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad));
+ GST_OBJECT_UNLOCK (sinkpad);
+ GST_OBJECT_UNLOCK (srcpad);
+ return FALSE;
+ }
not_linked_together:
{
/* we do not emit a warning in this case because unlinking cannot
* be made MT safe.*/
GST_OBJECT_UNLOCK (sinkpad);
GST_OBJECT_UNLOCK (srcpad);
- goto done;
+ return FALSE;
}
}
@@ -1922,13 +1800,8 @@
/* if we have caps on both pads we can check the intersection. If one
* of the caps is NULL, we return TRUE. */
- if (G_UNLIKELY (srccaps == NULL || sinkcaps == NULL)) {
- if (srccaps)
- gst_caps_unref (srccaps);
- if (sinkcaps)
- gst_caps_unref (sinkcaps);
+ if (srccaps == NULL || sinkcaps == NULL)
goto done;
- }
icaps = gst_caps_intersect (srccaps, sinkcaps);
gst_caps_unref (srccaps);
@@ -2036,16 +1909,26 @@
static GstPadLinkReturn
gst_pad_link_prepare (GstPad * srcpad, GstPad * sinkpad)
{
+ /* generic checks */
+ g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
+ g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
+
GST_CAT_INFO (GST_CAT_PADS, "trying to link %s:%s and %s:%s",
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
GST_OBJECT_LOCK (srcpad);
+ if (G_UNLIKELY (GST_PAD_DIRECTION (srcpad) != GST_PAD_SRC))
+ goto not_srcpad;
+
if (G_UNLIKELY (GST_PAD_PEER (srcpad) != NULL))
goto src_was_linked;
GST_OBJECT_LOCK (sinkpad);
+ if (G_UNLIKELY (GST_PAD_DIRECTION (sinkpad) != GST_PAD_SINK))
+ goto not_sinkpad;
+
if (G_UNLIKELY (GST_PAD_PEER (sinkpad) != NULL))
goto sink_was_linked;
@@ -2062,6 +1945,12 @@
return GST_PAD_LINK_OK;
+not_srcpad:
+ {
+ g_critical ("pad %s is not a source pad", GST_PAD_NAME (srcpad));
+ GST_OBJECT_UNLOCK (srcpad);
+ return GST_PAD_LINK_WRONG_DIRECTION;
+ }
src_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "src %s:%s was already linked to %s:%s",
@@ -2072,6 +1961,13 @@
GST_OBJECT_UNLOCK (srcpad);
return GST_PAD_LINK_WAS_LINKED;
}
+not_sinkpad:
+ {
+ g_critical ("pad %s is not a sink pad", GST_PAD_NAME (sinkpad));
+ GST_OBJECT_UNLOCK (sinkpad);
+ GST_OBJECT_UNLOCK (srcpad);
+ return GST_PAD_LINK_WRONG_DIRECTION;
+ }
sink_was_linked:
{
GST_CAT_INFO (GST_CAT_PADS, "sink %s:%s was already linked to %s:%s",
@@ -2100,46 +1996,6 @@
}
/**
- * gst_pad_can_link:
- * @srcpad: the source #GstPad.
- * @sinkpad: the sink #GstPad.
- *
- * Checks if the source pad and the sink pad are compatible so they can be
- * linked.
- *
- * Returns: TRUE if the pads can be linked.
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-gboolean
-gst_pad_can_link (GstPad * srcpad, GstPad * sinkpad)
-{
- GstPadLinkReturn result;
-
- /* generic checks */
- g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
- g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
-
- GST_CAT_INFO (GST_CAT_PADS, "check if %s:%s can link with %s:%s",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
-
- /* gst_pad_link_prepare does everything for us, we only release the locks
- * on the pads that it gets us. If this function returns !OK the locks are not
- * taken anymore. */
- result = gst_pad_link_prepare (srcpad, sinkpad);
- if (result != GST_PAD_LINK_OK)
- goto done;
-
- GST_OBJECT_UNLOCK (srcpad);
- GST_OBJECT_UNLOCK (sinkpad);
-
-done:
- return result == GST_PAD_LINK_OK;
-}
-
-/**
* gst_pad_link:
* @srcpad: the source #GstPad to link.
* @sinkpad: the sink #GstPad to link.
@@ -2159,31 +2015,12 @@
gst_pad_link (GstPad * srcpad, GstPad * sinkpad)
{
GstPadLinkReturn result;
- GstElement *parent;
-
- g_return_val_if_fail (GST_IS_PAD (srcpad), GST_PAD_LINK_REFUSED);
- g_return_val_if_fail (GST_PAD_IS_SRC (srcpad), GST_PAD_LINK_WRONG_DIRECTION);
- g_return_val_if_fail (GST_IS_PAD (sinkpad), GST_PAD_LINK_REFUSED);
- g_return_val_if_fail (GST_PAD_IS_SINK (sinkpad),
- GST_PAD_LINK_WRONG_DIRECTION);
-
- /* Notify the parent early. See gst_pad_unlink for details. */
- if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (srcpad)))) {
- if (GST_IS_ELEMENT (parent)) {
- gst_element_post_message (parent,
- gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
- GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, TRUE));
- } else {
- gst_object_unref (parent);
- parent = NULL;
- }
- }
/* prepare will also lock the two pads */
result = gst_pad_link_prepare (srcpad, sinkpad);
if (result != GST_PAD_LINK_OK)
- goto done;
+ goto prepare_failed;
/* must set peers before calling the link function */
GST_PAD_PEER (srcpad) = sinkpad;
@@ -2229,16 +2066,12 @@
GST_OBJECT_UNLOCK (sinkpad);
GST_OBJECT_UNLOCK (srcpad);
}
-
-done:
- if (parent) {
- gst_element_post_message (parent,
- gst_message_new_structure_change (GST_OBJECT_CAST (srcpad),
- GST_STRUCTURE_CHANGE_TYPE_PAD_LINK, parent, FALSE));
- gst_object_unref (parent);
+ return result;
+
+prepare_failed:
+ {
+ return result;
}
-
- return result;
}
static void
@@ -2361,7 +2194,7 @@
*
* Gets the capabilities this pad can produce or consume.
* Note that this method doesn't necessarily return the caps set by
- * gst_pad_set_caps() - use GST_PAD_CAPS() for that instead.
+ * gst_pad_set_caps() - use #GST_PAD_CAPS for that instead.
* gst_pad_get_caps returns all possible caps a pad can operate with, using
* the pad's get_caps function;
* this returns the pad template caps if not explicitly set.
@@ -2467,11 +2300,10 @@
g_value_unset (&temp);
} else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
gboolean res = FALSE;
- guint n, len;
-
- len = gst_value_array_get_size (src);
+ guint n;
+
g_value_init (dest, GST_TYPE_ARRAY);
- for (n = 0; n < len; n++) {
+ for (n = 0; n < gst_value_array_get_size (src); n++) {
GValue kid = { 0 };
const GValue *orig_kid = gst_value_array_get_value (src, n);
@@ -2524,7 +2356,7 @@
gst_pad_fixate_caps (GstPad * pad, GstCaps * caps)
{
GstPadFixateCapsFunction fixatefunc;
- guint n, len;
+ guint n;
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (caps != NULL);
@@ -2538,8 +2370,7 @@
}
/* default fixation */
- len = gst_caps_get_size (caps);
- for (n = 0; n < len; n++) {
+ for (n = 0; n < gst_caps_get_size (caps); n++) {
GstStructure *s = gst_caps_get_structure (caps, n);
gst_structure_foreach (s, gst_pad_default_fixate, s);
@@ -2570,6 +2401,8 @@
GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect);
result = !gst_caps_is_empty (intersect);
+ if (!result)
+ GST_DEBUG_OBJECT (pad, "intersection gave empty caps");
gst_caps_unref (allowed);
gst_caps_unref (intersect);
@@ -2612,13 +2445,13 @@
/* lock for checking the existing caps */
GST_OBJECT_LOCK (pad);
+ acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad);
GST_CAT_DEBUG_OBJECT (GST_CAT_CAPS, pad, "accept caps of %p", caps);
/* The current caps on a pad are trivially acceptable */
if (G_LIKELY ((existing = GST_PAD_CAPS (pad)))) {
if (caps == existing || gst_caps_is_equal (caps, existing))
goto is_same_caps;
}
- acceptfunc = GST_PAD_ACCEPTCAPSFUNC (pad);
GST_OBJECT_UNLOCK (pad);
if (G_LIKELY (acceptfunc)) {
@@ -2670,14 +2503,9 @@
if (G_UNLIKELY (peerpad == NULL))
goto no_peer;
- gst_object_ref (peerpad);
- /* release lock before calling external methods but keep ref to pad */
+ result = gst_pad_accept_caps (peerpad, caps);
GST_OBJECT_UNLOCK (pad);
- result = gst_pad_accept_caps (peerpad, caps);
-
- gst_object_unref (peerpad);
-
return result;
no_peer:
@@ -2806,15 +2634,15 @@
{
gboolean res;
- if (dosetcaps) {
- /* See if pad accepts the caps */
- if (!gst_pad_accept_caps (pad, caps))
- goto not_accepted;
-
+ /* See if pad accepts the caps */
+ if (!gst_pad_accept_caps (pad, caps))
+ goto not_accepted;
+
+ if (dosetcaps)
res = gst_pad_set_caps (pad, caps);
- } else {
+ else
res = TRUE;
- }
+
return res;
not_accepted:
@@ -3034,10 +2862,8 @@
goto fallback;
ret = bufferallocfunc (pad, offset, size, caps, buf);
-
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto error;
-
/* no error, but NULL buffer means fallback to the default */
if (G_UNLIKELY (*buf == NULL))
goto fallback;
@@ -3069,35 +2895,27 @@
/* fallback case, allocate a buffer of our own, add pad caps. */
GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad, "fallback buffer alloc");
- if ((*buf = gst_buffer_try_new_and_alloc (size))) {
- GST_BUFFER_OFFSET (*buf) = offset;
- gst_buffer_set_caps (*buf, caps);
- return GST_FLOW_OK;
- } else {
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "out of memory allocating %d bytes", size);
- return GST_FLOW_ERROR;
- }
+ *buf = gst_buffer_new_and_alloc (size);
+ GST_BUFFER_OFFSET (*buf) = offset;
+ gst_buffer_set_caps (*buf, caps);
+
+ return GST_FLOW_OK;
}
}
-/* FIXME 0.11: size should be unsigned */
static GstFlowReturn
gst_pad_alloc_buffer_full (GstPad * pad, guint64 offset, gint size,
GstCaps * caps, GstBuffer ** buf, gboolean setcaps)
{
GstPad *peer;
GstFlowReturn ret;
- GstCaps *newcaps;
gboolean caps_changed;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
- g_return_val_if_fail (size >= 0, GST_FLOW_ERROR);
-
- GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d, caps %"
- GST_PTR_FORMAT, offset, size, caps);
+
+ GST_DEBUG_OBJECT (pad, "offset %" G_GUINT64_FORMAT ", size %d", offset, size);
GST_OBJECT_LOCK (pad);
while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
@@ -3117,29 +2935,24 @@
goto peer_error;
/* FIXME, move capnego this into a base class? */
- newcaps = GST_BUFFER_CAPS (*buf);
+ caps = GST_BUFFER_CAPS (*buf);
/* Lock for checking caps, pretty pointless as the _pad_push() function might
* change it concurrently, one of the problems with automatic caps setting in
* pad_alloc_and_set_caps. Worst case, if does a check too much, but only
* when there is heavy renegotiation going on in both directions. */
GST_OBJECT_LOCK (pad);
- caps_changed = newcaps && newcaps != GST_PAD_CAPS (pad);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
GST_OBJECT_UNLOCK (pad);
/* we got a new datatype on the pad, see if it can handle it */
if (G_UNLIKELY (caps_changed)) {
GST_DEBUG_OBJECT (pad,
"caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
- GST_PAD_CAPS (pad), newcaps, newcaps);
- if (G_UNLIKELY (!gst_pad_configure_src (pad, newcaps, setcaps)))
+ GST_PAD_CAPS (pad), caps, caps);
+ if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, setcaps)))
goto not_negotiated;
}
-
- /* sanity check (only if caps are the same) */
- if (G_LIKELY (newcaps == caps) && G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size))
- goto wrong_size_fallback;
-
return ret;
flushed:
@@ -3170,24 +2983,6 @@
"alloc function returned unacceptable buffer");
return GST_FLOW_NOT_NEGOTIATED;
}
-wrong_size_fallback:
- {
- GST_CAT_ERROR_OBJECT (GST_CAT_PADS, pad, "buffer returned by alloc "
- "function is too small (%u < %d), doing fallback buffer alloc",
- GST_BUFFER_SIZE (*buf), size);
-
- gst_buffer_unref (*buf);
-
- if ((*buf = gst_buffer_try_new_and_alloc (size))) {
- GST_BUFFER_OFFSET (*buf) = offset;
- gst_buffer_set_caps (*buf, caps);
- return GST_FLOW_OK;
- } else {
- GST_CAT_DEBUG_OBJECT (GST_CAT_PADS, pad,
- "out of memory allocating %d bytes", size);
- return GST_FLOW_ERROR;
- }
- }
}
/**
@@ -3203,9 +2998,7 @@
*
* A new, empty #GstBuffer will be put in the @buf argument.
* You need to check the caps of the buffer after performing this
- * function and renegotiate to the format if needed. If the caps changed, it is
- * possible that the buffer returned in @buf is not of the right size for the
- * new format, @buf needs to be unreffed and reallocated if this is the case.
+ * function and renegotiate to the format if needed.
*
* Returns: a result code indicating success of the operation. Any
* result code other than #GST_FLOW_OK is an error and @buf should
@@ -3215,8 +3008,6 @@
*
* MT safe.
*/
-
-/* FIXME 0.11: size should be unsigned */
#ifdef __SYMBIAN32__
EXPORT_C
#endif
@@ -3240,10 +3031,6 @@
* automatically calls gst_pad_set_caps() when the caps of the
* newly allocated buffer are different from the @pad caps.
*
- * After a renegotiation, the size of the new buffer returned in @buf could
- * be of the wrong size for the new format and must be unreffed an reallocated
- * in that case.
- *
* Returns: a result code indicating success of the operation. Any
* result code other than #GST_FLOW_OK is an error and @buf should
* not be used.
@@ -3252,8 +3039,6 @@
*
* MT safe.
*/
-
-/* FIXME 0.11: size should be unsigned */
#ifdef __SYMBIAN32__
EXPORT_C
#endif
@@ -3265,170 +3050,6 @@
return gst_pad_alloc_buffer_full (pad, offset, size, caps, buf, TRUE);
}
-
-#ifndef GST_REMOVE_DEPRECATED
-typedef struct
-{
- GList *list;
- guint32 cookie;
-} IntLinkIterData;
-
-static void
-int_link_iter_data_free (IntLinkIterData * data)
-{
- g_list_free (data->list);
- g_free (data);
-}
-#endif
-
-static GstIteratorItem
-iterate_pad (GstIterator * it, GstPad * pad)
-{
- gst_object_ref (pad);
- return GST_ITERATOR_ITEM_PASS;
-}
-
-/**
- * gst_pad_iterate_internal_links_default:
- * @pad: the #GstPad to get the internal links of.
- *
- * Iterate the list of pads to which the given pad is linked to inside of
- * the parent element.
- * This is the default handler, and thus returns an iterator of all of the
- * pads inside the parent element with opposite direction.
- *
- * The caller must free this iterator after use with gst_iterator_free().
- *
- * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
- * returned pad with gst_object_unref().
- *
- * Since: 0.10.21
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstIterator *
-gst_pad_iterate_internal_links_default (GstPad * pad)
-{
- GstIterator *res;
- GList **padlist;
- guint32 *cookie;
- GMutex *lock;
- gpointer owner;
- GstIteratorDisposeFunction dispose;
-
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
-#ifndef GST_REMOVE_DEPRECATED
- /* when we get here, the default handler for the iterate links is called,
- * which means that the user has not installed a custom one. We first check if
- * there is maybe a custom legacy function we can call. */
- if (GST_PAD_INTLINKFUNC (pad) &&
- GST_PAD_INTLINKFUNC (pad) != gst_pad_get_internal_links_default) {
- IntLinkIterData *data;
-
- /* make an iterator for the list. We can't protect the list with a
- * cookie. If we would take the cookie of the parent element, we need to
- * have a parent, which is not required for GST_PAD_INTLINKFUNC(). We could
- * cache the per-pad list and invalidate the list when a new call to
- * INTLINKFUNC() returned a different list but then this would only work if
- * two concurrent iterators were used and the last iterator would still be
- * thread-unsafe. Just don't use this method anymore. */
- data = g_new0 (IntLinkIterData, 1);
- data->list = GST_PAD_INTLINKFUNC (pad) (pad);
- data->cookie = 0;
-
- GST_WARNING_OBJECT (pad, "Making unsafe iterator");
-
- cookie = &data->cookie;
- padlist = &data->list;
- owner = data;
- dispose = (GstIteratorDisposeFunction) int_link_iter_data_free;
- /* reuse the pad lock, it's all we have here */
- lock = GST_OBJECT_GET_LOCK (pad);
- } else
-#endif
- {
- GstElement *parent;
-
- GST_OBJECT_LOCK (pad);
- parent = GST_PAD_PARENT (pad);
- if (!parent || !GST_IS_ELEMENT (parent))
- goto no_parent;
-
- gst_object_ref (parent);
- GST_OBJECT_UNLOCK (pad);
-
- if (pad->direction == GST_PAD_SRC)
- padlist = &parent->sinkpads;
- else
- padlist = &parent->srcpads;
-
- GST_DEBUG_OBJECT (pad, "Making iterator");
-
- cookie = &parent->pads_cookie;
- owner = parent;
- dispose = (GstIteratorDisposeFunction) gst_object_unref;
- lock = GST_OBJECT_GET_LOCK (parent);
- }
-
- res = gst_iterator_new_list (GST_TYPE_PAD,
- lock, cookie, padlist, owner, (GstIteratorItemFunction) iterate_pad,
- dispose);
-
- return res;
-
- /* ERRORS */
-no_parent:
- {
- GST_OBJECT_UNLOCK (pad);
- GST_DEBUG_OBJECT (pad, "no parent element");
- return NULL;
- }
-}
-
-/**
- * gst_pad_iterate_internal_links:
- * @pad: the GstPad to get the internal links of.
- *
- * Gets an iterator for the pads to which the given pad is linked to inside
- * of the parent element.
- *
- * Each #GstPad element yielded by the iterator will have its refcount increased,
- * so unref after use.
- *
- * Returns: a new #GstIterator of #GstPad or %NULL when the pad does not have an
- * iterator function configured. Use gst_iterator_free() after usage.
- *
- * Since: 0.10.21
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstIterator *
-gst_pad_iterate_internal_links (GstPad * pad)
-{
- GstIterator *res = NULL;
-
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
-
- if (GST_PAD_ITERINTLINKFUNC (pad))
- res = GST_PAD_ITERINTLINKFUNC (pad) (pad);
-
- return res;
-}
-
-#ifndef GST_REMOVE_DEPRECATED
-static void
-add_unref_pad_to_list (GstPad * pad, GList * list)
-{
- list = g_list_prepend (list, pad);
- gst_object_unref (pad);
-}
-#endif
-
/**
* gst_pad_get_internal_links_default:
* @pad: the #GstPad to get the internal links of.
@@ -3437,98 +3058,52 @@
* inside of the parent element.
* This is the default handler, and thus returns a list of all of the
* pads inside the parent element with opposite direction.
- *
- * The caller must free this list after use with g_list_free().
+ * The caller must free this list after use.
*
* Returns: a newly allocated #GList of pads, or NULL if the pad has no parent.
*
* Not MT safe.
- *
- * Deprecated: This function does not ref the pads in the list so that they
- * could become invalid by the time the application accesses them. It's also
- * possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
- * gst_pad_iterate_internal_links_default() instead.
*/
-#ifndef GST_REMOVE_DEPRECATED
#ifdef __SYMBIAN32__
EXPORT_C
#endif
+
GList *
gst_pad_get_internal_links_default (GstPad * pad)
{
GList *res = NULL;
GstElement *parent;
+ GList *parent_pads;
+ GstPadDirection direction;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- GST_WARNING_OBJECT (pad, "Unsafe internal links used");
-
- /* when we get here, the default handler for get_internal_links is called,
- * which means that the user has not installed a custom one. We first check if
- * there is maybe a custom iterate function we can call. */
- if (GST_PAD_ITERINTLINKFUNC (pad) &&
- GST_PAD_ITERINTLINKFUNC (pad) != gst_pad_iterate_internal_links_default) {
- GstIterator *it;
- GstIteratorResult ires;
- gboolean done = FALSE;
-
- it = gst_pad_iterate_internal_links (pad);
- /* loop over the iterator and put all elements into a list, we also
- * immediatly unref them, which is bad. */
- do {
- ires = gst_iterator_foreach (it, (GFunc) add_unref_pad_to_list, res);
- switch (ires) {
- case GST_ITERATOR_OK:
- case GST_ITERATOR_DONE:
- case GST_ITERATOR_ERROR:
- done = TRUE;
- break;
- case GST_ITERATOR_RESYNC:
- /* restart, discard previous list */
- gst_iterator_resync (it);
- g_list_free (res);
- res = NULL;
- break;
- }
- } while (!done);
-
- gst_iterator_free (it);
- } else {
- /* lock pad, check and ref parent */
- GST_OBJECT_LOCK (pad);
- parent = GST_PAD_PARENT (pad);
- if (!parent || !GST_IS_ELEMENT (parent))
- goto no_parent;
-
- parent = gst_object_ref (parent);
- GST_OBJECT_UNLOCK (pad);
-
- /* now lock the parent while we copy the pads */
- GST_OBJECT_LOCK (parent);
- if (pad->direction == GST_PAD_SRC)
- res = g_list_copy (parent->sinkpads);
- else
- res = g_list_copy (parent->srcpads);
- GST_OBJECT_UNLOCK (parent);
-
- gst_object_unref (parent);
+ direction = pad->direction;
+
+ parent = GST_PAD_PARENT (pad);
+ if (!parent)
+ goto no_parent;
+
+ parent_pads = parent->pads;
+
+ while (parent_pads) {
+ GstPad *parent_pad = GST_PAD_CAST (parent_pads->data);
+
+ if (parent_pad->direction != direction) {
+ GST_DEBUG_OBJECT (pad, "adding pad %s:%s",
+ GST_DEBUG_PAD_NAME (parent_pad));
+ res = g_list_prepend (res, parent_pad);
+ }
+ parent_pads = g_list_next (parent_pads);
}
-
- /* At this point pads can be changed and unreffed. Nothing we can do about it
- * because for compatibility reasons this function cannot ref the pads or
- * notify the app that the list changed. */
-
return res;
no_parent:
{
GST_DEBUG_OBJECT (pad, "no parent");
- GST_OBJECT_UNLOCK (pad);
return NULL;
}
}
-#endif /* GST_REMOVE_DEPRECATED */
/**
* gst_pad_get_internal_links:
@@ -3538,20 +3113,14 @@
* inside of the parent element.
* The caller must free this list after use.
*
+ * Returns: a newly allocated #GList of pads.
+ *
* Not MT safe.
- *
- * Returns: a newly allocated #GList of pads, free with g_list_free().
- *
- * Deprecated: This function does not ref the pads in the list so that they
- * could become invalid by the time the application accesses them. It's also
- * possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
- * gst_pad_iterate_internal_links() instead.
*/
-#ifndef GST_REMOVE_DEPRECATED
#ifdef __SYMBIAN32__
EXPORT_C
#endif
+
GList *
gst_pad_get_internal_links (GstPad * pad)
{
@@ -3559,98 +3128,53 @@
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
- GST_WARNING_OBJECT (pad, "Calling unsafe internal links");
-
if (GST_PAD_INTLINKFUNC (pad))
res = GST_PAD_INTLINKFUNC (pad) (pad);
return res;
}
-#endif /* GST_REMOVE_DEPRECATED */
+
static gboolean
gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
{
- gboolean result = FALSE;
- GstIterator *iter;
- gboolean done = FALSE;
- gpointer item;
- GstPad *eventpad;
- GList *pushed_pads = NULL;
+ GList *orig, *pads;
+ gboolean result;
GST_INFO_OBJECT (pad, "Sending event %p (%s) to all internally linked pads",
event, GST_EVENT_TYPE_NAME (event));
- iter = gst_pad_iterate_internal_links (pad);
-
- if (!iter)
- goto no_iter;
-
- while (!done) {
- switch (gst_iterator_next (iter, &item)) {
- case GST_ITERATOR_OK:
- eventpad = GST_PAD (item);
-
- /* if already pushed, skip */
- if (g_list_find (pushed_pads, eventpad)) {
- gst_object_unref (item);
- break;
- }
-
- if (GST_PAD_IS_SRC (eventpad)) {
- /* for each pad we send to, we should ref the event; it's up
- * to downstream to unref again when handled. */
- GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
- event, GST_EVENT_TYPE_NAME (event),
- GST_DEBUG_PAD_NAME (eventpad));
- gst_event_ref (event);
- result |= gst_pad_push_event (eventpad, event);
- } else {
- /* we only send the event on one pad, multi-sinkpad elements
- * should implement a handler */
- GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
- event, GST_EVENT_TYPE_NAME (event),
- GST_DEBUG_PAD_NAME (eventpad));
- result = gst_pad_push_event (eventpad, event);
- done = TRUE;
- event = NULL;
- }
-
- pushed_pads = g_list_prepend (pushed_pads, eventpad);
-
- gst_object_unref (item);
- break;
- case GST_ITERATOR_RESYNC:
- /* FIXME, if we want to reset the result value we need to remember which
- * pads pushed with which result */
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads");
- done = TRUE;
- break;
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
+ result = (GST_PAD_DIRECTION (pad) == GST_PAD_SINK);
+
+ orig = pads = gst_pad_get_internal_links (pad);
+
+ while (pads) {
+ GstPad *eventpad = GST_PAD_CAST (pads->data);
+
+ pads = g_list_next (pads);
+
+ if (GST_PAD_DIRECTION (eventpad) == GST_PAD_SRC) {
+ /* for each pad we send to, we should ref the event; it's up
+ * to downstream to unref again when handled. */
+ GST_LOG_OBJECT (pad, "Reffing and sending event %p (%s) to %s:%s",
+ event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
+ gst_event_ref (event);
+ gst_pad_push_event (eventpad, event);
+ } else {
+ /* we only send the event on one pad, multi-sinkpad elements
+ * should implement a handler */
+ GST_LOG_OBJECT (pad, "sending event %p (%s) to one sink pad %s:%s",
+ event, GST_EVENT_TYPE_NAME (event), GST_DEBUG_PAD_NAME (eventpad));
+ result = gst_pad_push_event (eventpad, event);
+ goto done;
}
}
- gst_iterator_free (iter);
-
-no_iter:
-
- /* If this is a sinkpad and we don't have pads to send the event to, we
- * return TRUE. This is so that when using the default handler on a sink
- * element, we don't fail to push it. */
- if (!pushed_pads)
- result = GST_PAD_IS_SINK (pad);
-
- g_list_free (pushed_pads);
-
/* we handled the incoming event so we unref once */
- if (event) {
- GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
- gst_event_unref (event);
- }
+ GST_LOG_OBJECT (pad, "handled event %p, unreffing", event);
+ gst_event_unref (event);
+
+done:
+ g_list_free (orig);
return result;
}
@@ -3678,8 +3202,6 @@
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- GST_LOG_OBJECT (pad, "default event handler");
-
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
{
@@ -3716,54 +3238,32 @@
gpointer data)
{
gboolean res = FALSE;
- GstIterator *iter = NULL;
- gboolean done = FALSE;
- gpointer item;
+ GList *int_pads, *orig;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (dispatch != NULL, FALSE);
- iter = gst_pad_iterate_internal_links (pad);
-
- if (!iter)
- goto no_iter;
-
- while (!done) {
- switch (gst_iterator_next (iter, &item)) {
- case GST_ITERATOR_OK:
- {
- GstPad *int_pad = GST_PAD_CAST (item);
- GstPad *int_peer = gst_pad_get_peer (int_pad);
-
- if (int_peer) {
- GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
- GST_DEBUG_PAD_NAME (int_peer));
- done = res = dispatch (int_peer, data);
- gst_object_unref (int_peer);
- } else {
- GST_DEBUG_OBJECT (int_pad, "no peer");
- }
- }
- gst_object_unref (item);
+ orig = int_pads = gst_pad_get_internal_links (pad);
+
+ while (int_pads) {
+ GstPad *int_pad = GST_PAD_CAST (int_pads->data);
+ GstPad *int_peer = gst_pad_get_peer (int_pad);
+
+ if (int_peer) {
+ GST_DEBUG_OBJECT (int_pad, "dispatching to peer %s:%s",
+ GST_DEBUG_PAD_NAME (int_peer));
+ res = dispatch (int_peer, data);
+ gst_object_unref (int_peer);
+ if (res)
break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (iter);
- break;
- case GST_ITERATOR_ERROR:
- done = TRUE;
- GST_ERROR_OBJECT (pad, "Could not iterate internally linked pads");
- break;
- case GST_ITERATOR_DONE:
- done = TRUE;
- break;
+ } else {
+ GST_DEBUG_OBJECT (int_pad, "no peer");
}
+ int_pads = g_list_next (int_pads);
}
- gst_iterator_free (iter);
-
+ g_list_free (orig);
GST_DEBUG_OBJECT (pad, "done, result %d", res);
-no_iter:
-
return res;
}
@@ -3911,7 +3411,6 @@
{
xmlNodePtr field = self->xmlChildrenNode;
GstPad *pad = NULL, *targetpad;
- GstPadTemplate *tmpl;
gchar *peer = NULL;
gchar **split;
GstElement *target;
@@ -3921,10 +3420,7 @@
while (field) {
if (!strcmp ((char *) field->name, "name")) {
name = (gchar *) xmlNodeGetContent (field);
- pad = gst_element_get_static_pad (GST_ELEMENT (parent), name);
- if ((!pad) || ((tmpl = gst_pad_get_pad_template (pad))
- && (GST_PAD_REQUEST == GST_PAD_TEMPLATE_PRESENCE (tmpl))))
- pad = gst_element_get_request_pad (GST_ELEMENT (parent), name);
+ pad = gst_element_get_pad (GST_ELEMENT (parent), name);
g_free (name);
} else if (!strcmp ((char *) field->name, "peer")) {
peer = (gchar *) xmlNodeGetContent (field);
@@ -3960,17 +3456,12 @@
if (target == NULL)
goto cleanup;
- targetpad = gst_element_get_static_pad (target, split[1]);
- if (!pad)
- targetpad = gst_element_get_request_pad (target, split[1]);
+ targetpad = gst_element_get_pad (target, split[1]);
if (targetpad == NULL)
goto cleanup;
- if (gst_pad_get_direction (pad) == GST_PAD_SRC)
- gst_pad_link (pad, targetpad);
- else
- gst_pad_link (targetpad, pad);
+ gst_pad_link (pad, targetpad);
cleanup:
g_strfreev (split);
@@ -4102,38 +3593,31 @@
* all taken when calling this function. */
gst_object_ref (pad);
+ /* we either have a callback installed to notify the block or
+ * some other thread is doing a GCond wait. */
+ callback = pad->block_callback;
+ if (callback) {
+ /* there is a callback installed, call it. We release the
+ * lock so that the callback can do something usefull with the
+ * pad */
+ user_data = pad->block_data;
+ GST_OBJECT_UNLOCK (pad);
+ callback (pad, TRUE, user_data);
+ GST_OBJECT_LOCK (pad);
+
+ /* we released the lock, recheck flushing */
+ if (GST_PAD_IS_FLUSHING (pad))
+ goto flushing;
+ } else {
+ /* no callback, signal the thread that is doing a GCond wait
+ * if any. */
+ GST_PAD_BLOCK_BROADCAST (pad);
+ }
+
+ /* OBJECT_LOCK could have been released when we did the callback, which
+ * then could have made the pad unblock so we need to check the blocking
+ * condition again. */
while (GST_PAD_IS_BLOCKED (pad)) {
- do {
- /* we either have a callback installed to notify the block or
- * some other thread is doing a GCond wait. */
- callback = pad->block_callback;
- pad->abidata.ABI.block_callback_called = TRUE;
- if (callback) {
- /* there is a callback installed, call it. We release the
- * lock so that the callback can do something usefull with the
- * pad */
- user_data = pad->block_data;
- GST_OBJECT_UNLOCK (pad);
- callback (pad, TRUE, user_data);
- GST_OBJECT_LOCK (pad);
-
- /* we released the lock, recheck flushing */
- if (GST_PAD_IS_FLUSHING (pad))
- goto flushing;
- } else {
- /* no callback, signal the thread that is doing a GCond wait
- * if any. */
- GST_PAD_BLOCK_BROADCAST (pad);
- }
- } while (pad->abidata.ABI.block_callback_called == FALSE
- && GST_PAD_IS_BLOCKED (pad));
-
- /* OBJECT_LOCK could have been released when we did the callback, which
- * then could have made the pad unblock so we need to check the blocking
- * condition again. */
- if (!GST_PAD_IS_BLOCKED (pad))
- break;
-
/* now we block the streaming thread. It can be unlocked when we
* deactivate the pad (which will also set the FLUSHING flag) or
* when the pad is unblocked. A flushing event will also unblock
@@ -4219,42 +3703,15 @@
return res;
}
-static void
-gst_pad_data_unref (gboolean is_buffer, void *data)
-{
- if (G_LIKELY (is_buffer)) {
- gst_buffer_unref (data);
- } else {
- gst_buffer_list_unref (data);
- }
-}
-
-static GstCaps *
-gst_pad_data_get_caps (gboolean is_buffer, void *data)
-{
- GstCaps *caps;
-
- if (G_LIKELY (is_buffer)) {
- caps = GST_BUFFER_CAPS (data);
- } else {
- GstBuffer *buf;
-
- if ((buf = gst_buffer_list_get (GST_BUFFER_LIST_CAST (data), 0, 0)))
- caps = GST_BUFFER_CAPS (buf);
- else
- caps = NULL;
- }
- return caps;
-}
-
/* this is the chain function that does not perform the additional argument
* checking for that little extra speed.
*/
static inline GstFlowReturn
-gst_pad_chain_data_unchecked (GstPad * pad, gboolean is_buffer, void *data)
+gst_pad_chain_unchecked (GstPad * pad, GstBuffer * buffer)
{
GstCaps *caps;
gboolean caps_changed;
+ GstPadChainFunction chainfunc;
GstFlowReturn ret;
gboolean emit_signal;
@@ -4264,7 +3721,7 @@
if (G_UNLIKELY (GST_PAD_IS_FLUSHING (pad)))
goto flushing;
- caps = gst_pad_data_get_caps (is_buffer, data);
+ caps = GST_BUFFER_CAPS (buffer);
caps_changed = caps && caps != GST_PAD_CAPS (pad);
emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0;
@@ -4273,14 +3730,8 @@
/* see if the signal should be emited, we emit before caps nego as
* we might drop the buffer and do capsnego for nothing. */
if (G_UNLIKELY (emit_signal)) {
- if (G_LIKELY (is_buffer)) {
- if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
- goto dropping;
- } else {
- /* chain all groups in the buffer list one by one to avoid problems with
- * buffer probes that push buffers or events */
- goto chain_groups;
- }
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
+ goto dropping;
}
/* we got a new datatype on the pad, see if it can handle it */
@@ -4295,81 +3746,26 @@
* the data to the wrong function. This is not really a
* problem since functions are assigned at creation time
* and don't change that often... */
- if (G_LIKELY (is_buffer)) {
- GstPadChainFunction chainfunc;
-
- if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
- goto no_function;
-
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc));
-
- ret = chainfunc (pad, GST_BUFFER_CAST (data));
-
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "called chainfunction &%s, returned %s",
- GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret));
- } else {
- GstPadChainListFunction chainlistfunc;
-
- if (G_UNLIKELY ((chainlistfunc = GST_PAD_CHAINLISTFUNC (pad)) == NULL))
- goto chain_groups;
-
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "calling chainlistfunction &%s",
- GST_DEBUG_FUNCPTR_NAME (chainlistfunc));
-
- ret = chainlistfunc (pad, GST_BUFFER_LIST_CAST (data));
-
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "called chainlistfunction &%s, returned %s",
- GST_DEBUG_FUNCPTR_NAME (chainlistfunc), gst_flow_get_name (ret));
- }
+ if (G_UNLIKELY ((chainfunc = GST_PAD_CHAINFUNC (pad)) == NULL))
+ goto no_function;
+
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "calling chainfunction &%s", GST_DEBUG_FUNCPTR_NAME (chainfunc));
+
+ ret = chainfunc (pad, buffer);
+
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "called chainfunction &%s, returned %s",
+ GST_DEBUG_FUNCPTR_NAME (chainfunc), gst_flow_get_name (ret));
GST_PAD_STREAM_UNLOCK (pad);
return ret;
-chain_groups:
- {
- GstBufferList *list;
- GstBufferListIterator *it;
- GstBuffer *group;
-
- GST_PAD_STREAM_UNLOCK (pad);
-
- GST_INFO_OBJECT (pad, "chaining each group in list as a merged buffer");
-
- list = GST_BUFFER_LIST_CAST (data);
- it = gst_buffer_list_iterate (list);
-
- ret = GST_FLOW_OK;
- if (gst_buffer_list_iterator_next_group (it)) {
- do {
- group = gst_buffer_list_iterator_merge_group (it);
- if (group == NULL) {
- group = gst_buffer_new ();
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining group");
- }
- ret = gst_pad_chain_data_unchecked (pad, TRUE, group);
- } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "chaining empty group");
- ret = gst_pad_chain_data_unchecked (pad, TRUE, gst_buffer_new ());
- }
-
- gst_buffer_list_iterator_free (it);
- gst_buffer_list_unref (list);
-
- return ret;
- }
-
/* ERRORS */
flushing:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_buffer_unref (buffer);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but pad was flushing");
GST_OBJECT_UNLOCK (pad);
@@ -4378,22 +3774,22 @@
}
dropping:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_buffer_unref (buffer);
GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_OK;
}
not_negotiated:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_buffer_unref (buffer);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "pushing data but pad did not accept");
+ "pushing buffer but pad did not accept");
GST_PAD_STREAM_UNLOCK (pad);
return GST_FLOW_NOT_NEGOTIATED;
}
no_function:
{
- gst_pad_data_unref (is_buffer, data);
+ gst_buffer_unref (buffer);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
"pushing, but not chainhandler");
GST_ELEMENT_ERROR (GST_PAD_PARENT (pad), CORE, PAD, (NULL),
@@ -4438,180 +3834,11 @@
gst_pad_chain (GstPad * pad, GstBuffer * buffer)
{
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
+ GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
- return gst_pad_chain_data_unchecked (pad, TRUE, buffer);
-}
-
-/**
- * gst_pad_chain_list:
- * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
- * @list: the #GstBufferList to send, return GST_FLOW_ERROR if not.
- *
- * Chain a bufferlist to @pad.
- *
- * The function returns #GST_FLOW_WRONG_STATE if the pad was flushing.
- *
- * If the caps on the first buffer of @list are different from the current
- * caps on @pad, this function will call any setcaps function
- * (see gst_pad_set_setcaps_function()) installed on @pad. If the new caps
- * are not acceptable for @pad, this function returns #GST_FLOW_NOT_NEGOTIATED.
- *
- * The function proceeds calling the chainlist function installed on @pad (see
- * gst_pad_set_chain_list_function()) and the return value of that function is
- * returned to the caller. #GST_FLOW_NOT_SUPPORTED is returned if @pad has no
- * chainlist function.
- *
- * In all cases, success or failure, the caller loses its reference to @list
- * after calling this function.
- *
- * MT safe.
- *
- * Returns: a #GstFlowReturn from the pad.
- *
- * Since: 0.10.24
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstFlowReturn
-gst_pad_chain_list (GstPad * pad, GstBufferList * list)
-{
- g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
-
- return gst_pad_chain_data_unchecked (pad, FALSE, list);
-}
-
-static GstFlowReturn
-gst_pad_push_data (GstPad * pad, gboolean is_buffer, void *data)
-{
- GstPad *peer;
- GstFlowReturn ret;
- GstCaps *caps;
- gboolean caps_changed;
-
- GST_OBJECT_LOCK (pad);
-
- /* FIXME: this check can go away; pad_set_blocked could be implemented with
- * probes completely or probes with an extended pad block. */
- while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
- if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
- goto flushed;
-
- /* we emit signals on the pad arg, the peer will have a chance to
- * emit in the _chain() function */
- if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) {
- /* unlock before emitting */
- GST_OBJECT_UNLOCK (pad);
-
- if (G_LIKELY (is_buffer)) {
- /* if the signal handler returned FALSE, it means we should just drop the
- * buffer */
- if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (data)))
- goto dropped;
- } else {
- /* push all buffers in the list */
- goto push_groups;
- }
- GST_OBJECT_LOCK (pad);
- }
-
- if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
- goto not_linked;
-
- /* Before pushing the buffer to the peer pad, ensure that caps
- * are set on this pad */
- caps = gst_pad_data_get_caps (is_buffer, data);
- caps_changed = caps && caps != GST_PAD_CAPS (pad);
-
- /* take ref to peer pad before releasing the lock */
- gst_object_ref (peer);
-
- GST_OBJECT_UNLOCK (pad);
-
- /* we got a new datatype from the pad, it had better handle it */
- if (G_UNLIKELY (caps_changed)) {
- GST_DEBUG_OBJECT (pad,
- "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
- GST_PAD_CAPS (pad), caps, caps);
- if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
- goto not_negotiated;
- }
-
- ret = gst_pad_chain_data_unchecked (peer, is_buffer, data);
-
- gst_object_unref (peer);
-
- return ret;
-
-push_groups:
- {
- GstBufferList *list;
- GstBufferListIterator *it;
- GstBuffer *group;
-
- GST_INFO_OBJECT (pad, "pushing each group in list as a merged buffer");
-
- list = GST_BUFFER_LIST_CAST (data);
- it = gst_buffer_list_iterate (list);
-
- ret = GST_FLOW_OK;
- if (gst_buffer_list_iterator_next_group (it)) {
- do {
- group = gst_buffer_list_iterator_merge_group (it);
- if (group == NULL) {
- group = gst_buffer_new ();
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing group");
- }
- ret = gst_pad_push_data (pad, TRUE, group);
- } while (ret == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it));
- } else {
- GST_CAT_INFO_OBJECT (GST_CAT_SCHEDULING, pad, "pushing empty group");
- ret = gst_pad_push_data (pad, TRUE, gst_buffer_new ());
- }
-
- gst_buffer_list_iterator_free (it);
- gst_buffer_list_unref (list);
-
- return ret;
- }
-
- /* ERROR recovery here */
-flushed:
- {
- gst_pad_data_unref (is_buffer, data);
- GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
- GST_OBJECT_UNLOCK (pad);
- return ret;
- }
-dropped:
- {
- gst_pad_data_unref (is_buffer, data);
- GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
- return GST_FLOW_OK;
- }
-not_linked:
- {
- gst_pad_data_unref (is_buffer, data);
- GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
- "pushing, but it was not linked");
- GST_OBJECT_UNLOCK (pad);
- return GST_FLOW_NOT_LINKED;
- }
-not_negotiated:
- {
- gst_pad_data_unref (is_buffer, data);
- gst_object_unref (peer);
- GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
- "element pushed data then refused to accept the caps");
- return GST_FLOW_NOT_NEGOTIATED;
- }
+ return gst_pad_chain_unchecked (pad, buffer);
}
/**
@@ -4643,64 +3870,99 @@
#ifdef __SYMBIAN32__
EXPORT_C
#endif
-
GstFlowReturn
gst_pad_push (GstPad * pad, GstBuffer * buffer)
{
+ GstPad *peer;
+ GstFlowReturn ret;
+
+ GstCaps *caps;
+ gboolean caps_changed;
+
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR);
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
- return gst_pad_push_data (pad, TRUE, buffer);
-}
-
-/**
- * gst_pad_push_list:
- * @pad: a source #GstPad, returns #GST_FLOW_ERROR if not.
- * @list: the #GstBufferList to push returns GST_FLOW_ERROR if not.
- *
- * Pushes a buffer list to the peer of @pad.
- *
- * This function will call an installed pad block before triggering any
- * installed pad probes.
- *
- * If the caps on the first buffer in the first group of @list are different
- * from the currently configured caps on @pad, this function will call any
- * installed setcaps function on @pad (see gst_pad_set_setcaps_function()). In
- * case of failure to renegotiate the new format, this function returns
- * #GST_FLOW_NOT_NEGOTIATED.
- *
- * If there are any probes installed on @pad every group of the buffer list
- * will be merged into a normal #GstBuffer and pushed via gst_pad_push and the
- * buffer list will be unreffed.
- *
- * The function proceeds calling the chain function on the peer pad and returns
- * the value from that function. If @pad has no peer, #GST_FLOW_NOT_LINKED will
- * be returned. If the peer pad does not have any installed chainlist function
- * every group buffer of the list will be merged into a normal #GstBuffer and
- * chained via gst_pad_chain().
- *
- * In all cases, success or failure, the caller loses its reference to @list
- * after calling this function.
- *
- * Returns: a #GstFlowReturn from the peer pad.
- *
- * MT safe.
- *
- * Since: 0.10.24
- */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
-
-GstFlowReturn
-gst_pad_push_list (GstPad * pad, GstBufferList * list)
-{
- g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
-
- return gst_pad_push_data (pad, FALSE, list);
+ GST_OBJECT_LOCK (pad);
+
+ /* FIXME: this check can go away; pad_set_blocked could be implemented with
+ * probes completely or probes with an extended pad block. */
+ while (G_UNLIKELY (GST_PAD_IS_BLOCKED (pad)))
+ if ((ret = handle_pad_block (pad)) != GST_FLOW_OK)
+ goto flushed;
+
+ /* we emit signals on the pad arg, the peer will have a chance to
+ * emit in the _chain() function */
+ if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) {
+ /* unlock before emitting */
+ GST_OBJECT_UNLOCK (pad);
+
+ /* if the signal handler returned FALSE, it means we should just drop the
+ * buffer */
+ if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)))
+ goto dropped;
+
+ GST_OBJECT_LOCK (pad);
+ }
+
+ if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
+ goto not_linked;
+
+ /* take ref to peer pad before releasing the lock */
+ gst_object_ref (peer);
+
+ /* Before pushing the buffer to the peer pad, ensure that caps
+ * are set on this pad */
+ caps = GST_BUFFER_CAPS (buffer);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
+
+ GST_OBJECT_UNLOCK (pad);
+
+ /* we got a new datatype from the pad, it had better handle it */
+ if (G_UNLIKELY (caps_changed)) {
+ GST_DEBUG_OBJECT (pad,
+ "caps changed from %" GST_PTR_FORMAT " to %p %" GST_PTR_FORMAT,
+ GST_PAD_CAPS (pad), caps, caps);
+ if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
+ goto not_negotiated;
+ }
+
+ ret = gst_pad_chain_unchecked (peer, buffer);
+
+ gst_object_unref (peer);
+
+ return ret;
+
+ /* ERROR recovery here */
+flushed:
+ {
+ gst_buffer_unref (buffer);
+ GST_DEBUG_OBJECT (pad, "pad block stopped by flush");
+ GST_OBJECT_UNLOCK (pad);
+ return ret;
+ }
+dropped:
+ {
+ gst_buffer_unref (buffer);
+ GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return");
+ return GST_FLOW_OK;
+ }
+not_linked:
+ {
+ gst_buffer_unref (buffer);
+ GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "pushing, but it was not linked");
+ GST_OBJECT_UNLOCK (pad);
+ return GST_FLOW_NOT_LINKED;
+ }
+not_negotiated:
+ {
+ gst_buffer_unref (buffer);
+ gst_object_unref (peer);
+ GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "element pushed buffer then refused to accept the caps");
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
/**
@@ -4733,7 +3995,7 @@
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
GST_OBJECT_LOCK (pad);
- if (!GST_PAD_IS_SINK (pad))
+ if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK)
goto wrong_direction;
if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL))
@@ -4792,6 +4054,10 @@
* installed (see gst_pad_set_getrange_function()) this function returns
* #GST_FLOW_NOT_SUPPORTED.
*
+ * @buffer's caps must either be unset or the same as what is already
+ * configured on @pad. Renegotiation within a running pull-mode pipeline is not
+ * supported.
+ *
* This is a lowlevel function. Usualy gst_pad_pull_range() is used.
*
* Returns: a #GstFlowReturn from the pad.
@@ -4809,11 +4075,9 @@
GstFlowReturn ret;
GstPadGetRangeFunction getrangefunc;
gboolean emit_signal;
- GstCaps *caps;
- gboolean caps_changed;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SRC (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR);
g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
GST_PAD_STREAM_LOCK (pad);
@@ -4843,22 +4107,23 @@
GST_PAD_STREAM_UNLOCK (pad);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto get_range_failed;
-
- GST_OBJECT_LOCK (pad);
- /* Before pushing the buffer to the peer pad, ensure that caps
- * are set on this pad */
- caps = GST_BUFFER_CAPS (*buffer);
- caps_changed = caps && caps != GST_PAD_CAPS (pad);
- GST_OBJECT_UNLOCK (pad);
-
- if (G_UNLIKELY (caps_changed)) {
- GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
- /* this should usually work because the element produced the buffer */
- if (G_UNLIKELY (!gst_pad_configure_src (pad, caps, TRUE)))
+ if (G_LIKELY (ret == GST_FLOW_OK)) {
+ GstCaps *caps;
+ gboolean caps_changed;
+
+ GST_OBJECT_LOCK (pad);
+ /* Before pushing the buffer to the peer pad, ensure that caps
+ * are set on this pad */
+ caps = GST_BUFFER_CAPS (*buffer);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
+ GST_OBJECT_UNLOCK (pad);
+
+ /* we got a new datatype from the pad not supported in a running pull-mode
+ * pipeline */
+ if (G_UNLIKELY (caps_changed))
goto not_negotiated;
}
+
return ret;
/* ERRORS */
@@ -4887,20 +4152,23 @@
*buffer = NULL;
return GST_FLOW_UNEXPECTED;
}
-get_range_failed:
- {
- *buffer = NULL;
- GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
- "getrange failed %s", gst_flow_get_name (ret));
- return ret;
- }
not_negotiated:
{
+ /* ideally we want to use the commented-out code, but currently demuxers
+ * and typefind do not follow part-negotiation.txt. When switching into
+ * pull mode, typefind should probably return the found caps from
+ * getcaps(), and demuxers should do the setcaps(). */
+
+#if 0
gst_buffer_unref (*buffer);
*buffer = NULL;
GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
- "getrange returned buffer of unaccaptable caps");
+ "getrange returned buffer of different caps");
return GST_FLOW_NOT_NEGOTIATED;
+#endif
+ GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "getrange returned buffer of different caps");
+ return ret;
}
}
@@ -4945,11 +4213,10 @@
GstPad *peer;
GstFlowReturn ret;
gboolean emit_signal;
- GstCaps *caps;
- gboolean caps_changed;
g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
- g_return_val_if_fail (GST_PAD_IS_SINK (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SINK,
+ GST_FLOW_ERROR);
g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
GST_OBJECT_LOCK (pad);
@@ -4971,28 +4238,28 @@
gst_object_unref (peer);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- goto pull_range_failed;
-
/* can only fire the signal if we have a valid buffer */
- if (G_UNLIKELY (emit_signal)) {
+ if (G_UNLIKELY (emit_signal) && (ret == GST_FLOW_OK)) {
if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (*buffer)))
goto dropping;
}
- GST_OBJECT_LOCK (pad);
- /* Before pushing the buffer to the peer pad, ensure that caps
- * are set on this pad */
- caps = GST_BUFFER_CAPS (*buffer);
- caps_changed = caps && caps != GST_PAD_CAPS (pad);
- GST_OBJECT_UNLOCK (pad);
-
- /* we got a new datatype on the pad, see if it can handle it */
- if (G_UNLIKELY (caps_changed)) {
- GST_DEBUG_OBJECT (pad, "caps changed to %p %" GST_PTR_FORMAT, caps, caps);
- if (G_UNLIKELY (!gst_pad_configure_sink (pad, caps)))
+ if (G_LIKELY (ret == GST_FLOW_OK)) {
+ GstCaps *caps;
+ gboolean caps_changed;
+
+ GST_OBJECT_LOCK (pad);
+ /* Before pushing the buffer to the peer pad, ensure that caps
+ * are set on this pad */
+ caps = GST_BUFFER_CAPS (*buffer);
+ caps_changed = caps && caps != GST_PAD_CAPS (pad);
+ GST_OBJECT_UNLOCK (pad);
+
+ /* we got a new datatype on the pad, see if it can handle it */
+ if (G_UNLIKELY (caps_changed))
goto not_negotiated;
}
+
return ret;
/* ERROR recovery here */
@@ -5003,13 +4270,6 @@
GST_OBJECT_UNLOCK (pad);
return GST_FLOW_NOT_LINKED;
}
-pull_range_failed:
- {
- *buffer = NULL;
- GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
- "pullrange failed %s", gst_flow_get_name (ret));
- return ret;
- }
dropping:
{
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, pad,
@@ -5020,11 +4280,21 @@
}
not_negotiated:
{
+ /* ideally we want to use the commented-out code, but currently demuxers
+ * and typefind do not follow part-negotiation.txt. When switching into
+ * pull mode, typefind should probably return the found caps from
+ * getcaps(), and demuxers should do the setcaps(). */
+
+#if 0
gst_buffer_unref (*buffer);
*buffer = NULL;
GST_CAT_WARNING_OBJECT (GST_CAT_SCHEDULING, pad,
"pullrange returned buffer of different caps");
return GST_FLOW_NOT_NEGOTIATED;
+#endif
+ GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, pad,
+ "pullrange returned buffer of different caps");
+ return ret;
}
}
@@ -5353,53 +4623,6 @@
return pad->element_private;
}
-static void
-do_stream_status (GstPad * pad, GstStreamStatusType type,
- GThread * thread, GstTask * task)
-{
- GstElement *parent;
-
- GST_DEBUG_OBJECT (pad, "doing stream-status %d", type);
-
- if ((parent = GST_ELEMENT_CAST (gst_pad_get_parent (pad)))) {
- if (GST_IS_ELEMENT (parent)) {
- GstMessage *message;
- GValue value = { 0 };
-
- message = gst_message_new_stream_status (GST_OBJECT_CAST (pad),
- type, parent);
-
- g_value_init (&value, GST_TYPE_TASK);
- g_value_set_object (&value, task);
- gst_message_set_stream_status_object (message, &value);
- g_value_unset (&value);
-
- GST_DEBUG_OBJECT (pad, "posting stream-status %d", type);
- gst_element_post_message (parent, message);
- }
- gst_object_unref (parent);
- }
-}
-
-static void
-pad_enter_thread (GstTask * task, GThread * thread, gpointer user_data)
-{
- do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_ENTER,
- thread, task);
-}
-
-static void
-pad_leave_thread (GstTask * task, GThread * thread, gpointer user_data)
-{
- do_stream_status (GST_PAD_CAST (user_data), GST_STREAM_STATUS_TYPE_LEAVE,
- thread, task);
-}
-
-static GstTaskThreadCallbacks thr_callbacks = {
- pad_enter_thread,
- pad_leave_thread,
-};
-
/**
* gst_pad_start_task:
* @pad: the #GstPad to start the task of
@@ -5421,7 +4644,6 @@
gst_pad_start_task (GstPad * pad, GstTaskFunction func, gpointer data)
{
GstTask *task;
- gboolean res;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
g_return_val_if_fail (func != NULL, FALSE);
@@ -5433,33 +4655,13 @@
if (task == NULL) {
task = gst_task_create (func, data);
gst_task_set_lock (task, GST_PAD_GET_STREAM_LOCK (pad));
- gst_task_set_thread_callbacks (task, &thr_callbacks, pad, NULL);
+ GST_PAD_TASK (pad) = task;
GST_DEBUG_OBJECT (pad, "created task");
- GST_PAD_TASK (pad) = task;
- gst_object_ref (task);
- /* release lock to post the message */
- GST_OBJECT_UNLOCK (pad);
-
- do_stream_status (pad, GST_STREAM_STATUS_TYPE_CREATE, NULL, task);
-
- gst_object_unref (task);
-
- GST_OBJECT_LOCK (pad);
- /* nobody else is supposed to have changed the pad now */
- if (GST_PAD_TASK (pad) != task)
- goto concurrent_stop;
}
- res = gst_task_set_state (task, GST_TASK_STARTED);
+ gst_task_start (task);
GST_OBJECT_UNLOCK (pad);
- return res;
-
- /* ERRORS */
-concurrent_stop:
- {
- GST_OBJECT_UNLOCK (pad);
- return TRUE;
- }
+ return TRUE;
}
/**
@@ -5481,7 +4683,6 @@
gst_pad_pause_task (GstPad * pad)
{
GstTask *task;
- gboolean res;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@@ -5491,7 +4692,7 @@
task = GST_PAD_TASK (pad);
if (task == NULL)
goto no_task;
- res = gst_task_set_state (task, GST_TASK_PAUSED);
+ gst_task_pause (task);
GST_OBJECT_UNLOCK (pad);
/* wait for task function to finish, this lock is recursive so it does nothing
@@ -5499,7 +4700,7 @@
GST_PAD_STREAM_LOCK (pad);
GST_PAD_STREAM_UNLOCK (pad);
- return res;
+ return TRUE;
no_task:
{
@@ -5533,7 +4734,6 @@
gst_pad_stop_task (GstPad * pad)
{
GstTask *task;
- gboolean res;
g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
@@ -5544,7 +4744,7 @@
if (task == NULL)
goto no_task;
GST_PAD_TASK (pad) = NULL;
- res = gst_task_set_state (task, GST_TASK_STOPPED);
+ gst_task_stop (task);
GST_OBJECT_UNLOCK (pad);
GST_PAD_STREAM_LOCK (pad);
@@ -5555,7 +4755,7 @@
gst_object_unref (task);
- return res;
+ return TRUE;
no_task:
{