memory: make the allocator refcounted
[platform/upstream/gstreamer.git] / libs / gst / base / gstbasetransform.c
index 727efcc..3735a19 100644 (file)
 
 #include "../../../gst/gst_private.h"
 #include "../../../gst/gst-i18n-lib.h"
+#include "../../../gst/glib-compat-private.h"
 #include "gstbasetransform.h"
 #include <gst/gstmarshal.h>
 
@@ -240,7 +241,7 @@ struct _GstBaseTransformPrivate
   /* previous buffer had a discont */
   gboolean discont;
 
-  GstPadActivateMode pad_mode;
+  GstPadMode pad_mode;
 
   gboolean gap_aware;
 
@@ -253,7 +254,7 @@ struct _GstBaseTransformPrivate
   GstClockTime position_out;
 
   GstBufferPool *pool;
-  const GstAllocator *allocator;
+  GstAllocator *allocator;
   guint prefix;
   guint alignment;
 };
@@ -298,35 +299,39 @@ static void gst_base_transform_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
 static void gst_base_transform_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
-static gboolean gst_base_transform_src_activate_pull (GstPad * pad,
-    gboolean active);
-static gboolean gst_base_transform_sink_activate_push (GstPad * pad,
-    gboolean active);
+static gboolean gst_base_transform_src_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
+static gboolean gst_base_transform_sink_activate_mode (GstPad * pad,
+    GstObject * parent, GstPadMode mode, gboolean active);
 static gboolean gst_base_transform_activate (GstBaseTransform * trans,
     gboolean active);
 static gboolean gst_base_transform_get_unit_size (GstBaseTransform * trans,
     GstCaps * caps, gsize * size);
 
-static gboolean gst_base_transform_src_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static gboolean gst_base_transform_src_eventfunc (GstBaseTransform * trans,
     GstEvent * event);
-static gboolean gst_base_transform_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 static gboolean gst_base_transform_sink_eventfunc (GstBaseTransform * trans,
     GstEvent * event);
-static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
-    guint length, GstBuffer ** buffer);
-static GstFlowReturn gst_base_transform_chain (GstPad * pad,
+static GstFlowReturn gst_base_transform_getrange (GstPad * pad,
+    GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
+static GstFlowReturn gst_base_transform_chain (GstPad * pad, GstObject * parent,
     GstBuffer * buffer);
 static GstCaps *gst_base_transform_default_transform_caps (GstBaseTransform *
     trans, GstPadDirection direction, GstCaps * caps, GstCaps * filter);
 static void gst_base_transform_default_fixate (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
-static GstCaps *gst_base_transform_getcaps (GstPad * pad, GstCaps * filter);
+static GstCaps *gst_base_transform_query_caps (GstBaseTransform * trans,
+    GstPad * pad, GstCaps * filter);
 static gboolean gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps);
 static gboolean gst_base_transform_setcaps (GstBaseTransform * trans,
     GstPad * pad, GstCaps * caps);
-static gboolean gst_base_transform_query (GstPad * pad, GstQuery * query);
+static gboolean gst_base_transform_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static gboolean gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query);
 static gboolean gst_base_transform_default_transform_size (GstBaseTransform *
@@ -348,7 +353,7 @@ gst_base_transform_finalize (GObject * object)
 
   trans = GST_BASE_TRANSFORM (object);
 
-  g_mutex_free (trans->transform_lock);
+  g_mutex_clear (&trans->transform_lock);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -410,14 +415,12 @@ gst_base_transform_init (GstBaseTransform * trans,
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
   g_return_if_fail (pad_template != NULL);
   trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
-  gst_pad_set_getcaps_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   gst_pad_set_event_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
   gst_pad_set_chain_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_chain));
-  gst_pad_set_activatepush_function (trans->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));
+  gst_pad_set_activatemode_function (trans->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_mode));
   gst_pad_set_query_function (trans->sinkpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_query));
   gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);
