aggregator: Assert if the sink/src pad type that is to be used is not a GstAggregator...
[platform/upstream/gstreamer.git] / libs / gst / base / gstbasetransform.c
index c05289a..5ddad78 100644 (file)
@@ -23,6 +23,7 @@
 
 /**
  * SECTION:gstbasetransform
+ * @title: GstBaseTransform
  * @short_description: Base class for simple transform filters
  * @see_also: #GstBaseSrc, #GstBaseSink
  *
  * for more concrete use cases.
  *
  * It provides for:
- * <itemizedlist>
- *   <listitem><para>one sinkpad and one srcpad</para></listitem>
- *   <listitem><para>
- *      Possible formats on sink and source pad implemented
- *      with custom transform_caps function. By default uses
- *      same format on sink and source.
- *   </para></listitem>
- *   <listitem><para>Handles state changes</para></listitem>
- *   <listitem><para>Does flushing</para></listitem>
- *   <listitem><para>Push mode</para></listitem>
- *   <listitem><para>
- *       Pull mode if the sub-class transform can operate on arbitrary data
- *    </para></listitem>
- * </itemizedlist>
- *
- * <refsect2>
- * <title>Use Cases</title>
- * <para>
- * <orderedlist>
- * <listitem>
- *   <itemizedlist><title>Passthrough mode</title>
- *   <listitem><para>
- *     Element has no interest in modifying the buffer. It may want to inspect it,
+ *
+ * * one sinkpad and one srcpad
+ * * Possible formats on sink and source pad implemented
+ *   with custom transform_caps function. By default uses
+ *   same format on sink and source.
+ *
+ * * Handles state changes
+ * * Does flushing
+ * * Push mode
+ * * Pull mode if the sub-class transform can operate on arbitrary data
+ *
+ * # Use Cases
+ *
+ * ## Passthrough mode
+ *
+ *   * Element has no interest in modifying the buffer. It may want to inspect it,
  *     in which case the element should have a transform_ip function. If there
  *     is no transform_ip function in passthrough mode, the buffer is pushed
  *     intact.
- *   </para></listitem>
- *   <listitem><para>
- *     The #GstBaseTransformClass.passthrough_on_same_caps variable
+ *
+ *   * The #GstBaseTransformClass.passthrough_on_same_caps variable
  *     will automatically set/unset passthrough based on whether the
  *     element negotiates the same caps on both pads.
- *   </para></listitem>
- *   <listitem><para>
- *     #GstBaseTransformClass.passthrough_on_same_caps on an element that
+ *
+ *   * #GstBaseTransformClass.passthrough_on_same_caps on an element that
  *     doesn't implement a transform_caps function is useful for elements that
  *     only inspect data (such as level)
- *   </para></listitem>
- *   </itemizedlist>
- *   <itemizedlist>
- *   <title>Example elements</title>
- *     <listitem>Level</listitem>
- *     <listitem>Videoscale, audioconvert, videoconvert, audioresample in
- *     certain modes.</listitem>
- *   </itemizedlist>
- * </listitem>
- * <listitem>
- *   <itemizedlist>
- *     <title>Modifications in-place - input buffer and output buffer are the
- *     same thing.</title>
- *   <listitem><para>
- *     The element must implement a transform_ip function.
- *   </para></listitem>
- *   <listitem><para>
- *     Output buffer size must <= input buffer size
- *   </para></listitem>
- *   <listitem><para>
- *     If the always_in_place flag is set, non-writable buffers will be copied
- *     and passed to the transform_ip function, otherwise a new buffer will be
- *     created and the transform function called.
- *   </para></listitem>
- *   <listitem><para>
- *     Incoming writable buffers will be passed to the transform_ip function
- *     immediately.  </para></listitem>
- *   <listitem><para>
- *     only implementing transform_ip and not transform implies always_in_place
- *     = %TRUE
- *   </para></listitem>
- *   </itemizedlist>
- *   <itemizedlist>
- *   <title>Example elements</title>
- *     <listitem>Volume</listitem>
- *     <listitem>Audioconvert in certain modes (signed/unsigned
- *     conversion)</listitem>
- *     <listitem>videoconvert in certain modes (endianness
- *     swapping)</listitem>
- *   </itemizedlist>
- *  </listitem>
- * <listitem>
- *   <itemizedlist>
- *   <title>Modifications only to the caps/metadata of a buffer</title>
- *   <listitem><para>
- *     The element does not require writable data, but non-writable buffers
- *     should be subbuffered so that the meta-information can be replaced.
- *   </para></listitem>
- *   <listitem><para>
- *     Elements wishing to operate in this mode should replace the
- *     prepare_output_buffer method to create subbuffers of the input buffer
- *     and set always_in_place to %TRUE
- *   </para></listitem>
- *   </itemizedlist>
- *   <itemizedlist>
- *   <title>Example elements</title>
- *     <listitem>Capsfilter when setting caps on outgoing buffers that have
- *     none.</listitem>
- *     <listitem>identity when it is going to re-timestamp buffers by
- *     datarate.</listitem>
- *   </itemizedlist>
- * </listitem>
- * <listitem>
- *   <itemizedlist><title>Normal mode</title>
- *   <listitem><para>
- *     always_in_place flag is not set, or there is no transform_ip function
- *   </para></listitem>
- *   <listitem><para>
- *     Element will receive an input buffer and output buffer to operate on.
- *   </para></listitem>
- *   <listitem><para>
- *     Output buffer is allocated by calling the prepare_output_buffer function.
- *   </para></listitem>
- *   </itemizedlist>
- *   <itemizedlist>
- *   <title>Example elements</title>
- *     <listitem>Videoscale, videoconvert, audioconvert when doing
- *     scaling/conversions</listitem>
- *   </itemizedlist>
- * </listitem>
- * <listitem>
- *   <itemizedlist><title>Special output buffer allocations</title>
- *   <listitem><para>
- *     Elements which need to do special allocation of their output buffers
+ *
+ *   * Example elements
+ *
+ *     * Level
+ *     * Videoscale, audioconvert, videoconvert, audioresample in certain modes.
+ *
+ * ## Modifications in-place - input buffer and output buffer are the same thing.
+ *
+ * * The element must implement a transform_ip function.
+ * * Output buffer size must <= input buffer size
+ * * If the always_in_place flag is set, non-writable buffers will be copied
+ *   and passed to the transform_ip function, otherwise a new buffer will be
+ *   created and the transform function called.
+ *
+ * * Incoming writable buffers will be passed to the transform_ip function
+ *   immediately.
+ * * only implementing transform_ip and not transform implies always_in_place = %TRUE
+ *
+ *   * Example elements:
+ *     * Volume
+ *     * Audioconvert in certain modes (signed/unsigned conversion)
+ *     * videoconvert in certain modes (endianness swapping)
+ *
+ * ## Modifications only to the caps/metadata of a buffer
+ *
+ * * The element does not require writable data, but non-writable buffers
+ *   should be subbuffered so that the meta-information can be replaced.
+ *
+ * * Elements wishing to operate in this mode should replace the
+ *   prepare_output_buffer method to create subbuffers of the input buffer
+ *   and set always_in_place to %TRUE
+ *
+ * * Example elements
+ *   * Capsfilter when setting caps on outgoing buffers that have
+ *     none.
+ *   * identity when it is going to re-timestamp buffers by
+ *     datarate.
+ *
+ * ## Normal mode
+ *   * always_in_place flag is not set, or there is no transform_ip function
+ *   * Element will receive an input buffer and output buffer to operate on.
+ *   * Output buffer is allocated by calling the prepare_output_buffer function.
+ *   * Example elements:
+ *     * Videoscale, videoconvert, audioconvert when doing
+ *     scaling/conversions
+ *
+ * ## Special output buffer allocations
+ *   * Elements which need to do special allocation of their output buffers
  *     beyond allocating output buffers via the negotiated allocator or
  *     buffer pool should implement the prepare_output_buffer method.
- *   </para></listitem>
- *   </itemizedlist>
- *   <itemizedlist>
- *   <title>Example elements</title>
- *     <listitem>efence</listitem>
- *   </itemizedlist>
- * </listitem>
- * </orderedlist>
- * </para>
- * </refsect2>
- * <refsect2>
- * <title>Sub-class settable flags on GstBaseTransform</title>
- * <para>
- * <itemizedlist>
- * <listitem><para>
- *   <itemizedlist><title>passthrough</title>
- *     <listitem><para>
- *       Implies that in the current configuration, the sub-class is not
- *       interested in modifying the buffers.
- *     </para></listitem>
- *     <listitem><para>
- *       Elements which are always in passthrough mode whenever the same caps
- *       has been negotiated on both pads can set the class variable
- *       passthrough_on_same_caps to have this behaviour automatically.
- *     </para></listitem>
- *   </itemizedlist>
- * </para></listitem>
- * <listitem><para>
- *   <itemizedlist><title>always_in_place</title>
- *     <listitem><para>
- *       Determines whether a non-writable buffer will be copied before passing
- *       to the transform_ip function.
- *     </para></listitem>
- *     <listitem><para>
- *       Implied %TRUE if no transform function is implemented.
- *     </para></listitem>
- *     <listitem><para>
- *       Implied %FALSE if ONLY transform function is implemented.
- *     </para></listitem>
- *   </itemizedlist>
- * </para></listitem>
- * </itemizedlist>
- * </para>
- * </refsect2>
+ *
+ *   * Example elements:
+ *     * efence
+ *
+ * # Sub-class settable flags on GstBaseTransform
+ *
+ * * passthrough
+ *
+ *   * Implies that in the current configuration, the sub-class is not interested in modifying the buffers.
+ *   * Elements which are always in passthrough mode whenever the same caps has been negotiated on both pads can set the class variable passthrough_on_same_caps to have this behaviour automatically.
+ *
+ * * always_in_place
+ *   * Determines whether a non-writable buffer will be copied before passing
+ *     to the transform_ip function.
+ *
+ *   * Implied %TRUE if no transform function is implemented.
+ *   * Implied %FALSE if ONLY transform function is implemented.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -234,9 +163,6 @@ enum
   PROP_QOS
 };
 
-#define GST_BASE_TRANSFORM_GET_PRIVATE(obj)  \
-    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_TRANSFORM, GstBaseTransformPrivate))
-
 struct _GstBaseTransformPrivate
 {
   /* Set by sub-class */
