gstreamer_core/gst/gstpad.c
branchRCL_3
changeset 8 7e817e7e631c
parent 7 567bb019e3e3
--- 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:
   {