@@ -426,23 +429,21 @@ gst_base_transform_init (GstBaseTransform * trans,
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
   g_return_if_fail (pad_template != NULL);
   trans->srcpad = gst_pad_new_from_template (pad_template, "src");
-  gst_pad_set_getcaps_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   gst_pad_set_event_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
   gst_pad_set_getrange_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_getrange));
-  gst_pad_set_activatepull_function (trans->srcpad,
-      GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
+  gst_pad_set_activatemode_function (trans->srcpad,
+      GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_mode));
   gst_pad_set_query_function (trans->srcpad,
       GST_DEBUG_FUNCPTR (gst_base_transform_query));
   gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
 
-  trans->transform_lock = g_mutex_new ();
+  g_mutex_init (&trans->transform_lock);
   trans->priv->qos_enabled = DEFAULT_PROP_QOS;
   trans->cache_caps1 = NULL;
   trans->cache_caps2 = NULL;
-  trans->priv->pad_mode = GST_PAD_ACTIVATE_NONE;
+  trans->priv->pad_mode = GST_PAD_MODE_NONE;
   trans->priv->gap_aware = FALSE;
 
   trans->passthrough = FALSE;
@@ -637,15 +638,13 @@ gst_base_transform_transform_size (GstBaseTransform * trans,
  * If there is no peer, we simply return the caps of the padtemplate of pad.
  */
 static GstCaps *
-gst_base_transform_getcaps (GstPad * pad, GstCaps * filter)
+gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
+    GstCaps * filter)
 {
-  GstBaseTransform *trans;
   GstPad *otherpad;
   GstCaps *peercaps, *caps, *temp, *peerfilter = NULL;
   GstCaps *templ;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
 
   /* we can do what the peer can */
@@ -678,7 +677,7 @@ gst_base_transform_getcaps (GstPad * pad, GstCaps * filter)
     peerfilter = temp;
   }
 
-  peercaps = gst_pad_peer_get_caps (otherpad, peerfilter);
+  peercaps = gst_pad_peer_query_caps (otherpad, peerfilter);
 
   if (peerfilter)
     gst_caps_unref (peerfilter);
@@ -693,7 +692,7 @@ gst_base_transform_getcaps (GstPad * pad, GstCaps * filter)
     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
     gst_caps_unref (templ);
   } else {
-    temp = gst_caps_copy (gst_pad_get_pad_template_caps (otherpad));
+    temp = gst_pad_get_pad_template_caps (otherpad);
   }
 
   /* then see what we can transform this to */
@@ -743,16 +742,15 @@ done:
   if (peercaps)
     gst_caps_unref (peercaps);
 
-  gst_object_unref (trans);
-
   return caps;
 }
 
 static gboolean
 gst_base_transform_set_allocation (GstBaseTransform * trans,
-    GstBufferPool * pool, const GstAllocator * allocator, guint prefix,
+    GstBufferPool * pool, GstAllocator * allocator, guint prefix,
     guint alignment)
 {
+  GstAllocator *oldalloc;
   GstBufferPool *oldpool;
   GstBaseTransformPrivate *priv = trans->priv;
 
@@ -766,6 +764,7 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
   GST_OBJECT_LOCK (trans);
   oldpool = priv->pool;
   priv->pool = pool;
+  oldalloc = priv->allocator;
   priv->allocator = allocator;
   priv->prefix = prefix;
   priv->alignment = alignment;
@@ -776,6 +775,9 @@ gst_base_transform_set_allocation (GstBaseTransform * trans,
     gst_buffer_pool_set_active (oldpool, FALSE);
     gst_object_unref (oldpool);
   }
+  if (oldalloc) {
+    gst_allocator_unref (oldalloc);
+  }
   return TRUE;
 
   /* ERRORS */
@@ -794,7 +796,7 @@ gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps)
   GstBufferPool *pool = NULL, *oldpool;
   guint size, min, max, prefix, alignment;
   GstBaseTransformClass *klass;