@@ -278,6 +204,7 @@ struct _GstBaseTransformPrivate
 
 
 static GstElementClass *parent_class = NULL;
+static gint private_offset = 0;
 
 static void gst_base_transform_class_init (GstBaseTransformClass * klass);
 static void gst_base_transform_init (GstBaseTransform * trans,
@@ -310,11 +237,21 @@ gst_base_transform_get_type (void)
 
     _type = g_type_register_static (GST_TYPE_ELEMENT,
         "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);
+
+    private_offset =
+        g_type_add_instance_private (_type, sizeof (GstBaseTransformPrivate));
+
     g_once_init_leave (&base_transform_type, _type);
   }
   return base_transform_type;
 }
 
+static inline GstBaseTransformPrivate *
+gst_base_transform_get_instance_private (GstBaseTransform * self)
+{
+  return (G_STRUCT_MEMBER_P (self, private_offset));
+}
+
 static void gst_base_transform_finalize (GObject * object);
 static void gst_base_transform_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec);
@@ -387,13 +324,14 @@ gst_base_transform_class_init (GstBaseTransformClass * klass)
 
   gobject_class = G_OBJECT_CLASS (klass);
 
+  if (private_offset != 0)
+    g_type_class_adjust_private_offset (klass, &private_offset);
+
   GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,
       "basetransform element");
 
   GST_DEBUG ("gst_base_transform_class_init");
 