-  const GstAllocator *allocator = NULL;
+  GstAllocator *allocator = NULL;
 
   /* there are these possibilities:
    *
@@ -1004,31 +1006,37 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
       GST_DEBUG_OBJECT (trans,
           "Checking peer caps with filter %" GST_PTR_FORMAT, othercaps);
 
-      peercaps = gst_pad_get_caps (otherpeer, othercaps);
+      peercaps = gst_pad_query_caps (otherpeer, othercaps);
       GST_DEBUG_OBJECT (trans, "Resulted in %" GST_PTR_FORMAT, peercaps);
+      if (!gst_caps_is_empty (peercaps)) {
+        templ_caps = gst_pad_get_pad_template_caps (otherpad);
 
-      templ_caps = gst_pad_get_pad_template_caps (otherpad);
-
-      GST_DEBUG_OBJECT (trans,
-          "Intersecting with template caps %" GST_PTR_FORMAT, templ_caps);
+        GST_DEBUG_OBJECT (trans,
+            "Intersecting with template caps %" GST_PTR_FORMAT, templ_caps);
 
-      intersection =
-          gst_caps_intersect_full (peercaps, templ_caps,
-          GST_CAPS_INTERSECT_FIRST);
-      GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT, intersection);
-      gst_caps_unref (peercaps);
-      gst_caps_unref (templ_caps);
-      peercaps = intersection;
+        intersection =
+            gst_caps_intersect_full (peercaps, templ_caps,
+            GST_CAPS_INTERSECT_FIRST);
+        GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
+            intersection);
+        gst_caps_unref (peercaps);
+        gst_caps_unref (templ_caps);
+        peercaps = intersection;
+
+        GST_DEBUG_OBJECT (trans,
+            "Intersecting with transformed caps %" GST_PTR_FORMAT, othercaps);
+        intersection =
+            gst_caps_intersect_full (peercaps, othercaps,
+            GST_CAPS_INTERSECT_FIRST);
+        GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT,
+            intersection);
+        gst_caps_unref (peercaps);
+        gst_caps_unref (othercaps);
+        othercaps = intersection;
+      } else {
+        othercaps = peercaps;
+      }
 
-      GST_DEBUG_OBJECT (trans,
-          "Intersecting with transformed caps %" GST_PTR_FORMAT, othercaps);
-      intersection =
-          gst_caps_intersect_full (peercaps, othercaps,
-          GST_CAPS_INTERSECT_FIRST);
-      GST_DEBUG_OBJECT (trans, "Intersection: %" GST_PTR_FORMAT, intersection);
-      gst_caps_unref (peercaps);
-      gst_caps_unref (othercaps);
-      othercaps = intersection;
       is_fixed = gst_caps_is_fixed (othercaps);
     } else {
       GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
@@ -1048,7 +1056,7 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
   if (klass->fixate_caps) {
     othercaps = gst_caps_make_writable (othercaps);
 
-    GST_DEBUG_OBJECT (trans, "calling faxate_caps for %" GST_PTR_FORMAT
+    GST_DEBUG_OBJECT (trans, "calling fixate_caps for %" GST_PTR_FORMAT
         " using caps %" GST_PTR_FORMAT " on pad %s:%s", othercaps, caps,
         GST_DEBUG_PAD_NAME (otherpad));
     /* note that we pass the complete array of structures to the fixate
@@ -1063,7 +1071,7 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
     goto could_not_fixate;
 
   /* and peer should accept */
-  if (otherpeer && !gst_pad_accept_caps (otherpeer, othercaps))
+  if (otherpeer && !gst_pad_query_accept_caps (otherpeer, othercaps))
     goto peer_no_accept;
 
   GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
@@ -1133,12 +1141,12 @@ gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
 
     /* get all the formats we can handle on this pad */
     if (direction == GST_PAD_SRC)
-      allowed = gst_pad_get_caps (trans->srcpad, NULL);
+      allowed = gst_pad_query_caps (trans->srcpad, NULL);
     else
-      allowed = gst_pad_get_caps (trans->sinkpad, NULL);
+      allowed = gst_pad_query_caps (trans->sinkpad, NULL);
 
     if (!allowed) {
-      GST_DEBUG_OBJECT (trans, "gst_pad_get_caps() failed");
+      GST_DEBUG_OBJECT (trans, "gst_pad_query_caps() failed");
       goto no_transform_possible;
     }
 
@@ -1234,14 +1242,14 @@ gst_base_transform_setcaps (GstBaseTransform * trans, GstPad * pad,
     goto failed_configure;
 
   GST_OBJECT_LOCK (trans->sinkpad);
-  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_NEED_RECONFIGURE);
+  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_FLAG_NEED_RECONFIGURE);
   trans->priv->reconfigure = FALSE;
   GST_OBJECT_UNLOCK (trans->sinkpad);
 
   /* we know this will work, we implement the setcaps */
   gst_pad_push_event (otherpad, gst_event_new_caps (othercaps));
 
-  if (pad == trans->srcpad && trans->priv->pad_mode == GST_PAD_ACTIVATE_PULL) {
+  if (pad == trans->srcpad && trans->priv->pad_mode == GST_PAD_MODE_PULL) {
     /* FIXME hm? */
     ret &= gst_pad_push_event (otherpeer, gst_event_new_caps (othercaps));
     if (!ret) {
@@ -1288,10 +1296,16 @@ gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query)
 {
   gboolean ret = FALSE;
-  GstPad *otherpad;
+  GstPad *pad, *otherpad;
   GstBaseTransformClass *klass;
 
-  otherpad = (direction == GST_PAD_SRC) ? trans->sinkpad : trans->srcpad;
+  if (direction == GST_PAD_SRC) {
+    pad = trans->srcpad;
+    otherpad = trans->sinkpad;
+  } else {
+    pad = trans->sinkpad;
+    otherpad = trans->srcpad;
+  }
 
   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
@@ -1305,19 +1319,18 @@ gst_base_transform_default_query (GstBaseTransform * trans,
         goto done;
 
       GST_BASE_TRANSFORM_LOCK (trans);
-      passthrough = trans->passthrough || trans->always_in_place;
+      passthrough = trans->passthrough;
       GST_BASE_TRANSFORM_UNLOCK (trans);
 
-      if (passthrough) {
+      GST_DEBUG_OBJECT (trans, "propose allocation values");
+      /* pass the query to the propose_allocation vmethod if any */
+      if (G_LIKELY (klass->propose_allocation)) {
+        ret = klass->propose_allocation (trans, query);
+      } else if (passthrough) {
         GST_DEBUG_OBJECT (trans, "doing passthrough query");
         ret = gst_pad_peer_query (otherpad, query);
       } else {
-        GST_DEBUG_OBJECT (trans, "propose allocation values");
-        /* pass the query to the propose_allocation vmethod if any */
-        if (G_LIKELY (klass->propose_allocation))
-          ret = klass->propose_allocation (trans, query);
-        else
-          ret = FALSE;
+        ret = FALSE;
       }
       GST_DEBUG_OBJECT (trans, "ALLOCATION ret %d, %" GST_PTR_FORMAT, ret,
           query);
@@ -1360,6 +1373,17 @@ gst_base_transform_default_query (GstBaseTransform * trans,
       }
       break;
     }
+    case GST_QUERY_CAPS:
+    {
+      GstCaps *filter, *caps;
+
+      gst_query_parse_caps (query, &filter);
+      caps = gst_base_transform_query_caps (trans, pad, filter);
+      gst_query_set_caps_result (query, caps);
+      gst_caps_unref (caps);
+      ret = TRUE;
+      break;
+    }
     default:
       ret = gst_pad_peer_query (otherpad, query);
       break;
@@ -1370,23 +1394,18 @@ done:
 }
 
 static gboolean
-gst_base_transform_query (GstPad * pad, GstQuery * query)
+gst_base_transform_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
   gboolean ret = FALSE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL))
-    return FALSE;
-
+  trans = GST_BASE_TRANSFORM (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->query)
     ret = bclass->query (trans, GST_PAD_DIRECTION (pad), query);
 
-  gst_object_unref (trans);
-
   return ret;
 }
 