-  g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate));
-
   parent_class = g_type_class_peek_parent (klass);
 
   gobject_class->set_property = gst_base_transform_set_property;
@@ -442,7 +380,7 @@ gst_base_transform_init (GstBaseTransform * trans,
 
   GST_DEBUG ("gst_base_transform_init");
 
-  priv = trans->priv = GST_BASE_TRANSFORM_GET_PRIVATE (trans);
+  priv = trans->priv = gst_base_transform_get_instance_private (trans);
 
   pad_template =
       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
@@ -536,7 +474,7 @@ gst_base_transform_transform_caps (GstBaseTransform * trans,
     ret = klass->transform_caps (trans, direction, caps, filter);
     GST_LOG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, ret);
 
-#ifndef G_DISABLE_ASSERT
+#ifdef GST_ENABLE_EXTRA_CHECKS
     if (filter) {
       if (!gst_caps_is_subset (ret, filter)) {
         GstCaps *intersection;
@@ -679,7 +617,7 @@ gst_base_transform_transform_size (GstBaseTransform * trans,
 /* get the caps that can be handled by @pad. We perform:
  *
  *  - take the caps of peer of otherpad,
- *  - filter against the padtemplate of otherpad, 
+ *  - filter against the padtemplate of otherpad,
  *  - calculate all transforms of remaining caps
  *  - filter against template of @pad
  *
@@ -714,7 +652,7 @@ gst_base_transform_query_caps (GstBaseTransform * trans, GstPad * pad,
     GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, peerfilter);
     gst_caps_unref (temp);
 
-    if (!gst_caps_is_empty (peerfilter)) {
+    if (peerfilter && !gst_caps_is_empty (peerfilter)) {
       /* and filter against the template of the other pad */
       GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, otempl);
       /* We keep the caps sorted like the returned caps */
@@ -932,7 +870,7 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
       /* If change are not acceptable, fallback to generic pool */
       if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
               max)) {
-        GST_DEBUG_OBJECT (trans, "unsuported pool, making new pool");
+        GST_DEBUG_OBJECT (trans, "unsupported pool, making new pool");
 
         gst_object_unref (pool);
         pool = gst_buffer_pool_new ();
@@ -960,6 +898,9 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
   return TRUE;
 
 config_failed:
+  if (pool)
+    gst_object_unref (pool);
+
   GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS,
       ("Failed to configure the buffer pool"),
       ("Configuration is most likely invalid, please report this issue."));
@@ -1017,6 +958,15 @@ gst_base_transform_do_bufferpool (GstBaseTransform * trans, GstCaps * outcaps)
   if (!result)
     goto no_decide_allocation;
 
+  /* check again in case the sub-class have switch to passthrough/in-place
+   * after looking at the meta APIs */
+  if (priv->passthrough || priv->always_in_place) {
+    GST_DEBUG_OBJECT (trans, "no doing passthrough, delay bufferpool");
+    gst_base_transform_set_allocation (trans, NULL, NULL, NULL, NULL);
+    gst_query_unref (query);
+    return TRUE;
+  }
+
   /* we got configuration from our peer or the decide_allocation method,
    * parse them */
   if (gst_query_get_n_allocation_params (query) > 0) {
@@ -1285,46 +1235,51 @@ static gboolean
 gst_base_transform_acceptcaps_default (GstBaseTransform * trans,
     GstPadDirection direction, GstCaps * caps)
 {
-  GstPad *pad;
-  GstCaps *allowed;
+  GstPad *pad, *otherpad;
+  GstCaps *templ, *otempl, *ocaps = NULL;
   gboolean ret = TRUE;
 
   pad =
       (direction ==
       GST_PAD_SINK) ? GST_BASE_TRANSFORM_SINK_PAD (trans) :
       GST_BASE_TRANSFORM_SRC_PAD (trans);
+  otherpad =
+      (direction ==
+      GST_PAD_SINK) ? GST_BASE_TRANSFORM_SRC_PAD (trans) :
+      GST_BASE_TRANSFORM_SINK_PAD (trans);
 
   GST_DEBUG_OBJECT (trans, "accept caps %" GST_PTR_FORMAT, caps);
 
-  /* get all the formats we can handle on this pad */
-  allowed = gst_pad_query_caps (pad, caps);
-  if (!allowed) {
-    GST_DEBUG_OBJECT (trans, "gst_pad_query_caps() failed");
-    goto no_transform_possible;
-  }
-
-  GST_DEBUG_OBJECT (trans, "allowed caps %" GST_PTR_FORMAT, allowed);
-
-  /* intersect with the requested format */
-  if (GST_PAD_IS_ACCEPT_INTERSECT (pad)) {
-    GST_DEBUG_OBJECT (pad,
-        "allowed caps intersect %" GST_PTR_FORMAT ", caps %" GST_PTR_FORMAT,
-        allowed, caps);
-    ret = gst_caps_can_intersect (caps, allowed);
-  } else {
-    GST_DEBUG_OBJECT (pad, "allowed caps subset %" GST_PTR_FORMAT ", caps %"
-        GST_PTR_FORMAT, allowed, caps);
-    ret = gst_caps_is_subset (caps, allowed);
-  }
-  gst_caps_unref (allowed);
+  templ = gst_pad_get_pad_template_caps (pad);
+  otempl = gst_pad_get_pad_template_caps (otherpad);
 
-  if (!ret)
+  /* get all the formats we can handle on this pad */
+  GST_DEBUG_OBJECT (trans, "intersect with pad template: %" GST_PTR_FORMAT,
+      templ);
+  if (!gst_caps_can_intersect (caps, templ))
+    goto reject_caps;
+
+  GST_DEBUG_OBJECT (trans, "trying to transform with filter: %"
+      GST_PTR_FORMAT " (the other pad template)", otempl);
+  ocaps = gst_base_transform_transform_caps (trans, direction, caps, otempl);
+  if (!ocaps || gst_caps_is_empty (ocaps))
     goto no_transform_possible;
 
 done:
+  GST_DEBUG_OBJECT (trans, "accept-caps result: %d", ret);
+  if (ocaps)
+    gst_caps_unref (ocaps);
+  gst_caps_unref (templ);
+  gst_caps_unref (otempl);
   return ret;
 
   /* ERRORS */
+reject_caps:
+  {
+    GST_DEBUG_OBJECT (trans, "caps can't intersect with the template");
+    ret = FALSE;
+    goto done;
+  }
 no_transform_possible:
   {
     GST_DEBUG_OBJECT (trans,
@@ -1447,6 +1402,41 @@ gst_base_transform_default_propose_allocation (GstBaseTransform * trans,
 }
 
 static gboolean
+gst_base_transform_reconfigure (GstBaseTransform * trans)
+{
+  gboolean reconfigure, ret = TRUE;
+
+  reconfigure = gst_pad_check_reconfigure (trans->srcpad);
+
+  if (G_UNLIKELY (reconfigure)) {
+    GstCaps *incaps;
+
+    GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
+
+    incaps = gst_pad_get_current_caps (trans->sinkpad);
+    if (incaps == NULL)
+      goto done;
+
+    /* if we need to reconfigure we pretend new caps arrived. This
+     * will reconfigure the transform with the new output format. */
+    if (!gst_base_transform_setcaps (trans, trans->sinkpad, incaps)) {
+      GST_ELEMENT_WARNING (trans, STREAM, FORMAT,
+          ("not negotiated"), ("not negotiated"));
+      ret = FALSE;
+    }
+
+    gst_caps_unref (incaps);
+  }
+
+done:
+
+  if (!ret)
+    gst_pad_mark_reconfigure (trans->srcpad);
+
+  return ret;
+}
+
+static gboolean
 gst_base_transform_default_query (GstBaseTransform * trans,
     GstPadDirection direction, GstQuery * query)
 {
@@ -1474,6 +1464,10 @@ gst_base_transform_default_query (GstBaseTransform * trans,
       if (direction != GST_PAD_SINK)
         goto done;
 
+      ret = gst_base_transform_reconfigure (trans);
+      if (G_UNLIKELY (!ret))
+        goto done;
+
       GST_OBJECT_LOCK (trans);
       if (!priv->negotiated && !priv->passthrough && (klass->set_caps != NULL)) {
         GST_DEBUG_OBJECT (trans,
@@ -1484,7 +1478,6 @@ gst_base_transform_default_query (GstBaseTransform * trans,
 
       decide_query = trans->priv->query;
       trans->priv->query = NULL;
-
       GST_OBJECT_UNLOCK (trans);
 
       GST_DEBUG_OBJECT (trans,
@@ -1576,7 +1569,7 @@ gst_base_transform_query (GstPad * pad, GstObject * parent, GstQuery * query)
   GstBaseTransformClass *bclass;
   gboolean ret = FALSE;
 
-  trans = GST_BASE_TRANSFORM (parent);
+  trans = GST_BASE_TRANSFORM_CAST (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->query)
@@ -1737,10 +1730,15 @@ foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
    * function and when it returns %TRUE */
   if (do_copy) {
     GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
-    GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api));
     /* simply copy then */
-    info->transform_func (outbuf, *meta, inbuf,
-        _gst_meta_transform_copy, &copy_data);
+    if (info->transform_func) {
+      GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api));
+      info->transform_func (outbuf, *meta, inbuf,
+          _gst_meta_transform_copy, &copy_data);
+    } else {
+      GST_DEBUG_OBJECT (trans, "couldn't copy metadata %s",
+          g_type_name (info->api));
+    }
   }
   return TRUE;
 }
@@ -1784,7 +1782,7 @@ not_writable:
   }
 }
 
-/* Given @caps calcultate the size of one unit.
+/* Given @caps calculate the size of one unit.
  *
  * For video caps, this is the size of one frame (and thus one buffer).
  * For audio caps, this is the size of one sample.
@@ -1822,7 +1820,7 @@ gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   res = bclass->get_unit_size (trans, caps, size);
   GST_DEBUG_OBJECT (trans,
-      "caps %" GST_PTR_FORMAT ") has unit size %" G_GSIZE_FORMAT ", res %s",
+      "caps %" GST_PTR_FORMAT " has unit size %" G_GSIZE_FORMAT ", res %s",
       caps, *size, res ? "TRUE" : "FALSE");
 
   if (res) {
@@ -1852,7 +1850,7 @@ gst_base_transform_sink_event (GstPad * pad, GstObject * parent,
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
 
-  trans = GST_BASE_TRANSFORM (parent);
+  trans = GST_BASE_TRANSFORM_CAST (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->sink_event)
@@ -1898,6 +1896,8 @@ gst_base_transform_sink_eventfunc (GstBaseTransform * trans, GstEvent * event)
       /* clear any pending reconfigure flag */
       gst_pad_check_reconfigure (trans->srcpad);
       ret = gst_base_transform_setcaps (trans, trans->sinkpad, caps);
+      if (!ret)
+        gst_pad_mark_reconfigure (trans->srcpad);
 
       forward = FALSE;
       break;
@@ -1931,7 +1931,7 @@ gst_base_transform_src_event (GstPad * pad, GstObject * parent,
   GstBaseTransformClass *bclass;
   gboolean ret = TRUE;
 
-  trans = GST_BASE_TRANSFORM (parent);
+  trans = GST_BASE_TRANSFORM_CAST (parent);
   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
 
   if (bclass->src_event)
@@ -1981,40 +1981,22 @@ default_submit_input_buffer (GstBaseTransform * trans, gboolean is_discont,
   GstBaseTransformClass *bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   GstBaseTransformPrivate *priv = trans->priv;
   GstFlowReturn ret = GST_FLOW_OK;
-  gboolean reconfigure;
   GstClockTime running_time;
   GstClockTime timestamp;
 
-  reconfigure = gst_pad_check_reconfigure (trans->srcpad);
-
-  if (G_UNLIKELY (reconfigure)) {
-    GstCaps *incaps;
-
-    GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
-
-    incaps = gst_pad_get_current_caps (trans->sinkpad);
-    if (incaps == NULL)
-      goto no_reconfigure;
-
-    /* if we need to reconfigure we pretend new caps arrived. This
-     * will reconfigure the transform with the new output format. */
-    if (!gst_base_transform_setcaps (trans, trans->sinkpad, incaps)) {
-      gst_caps_unref (incaps);
-      goto not_negotiated;
-    }
-    gst_caps_unref (incaps);
-  }
+  if (G_UNLIKELY (!gst_base_transform_reconfigure (trans)))
+    goto not_negotiated;
 
-no_reconfigure:
   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
     GST_DEBUG_OBJECT (trans,
-        "handling buffer %p of size %" G_GSIZE_FORMAT " and offset %"
-        G_GUINT64_FORMAT, inbuf, gst_buffer_get_size (inbuf),
-        GST_BUFFER_OFFSET (inbuf));
+        "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT
+        " and offset %" G_GUINT64_FORMAT, inbuf, gst_buffer_get_size (inbuf),
+        GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)), GST_BUFFER_OFFSET (inbuf));
   else
     GST_DEBUG_OBJECT (trans,
-        "handling buffer %p of size %" G_GSIZE_FORMAT " and offset NONE", inbuf,
-        gst_buffer_get_size (inbuf));
+        "handling buffer %p of size %" G_GSIZE_FORMAT ", PTS %" GST_TIME_FORMAT
+        " and offset NONE", inbuf, gst_buffer_get_size (inbuf),
+        GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)));
 
   /* Don't allow buffer handling before negotiation, except in passthrough mode
    * or if the class doesn't implement a set_caps function (in which case it doesn't
@@ -2097,8 +2079,6 @@ not_negotiated:
     gst_buffer_unref (inbuf);
     if (GST_PAD_IS_FLUSHING (trans->srcpad))
       return GST_FLOW_FLUSHING;
-    GST_ELEMENT_WARNING (trans, STREAM, FORMAT,
-        ("not negotiated"), ("not negotiated"));
     return GST_FLOW_NOT_NEGOTIATED;
   }
 }
@@ -2198,7 +2178,7 @@ gst_base_transform_getrange (GstPad * pad, GstObject * parent, guint64 offset,
     guint length, GstBuffer ** buffer)
 {
   GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (parent);
-  GstBaseTransform *trans = GST_BASE_TRANSFORM (parent);
+  GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent);
   GstBaseTransformPrivate *priv = trans->priv;
   GstFlowReturn ret;
   GstBuffer *inbuf = NULL;
@@ -2275,7 +2255,7 @@ pull_error:
 static GstFlowReturn
 gst_base_transform_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
-  GstBaseTransform *trans = GST_BASE_TRANSFORM (parent);
+  GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (parent);
   GstBaseTransformClass *klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   GstBaseTransformPrivate *priv = trans->priv;
   GstFlowReturn ret;
@@ -2372,7 +2352,7 @@ gst_base_transform_set_property (GObject * object, guint prop_id,
 {
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (object);
+  trans = GST_BASE_TRANSFORM_CAST (object);
 
   switch (prop_id) {
     case PROP_QOS:
@@ -2390,7 +2370,7 @@ gst_base_transform_get_property (GObject * object, guint prop_id,
 {
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (object);
+  trans = GST_BASE_TRANSFORM_CAST (object);
 
   switch (prop_id) {
     case PROP_QOS:
@@ -2450,7 +2430,7 @@ gst_base_transform_activate (GstBaseTransform * trans, gboolean active)
     GST_PAD_STREAM_UNLOCK (trans->sinkpad);
 
     priv->have_same_caps = FALSE;
-    /* We can only reset the passthrough mode if the instance told us to 
+    /* We can only reset the passthrough mode if the instance told us to
        handle it in configure_caps */
     if (bclass->passthrough_on_same_caps) {
       gst_base_transform_set_passthrough (trans, FALSE);
@@ -2477,7 +2457,7 @@ gst_base_transform_sink_activate_mode (GstPad * pad, GstObject * parent,
   gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (parent);
+  trans = GST_BASE_TRANSFORM_CAST (parent);
 
   switch (mode) {
     case GST_PAD_MODE_PUSH:
@@ -2503,7 +2483,7 @@ gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
   gboolean result = FALSE;
   GstBaseTransform *trans;
 
-  trans = GST_BASE_TRANSFORM (parent);
+  trans = GST_BASE_TRANSFORM_CAST (parent);
 
   switch (mode) {
     case GST_PAD_MODE_PULL:
@@ -2593,10 +2573,9 @@ gst_base_transform_is_passthrough (GstBaseTransform * trans)
  *
  * Determines whether a non-writable buffer will be copied before passing
  * to the transform_ip function.
- * <itemizedlist>
- *   <listitem>Always %TRUE if no transform function is implemented.</listitem>
- *   <listitem>Always %FALSE if ONLY transform function is implemented.</listitem>
- * </itemizedlist>
+ *
+ *   * Always %TRUE if no transform function is implemented.
+ *   * Always %FALSE if ONLY transform function is implemented.
  *
  * MT safe.
  */
@@ -2869,8 +2848,8 @@ gst_base_transform_get_allocator (GstBaseTransform * trans,
  *
  * Updates the srcpad caps and send the caps downstream. This function
  * can be used by subclasses when they have already negotiated their caps
- * but found a change in them (or computed new informations). This way,
- * they can notify downstream about that change without loosing any
+ * but found a change in them (or computed new information). This way,
+ * they can notify downstream about that change without losing any
  * buffer.
  *
  * Returns: %TRUE if the caps could be send downstream %FALSE otherwise