@@ -1559,17 +1578,14 @@ gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
 }
 
 static gboolean
-gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
+gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  trans = GST_BASE_TRANSFORM (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->sink_event)
@@ -1577,8 +1593,6 @@ gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
   else
     gst_event_unref (event);
 
-  gst_object_unref (trans);
-
   return ret;
 }
 
@@ -1640,18 +1654,14 @@ gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
 }
 
 static gboolean
-gst_base_transform_src_event (GstPad * pad, GstEvent * event)
+gst_base_transform_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (trans == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
-
+  trans = GST_BASE_TRANSFORM (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->src_event)
@@ -1659,8 +1669,6 @@ gst_base_transform_src_event (GstPad * pad, GstEvent * event)
   else
     gst_event_unref (event);
 
-  gst_object_unref (trans);
-
   return ret;
 }
 
@@ -1716,7 +1724,7 @@ gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
   GST_OBJECT_LOCK (trans->sinkpad);
   reconfigure = GST_PAD_NEEDS_RECONFIGURE (trans->srcpad)
       || trans->priv->reconfigure;
-  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_NEED_RECONFIGURE);
+  GST_OBJECT_FLAG_UNSET (trans->srcpad, GST_PAD_FLAG_NEED_RECONFIGURE);
   trans->priv->reconfigure = FALSE;
   GST_OBJECT_UNLOCK (trans->sinkpad);
 
@@ -1875,21 +1883,20 @@ no_qos:
       GST_DEBUG_OBJECT (trans, "doing inplace transform");
 
       if (inbuf != *outbuf) {
-        guint8 *indata, *outdata;
-        gsize insize, outsize;
+        GstMapInfo ininfo, outinfo;
 
         /* Different buffer. The data can still be the same when we are dealing
          * with subbuffers of the same buffer. Note that because of the FIXME in
          * prepare_output_buffer() we have decreased the refcounts of inbuf and
          * outbuf to keep them writable */
-        indata = gst_buffer_map (inbuf, &insize, NULL, GST_MAP_READ);
-        outdata = gst_buffer_map (*outbuf, &outsize, NULL, GST_MAP_WRITE);
+        g_assert (gst_buffer_map (inbuf, &ininfo, GST_MAP_READ));
+        g_assert (gst_buffer_map (*outbuf, &outinfo, GST_MAP_WRITE));
 
-        if (indata != outdata)
-          memcpy (outdata, indata, insize);
+        if (ininfo.data != outinfo.data)
+          memcpy (outinfo.data, ininfo.data, ininfo.size);
 
-        gst_buffer_unmap (inbuf, indata, insize);
-        gst_buffer_unmap (*outbuf, outdata, outsize);
+        gst_buffer_unmap (inbuf, &ininfo);
+        gst_buffer_unmap (*outbuf, &outinfo);
       }
       ret = bclass->transform_ip (trans, *outbuf);
     } else {
@@ -1941,7 +1948,7 @@ no_buffer:
  * end based on the transform_size result.
  */
 static GstFlowReturn
-gst_base_transform_getrange (GstPad * pad, guint64 offset,
+gst_base_transform_getrange (GstPad * pad, GstObject * parent, guint64 offset,
     guint length, GstBuffer ** buffer)
 {
   GstBaseTransform *trans;
@@ -1949,7 +1956,7 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
   GstFlowReturn ret;
   GstBuffer *inbuf;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
+  trans = GST_BASE_TRANSFORM (parent);
 
   ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
@@ -1964,8 +1971,6 @@ gst_base_transform_getrange (GstPad * pad, guint64 offset,
   GST_BASE_TRANSFORM_UNLOCK (trans);
 
 done:
-  gst_object_unref (trans);
-
   return ret;
 
   /* ERRORS */
@@ -1978,7 +1983,7 @@ pull_error:
 }
 
 static GstFlowReturn
-gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
+gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstBaseTransform *trans;
   GstBaseTransformClass *klass;
@@ -1987,7 +1992,7 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
   GstClockTime timestamp, duration;
   GstBuffer *outbuf = NULL;
 
-  trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
+  trans = GST_BASE_TRANSFORM (parent);
 
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   duration = GST_BUFFER_DURATION (buffer);
@@ -2033,7 +2038,9 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
 
       /* apply DISCONT flag if the buffer is not yet marked as such */
       if (trans->priv->discont) {
+        GST_DEBUG_OBJECT (trans, "we have a pending DISCONT");
         if (!GST_BUFFER_IS_DISCONT (outbuf)) {
+          GST_DEBUG_OBJECT (trans, "marking DISCONT on output buffer");
           outbuf = gst_buffer_make_writable (outbuf);
           GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
         }
@@ -2043,12 +2050,14 @@ gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
 
       ret = gst_pad_push (trans->srcpad, outbuf);
     } else {
+      GST_DEBUG_OBJECT (trans, "we got return %s", gst_flow_get_name (ret));
       gst_buffer_unref (outbuf);
     }
   }
 
   /* convert internal flow to OK and mark discont for the next buffer. */
   if (ret == GST_BASE_TRANSFORM_FLOW_DROPPED) {
+    GST_DEBUG_OBJECT (trans, "dropped a buffer, marking DISCONT");
     trans->priv->discont = TRUE;
     ret = GST_FLOW_OK;
   }
@@ -2104,7 +2113,7 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
   if (active) {
     GstCaps *incaps, *outcaps;
 
-    if (trans->priv->pad_mode == GST_PAD_ACTIVATE_NONE && bclass->start)
+    if (trans->priv->pad_mode == GST_PAD_MODE_NONE && bclass->start)
       result &= bclass->start (trans);
 
     incaps = gst_pad_get_current_caps (trans->sinkpad);
@@ -2147,7 +2156,7 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
     gst_caps_replace (&trans->cache_caps1, NULL);
     gst_caps_replace (&trans->cache_caps2, NULL);
 
-    if (trans->priv->pad_mode != GST_PAD_ACTIVATE_NONE && bclass->stop)
+    if (trans->priv->pad_mode != GST_PAD_MODE_NONE && bclass->stop)
       result &= bclass->stop (trans);
 
     gst_base_transform_set_allocation (trans, NULL, NULL, 0, 0);
@@ -2157,42 +2166,57 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
 }
 
 static gboolean
-gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
+gst_base_transform_sink_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
-  gboolean result = TRUE;
+  gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
-  result = gst_base_transform_activate (trans, active);
+  trans = GST_BASE_TRANSFORM (parent);
 
-  if (result)
-    trans->priv->pad_mode =
-        active ? GST_PAD_ACTIVATE_PUSH : GST_PAD_ACTIVATE_NONE;
+  switch (mode) {
+    case GST_PAD_MODE_PUSH:
+    {
+      result = gst_base_transform_activate (trans, active);
 
-  gst_object_unref (trans);
+      if (result)
+        trans->priv->pad_mode = active ? GST_PAD_MODE_PUSH : GST_PAD_MODE_NONE;
 
+      break;
+    }
+    default:
+      result = TRUE;
+      break;
+  }
   return result;
 }
 
 static gboolean
-gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
+gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
   gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
-
-  result = gst_pad_activate_pull (trans->sinkpad, active);
+  trans = GST_BASE_TRANSFORM (parent);
 
-  if (result)
-    result &= gst_base_transform_activate (trans, active);
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+    {
+      result =
+          gst_pad_activate_mode (trans->sinkpad, GST_PAD_MODE_PULL, active);
 
-  if (result)
-    trans->priv->pad_mode =
-        active ? GST_PAD_ACTIVATE_PULL : GST_PAD_ACTIVATE_NONE;
+      if (result)
+        result &= gst_base_transform_activate (trans, active);
 
-  gst_object_unref (trans);
+      if (result)
+        trans->priv->pad_mode = active ? mode : GST_PAD_MODE_NONE;
+      break;
+    }
+    default:
+      result = TRUE;
+      break;
+  }
 
   return result;
 }