gstreamer_core/libs/gst/base/gstbasetransform.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /* GStreamer
     1 /* GStreamer
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *                    2000 Wim Taymans <wtay@chello.be>
     3  *                    2005 Wim Taymans <wim@fluendo.com>
     4  *                    2005 Wim Taymans <wim@fluendo.com>
     4  *                    2005 Andy Wingo <wingo@fluendo.com>
     5  *                    2005 Andy Wingo <wingo@fluendo.com>
     5  *                    2005 Thomas Vander Stichele <thomas at apestaart dot org>
     6  *                    2005 Thomas Vander Stichele <thomas at apestaart dot org>
     6  *                    2008 Wim Taymans <wim.taymans@gmail.com>
       
     7  *
     7  *
     8  * This library is free software; you can redistribute it and/or
     8  * This library is free software; you can redistribute it and/or
     9  * modify it under the terms of the GNU Library General Public
     9  * modify it under the terms of the GNU Library General Public
    10  * License as published by the Free Software Foundation; either
    10  * License as published by the Free Software Foundation; either
    11  * version 2 of the License, or (at your option) any later version.
    11  * version 2 of the License, or (at your option) any later version.
    42  *   <listitem><para>
    42  *   <listitem><para>
    43  *       Pull mode if the sub-class transform can operate on arbitrary data
    43  *       Pull mode if the sub-class transform can operate on arbitrary data
    44  *    </para></listitem>
    44  *    </para></listitem>
    45  * </itemizedlist>
    45  * </itemizedlist>
    46  *
    46  *
    47  * <refsect2>
    47  * Use Cases:
    48  * <title>Use Cases</title>
       
    49  * <para>
       
    50  * <orderedlist>
    48  * <orderedlist>
    51  * <listitem>
    49  * <listitem>
    52  *   <itemizedlist><title>Passthrough mode</title>
    50  *   <itemizedlist><title>Passthrough mode</title>
    53  *   <listitem><para>
    51  *   <listitem><para>
    54  *     Element has no interest in modifying the buffer. It may want to inspect it,
    52  *     Element has no interest in modifying the buffer. It may want to inspect it,
   158  *   <title>Example elements</title>
   156  *   <title>Example elements</title>
   159  *     <listitem>efence</listitem>
   157  *     <listitem>efence</listitem>
   160  *   </itemizedlist>
   158  *   </itemizedlist>
   161  * </listitem>
   159  * </listitem>
   162  * </orderedlist>
   160  * </orderedlist>
   163  * </para>
   161  *
   164  * </refsect2>
   162  * <itemizedlist><title>Sub-class settable flags on GstBaseTransform</title>
   165  * <refsect2>
       
   166  * <title>Sub-class settable flags on GstBaseTransform</title>
       
   167  * <para>
       
   168  * <itemizedlist>
       
   169  * <listitem><para>
   163  * <listitem><para>
   170  *   <itemizedlist><title>passthrough</title>
   164  *   <itemizedlist><title>passthrough</title>
   171  *     <listitem><para>
   165  *     <listitem><para>
   172  *       Implies that in the current configuration, the sub-class is not
   166  *       Implies that in the current configuration, the sub-class is not
   173  *       interested in modifying the buffers.
   167  *       interested in modifying the buffers.
   192  *       Implied FALSE if ONLY transform function is implemented.
   186  *       Implied FALSE if ONLY transform function is implemented.
   193  *     </para></listitem>
   187  *     </para></listitem>
   194  *   </itemizedlist>
   188  *   </itemizedlist>
   195  * </para></listitem>
   189  * </para></listitem>
   196  * </itemizedlist>
   190  * </itemizedlist>
   197  * </para>
   191  *
   198  * </refsect2>
   192 */
   199  */
       
   200 
   193 
   201 #ifdef HAVE_CONFIG_H
   194 #ifdef HAVE_CONFIG_H
   202 #  include "config.h"
   195 #  include "config.h"
   203 #endif
   196 #endif
   204 
   197 
   250   gboolean discont;
   243   gboolean discont;
   251 
   244 
   252   GstActivateMode pad_mode;
   245   GstActivateMode pad_mode;
   253 
   246 
   254   gboolean gap_aware;
   247   gboolean gap_aware;
   255 
       
   256   /* caps used for allocating buffers */
       
   257   gboolean proxy_alloc;
       
   258   GstCaps *sink_alloc;
       
   259   GstCaps *src_alloc;
       
   260   /* upstream caps and size suggestions */
       
   261   GstCaps *sink_suggest;
       
   262   guint size_suggest;
       
   263   gboolean suggest_pending;
       
   264 
       
   265   gboolean reconfigure;
       
   266 };
   248 };
   267 
   249 
   268 static GstElementClass *parent_class = NULL;
   250 static GstElementClass *parent_class = NULL;
   269 
   251 
   270 static void gst_base_transform_class_init (GstBaseTransformClass * klass);
   252 static void gst_base_transform_class_init (GstBaseTransformClass * klass);
   271 static void gst_base_transform_init (GstBaseTransform * trans,
   253 static void gst_base_transform_init (GstBaseTransform * trans,
   272     GstBaseTransformClass * klass);
   254     GstBaseTransformClass * klass);
   273 static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform
   255 static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform
   274     * trans, GstBuffer * input, GstBuffer ** buf);
   256     * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);
   275 #ifdef __SYMBIAN32__
   257 #ifdef __SYMBIAN32__
   276 EXPORT_C
   258 EXPORT_C
   277 #endif
   259 #endif
   278 
   260 
   279 
   261 
   280 GType
   262 GType
   281 gst_base_transform_get_type (void)
   263 gst_base_transform_get_type (void)
   282 {
   264 {
   283   static volatile gsize base_transform_type = 0;
   265   static GType base_transform_type = 0;
   284 
   266 
   285   if (g_once_init_enter (&base_transform_type)) {
   267   if (!base_transform_type) {
   286     GType _type;
       
   287     static const GTypeInfo base_transform_info = {
   268     static const GTypeInfo base_transform_info = {
   288       sizeof (GstBaseTransformClass),
   269       sizeof (GstBaseTransformClass),
   289       NULL,
   270       NULL,
   290       NULL,
   271       NULL,
   291       (GClassInitFunc) gst_base_transform_class_init,
   272       (GClassInitFunc) gst_base_transform_class_init,
   294       sizeof (GstBaseTransform),
   275       sizeof (GstBaseTransform),
   295       0,
   276       0,
   296       (GInstanceInitFunc) gst_base_transform_init,
   277       (GInstanceInitFunc) gst_base_transform_init,
   297     };
   278     };
   298 
   279 
   299     _type = g_type_register_static (GST_TYPE_ELEMENT,
   280     base_transform_type = g_type_register_static (GST_TYPE_ELEMENT,
   300         "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);
   281         "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);
   301     g_once_init_leave (&base_transform_type, _type);
       
   302   }
   282   }
   303   return base_transform_type;
   283   return base_transform_type;
   304 }
   284 }
   305 
   285 
   306 static void gst_base_transform_finalize (GObject * object);
   286 static void gst_base_transform_finalize (GObject * object);
   327 static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
   307 static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,
   328     guint length, GstBuffer ** buffer);
   308     guint length, GstBuffer ** buffer);
   329 static GstFlowReturn gst_base_transform_chain (GstPad * pad,
   309 static GstFlowReturn gst_base_transform_chain (GstPad * pad,
   330     GstBuffer * buffer);
   310     GstBuffer * buffer);
   331 static GstCaps *gst_base_transform_getcaps (GstPad * pad);
   311 static GstCaps *gst_base_transform_getcaps (GstPad * pad);
   332 static gboolean gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps);
       
   333 static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
   312 static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);
   334 static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
   313 static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,
   335     guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
   314     guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
   336 
   315 
   337 /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
   316 /* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */
   341 {
   320 {
   342   GstBaseTransform *trans;
   321   GstBaseTransform *trans;
   343 
   322 
   344   trans = GST_BASE_TRANSFORM (object);
   323   trans = GST_BASE_TRANSFORM (object);
   345 
   324 
   346   gst_caps_replace (&trans->priv->sink_suggest, NULL);
       
   347   g_mutex_free (trans->transform_lock);
   325   g_mutex_free (trans->transform_lock);
   348 
   326 
   349   G_OBJECT_CLASS (parent_class)->finalize (object);
   327   G_OBJECT_CLASS (parent_class)->finalize (object);
   350 }
   328 }
   351 
   329 
   356 
   334 
   357   gobject_class = G_OBJECT_CLASS (klass);
   335   gobject_class = G_OBJECT_CLASS (klass);
   358 
   336 
   359   GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,
   337   GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,
   360       "basetransform element");
   338       "basetransform element");
   361 
       
   362   GST_DEBUG ("gst_base_transform_class_init");
       
   363 
   339 
   364   g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate));
   340   g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate));
   365 
   341 
   366   parent_class = g_type_class_peek_parent (klass);
   342   parent_class = g_type_class_peek_parent (klass);
   367 
   343 
   370   gobject_class->get_property =
   346   gobject_class->get_property =
   371       GST_DEBUG_FUNCPTR (gst_base_transform_get_property);
   347       GST_DEBUG_FUNCPTR (gst_base_transform_get_property);
   372 
   348 
   373   g_object_class_install_property (gobject_class, PROP_QOS,
   349   g_object_class_install_property (gobject_class, PROP_QOS,
   374       g_param_spec_boolean ("qos", "QoS", "Handle Quality-of-Service events",
   350       g_param_spec_boolean ("qos", "QoS", "Handle Quality-of-Service events",
   375           DEFAULT_PROP_QOS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   351           DEFAULT_PROP_QOS, G_PARAM_READWRITE));
   376 
   352 
   377   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize);
   353   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize);
   378 
   354 
   379   klass->passthrough_on_same_caps = FALSE;
   355   klass->passthrough_on_same_caps = FALSE;
   380   klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
   356   klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);
   395       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
   371       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
   396   g_return_if_fail (pad_template != NULL);
   372   g_return_if_fail (pad_template != NULL);
   397   trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
   373   trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");
   398   gst_pad_set_getcaps_function (trans->sinkpad,
   374   gst_pad_set_getcaps_function (trans->sinkpad,
   399       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   375       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   400   gst_pad_set_acceptcaps_function (trans->sinkpad,
       
   401       GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
       
   402   gst_pad_set_setcaps_function (trans->sinkpad,
   376   gst_pad_set_setcaps_function (trans->sinkpad,
   403       GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
   377       GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
   404   gst_pad_set_event_function (trans->sinkpad,
   378   gst_pad_set_event_function (trans->sinkpad,
   405       GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
   379       GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));
   406   gst_pad_set_chain_function (trans->sinkpad,
   380   gst_pad_set_chain_function (trans->sinkpad,
   415       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
   389       gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
   416   g_return_if_fail (pad_template != NULL);
   390   g_return_if_fail (pad_template != NULL);
   417   trans->srcpad = gst_pad_new_from_template (pad_template, "src");
   391   trans->srcpad = gst_pad_new_from_template (pad_template, "src");
   418   gst_pad_set_getcaps_function (trans->srcpad,
   392   gst_pad_set_getcaps_function (trans->srcpad,
   419       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   393       GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));
   420   gst_pad_set_acceptcaps_function (trans->srcpad,
   394   gst_pad_set_setcaps_function (trans->srcpad,
   421       GST_DEBUG_FUNCPTR (gst_base_transform_acceptcaps));
   395       GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));
   422   gst_pad_set_event_function (trans->srcpad,
   396   gst_pad_set_event_function (trans->srcpad,
   423       GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
   397       GST_DEBUG_FUNCPTR (gst_base_transform_src_event));
   424   gst_pad_set_checkgetrange_function (trans->srcpad,
   398   gst_pad_set_checkgetrange_function (trans->srcpad,
   425       GST_DEBUG_FUNCPTR (gst_base_transform_check_get_range));
   399       GST_DEBUG_FUNCPTR (gst_base_transform_check_get_range));
   426   gst_pad_set_getrange_function (trans->srcpad,
   400   gst_pad_set_getrange_function (trans->srcpad,
   428   gst_pad_set_activatepull_function (trans->srcpad,
   402   gst_pad_set_activatepull_function (trans->srcpad,
   429       GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
   403       GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));
   430   gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
   404   gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);
   431 
   405 
   432   trans->transform_lock = g_mutex_new ();
   406   trans->transform_lock = g_mutex_new ();
       
   407   trans->delay_configure = FALSE;
   433   trans->pending_configure = FALSE;
   408   trans->pending_configure = FALSE;
   434   trans->priv->qos_enabled = DEFAULT_PROP_QOS;
   409   trans->priv->qos_enabled = DEFAULT_PROP_QOS;
   435   trans->cache_caps1 = NULL;
   410   trans->cache_caps1 = NULL;
   436   trans->cache_caps2 = NULL;
   411   trans->cache_caps2 = NULL;
   437   trans->priv->pad_mode = GST_ACTIVATE_NONE;
   412   trans->priv->pad_mode = GST_ACTIVATE_NONE;
   441   if (bclass->transform == NULL) {
   416   if (bclass->transform == NULL) {
   442     /* If no transform function, always_in_place is TRUE */
   417     /* If no transform function, always_in_place is TRUE */
   443     GST_DEBUG_OBJECT (trans, "setting in_place TRUE");
   418     GST_DEBUG_OBJECT (trans, "setting in_place TRUE");
   444     trans->always_in_place = TRUE;
   419     trans->always_in_place = TRUE;
   445 
   420 
   446     if (bclass->transform_ip == NULL) {
   421     if (bclass->transform_ip == NULL)
   447       GST_DEBUG_OBJECT (trans, "setting passthrough TRUE");
       
   448       trans->passthrough = TRUE;
   422       trans->passthrough = TRUE;
   449     }
       
   450   }
   423   }
   451 }
   424 }
   452 
   425 
   453 /* given @caps on the src or sink pad (given by @direction)
   426 /* given @caps on the src or sink pad (given by @direction)
   454  * calculate the possible caps on the other pad.
   427  * calculate the possible caps on the other pad.
   460     GstPadDirection direction, GstCaps * caps)
   433     GstPadDirection direction, GstCaps * caps)
   461 {
   434 {
   462   GstCaps *ret;
   435   GstCaps *ret;
   463   GstBaseTransformClass *klass;
   436   GstBaseTransformClass *klass;
   464 
   437 
   465   if (caps == NULL)
       
   466     return NULL;
       
   467 
       
   468   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   438   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   469 
   439 
   470   /* if there is a custom transform function, use this */
   440   /* if there is a custom transform function, use this */
   471   if (klass->transform_caps) {
   441   if (klass->transform_caps) {
   472     GstCaps *temp;
   442     GstCaps *temp;
   483       GST_DEBUG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, temp);
   453       GST_DEBUG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, temp);
   484 
   454 
   485       temp = gst_caps_make_writable (temp);
   455       temp = gst_caps_make_writable (temp);
   486       gst_caps_append (ret, temp);
   456       gst_caps_append (ret, temp);
   487     } else {
   457     } else {
   488       gint n = gst_caps_get_size (caps);
       
   489       /* we send caps with just one structure to the transform
   458       /* we send caps with just one structure to the transform
   490        * function as this is easier for the element */
   459        * function as this is easier for the element */
   491       for (i = 0; i < n; i++) {
   460       for (i = 0; i < gst_caps_get_size (caps); i++) {
   492         GstCaps *nth;
   461         GstCaps *nth;
   493 
   462 
   494         nth = gst_caps_copy_nth (caps, i);
   463         nth = gst_caps_copy_nth (caps, i);
   495         GST_LOG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
   464         GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);
   496         temp = klass->transform_caps (trans, direction, nth);
   465         temp = klass->transform_caps (trans, direction, nth);
   497         gst_caps_unref (nth);
   466         gst_caps_unref (nth);
   498         GST_LOG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
   467         GST_DEBUG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);
   499 
   468 
   500         temp = gst_caps_make_writable (temp);
   469         temp = gst_caps_make_writable (temp);
   501 
   470         /* FIXME: here we need to only append those structures, that are not yet
   502         /* here we need to only append those structures, that are not yet
   471          * in there
   503          * in there, we use the merge function for this */
   472          * gst_caps_append (ret, temp);
       
   473          */
   504         gst_caps_merge (ret, temp);
   474         gst_caps_merge (ret, temp);
   505 
       
   506         GST_LOG_OBJECT (trans, "  merged[%d]: %" GST_PTR_FORMAT, i, ret);
       
   507       }
   475       }
   508       GST_LOG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
   476       GST_DEBUG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));
   509       /* FIXME: we can't do much simplification here because we don't really want to
   477       /* now simplify caps
   510        * change the caps order
   478          gst_caps_do_simplify (ret);
   511        gst_caps_do_simplify (ret);
   479          GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));
   512        GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));
       
   513        */
   480        */
   514     }
   481     }
   515   } else {
   482   } else {
   516     GST_DEBUG_OBJECT (trans, "identity from: %" GST_PTR_FORMAT, caps);
   483     /* else use the identity transform */
   517     /* no transform function, use the identity transform */
       
   518     ret = gst_caps_ref (caps);
   484     ret = gst_caps_ref (caps);
   519   }
   485   }
   520 
   486 
   521   GST_DEBUG_OBJECT (trans, "to: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (ret),
   487   GST_DEBUG_OBJECT (trans, "to: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (ret),
   522       ret);
   488       ret);
   523 
   489 
   524   return ret;
   490   return ret;
   525 }
   491 }
   526 
   492 
   527 /* transform a buffer of @size with @caps on the pad with @direction to
       
   528  * the size of a buffer with @othercaps and store the result in @othersize
       
   529  *
       
   530  * We have two ways of doing this:
       
   531  *  1) use a custom transform size function, this is for complicated custom
       
   532  *     cases with no fixed unit_size.
       
   533  *  2) use the unit_size functions where there is a relationship between the
       
   534  *     caps and the size of a buffer.
       
   535  */
       
   536 static gboolean
   493 static gboolean
   537 gst_base_transform_transform_size (GstBaseTransform * trans,
   494 gst_base_transform_transform_size (GstBaseTransform * trans,
   538     GstPadDirection direction, GstCaps * caps,
   495     GstPadDirection direction, GstCaps * caps,
   539     guint size, GstCaps * othercaps, guint * othersize)
   496     guint size, GstCaps * othercaps, guint * othersize)
   540 {
   497 {
   546 
   503 
   547   GST_DEBUG_OBJECT (trans, "asked to transform size %d for caps %"
   504   GST_DEBUG_OBJECT (trans, "asked to transform size %d for caps %"
   548       GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
   505       GST_PTR_FORMAT " to size for caps %" GST_PTR_FORMAT " in direction %s",
   549       size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
   506       size, caps, othercaps, direction == GST_PAD_SRC ? "SRC" : "SINK");
   550 
   507 
       
   508   /* if there is a custom transform function, use this */
   551   if (klass->transform_size) {
   509   if (klass->transform_size) {
   552     /* if there is a custom transform function, use this */
       
   553     ret = klass->transform_size (trans, direction, caps, size, othercaps,
   510     ret = klass->transform_size (trans, direction, caps, size, othercaps,
   554         othersize);
   511         othersize);
   555   } else {
   512   } else {
   556     /* there is no transform_size function, we have to use the unit_size
       
   557      * functions. This method assumes there is a fixed unit_size associated with
       
   558      * each caps. We provide the same amount of units on both sides. */
       
   559     if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))
   513     if (!gst_base_transform_get_unit_size (trans, caps, &inunitsize))
   560       goto no_in_size;
   514       goto no_in_size;
   561 
   515 
   562     GST_DEBUG_OBJECT (trans, "input size %d, input unit size %d", size,
   516     GST_DEBUG_OBJECT (trans, "input size %d, input unit size %d", size,
   563         inunitsize);
   517         inunitsize);
   564 
   518 
   565     /* input size must be a multiple of the unit_size of the input caps */
       
   566     if (inunitsize == 0 || (size % inunitsize != 0))
   519     if (inunitsize == 0 || (size % inunitsize != 0))
   567       goto no_multiple;
   520       goto no_multiple;
   568 
   521 
   569     /* get the amount of units */
       
   570     units = size / inunitsize;
   522     units = size / inunitsize;
   571 
       
   572     /* now get the unit size of the output */
       
   573     if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize))
   523     if (!gst_base_transform_get_unit_size (trans, othercaps, &outunitsize))
   574       goto no_out_size;
   524       goto no_out_size;
   575 
   525 
   576     /* the output size is the unit_size times the amount of units on the
       
   577      * input */
       
   578     *othersize = units * outunitsize;
   526     *othersize = units * outunitsize;
   579     GST_DEBUG_OBJECT (trans, "transformed size to %d", *othersize);
   527     GST_DEBUG_OBJECT (trans, "transformed size to %d", *othersize);
   580 
   528 
   581     ret = TRUE;
   529     ret = TRUE;
   582   }
   530   }
   603     g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans));
   551     g_warning ("%s: could not get out_size", GST_ELEMENT_NAME (trans));
   604     return FALSE;
   552     return FALSE;
   605   }
   553   }
   606 }
   554 }
   607 
   555 
   608 /* get the caps that can be handled by @pad. We perform:
       
   609  *
       
   610  *  - take the caps of peer of otherpad,
       
   611  *  - filter against the padtemplate of otherpad, 
       
   612  *  - calculate all transforms of remaining caps
       
   613  *  - filter against template of @pad
       
   614  *
       
   615  * If there is no peer, we simply return the caps of the padtemplate of pad.
       
   616  */
       
   617 static GstCaps *
   556 static GstCaps *
   618 gst_base_transform_getcaps (GstPad * pad)
   557 gst_base_transform_getcaps (GstPad * pad)
   619 {
   558 {
   620   GstBaseTransform *trans;
   559   GstBaseTransform *trans;
   621   GstPad *otherpad;
   560   GstPad *otherpad;
   637     templ = gst_pad_get_pad_template_caps (otherpad);
   576     templ = gst_pad_get_pad_template_caps (otherpad);
   638     GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
   577     GST_DEBUG_OBJECT (pad, "our template  %" GST_PTR_FORMAT, templ);
   639     temp = gst_caps_intersect (caps, templ);
   578     temp = gst_caps_intersect (caps, templ);
   640     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
   579     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
   641     gst_caps_unref (caps);
   580     gst_caps_unref (caps);
   642 
       
   643     /* then see what we can transform this to */
   581     /* then see what we can transform this to */
   644     caps = gst_base_transform_transform_caps (trans,
   582     caps = gst_base_transform_transform_caps (trans,
   645         GST_PAD_DIRECTION (otherpad), temp);
   583         GST_PAD_DIRECTION (otherpad), temp);
   646     GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, caps);
   584     GST_DEBUG_OBJECT (pad, "transformed  %" GST_PTR_FORMAT, caps);
   647     gst_caps_unref (temp);
   585     gst_caps_unref (temp);
   655     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
   593     GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
   656     gst_caps_unref (caps);
   594     gst_caps_unref (caps);
   657     /* this is what we can do */
   595     /* this is what we can do */
   658     caps = temp;
   596     caps = temp;
   659   } else {
   597   } else {
   660     /* no peer or the peer can do anything, our padtemplate is enough then */
   598     /* no peer, our padtemplate is enough then */
   661     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
   599     caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
   662   }
   600   }
   663 
   601 
   664 done:
   602 done:
   665   GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);
   603   GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);
   678   gboolean ret = TRUE;
   616   gboolean ret = TRUE;
   679   GstBaseTransformClass *klass;
   617   GstBaseTransformClass *klass;
   680 
   618 
   681   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   619   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   682 
   620 
   683   GST_DEBUG_OBJECT (trans, "in caps:  %" GST_PTR_FORMAT, in);
       
   684   GST_DEBUG_OBJECT (trans, "out caps: %" GST_PTR_FORMAT, out);
       
   685 
       
   686   /* clear the cache */
   621   /* clear the cache */
   687   gst_caps_replace (&trans->cache_caps1, NULL);
   622   gst_caps_replace (&trans->cache_caps1, NULL);
   688   gst_caps_replace (&trans->cache_caps2, NULL);
   623   gst_caps_replace (&trans->cache_caps2, NULL);
   689 
       
   690   /* figure out same caps state */
       
   691   trans->have_same_caps = gst_caps_is_equal (in, out);
       
   692   GST_DEBUG_OBJECT (trans, "have_same_caps: %d", trans->have_same_caps);
       
   693 
   624 
   694   /* If we've a transform_ip method and same input/output caps, set in_place
   625   /* If we've a transform_ip method and same input/output caps, set in_place
   695    * by default. If for some reason the sub-class prefers using a transform
   626    * by default. If for some reason the sub-class prefers using a transform
   696    * function, it can clear the in place flag in the set_caps */
   627    * function, it can clear the in place flag in the set_caps */
   697   gst_base_transform_set_in_place (trans,
   628   gst_base_transform_set_in_place (trans,
   711   trans->negotiated = ret;
   642   trans->negotiated = ret;
   712 
   643 
   713   return ret;
   644   return ret;
   714 }
   645 }
   715 
   646 
   716 /* check if caps @in on @pad can be transformed to @out on the other pad.
   647 /* called when new caps arrive on the sink or source pad */
   717  * We don't have a vmethod to test this yet so we have to do a somewhat less
       
   718  * efficient check for this.
       
   719  */
       
   720 static gboolean
   648 static gboolean
   721 gst_base_transform_can_transform (GstBaseTransform * trans, GstPad * pad,
   649 gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
   722     GstCaps * in, GstCaps * out)
   650 {
   723 {
   651   GstBaseTransform *trans;
   724   GstCaps *othercaps;
       
   725 
       
   726   /* convert the in caps to all possible out caps */
       
   727   othercaps =
       
   728       gst_base_transform_transform_caps (trans, GST_PAD_DIRECTION (pad), in);
       
   729 
       
   730   /* check if transform is empty */
       
   731   if (!othercaps || gst_caps_is_empty (othercaps))
       
   732     goto no_transform;
       
   733 
       
   734   /* check if the out caps is a subset of the othercaps */
       
   735   if (!gst_caps_is_subset (out, othercaps))
       
   736     goto no_subset;
       
   737 
       
   738   if (othercaps)
       
   739     gst_caps_unref (othercaps);
       
   740 
       
   741   GST_DEBUG_OBJECT (trans, "from %" GST_PTR_FORMAT, in);
       
   742   GST_DEBUG_OBJECT (trans, "to   %" GST_PTR_FORMAT, out);
       
   743 
       
   744   return TRUE;
       
   745 
       
   746   /* ERRORS */
       
   747 no_transform:
       
   748   {
       
   749     GST_DEBUG_OBJECT (trans,
       
   750         "transform returned useless %" GST_PTR_FORMAT, othercaps);
       
   751     if (othercaps)
       
   752       gst_caps_unref (othercaps);
       
   753     return FALSE;
       
   754   }
       
   755 no_subset:
       
   756   {
       
   757     GST_DEBUG_OBJECT (trans, "no subset");
       
   758     if (othercaps)
       
   759       gst_caps_unref (othercaps);
       
   760     return FALSE;
       
   761   }
       
   762 }
       
   763 
       
   764 /* given a fixed @caps on @pad, create the best possible caps for the
       
   765  * other pad.
       
   766  * @caps must be fixed when calling this function.
       
   767  *
       
   768  * This function calls the transform caps vmethod of the basetransform to figure
       
   769  * out the possible target formats. It then tries to select the best format from
       
   770  * this list by:
       
   771  *
       
   772  * - attempt passthrough if the target caps is a superset of the input caps
       
   773  * - fixating by using peer caps
       
   774  * - fixating with transform fixate function
       
   775  * - fixating with pad fixate functions.
       
   776  *
       
   777  * this function returns a caps that can be transformed into and is accepted by
       
   778  * the peer element.
       
   779  */
       
   780 static GstCaps *
       
   781 gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
       
   782     GstCaps * caps)
       
   783 {
       
   784   GstBaseTransformClass *klass;
   652   GstBaseTransformClass *klass;
   785   GstPad *otherpad, *otherpeer;
   653   GstPad *otherpad, *otherpeer;
   786   GstCaps *othercaps;
   654   GstCaps *othercaps = NULL;
       
   655   gboolean ret = TRUE;
   787   gboolean peer_checked = FALSE;
   656   gboolean peer_checked = FALSE;
   788 
   657 
   789   /* caps must be fixed here, this is a programming error if it's not */
   658   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
   790   g_return_val_if_fail (gst_caps_is_fixed (caps), NULL);
       
   791 
       
   792   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   659   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   793 
   660 
   794   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
   661   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
   795   otherpeer = gst_pad_get_peer (otherpad);
   662   otherpeer = gst_pad_get_peer (otherpad);
   796 
   663 
   797   /* see how we can transform the input caps. We need to do this even for
   664   /* if we get called recursively, we bail out now to avoid an
   798    * passthrough because it might be possible that this element cannot support
   665    * infinite loop. */
   799    * passthrough at all. */
   666   if (GST_PAD_IS_IN_SETCAPS (otherpad))
       
   667     goto done;
       
   668 
       
   669   /* caps must be fixed here */
       
   670   if (!gst_caps_is_fixed (caps))
       
   671     goto unfixed_caps;
       
   672 
       
   673   /* see how we can transform the input caps. */
   800   othercaps = gst_base_transform_transform_caps (trans,
   674   othercaps = gst_base_transform_transform_caps (trans,
   801       GST_PAD_DIRECTION (pad), caps);
   675       GST_PAD_DIRECTION (pad), caps);
   802 
   676 
   803   /* The caps we can actually output is the intersection of the transformed
   677   /* The caps we can actually output is the intersection of the transformed
   804    * caps with the pad template for the pad */
   678    * caps with the pad template for the pad */
   805   if (othercaps) {
   679   if (othercaps) {
   806     GstCaps *intersect;
   680     GstCaps *intersect;
   807     const GstCaps *templ_caps;
   681     const GstCaps *templ_caps;
   808 
   682 
   809     templ_caps = gst_pad_get_pad_template_caps (otherpad);
   683     templ_caps = gst_pad_get_pad_template_caps (otherpad);
   810     GST_DEBUG_OBJECT (trans,
       
   811         "intersecting against padtemplate %" GST_PTR_FORMAT, templ_caps);
       
   812 
       
   813     intersect = gst_caps_intersect (othercaps, templ_caps);
   684     intersect = gst_caps_intersect (othercaps, templ_caps);
   814 
   685 
   815     gst_caps_unref (othercaps);
   686     gst_caps_unref (othercaps);
   816     othercaps = intersect;
   687     othercaps = intersect;
   817   }
   688   }
   820   if (!othercaps || gst_caps_is_empty (othercaps))
   691   if (!othercaps || gst_caps_is_empty (othercaps))
   821     goto no_transform;
   692     goto no_transform;
   822 
   693 
   823   /* if the othercaps are not fixed, we need to fixate them, first attempt
   694   /* if the othercaps are not fixed, we need to fixate them, first attempt
   824    * is by attempting passthrough if the othercaps are a superset of caps. */
   695    * is by attempting passthrough if the othercaps are a superset of caps. */
   825   /* FIXME. maybe the caps is not fixed because it has multiple structures of
       
   826    * fixed caps */
       
   827   if (!gst_caps_is_fixed (othercaps)) {
   696   if (!gst_caps_is_fixed (othercaps)) {
   828     GstCaps *temp;
   697     GstCaps *temp;
   829 
   698 
   830     GST_DEBUG_OBJECT (trans,
   699     GST_DEBUG_OBJECT (trans,
   831         "transform returned non fixed  %" GST_PTR_FORMAT, othercaps);
   700         "transform returned non fixed  %" GST_PTR_FORMAT, othercaps);
   833     /* see if the target caps are a superset of the source caps, in this
   702     /* see if the target caps are a superset of the source caps, in this
   834      * case we can try to perform passthrough */
   703      * case we can try to perform passthrough */
   835     temp = gst_caps_intersect (othercaps, caps);
   704     temp = gst_caps_intersect (othercaps, caps);
   836     GST_DEBUG_OBJECT (trans, "intersect returned %" GST_PTR_FORMAT, temp);
   705     GST_DEBUG_OBJECT (trans, "intersect returned %" GST_PTR_FORMAT, temp);
   837     if (temp) {
   706     if (temp) {
   838       if (!gst_caps_is_empty (temp)) {
   707       if (!gst_caps_is_empty (temp) && otherpeer) {
   839         GST_DEBUG_OBJECT (trans, "try passthrough with %" GST_PTR_FORMAT, caps);
   708         GST_DEBUG_OBJECT (trans, "try passthrough with %" GST_PTR_FORMAT, caps);
   840         if (otherpeer) {
   709         /* try passthrough. we know it's fixed, because caps is fixed */
   841           /* try passthrough. we know it's fixed, because caps is fixed */
   710         if (gst_pad_accept_caps (otherpeer, caps)) {
   842           if (gst_pad_accept_caps (otherpeer, caps)) {
   711           GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);
   843             GST_DEBUG_OBJECT (trans, "peer accepted %" GST_PTR_FORMAT, caps);
   712           /* peer accepted unmodified caps, we free the original non-fixed
   844             /* peer accepted unmodified caps, we free the original non-fixed
   713            * caps and work with the passthrough caps */
   845              * caps and work with the passthrough caps */
       
   846             gst_caps_unref (othercaps);
       
   847             othercaps = gst_caps_ref (caps);
       
   848             /* mark that we checked othercaps with the peer, this
       
   849              * makes sure we don't call accept_caps again with these same
       
   850              * caps */
       
   851             peer_checked = TRUE;
       
   852           } else {
       
   853             GST_DEBUG_OBJECT (trans,
       
   854                 "peer did not accept %" GST_PTR_FORMAT, caps);
       
   855           }
       
   856         } else {
       
   857           GST_DEBUG_OBJECT (trans, "no peer, doing passthrough");
       
   858           gst_caps_unref (othercaps);
   714           gst_caps_unref (othercaps);
   859           othercaps = gst_caps_ref (caps);
   715           othercaps = gst_caps_ref (caps);
       
   716           /* mark that we checked othercaps with the peer, this
       
   717            * makes sure we don't call accept_caps again with these same
       
   718            * caps */
       
   719           peer_checked = TRUE;
       
   720         } else {
       
   721           GST_DEBUG_OBJECT (trans,
       
   722               "peer did not accept %" GST_PTR_FORMAT, caps);
   860         }
   723         }
   861       }
   724       }
   862       gst_caps_unref (temp);
   725       gst_caps_unref (temp);
   863     }
   726     }
   864   }
   727   }
   919           " on pad %s:%s using gst_pad_fixate_caps", othercaps,
   782           " on pad %s:%s using gst_pad_fixate_caps", othercaps,
   920           GST_DEBUG_PAD_NAME (otherpad));
   783           GST_DEBUG_PAD_NAME (otherpad));
   921       gst_pad_fixate_caps (otherpad, othercaps);
   784       gst_pad_fixate_caps (otherpad, othercaps);
   922     }
   785     }
   923     GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
   786     GST_DEBUG_OBJECT (trans, "after fixating %" GST_PTR_FORMAT, othercaps);
   924   } else {
       
   925     /* else caps are fixed but the subclass may want to add fields */
       
   926     if (klass->fixate_caps) {
       
   927       othercaps = gst_caps_make_writable (othercaps);
       
   928 
       
   929       GST_DEBUG_OBJECT (trans, "doing fixate %" GST_PTR_FORMAT
       
   930           " using caps %" GST_PTR_FORMAT
       
   931           " on pad %s:%s using fixate_caps vmethod", othercaps, caps,
       
   932           GST_DEBUG_PAD_NAME (otherpad));
       
   933 
       
   934       klass->fixate_caps (trans, GST_PAD_DIRECTION (pad), caps, othercaps);
       
   935     }
       
   936   }
   787   }
   937 
   788 
   938   /* caps should be fixed now, if not we have to fail. */
   789   /* caps should be fixed now, if not we have to fail. */
   939   if (!gst_caps_is_fixed (othercaps))
   790   if (!gst_caps_is_fixed (othercaps))
   940     goto could_not_fixate;
   791     goto could_not_fixate;
   945     goto peer_no_accept;
   796     goto peer_no_accept;
   946 
   797 
   947   GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
   798   GST_DEBUG_OBJECT (trans, "Input caps were %" GST_PTR_FORMAT
   948       ", and got final caps %" GST_PTR_FORMAT, caps, othercaps);
   799       ", and got final caps %" GST_PTR_FORMAT, caps, othercaps);
   949 
   800 
       
   801   trans->have_same_caps = gst_caps_is_equal (caps, othercaps);
       
   802   GST_DEBUG_OBJECT (trans, "have_same_caps: %d", trans->have_same_caps);
       
   803 
       
   804   /* see if we have to configure the element now */
       
   805   if (!trans->delay_configure) {
       
   806     GstCaps *incaps, *outcaps;
       
   807 
       
   808     /* make sure in and out caps are correct */
       
   809     if (pad == trans->sinkpad) {
       
   810       incaps = caps;
       
   811       outcaps = othercaps;
       
   812     } else {
       
   813       incaps = othercaps;
       
   814       outcaps = caps;
       
   815     }
       
   816     /* call configure now */
       
   817     if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
       
   818       goto failed_configure;
       
   819   } else {
       
   820     /* set pending configure, the configure will happen later with the
       
   821      * caps we set on the pads above. */
       
   822     trans->pending_configure = TRUE;
       
   823   }
       
   824 
       
   825   /* we know this will work, we implement the setcaps */
       
   826   gst_pad_set_caps (otherpad, othercaps);
       
   827 
       
   828   if (pad == trans->srcpad && trans->priv->pad_mode == GST_ACTIVATE_PULL) {
       
   829     ret &= gst_pad_set_caps (otherpeer, othercaps);
       
   830     if (!ret) {
       
   831       GST_INFO_OBJECT (trans, "otherpeer setcaps(%" GST_PTR_FORMAT ") failed",
       
   832           othercaps);
       
   833     }
       
   834   }
       
   835 
       
   836 done:
   950   if (otherpeer)
   837   if (otherpeer)
   951     gst_object_unref (otherpeer);
   838     gst_object_unref (otherpeer);
   952 
   839   if (othercaps)
   953   return othercaps;
   840     gst_caps_unref (othercaps);
       
   841 
       
   842   trans->negotiated = ret;
       
   843 
       
   844   gst_object_unref (trans);
       
   845 
       
   846   return ret;
   954 
   847 
   955   /* ERRORS */
   848   /* ERRORS */
       
   849 unfixed_caps:
       
   850   {
       
   851     GST_DEBUG_OBJECT (trans, "caps are not fixed  %" GST_PTR_FORMAT, caps);
       
   852     ret = FALSE;
       
   853     goto done;
       
   854   }
   956 no_transform:
   855 no_transform:
   957   {
   856   {
   958     GST_DEBUG_OBJECT (trans,
   857     GST_DEBUG_OBJECT (trans,
   959         "transform returned useless  %" GST_PTR_FORMAT, othercaps);
   858         "transform returned useless  %" GST_PTR_FORMAT, othercaps);
   960     goto error_cleanup;
   859     ret = FALSE;
       
   860     goto done;
   961   }
   861   }
   962 no_transform_possible:
   862 no_transform_possible:
   963   {
   863   {
   964     GST_DEBUG_OBJECT (trans,
   864     GST_DEBUG_OBJECT (trans,
   965         "transform could not transform %" GST_PTR_FORMAT
   865         "transform could not transform %" GST_PTR_FORMAT
   966         " in anything we support", caps);
   866         " in anything we support", caps);
   967     goto error_cleanup;
   867     ret = FALSE;
       
   868     goto done;
   968   }
   869   }
   969 could_not_fixate:
   870 could_not_fixate:
   970   {
   871   {
   971     GST_DEBUG_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
   872     GST_ERROR_OBJECT (trans, "FAILED to fixate %" GST_PTR_FORMAT, othercaps);
   972     goto error_cleanup;
   873     ret = FALSE;
       
   874     goto done;
   973   }
   875   }
   974 peer_no_accept:
   876 peer_no_accept:
   975   {
   877   {
   976     GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT
   878     GST_DEBUG_OBJECT (trans, "FAILED to get peer of %" GST_PTR_FORMAT
   977         " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
   879         " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
   978     goto error_cleanup;
       
   979   }
       
   980 error_cleanup:
       
   981   {
       
   982     if (otherpeer)
       
   983       gst_object_unref (otherpeer);
       
   984     if (othercaps)
       
   985       gst_caps_unref (othercaps);
       
   986     return NULL;
       
   987   }
       
   988 }
       
   989 
       
   990 static gboolean
       
   991 gst_base_transform_acceptcaps (GstPad * pad, GstCaps * caps)
       
   992 {
       
   993   GstBaseTransform *trans;
       
   994 #if 0
       
   995   GstPad *otherpad;
       
   996   GstCaps *othercaps = NULL;
       
   997 #endif
       
   998   gboolean ret = TRUE;
       
   999 
       
  1000   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
       
  1001 
       
  1002 #if 0
       
  1003   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
       
  1004 
       
  1005   /* we need fixed caps for the check, fall back to the default implementation
       
  1006    * if we don't */
       
  1007   if (!gst_caps_is_fixed (caps))
       
  1008 #endif
       
  1009   {
       
  1010     GstCaps *allowed, *intersect;
       
  1011 
       
  1012     GST_DEBUG_OBJECT (pad, "non fixed accept caps %" GST_PTR_FORMAT, caps);
       
  1013 
       
  1014     /* get all the formats we can handle on this pad */
       
  1015     allowed = gst_pad_get_caps (pad);
       
  1016     if (!allowed)
       
  1017       goto no_transform_possible;
       
  1018 
       
  1019     /* intersect with the requested format */
       
  1020     intersect = gst_caps_intersect (allowed, caps);
       
  1021 
       
  1022     GST_DEBUG_OBJECT (pad, "intersection %" GST_PTR_FORMAT, intersect);
       
  1023 
       
  1024     /* we can accept if the intersection is not empty  */
       
  1025     ret = !gst_caps_is_empty (intersect);
       
  1026     gst_caps_unref (intersect);
       
  1027     gst_caps_unref (allowed);
       
  1028 
       
  1029     if (!ret)
       
  1030       goto no_transform_possible;
       
  1031   }
       
  1032 #if 0
       
  1033   else {
       
  1034     GST_DEBUG_OBJECT (pad, "accept caps %" GST_PTR_FORMAT, caps);
       
  1035 
       
  1036     /* find best possible caps for the other pad as a way to see if we can
       
  1037      * transform this caps. */
       
  1038     othercaps = gst_base_transform_find_transform (trans, pad, caps);
       
  1039     if (!othercaps || gst_caps_is_empty (othercaps))
       
  1040       goto no_transform_possible;
       
  1041 
       
  1042     GST_DEBUG_OBJECT (pad, "we can transform to %" GST_PTR_FORMAT, othercaps);
       
  1043   }
       
  1044 #endif
       
  1045 
       
  1046 done:
       
  1047 #if 0
       
  1048   /* We know it's always NULL since we never use it */
       
  1049   if (othercaps)
       
  1050     gst_caps_unref (othercaps);
       
  1051 #endif
       
  1052   gst_object_unref (trans);
       
  1053 
       
  1054   return ret;
       
  1055 
       
  1056   /* ERRORS */
       
  1057 no_transform_possible:
       
  1058   {
       
  1059     GST_WARNING_OBJECT (trans,
       
  1060         "transform could not transform %" GST_PTR_FORMAT
       
  1061         " in anything we support", caps);
       
  1062     ret = FALSE;
   880     ret = FALSE;
  1063     goto done;
   881     goto done;
  1064   }
   882   }
  1065 }
       
  1066 
       
  1067 /* called when new caps arrive on the sink or source pad,
       
  1068  * We try to find the best caps for the other side using our _find_transform()
       
  1069  * function. If there are caps, we configure the transform for this new
       
  1070  * transformation.
       
  1071  *
       
  1072  * FIXME, this function is currently commutative but this should not really be
       
  1073  * because we never set caps starting from the srcpad.
       
  1074  */
       
  1075 static gboolean
       
  1076 gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
       
  1077 {
       
  1078   GstBaseTransform *trans;
       
  1079   GstPad *otherpad, *otherpeer;
       
  1080   GstCaps *othercaps = NULL;
       
  1081   gboolean ret = TRUE;
       
  1082   GstCaps *incaps, *outcaps;
       
  1083 
       
  1084   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
       
  1085 
       
  1086   otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
       
  1087   otherpeer = gst_pad_get_peer (otherpad);
       
  1088 
       
  1089   /* if we get called recursively, we bail out now to avoid an
       
  1090    * infinite loop. */
       
  1091   if (GST_PAD_IS_IN_SETCAPS (otherpad))
       
  1092     goto done;
       
  1093 
       
  1094   GST_DEBUG_OBJECT (pad, "have new caps %" GST_PTR_FORMAT, caps);
       
  1095 
       
  1096   /* find best possible caps for the other pad */
       
  1097   othercaps = gst_base_transform_find_transform (trans, pad, caps);
       
  1098   if (!othercaps || gst_caps_is_empty (othercaps))
       
  1099     goto no_transform_possible;
       
  1100 
       
  1101   /* configure the element now */
       
  1102   /* make sure in and out caps are correct */
       
  1103   if (pad == trans->sinkpad) {
       
  1104     incaps = caps;
       
  1105     outcaps = othercaps;
       
  1106   } else {
       
  1107     incaps = othercaps;
       
  1108     outcaps = caps;
       
  1109   }
       
  1110 
       
  1111 #if 0
       
  1112   /* if we have the same caps, we can optimize and reuse the input caps */
       
  1113   if (gst_caps_is_equal (incaps, outcaps)) {
       
  1114     GST_INFO_OBJECT (trans, "reuse caps");
       
  1115     gst_caps_unref (outcaps);
       
  1116     outcaps = gst_caps_ref (incaps);
       
  1117   }
       
  1118 #endif
       
  1119 
       
  1120   /* call configure now */
       
  1121   if (!(ret = gst_base_transform_configure_caps (trans, incaps, outcaps)))
       
  1122     goto failed_configure;
       
  1123 
       
  1124   /* we know this will work, we implement the setcaps */
       
  1125   gst_pad_set_caps (otherpad, othercaps);
       
  1126 
       
  1127   if (pad == trans->srcpad && trans->priv->pad_mode == GST_ACTIVATE_PULL) {
       
  1128     /* FIXME hm? */
       
  1129     ret &= gst_pad_set_caps (otherpeer, othercaps);
       
  1130     if (!ret) {
       
  1131       GST_INFO_OBJECT (trans, "otherpeer setcaps(%" GST_PTR_FORMAT ") failed",
       
  1132           othercaps);
       
  1133     }
       
  1134   }
       
  1135 
       
  1136 done:
       
  1137   if (otherpeer)
       
  1138     gst_object_unref (otherpeer);
       
  1139   if (othercaps)
       
  1140     gst_caps_unref (othercaps);
       
  1141 
       
  1142   trans->negotiated = ret;
       
  1143 
       
  1144   gst_object_unref (trans);
       
  1145 
       
  1146   return ret;
       
  1147 
       
  1148   /* ERRORS */
       
  1149 no_transform_possible:
       
  1150   {
       
  1151     GST_WARNING_OBJECT (trans,
       
  1152         "transform could not transform %" GST_PTR_FORMAT
       
  1153         " in anything we support", caps);
       
  1154     ret = FALSE;
       
  1155     goto done;
       
  1156   }
       
  1157 failed_configure:
   883 failed_configure:
  1158   {
   884   {
  1159     GST_WARNING_OBJECT (trans, "FAILED to configure caps %" GST_PTR_FORMAT
   885     GST_DEBUG_OBJECT (trans, "FAILED to configure caps %" GST_PTR_FORMAT
  1160         " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
   886         " to accept %" GST_PTR_FORMAT, otherpad, othercaps);
  1161     ret = FALSE;
   887     ret = FALSE;
  1162     goto done;
   888     goto done;
  1163   }
   889   }
  1164 }
   890 }
  1165 
   891 
  1166 /* Allocate a buffer using gst_pad_alloc_buffer
   892 /* Allocate a buffer using gst_pad_alloc_buffer
  1167  *
   893  *
  1168  * This function can do renegotiation on the source pad
   894  * This function does not do renegotiation on the source pad
  1169  *
   895  *
  1170  * The output buffer is always writable. outbuf can be equal to
   896  * The output buffer is always writable. outbuf can be equal to
  1171  * inbuf, the caller should be prepared for this and perform 
   897  * inbuf, the caller should be prepared for this and perform 
  1172  * appropriate refcounting.
   898  * appropriate refcounting.
  1173  */
   899  */
  1174 static GstFlowReturn
   900 static GstFlowReturn
  1175 gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
   901 gst_base_transform_prepare_output_buffer (GstBaseTransform * trans,
  1176     GstBuffer * in_buf, GstBuffer ** out_buf)
   902     GstBuffer * in_buf, gint out_size, GstCaps * out_caps, GstBuffer ** out_buf)
  1177 {
   903 {
  1178   GstBaseTransformClass *bclass;
   904   GstBaseTransformClass *bclass;
  1179   GstBaseTransformPrivate *priv;
       
  1180   GstFlowReturn ret = GST_FLOW_OK;
   905   GstFlowReturn ret = GST_FLOW_OK;
  1181   guint outsize, newsize, expsize;
   906   gboolean copy_inbuf = FALSE;
  1182   gboolean discard;
       
  1183   GstCaps *incaps, *oldcaps, *newcaps;
       
  1184 
   907 
  1185   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
   908   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1186 
   909 
  1187   priv = trans->priv;
   910   /* we cannot reconfigure the element yet as we are still processing
  1188 
   911    * the old buffer. We will therefore delay the reconfiguration of the
  1189   *out_buf = NULL;
   912    * element until we have processed this last buffer. */
  1190 
   913   trans->delay_configure = TRUE;
  1191   /* figure out how to allocate a buffer based on the current configuration */
   914 
  1192   if (trans->passthrough) {
   915   /* out_caps is the caps of the src pad gathered through the GST_PAD_CAPS 
  1193     GST_DEBUG_OBJECT (trans, "doing passthrough alloc");
   916      macro. If a set_caps occurs during this function this caps will become
  1194     /* passthrough, we don't really need to call pad alloc but we still need to
   917      invalid. We want to keep them during preparation of the output buffer. */
  1195      * in order to get upstream negotiation. The output size is the same as the
   918   if (out_caps)
  1196      * input size. */
   919     gst_caps_ref (out_caps);
  1197     outsize = GST_BUFFER_SIZE (in_buf);
   920 
  1198     /* we always alloc and discard here */
   921   /* see if the subclass wants to alloc a buffer */
  1199     discard = TRUE;
       
  1200   } else {
       
  1201     gboolean want_in_place = (bclass->transform_ip != NULL)
       
  1202         && trans->always_in_place;
       
  1203 
       
  1204     if (want_in_place) {
       
  1205       GST_DEBUG_OBJECT (trans, "doing inplace alloc");
       
  1206       /* we alloc a buffer of the same size as the input */
       
  1207       outsize = GST_BUFFER_SIZE (in_buf);
       
  1208       /* only discard it when the input was not writable, otherwise, we reuse
       
  1209        * the input buffer. */
       
  1210       discard = gst_buffer_is_writable (in_buf);
       
  1211       GST_DEBUG_OBJECT (trans, "discard: %d", discard);
       
  1212     } else {
       
  1213       GST_DEBUG_OBJECT (trans, "getting output size for copy transform");
       
  1214       /* copy transform, figure out the output size */
       
  1215       if (!gst_base_transform_transform_size (trans,
       
  1216               GST_PAD_SINK, GST_PAD_CAPS (trans->sinkpad),
       
  1217               GST_BUFFER_SIZE (in_buf), GST_PAD_CAPS (trans->srcpad),
       
  1218               &outsize)) {
       
  1219         goto unknown_size;
       
  1220       }
       
  1221       /* never discard this buffer, we need it for storing the output */
       
  1222       discard = FALSE;
       
  1223     }
       
  1224   }
       
  1225 
       
  1226   oldcaps = GST_PAD_CAPS (trans->srcpad);
       
  1227 
       
  1228   if (bclass->prepare_output_buffer) {
   922   if (bclass->prepare_output_buffer) {
  1229     GST_DEBUG_OBJECT (trans,
       
  1230         "calling prepare buffer with caps %" GST_PTR_FORMAT, oldcaps);
       
  1231     ret =
   923     ret =
  1232         bclass->prepare_output_buffer (trans, in_buf, outsize, oldcaps,
   924         bclass->prepare_output_buffer (trans, in_buf, out_size, out_caps,
  1233         out_buf);
   925         out_buf);
  1234 
   926     if (ret != GST_FLOW_OK)
  1235     /* get a new ref to the srcpad caps, the prepare_output_buffer function can
   927       goto done;
  1236      * update the pad caps if it wants */
   928 
  1237     oldcaps = GST_PAD_CAPS (trans->srcpad);
   929     /* decrease refcount again if vmethod returned refcounted in_buf. This
  1238 
       
  1239     /* FIXME 0.11:
       
  1240      * decrease refcount again if vmethod returned refcounted in_buf. This
       
  1241      * is because we need to make sure that the buffer is writable for the
   930      * is because we need to make sure that the buffer is writable for the
  1242      * in_place transform. The docs of the vmethod say that you should return
   931      * in_place transform. The docs of the vmethod say that you should return
  1243      * a reffed inbuf, which is exactly what we don't want :), oh well.. */
   932      * a reffed inbuf, which is exactly what we don't want :), oh well.. */
  1244     if (in_buf == *out_buf)
   933     if (in_buf == *out_buf)
  1245       gst_buffer_unref (in_buf);
   934       gst_buffer_unref (in_buf);
  1246 
   935   }
  1247     /* never discard the buffer from the prepare_buffer method */
   936 
  1248     if (*out_buf != NULL)
   937   /* See if we want to prepare the buffer for in place output */
  1249       discard = FALSE;
   938   if (*out_buf == NULL && GST_BUFFER_SIZE (in_buf) == out_size
  1250   }
   939       && bclass->transform_ip) {
  1251 
   940     if (gst_buffer_is_writable (in_buf)) {
  1252   if (ret != GST_FLOW_OK)
   941       if (trans->have_same_caps) {
  1253     goto alloc_failed;
   942         /* Input buffer is already writable and caps are the same, return input as
       
   943          * output buffer. We don't take an additional ref since that would make the
       
   944          * output buffer not writable anymore. Caller should be prepared to deal
       
   945          * with proper refcounting of input/output buffers. */
       
   946         *out_buf = in_buf;
       
   947         GST_LOG_OBJECT (trans, "reuse input buffer");
       
   948       } else {
       
   949         /* Writable buffer, but need to change caps => subbuffer */
       
   950         *out_buf = gst_buffer_create_sub (in_buf, 0, GST_BUFFER_SIZE (in_buf));
       
   951         gst_caps_replace (&GST_BUFFER_CAPS (*out_buf), out_caps);
       
   952         GST_LOG_OBJECT (trans, "created sub-buffer of input buffer");
       
   953       }
       
   954       /* we are done now */
       
   955       goto done;
       
   956     } else {
       
   957       /* Make a writable buffer below and copy the data */
       
   958       copy_inbuf = TRUE;
       
   959       GST_LOG_OBJECT (trans, "need to copy input buffer to new output buffer");
       
   960     }
       
   961   }
  1254 
   962 
  1255   if (*out_buf == NULL) {
   963   if (*out_buf == NULL) {
  1256     GST_DEBUG_OBJECT (trans, "doing alloc with caps %" GST_PTR_FORMAT, oldcaps);
   964     /* Sub-class didn't already provide a buffer for us. Make one */
  1257 
       
  1258     ret = gst_pad_alloc_buffer (trans->srcpad,
   965     ret = gst_pad_alloc_buffer (trans->srcpad,
  1259         GST_BUFFER_OFFSET (in_buf), outsize, oldcaps, out_buf);
   966         GST_BUFFER_OFFSET (in_buf), out_size, out_caps, out_buf);
  1260     if (ret != GST_FLOW_OK)
   967     if (ret != GST_FLOW_OK || *out_buf == NULL)
  1261       goto alloc_failed;
   968       goto done;
  1262   }
   969 
  1263 
   970     /* allocated buffer could be of different caps than what we requested */
  1264   /* must always have a buffer by now */
   971     if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
  1265   if (*out_buf == NULL)
   972       /* FIXME, it is possible we can reconfigure the transform with new caps at this
  1266     goto no_buffer;
   973        * point but for now we just create a buffer ourselves */
  1267 
   974       gst_buffer_unref (*out_buf);
  1268   /* check if we got different caps on this new output buffer */
   975       *out_buf = gst_buffer_new_and_alloc (out_size);
  1269   newcaps = GST_BUFFER_CAPS (*out_buf);
   976       gst_buffer_set_caps (*out_buf, out_caps);
  1270   newsize = GST_BUFFER_SIZE (*out_buf);
       
  1271   if (!gst_caps_is_equal (newcaps, oldcaps)) {
       
  1272     GstCaps *othercaps;
       
  1273     gboolean can_convert;
       
  1274 
       
  1275     GST_DEBUG_OBJECT (trans, "received new caps %" GST_PTR_FORMAT, newcaps);
       
  1276 
       
  1277     incaps = GST_PAD_CAPS (trans->sinkpad);
       
  1278 
       
  1279     /* it's possible that the buffer we got is of the wrong size, get the
       
  1280      * expected size here, we will check the size if we are going to use the
       
  1281      * buffer later on. */
       
  1282     gst_base_transform_transform_size (trans,
       
  1283         GST_PAD_SINK, incaps, GST_BUFFER_SIZE (in_buf), newcaps, &expsize);
       
  1284 
       
  1285     /* check if we can convert the current incaps to the new target caps */
       
  1286     can_convert =
       
  1287         gst_base_transform_can_transform (trans, trans->sinkpad, incaps,
       
  1288         newcaps);
       
  1289 
       
  1290     if (can_convert) {
       
  1291       GST_DEBUG_OBJECT (trans, "reconfigure transform for current buffer");
       
  1292       /* caps not empty, try to renegotiate to the new format */
       
  1293       if (!gst_base_transform_configure_caps (trans, incaps, newcaps)) {
       
  1294         /* not sure we need to fail hard here, we can simply continue our
       
  1295          * conversion with what we negotiated before */
       
  1296         goto failed_configure;
       
  1297       }
       
  1298       /* new format configure, and use the new output buffer */
       
  1299       gst_pad_set_caps (trans->srcpad, newcaps);
       
  1300       discard = FALSE;
       
  1301       /* if we got a buffer of the wrong size, discard it now and make sure we
       
  1302        * allocate a propertly sized buffer later. */
       
  1303       if (newsize != expsize) {
       
  1304         if (in_buf != *out_buf)
       
  1305           gst_buffer_unref (*out_buf);
       
  1306         *out_buf = NULL;
       
  1307       }
       
  1308       outsize = expsize;
       
  1309     } else {
       
  1310       GST_DEBUG_OBJECT (trans, "cannot perform transform on current buffer");
       
  1311 
       
  1312       /* we cannot convert the current buffer but we might be able to suggest a
       
  1313        * new format upstream, try to find what the best format is. */
       
  1314       othercaps =
       
  1315           gst_base_transform_find_transform (trans, trans->srcpad, newcaps);
       
  1316 
       
  1317       if (!othercaps) {
       
  1318         GST_DEBUG_OBJECT (trans, "incompatible caps, ignoring");
       
  1319         /* we received caps that we cannot transform. Upstream is behaving badly
       
  1320          * because it should have checked if we could handle these caps. We can
       
  1321          * simply ignore these caps and produce a buffer with our original caps. */
       
  1322       } else {
       
  1323         guint size_suggest;
       
  1324 
       
  1325         GST_DEBUG_OBJECT (trans, "getting size of suggestion");
       
  1326 
       
  1327         /* not a subset, we have a new upstream suggestion, remember it and
       
  1328          * allocate a default buffer. First we try to convert the size */
       
  1329         if (gst_base_transform_transform_size (trans,
       
  1330                 GST_PAD_SRC, newcaps, expsize, othercaps, &size_suggest)) {
       
  1331 
       
  1332           /* ok, remember the suggestions now */
       
  1333           GST_DEBUG_OBJECT (trans,
       
  1334               "storing new caps and size suggestion of %u and %" GST_PTR_FORMAT,
       
  1335               size_suggest, othercaps);
       
  1336 
       
  1337           GST_OBJECT_LOCK (trans->sinkpad);
       
  1338           if (priv->sink_suggest)
       
  1339             gst_caps_unref (priv->sink_suggest);
       
  1340           priv->sink_suggest = gst_caps_ref (othercaps);
       
  1341           priv->size_suggest = size_suggest;
       
  1342           trans->priv->suggest_pending = TRUE;
       
  1343           GST_OBJECT_UNLOCK (trans->sinkpad);
       
  1344         }
       
  1345         gst_caps_unref (othercaps);
       
  1346       }
       
  1347       if (in_buf != *out_buf)
       
  1348         gst_buffer_unref (*out_buf);
       
  1349       *out_buf = NULL;
       
  1350     }
   977     }
  1351   }
   978   }
  1352 
   979 
  1353   if (*out_buf == NULL) {
   980   /* If the output buffer metadata is modifiable, copy timestamps and
  1354     if (!discard) {
   981    * buffer flags */
  1355       GST_DEBUG_OBJECT (trans, "make default output buffer of size %d",
   982   if (*out_buf != in_buf && gst_buffer_is_metadata_writable (*out_buf)) {
  1356           outsize);
   983 
  1357       /* no valid buffer yet, make one */
   984     if (copy_inbuf && gst_buffer_is_writable (*out_buf))
  1358       *out_buf = gst_buffer_new_and_alloc (outsize);
   985       memcpy (GST_BUFFER_DATA (*out_buf), GST_BUFFER_DATA (in_buf), out_size);
  1359       gst_buffer_copy_metadata (*out_buf, in_buf,
   986 
  1360           GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
   987     gst_buffer_copy_metadata (*out_buf, in_buf,
  1361     } else {
   988         GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
  1362       GST_DEBUG_OBJECT (trans, "reuse input buffer");
   989 
  1363       *out_buf = in_buf;
   990     /* Unset the GAP flag if the element is _not_ GAP aware. Otherwise
  1364     }
   991      * it might create an output buffer that does not contain neutral data
  1365   } else {
   992      * but still has the GAP flag on it! */
  1366     if (trans->passthrough && in_buf != *out_buf) {
   993     if (!trans->priv->gap_aware)
  1367       /* we are asked to perform a passthrough transform but the input and
   994       GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
  1368        * output buffers are different. We have to discard the output buffer and
   995   }
  1369        * reuse the input buffer. */
   996 
  1370       GST_DEBUG_OBJECT (trans, "passthrough but different buffers");
   997 done:
  1371       discard = TRUE;
   998   if (out_caps)
  1372     }
   999     gst_caps_unref (out_caps);
  1373     if (discard) {
  1000 
  1374       GST_DEBUG_OBJECT (trans, "discard buffer, reuse input buffer");
  1001   trans->delay_configure = FALSE;
  1375       gst_buffer_unref (*out_buf);
       
  1376       *out_buf = in_buf;
       
  1377     } else {
       
  1378       GST_DEBUG_OBJECT (trans, "using allocated buffer");
       
  1379       gst_buffer_copy_metadata (*out_buf, in_buf,
       
  1380           GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
       
  1381     }
       
  1382   }
       
  1383   gst_buffer_set_caps (*out_buf, GST_PAD_CAPS (trans->srcpad));
       
  1384 
       
  1385   /* clear the GAP flag when the subclass does not understand it */
       
  1386   if (!trans->priv->gap_aware)
       
  1387     GST_BUFFER_FLAG_UNSET (*out_buf, GST_BUFFER_FLAG_GAP);
       
  1388 
  1002 
  1389   return ret;
  1003   return ret;
  1390 
       
  1391   /* ERRORS */
       
  1392 alloc_failed:
       
  1393   {
       
  1394     GST_WARNING_OBJECT (trans, "pad-alloc failed: %s", gst_flow_get_name (ret));
       
  1395     return ret;
       
  1396   }
       
  1397 no_buffer:
       
  1398   {
       
  1399     GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
       
  1400         ("Sub-class failed to provide an output buffer"), (NULL));
       
  1401     return GST_FLOW_ERROR;
       
  1402   }
       
  1403 unknown_size:
       
  1404   {
       
  1405     GST_ERROR_OBJECT (trans, "unknown output size");
       
  1406     return GST_FLOW_ERROR;
       
  1407   }
       
  1408 failed_configure:
       
  1409   {
       
  1410     GST_WARNING_OBJECT (trans, "failed to configure caps");
       
  1411     return GST_FLOW_NOT_NEGOTIATED;
       
  1412   }
       
  1413 }
  1004 }
  1414 
  1005 
  1415 /* Given @caps calcultate the size of one unit.
  1006 /* Given @caps calcultate the size of one unit.
  1416  *
  1007  *
  1417  * For video caps, this is the size of one frame (and thus one buffer).
  1008  * For video caps, this is the size of one frame (and thus one buffer).
  1445   }
  1036   }
  1446 
  1037 
  1447   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1038   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1448   if (bclass->get_unit_size) {
  1039   if (bclass->get_unit_size) {
  1449     res = bclass->get_unit_size (trans, caps, size);
  1040     res = bclass->get_unit_size (trans, caps, size);
  1450     if(res)
  1041 //    GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
  1451         {
  1042 //        ") has unit size %d, result %s", caps, *size, res ? "TRUE" : "FALSE");
  1452         GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
  1043 
  1453                 ") has unit size %d, result TRUE", caps, *size);
       
  1454         }else{ 
       
  1455   
       
  1456         GST_DEBUG_OBJECT (trans, "caps %" GST_PTR_FORMAT
       
  1457                 ") has unit size %d, result FALSE", caps, *size);
       
  1458         }
       
  1459     if (res) {
  1044     if (res) {
  1460       /* and cache the values */
  1045       /* and cache the values */
  1461       if (trans->cache_caps1 == NULL) {
  1046       if (trans->cache_caps1 == NULL) {
  1462         gst_caps_replace (&trans->cache_caps1, caps);
  1047         gst_caps_replace (&trans->cache_caps1, caps);
  1463         trans->cache_caps1_size = *size;
  1048         trans->cache_caps1_size = *size;
  1483 static GstFlowReturn
  1068 static GstFlowReturn
  1484 gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
  1069 gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
  1485     GstCaps * caps, GstBuffer ** buf)
  1070     GstCaps * caps, GstBuffer ** buf)
  1486 {
  1071 {
  1487   GstBaseTransform *trans;
  1072   GstBaseTransform *trans;
  1488   GstBaseTransformPrivate *priv;
       
  1489   GstFlowReturn res;
  1073   GstFlowReturn res;
  1490   gboolean proxy, suggest, same_caps;
  1074   guint new_size;
  1491   GstCaps *sink_suggest;
  1075   gboolean issinkcaps = TRUE;
  1492   guint size_suggest;
       
  1493 
  1076 
  1494   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
  1077   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
  1495   priv = trans->priv;
  1078 
  1496 
  1079   /* we cannot run this when we are transforming data and as such doing 
  1497   GST_DEBUG_OBJECT (pad, "alloc with caps %" GST_PTR_FORMAT ", size %u", caps,
  1080    * another negotiation in the transform method. */
  1498       size);
  1081   g_mutex_lock (trans->transform_lock);
  1499 
  1082 
  1500   /* if the code below does not come up with a better buffer, we will return _OK
       
  1501    * and an empty buffer. This will trigger the core to allocate a buffer with
       
  1502    * given input size and caps. */
       
  1503   *buf = NULL;
  1083   *buf = NULL;
  1504   res = GST_FLOW_OK;
  1084 
  1505 
  1085   GST_DEBUG_OBJECT (trans, "allocating a buffer of size %d ...", size);
  1506   /* we remember our previous alloc request to quickly see if we can proxy or
  1086   if (offset == GST_BUFFER_OFFSET_NONE)
  1507    * not. We skip this check if we have a pending suggestion. */
  1087     GST_DEBUG_OBJECT (trans, "... and offset NONE");
  1508   GST_OBJECT_LOCK (pad);
  1088   else
  1509   same_caps = !priv->suggest_pending && caps &&
  1089     GST_DEBUG_OBJECT (trans, "... and offset %" G_GUINT64_FORMAT, offset);
  1510       gst_caps_is_equal (priv->sink_alloc, caps);
  1090 
  1511   GST_OBJECT_UNLOCK (pad);
  1091   /* if have_same_caps was previously set to TRUE we need to double check if it
  1512 
  1092    * hasn't changed */
  1513   if (same_caps) {
  1093   if (trans->have_same_caps) {
  1514     /* we have seen this before, see below if we need to proxy */
  1094     GstCaps *sinkcaps;
  1515     GST_DEBUG_OBJECT (trans, "have old caps");
  1095 
  1516     sink_suggest = caps;
  1096     GST_OBJECT_LOCK (trans->sinkpad);
  1517     size_suggest = size;
  1097     sinkcaps = GST_PAD_CAPS (trans->sinkpad);
  1518     suggest = FALSE;
  1098     issinkcaps = sinkcaps && (gst_caps_is_equal (sinkcaps, caps));
       
  1099     GST_OBJECT_UNLOCK (trans->sinkpad);
       
  1100   }
       
  1101 
       
  1102   /* before any buffers are pushed, have_same_caps is TRUE; allocating can trigger
       
  1103    * a renegotiation and change that to FALSE */
       
  1104 
       
  1105   /* bilboed: This seems wrong, from all debug logs, have_same_caps is
       
  1106    * initialized to FALSE */
       
  1107 
       
  1108   /* checking against trans->have_same_caps is not enough !! It should also
       
  1109    *  check to see if the requested caps are equal to the sink caps */
       
  1110   if (trans->have_same_caps && issinkcaps) {
       
  1111     /* request a buffer with the same caps */
       
  1112     GST_DEBUG_OBJECT (trans, "requesting buffer with same caps, size %d", size);
       
  1113 
       
  1114     res =
       
  1115         gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, size, caps,
       
  1116         buf);
  1519   } else {
  1117   } else {
  1520     GstCaps *temp;
  1118     /* if we are configured, request a buffer with the src caps */
  1521     const GstCaps *templ;
  1119     GstCaps *srccaps;
  1522     gboolean empty;
  1120     GstCaps *sinkcaps;
  1523 
  1121     gboolean configured;
  1524     GST_DEBUG_OBJECT (trans, "new format %" GST_PTR_FORMAT, caps);
  1122 
  1525 
  1123     /* take lock, peek if the caps are ok */
  1526     /* if we have a suggestion, pretend we got these as input */
  1124     GST_OBJECT_LOCK (trans->sinkpad);
  1527     GST_OBJECT_LOCK (pad);
  1125     sinkcaps = GST_PAD_CAPS (trans->sinkpad);
  1528     if ((priv->sink_suggest && !gst_caps_is_equal (caps, priv->sink_suggest))) {
  1126     configured = (sinkcaps == NULL || gst_caps_is_equal (sinkcaps, caps));
  1529       sink_suggest = gst_caps_ref (priv->sink_suggest);
  1127     GST_OBJECT_UNLOCK (trans->sinkpad);
  1530       size_suggest = priv->size_suggest;
  1128     if (!configured)
  1531       GST_DEBUG_OBJECT (trans, "have suggestion %" GST_PTR_FORMAT,
  1129       goto not_configured;
  1532           sink_suggest);
  1130 
  1533       /* suggest is TRUE when we have a custom suggestion pending that we need
  1131     /* take lock on srcpad to grab the caps, caps can change when pushing a
  1534        * to unref later. */
  1132      * buffer. */
  1535       suggest = TRUE;
  1133     GST_OBJECT_LOCK (trans->srcpad);
       
  1134     if ((srccaps = GST_PAD_CAPS (trans->srcpad)))
       
  1135       gst_caps_ref (srccaps);
       
  1136     GST_OBJECT_UNLOCK (trans->srcpad);
       
  1137     if (!srccaps)
       
  1138       goto not_configured;
       
  1139 
       
  1140     GST_DEBUG_OBJECT (trans, "calling transform_size");
       
  1141     if (!gst_base_transform_transform_size (trans,
       
  1142             GST_PAD_DIRECTION (pad), caps, size, srccaps, &new_size)) {
       
  1143       gst_caps_unref (srccaps);
       
  1144       goto unknown_size;
       
  1145     }
       
  1146 
       
  1147     res =
       
  1148         gst_pad_alloc_buffer_and_set_caps (trans->srcpad, offset, new_size,
       
  1149         srccaps, buf);
       
  1150 
       
  1151     gst_caps_unref (srccaps);
       
  1152   }
       
  1153 
       
  1154   if (res == GST_FLOW_OK && !trans->have_same_caps) {
       
  1155     /* note that we might have had same caps before, but calling the
       
  1156        alloc_buffer caused setcaps to switch us out of in_place -- in any case
       
  1157        the alloc_buffer served to transmit caps information but we can't use the
       
  1158        buffer. fall through and allocate a buffer corresponding to our sink
       
  1159        caps, if any */
       
  1160     GstCaps *sinkcaps;
       
  1161     GstCaps *srccaps;
       
  1162 
       
  1163     GST_OBJECT_LOCK (trans->sinkpad);
       
  1164     if ((sinkcaps = GST_PAD_CAPS (trans->sinkpad)))
       
  1165       gst_caps_ref (sinkcaps);
       
  1166     GST_OBJECT_UNLOCK (trans->sinkpad);
       
  1167     if (!sinkcaps)
       
  1168       goto not_configured;
       
  1169 
       
  1170     GST_OBJECT_LOCK (trans->srcpad);
       
  1171     if ((srccaps = GST_PAD_CAPS (trans->srcpad)))
       
  1172       gst_caps_ref (srccaps);
       
  1173     GST_OBJECT_UNLOCK (trans->srcpad);
       
  1174     if (!srccaps) {
       
  1175       gst_caps_unref (sinkcaps);
       
  1176       goto not_configured;
       
  1177     }
       
  1178 
       
  1179     if (!gst_base_transform_transform_size (trans,
       
  1180             GST_PAD_DIRECTION (trans->srcpad), srccaps, GST_BUFFER_SIZE (*buf),
       
  1181             sinkcaps, &new_size)) {
       
  1182       gst_caps_unref (srccaps);
       
  1183       gst_caps_unref (sinkcaps);
       
  1184       goto unknown_size;
       
  1185     }
       
  1186     /* don't need the caps anymore now */
       
  1187     gst_caps_unref (srccaps);
       
  1188 
       
  1189     gst_buffer_unref (*buf);
       
  1190 
       
  1191     *buf = gst_buffer_new_and_alloc (new_size);
       
  1192     GST_BUFFER_OFFSET (*buf) = offset;
       
  1193     /* set caps, gives away the ref */
       
  1194     GST_BUFFER_CAPS (*buf) = sinkcaps;
       
  1195 
       
  1196     res = GST_FLOW_OK;
       
  1197   }
       
  1198 
       
  1199 done:
       
  1200   g_mutex_unlock (trans->transform_lock);
       
  1201   gst_object_unref (trans);
       
  1202 
       
  1203   return res;
       
  1204 
       
  1205 not_configured:
       
  1206   {
       
  1207     /* let the default allocator handle it... */
       
  1208     GST_DEBUG_OBJECT (trans, "not configured");
       
  1209     gst_buffer_replace (buf, NULL);
       
  1210     if (trans->passthrough) {
       
  1211       /* ...by calling alloc_buffer without setting caps on the src pad, which
       
  1212        * will force negotiation in the chain function. */
       
  1213       res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
  1536     } else {
  1214     } else {
  1537       GST_DEBUG_OBJECT (trans, "using caps %" GST_PTR_FORMAT, caps);
  1215       /* ...by letting the default handler create a buffer */
  1538       sink_suggest = caps;
  1216       res = GST_FLOW_OK;
  1539       size_suggest = size;
       
  1540       suggest = FALSE;
       
  1541     }
  1217     }
  1542     priv->suggest_pending = FALSE;
  1218     goto done;
  1543     GST_OBJECT_UNLOCK (pad);
  1219   }
  1544 
  1220 unknown_size:
  1545     /* check if we actually handle this format on the sinkpad */
  1221   {
  1546     if (sink_suggest) {
  1222     /* let the default allocator handle it... */
  1547       templ = gst_pad_get_pad_template_caps (pad);
  1223     GST_DEBUG_OBJECT (trans, "unknown size");
  1548       temp = gst_caps_intersect (sink_suggest, templ);
  1224     gst_buffer_replace (buf, NULL);
  1549 
  1225     if (trans->passthrough) {
  1550       empty = gst_caps_is_empty (temp);
  1226       /* ...by calling alloc_buffer without setting caps on the src pad, which
  1551       gst_caps_unref (temp);
  1227        * will force negotiation in the chain function. */
  1552 
  1228       res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
  1553       if (empty)
  1229     } else {
  1554         goto not_supported;
  1230       /* ...by letting the default handler create a buffer */
       
  1231       res = GST_FLOW_OK;
  1555     }
  1232     }
  1556 
  1233     goto done;
  1557     /* find the best format for the other side here we decide if we will proxy
       
  1558      * the caps or not. */
       
  1559     if (sink_suggest == NULL) {
       
  1560       /* always proxy when the caps are NULL. When this is a new format, see if
       
  1561        * we can proxy it downstream */
       
  1562       GST_DEBUG_OBJECT (trans, "null caps, marking for proxy");
       
  1563       priv->proxy_alloc = TRUE;
       
  1564     } else {
       
  1565       GstCaps *othercaps;
       
  1566 
       
  1567       /* we have a new format, see what we need to proxy to */
       
  1568       othercaps = gst_base_transform_find_transform (trans, pad, sink_suggest);
       
  1569       if (!othercaps || gst_caps_is_empty (othercaps)) {
       
  1570         /* no transform possible, we certainly can't proxy */
       
  1571         GST_DEBUG_OBJECT (trans, "can't find transform, disable proxy");
       
  1572         priv->proxy_alloc = FALSE;
       
  1573       } else {
       
  1574         /* we transformed into something */
       
  1575         if (gst_caps_is_equal (caps, othercaps)) {
       
  1576           GST_DEBUG_OBJECT (trans,
       
  1577               "best caps same as input, marking for proxy");
       
  1578           priv->proxy_alloc = TRUE;
       
  1579         } else {
       
  1580           GST_DEBUG_OBJECT (trans,
       
  1581               "best caps different from input, disable proxy");
       
  1582           priv->proxy_alloc = FALSE;
       
  1583         }
       
  1584       }
       
  1585       if (othercaps)
       
  1586         gst_caps_unref (othercaps);
       
  1587     }
       
  1588   }
       
  1589   /* remember the new caps */
       
  1590   GST_OBJECT_LOCK (pad);
       
  1591   gst_caps_replace (&priv->sink_alloc, sink_suggest);
       
  1592   GST_OBJECT_UNLOCK (pad);
       
  1593 
       
  1594   proxy = priv->proxy_alloc;
       
  1595   GST_DEBUG_OBJECT (trans, "doing default alloc, proxy %d", proxy);
       
  1596 
       
  1597   /* we only want to proxy if we have no suggestion pending, FIXME */
       
  1598   if (proxy && !suggest) {
       
  1599     GstCaps *newcaps;
       
  1600 
       
  1601     GST_DEBUG_OBJECT (trans, "proxy buffer-alloc with caps %" GST_PTR_FORMAT
       
  1602         ", size %u", caps, size);
       
  1603 
       
  1604     /* we always proxy the input caps, never the suggestion. The reason is that
       
  1605      * We don't yet handle the caps of renegotiation in here. FIXME */
       
  1606     res = gst_pad_alloc_buffer (trans->srcpad, offset, size, caps, buf);
       
  1607     if (res != GST_FLOW_OK)
       
  1608       goto alloc_failed;
       
  1609 
       
  1610     /* check if the caps changed */
       
  1611     newcaps = GST_BUFFER_CAPS (*buf);
       
  1612 
       
  1613     GST_DEBUG_OBJECT (trans, "got caps %" GST_PTR_FORMAT, newcaps);
       
  1614 
       
  1615     if (!gst_caps_is_equal (newcaps, caps)) {
       
  1616       GST_DEBUG_OBJECT (trans, "caps are new");
       
  1617       /* we have new caps, see if we can proxy downstream */
       
  1618       if (gst_pad_peer_accept_caps (pad, newcaps)) {
       
  1619         /* peer accepts the caps, return a buffer in this format */
       
  1620         GST_DEBUG_OBJECT (trans, "peer accepted new caps");
       
  1621         /* remember the format */
       
  1622         GST_OBJECT_LOCK (pad);
       
  1623         gst_caps_replace (&priv->sink_alloc, newcaps);
       
  1624         GST_OBJECT_UNLOCK (pad);
       
  1625       } else {
       
  1626         GST_DEBUG_OBJECT (trans, "peer did not accept new caps");
       
  1627         /* peer does not accept the caps, free the buffer we received and
       
  1628          * create a buffer of the requested format by the default handler. */
       
  1629         gst_buffer_unref (*buf);
       
  1630         *buf = NULL;
       
  1631       }
       
  1632     } else {
       
  1633       GST_DEBUG_OBJECT (trans, "received required caps from peer");
       
  1634     }
       
  1635   }
       
  1636 
       
  1637   if (suggest) {
       
  1638     /* there was a custom suggestion, create a buffer of this format and return
       
  1639      * it. Note that this format  */
       
  1640     *buf = gst_buffer_new_and_alloc (size_suggest);
       
  1641     GST_DEBUG_OBJECT (trans,
       
  1642         "doing suggestion of size %u, caps %" GST_PTR_FORMAT, size_suggest,
       
  1643         sink_suggest);
       
  1644     GST_BUFFER_CAPS (*buf) = sink_suggest;
       
  1645   }
       
  1646 
       
  1647   gst_object_unref (trans);
       
  1648 
       
  1649   return res;
       
  1650 
       
  1651   /* ERRORS */
       
  1652 alloc_failed:
       
  1653   {
       
  1654     GST_DEBUG_OBJECT (trans, "pad alloc failed: %s", gst_flow_get_name (res));
       
  1655     if (suggest)
       
  1656       gst_caps_unref (sink_suggest);
       
  1657     gst_object_unref (trans);
       
  1658     return res;
       
  1659   }
       
  1660 not_supported:
       
  1661   {
       
  1662     GST_DEBUG_OBJECT (trans, "pad alloc with unsupported caps");
       
  1663     if (suggest)
       
  1664       gst_caps_unref (sink_suggest);
       
  1665     gst_object_unref (trans);
       
  1666     return GST_FLOW_NOT_NEGOTIATED;
       
  1667   }
  1234   }
  1668 }
  1235 }
  1669 
  1236 
  1670 static gboolean
  1237 static gboolean
  1671 gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
  1238 gst_base_transform_sink_event (GstPad * pad, GstEvent * event)
  1683 
  1250 
  1684   /* FIXME, do this in the default event handler so the subclass can do
  1251   /* FIXME, do this in the default event handler so the subclass can do
  1685    * something different. */
  1252    * something different. */
  1686   if (forward)
  1253   if (forward)
  1687     ret = gst_pad_push_event (trans->srcpad, event);
  1254     ret = gst_pad_push_event (trans->srcpad, event);
  1688   else
       
  1689     gst_event_unref (event);
       
  1690 
  1255 
  1691   gst_object_unref (trans);
  1256   gst_object_unref (trans);
  1692 
  1257 
  1693   return ret;
  1258   return ret;
  1694 }
  1259 }
  1798   ret = gst_pad_push_event (trans->sinkpad, event);
  1363   ret = gst_pad_push_event (trans->sinkpad, event);
  1799 
  1364 
  1800   return ret;
  1365   return ret;
  1801 }
  1366 }
  1802 
  1367 
  1803 /* perform a transform on @inbuf and put the result in @outbuf.
       
  1804  *
       
  1805  * This function is common to the push and pull-based operations.
       
  1806  *
       
  1807  * This function takes ownership of @inbuf */
       
  1808 static GstFlowReturn
  1368 static GstFlowReturn
  1809 gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
  1369 gst_base_transform_handle_buffer (GstBaseTransform * trans, GstBuffer * inbuf,
  1810     GstBuffer ** outbuf)
  1370     GstBuffer ** outbuf)
  1811 {
  1371 {
  1812   GstBaseTransformClass *bclass;
  1372   GstBaseTransformClass *bclass;
  1813   GstFlowReturn ret = GST_FLOW_OK;
  1373   GstFlowReturn ret = GST_FLOW_OK;
  1814   gboolean want_in_place, reconfigure;
  1374   guint out_size;
       
  1375   gboolean want_in_place;
  1815   GstClockTime qostime;
  1376   GstClockTime qostime;
  1816   GstCaps *incaps;
       
  1817 
  1377 
  1818   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1378   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1819 
  1379 
  1820   if (G_LIKELY ((incaps = GST_BUFFER_CAPS (inbuf)))) {
       
  1821     GST_OBJECT_LOCK (trans);
       
  1822     reconfigure = trans->priv->reconfigure;
       
  1823     trans->priv->reconfigure = FALSE;
       
  1824     GST_OBJECT_UNLOCK (trans);
       
  1825 
       
  1826     if (G_UNLIKELY (reconfigure)) {
       
  1827       GST_DEBUG_OBJECT (trans, "we had a pending reconfigure");
       
  1828       /* if we need to reconfigure we pretend a buffer with new caps arrived. This
       
  1829        * will reconfigure the transform with the new output format. We can only
       
  1830        * do this if the buffer actually has caps. */
       
  1831       if (!gst_base_transform_setcaps (trans->sinkpad, incaps))
       
  1832         goto not_negotiated;
       
  1833     }
       
  1834   }
       
  1835 
       
  1836   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
  1380   if (GST_BUFFER_OFFSET_IS_VALID (inbuf))
  1837     GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset %"
  1381     GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset %"
  1838         G_GUINT64_FORMAT, inbuf, GST_BUFFER_SIZE (inbuf),
  1382         G_GUINT64_FORMAT, inbuf, GST_BUFFER_SIZE (inbuf),
  1839         GST_BUFFER_OFFSET (inbuf));
  1383         GST_BUFFER_OFFSET (inbuf));
  1840   else
  1384   else
  1841     GST_DEBUG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
  1385     GST_LOG_OBJECT (trans, "handling buffer %p of size %d and offset NONE",
  1842         inbuf, GST_BUFFER_SIZE (inbuf));
  1386         inbuf, GST_BUFFER_SIZE (inbuf));
  1843 
  1387 
  1844   /* Don't allow buffer handling before negotiation, except in passthrough mode
  1388   /* Don't allow buffer handling before negotiation, except in passthrough mode
  1845    * or if the class doesn't implement a set_caps function (in which case it doesn't
  1389    * or if the class doesn't implement a set_caps function (in which case it doesn't
  1846    * care about caps)
  1390    * care about caps)
  1848   if (!trans->negotiated && !trans->passthrough && (bclass->set_caps != NULL))
  1392   if (!trans->negotiated && !trans->passthrough && (bclass->set_caps != NULL))
  1849     goto not_negotiated;
  1393     goto not_negotiated;
  1850 
  1394 
  1851   /* Set discont flag so we can mark the outgoing buffer */
  1395   /* Set discont flag so we can mark the outgoing buffer */
  1852   if (GST_BUFFER_IS_DISCONT (inbuf)) {
  1396   if (GST_BUFFER_IS_DISCONT (inbuf)) {
  1853     GST_DEBUG_OBJECT (trans, "got DISCONT buffer %p", inbuf);
  1397     GST_LOG_OBJECT (trans, "got DISCONT buffer %p", inbuf);
  1854     trans->priv->discont = TRUE;
  1398     trans->priv->discont = TRUE;
  1855   }
  1399   }
  1856 
  1400 
  1857   /* can only do QoS if the segment is in TIME */
  1401   /* can only do QoS if the segment is in TIME */
  1858   if (trans->segment.format != GST_FORMAT_TIME)
  1402   if (trans->segment.format != GST_FORMAT_TIME)
  1859     goto no_qos;
  1403     goto no_qos;
  1860 
  1404 
  1861   /* QOS is done on the running time of the buffer, get it now */
       
  1862   qostime = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
  1405   qostime = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
  1863       GST_BUFFER_TIMESTAMP (inbuf));
  1406       GST_BUFFER_TIMESTAMP (inbuf));
  1864 
  1407 
  1865   if (qostime != -1) {
  1408   if (qostime != -1) {
  1866     gboolean need_skip;
  1409     gboolean need_skip;
  1867     GstClockTime earliest_time;
  1410     GstClockTime earliest_time;
  1868 
  1411 
  1869     /* lock for getting the QoS parameters that are set (in a different thread)
       
  1870      * with the QOS events */
       
  1871     GST_OBJECT_LOCK (trans);
  1412     GST_OBJECT_LOCK (trans);
  1872     earliest_time = trans->priv->earliest_time;
  1413     earliest_time = trans->priv->earliest_time;
  1873     /* check for QoS, don't perform conversion for buffers
  1414     /* check for QoS, don't perform conversion for buffers
  1874      * that are known to be late. */
  1415      * that are known to be late. */
  1875     need_skip = trans->priv->qos_enabled &&
  1416     need_skip = trans->priv->qos_enabled &&
  1885       goto skip;
  1426       goto skip;
  1886     }
  1427     }
  1887   }
  1428   }
  1888 
  1429 
  1889 no_qos:
  1430 no_qos:
  1890 
       
  1891   /* first try to allocate an output buffer based on the currently negotiated
       
  1892    * format. While we call pad-alloc we could renegotiate the srcpad format or
       
  1893    * have a new suggestion for upstream buffer-alloc. 
       
  1894    * In any case, outbuf will contain a buffer suitable for doing the configured
       
  1895    * transform after this function. */
       
  1896   ret = gst_base_transform_prepare_output_buffer (trans, inbuf, outbuf);
       
  1897   if (G_UNLIKELY (ret != GST_FLOW_OK))
       
  1898     goto no_buffer;
       
  1899 
       
  1900   /* now perform the needed transform */
       
  1901   if (trans->passthrough) {
  1431   if (trans->passthrough) {
  1902     /* In passthrough mode, give transform_ip a look at the
  1432     /* In passthrough mode, give transform_ip a look at the
  1903      * buffer, without making it writable, or just push the
  1433      * buffer, without making it writable, or just push the
  1904      * data through */
  1434      * data through */
  1905     if (bclass->transform_ip) {
  1435     GST_LOG_OBJECT (trans, "element is in passthrough mode");
  1906       GST_DEBUG_OBJECT (trans, "doing passthrough transform");
  1436 
  1907       ret = bclass->transform_ip (trans, *outbuf);
  1437     if (bclass->transform_ip)
       
  1438       ret = bclass->transform_ip (trans, inbuf);
       
  1439 
       
  1440     *outbuf = inbuf;
       
  1441 
       
  1442     goto done;
       
  1443   }
       
  1444 
       
  1445   want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
       
  1446   *outbuf = NULL;
       
  1447 
       
  1448   if (want_in_place) {
       
  1449     /* If want_in_place is TRUE, we may need to prepare a new output buffer
       
  1450      * Sub-classes can implement a prepare_output_buffer function as they
       
  1451      * wish. */
       
  1452     GST_LOG_OBJECT (trans, "doing inplace transform");
       
  1453 
       
  1454     ret = gst_base_transform_prepare_output_buffer (trans, inbuf,
       
  1455         GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad), outbuf);
       
  1456     if (G_UNLIKELY (ret != GST_FLOW_OK))
       
  1457       goto no_buffer;
       
  1458 
       
  1459     ret = bclass->transform_ip (trans, *outbuf);
       
  1460 
       
  1461   } else {
       
  1462     GST_LOG_OBJECT (trans, "doing non-inplace transform");
       
  1463 
       
  1464     /* not transforming inplace, figure out the output size */
       
  1465     if (trans->always_in_place) {
       
  1466       out_size = GST_BUFFER_SIZE (inbuf);
  1908     } else {
  1467     } else {
  1909       GST_DEBUG_OBJECT (trans, "element is in passthrough");
  1468       if (!gst_base_transform_transform_size (trans,
       
  1469               GST_PAD_DIRECTION (trans->sinkpad), GST_PAD_CAPS (trans->sinkpad),
       
  1470               GST_BUFFER_SIZE (inbuf), GST_PAD_CAPS (trans->srcpad),
       
  1471               &out_size)) {
       
  1472         /* we have an error */
       
  1473         goto no_size;
       
  1474       }
  1910     }
  1475     }
  1911   } else {
  1476 
  1912     want_in_place = (bclass->transform_ip != NULL) && trans->always_in_place;
  1477     /* no in place transform, get buffer, this might renegotiate. */
  1913 
  1478     ret = gst_base_transform_prepare_output_buffer (trans, inbuf, out_size,
  1914     if (want_in_place) {
  1479         GST_PAD_CAPS (trans->srcpad), outbuf);
  1915       GST_DEBUG_OBJECT (trans, "doing inplace transform");
  1480     if (ret != GST_FLOW_OK)
  1916 
  1481       goto no_buffer;
  1917       if (inbuf != *outbuf) {
  1482 
  1918         /* different buffers, copy the input to the output first, we then do an
  1483     if (bclass->transform)
  1919          * in-place transform on the output buffer. */
  1484       ret = bclass->transform (trans, inbuf, *outbuf);
  1920         memcpy (GST_BUFFER_DATA (*outbuf), GST_BUFFER_DATA (inbuf),
  1485     else
  1921             GST_BUFFER_SIZE (inbuf));
  1486       ret = GST_FLOW_NOT_SUPPORTED;
  1922       }
  1487   }
  1923       ret = bclass->transform_ip (trans, *outbuf);
  1488 
  1924     } else {
  1489   /* if we got renegotiated we can configure now */
  1925       GST_DEBUG_OBJECT (trans, "doing non-inplace transform");
  1490   if (trans->pending_configure) {
  1926 
  1491     gboolean success;
  1927       if (bclass->transform)
  1492 
  1928         ret = bclass->transform (trans, inbuf, *outbuf);
  1493     success =
  1929       else
  1494         gst_base_transform_configure_caps (trans,
  1930         ret = GST_FLOW_NOT_SUPPORTED;
  1495         GST_PAD_CAPS (trans->sinkpad), GST_PAD_CAPS (trans->srcpad));
  1931     }
  1496 
       
  1497     trans->pending_configure = FALSE;
       
  1498 
       
  1499     if (!success)
       
  1500       goto configure_failed;
  1932   }
  1501   }
  1933 
  1502 
  1934 skip:
  1503 skip:
  1935   /* only unref input buffer if we allocated a new outbuf buffer */
  1504   /* only unref input buffer if we allocated a new outbuf buffer */
  1936   if (*outbuf != inbuf)
  1505   if (*outbuf != inbuf)
  1937     gst_buffer_unref (inbuf);
  1506     gst_buffer_unref (inbuf);
  1938 
  1507 
       
  1508 done:
  1939   return ret;
  1509   return ret;
  1940 
  1510 
  1941   /* ERRORS */
  1511   /* ERRORS */
  1942 not_negotiated:
  1512 not_negotiated:
  1943   {
  1513   {
  1944     gst_buffer_unref (inbuf);
  1514     gst_buffer_unref (inbuf);
  1945     GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
  1515     GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
  1946         ("not negotiated"), ("not negotiated"));
  1516         ("not negotiated"), ("not negotiated"));
  1947     return GST_FLOW_NOT_NEGOTIATED;
  1517     return GST_FLOW_NOT_NEGOTIATED;
  1948   }
  1518   }
       
  1519 no_size:
       
  1520   {
       
  1521     gst_buffer_unref (inbuf);
       
  1522     GST_ELEMENT_ERROR (trans, STREAM, NOT_IMPLEMENTED,
       
  1523         ("subclass did not specify output size"),
       
  1524         ("subclass did not specify output size"));
       
  1525     return GST_FLOW_ERROR;
       
  1526   }
  1949 no_buffer:
  1527 no_buffer:
  1950   {
  1528   {
  1951     gst_buffer_unref (inbuf);
  1529     gst_buffer_unref (inbuf);
  1952     GST_WARNING_OBJECT (trans, "could not get buffer from pool: %s",
  1530     GST_DEBUG_OBJECT (trans, "could not get buffer from pool: %s",
  1953         gst_flow_get_name (ret));
  1531         gst_flow_get_name (ret));
  1954     return ret;
  1532     return ret;
       
  1533   }
       
  1534 configure_failed:
       
  1535   {
       
  1536     if (*outbuf != inbuf)
       
  1537       gst_buffer_unref (inbuf);
       
  1538     GST_DEBUG_OBJECT (trans, "could not negotiate");
       
  1539     return GST_FLOW_NOT_NEGOTIATED;
  1955   }
  1540   }
  1956 }
  1541 }
  1957 
  1542 
  1958 static gboolean
  1543 static gboolean
  1959 gst_base_transform_check_get_range (GstPad * pad)
  1544 gst_base_transform_check_get_range (GstPad * pad)
  1976 static GstFlowReturn
  1561 static GstFlowReturn
  1977 gst_base_transform_getrange (GstPad * pad, guint64 offset,
  1562 gst_base_transform_getrange (GstPad * pad, guint64 offset,
  1978     guint length, GstBuffer ** buffer)
  1563     guint length, GstBuffer ** buffer)
  1979 {
  1564 {
  1980   GstBaseTransform *trans;
  1565   GstBaseTransform *trans;
  1981   GstBaseTransformClass *klass;
       
  1982   GstFlowReturn ret;
  1566   GstFlowReturn ret;
  1983   GstBuffer *inbuf;
  1567   GstBuffer *inbuf;
  1984 
  1568 
  1985   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
  1569   trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
  1986 
  1570 
  1987   ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
  1571   ret = gst_pad_pull_range (trans->sinkpad, offset, length, &inbuf);
  1988   if (G_UNLIKELY (ret != GST_FLOW_OK))
  1572   if (ret == GST_FLOW_OK) {
  1989     goto pull_error;
  1573     g_mutex_lock (trans->transform_lock);
  1990 
  1574     ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
  1991   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1575     g_mutex_unlock (trans->transform_lock);
  1992   if (klass->before_transform)
  1576   }
  1993     klass->before_transform (trans, inbuf);
  1577 
  1994 
       
  1995   GST_BASE_TRANSFORM_LOCK (trans);
       
  1996   ret = gst_base_transform_handle_buffer (trans, inbuf, buffer);
       
  1997   GST_BASE_TRANSFORM_UNLOCK (trans);
       
  1998 
       
  1999 done:
       
  2000   gst_object_unref (trans);
  1578   gst_object_unref (trans);
  2001 
  1579 
  2002   return ret;
  1580   return ret;
  2003 
       
  2004   /* ERRORS */
       
  2005 pull_error:
       
  2006   {
       
  2007     GST_DEBUG_OBJECT (trans, "failed to pull a buffer: %s",
       
  2008         gst_flow_get_name (ret));
       
  2009     goto done;
       
  2010   }
       
  2011 }
  1581 }
  2012 
  1582 
  2013 static GstFlowReturn
  1583 static GstFlowReturn
  2014 gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
  1584 gst_base_transform_chain (GstPad * pad, GstBuffer * buffer)
  2015 {
  1585 {
  2016   GstBaseTransform *trans;
  1586   GstBaseTransform *trans;
  2017   GstBaseTransformClass *klass;
       
  2018   GstFlowReturn ret;
  1587   GstFlowReturn ret;
  2019   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
  1588   GstClockTime last_stop = GST_CLOCK_TIME_NONE;
  2020   GstBuffer *outbuf = NULL;
  1589   GstBuffer *outbuf = NULL;
  2021 
  1590 
  2022   trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
  1591   trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
  2027       last_stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
  1596       last_stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer);
  2028     else
  1597     else
  2029       last_stop = GST_BUFFER_TIMESTAMP (buffer);
  1598       last_stop = GST_BUFFER_TIMESTAMP (buffer);
  2030   }
  1599   }
  2031 
  1600 
  2032   klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
       
  2033   if (klass->before_transform)
       
  2034     klass->before_transform (trans, buffer);
       
  2035 
       
  2036   /* protect transform method and concurrent buffer alloc */
  1601   /* protect transform method and concurrent buffer alloc */
  2037   GST_BASE_TRANSFORM_LOCK (trans);
  1602   g_mutex_lock (trans->transform_lock);
  2038   ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
  1603   ret = gst_base_transform_handle_buffer (trans, buffer, &outbuf);
  2039   GST_BASE_TRANSFORM_UNLOCK (trans);
  1604   g_mutex_unlock (trans->transform_lock);
  2040 
  1605 
  2041   /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but
  1606   /* outbuf can be NULL, this means a dropped buffer, if we have a buffer but
  2042    * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */
  1607    * GST_BASE_TRANSFORM_FLOW_DROPPED we will not push either. */
  2043   if (outbuf != NULL) {
  1608   if (outbuf != NULL) {
  2044     if ((ret == GST_FLOW_OK)) {
  1609     if ((ret == GST_FLOW_OK)) {
  2131     trans->have_newsegment = FALSE;
  1696     trans->have_newsegment = FALSE;
  2132     gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
  1697     gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
  2133     trans->priv->proportion = 1.0;
  1698     trans->priv->proportion = 1.0;
  2134     trans->priv->earliest_time = -1;
  1699     trans->priv->earliest_time = -1;
  2135     trans->priv->discont = FALSE;
  1700     trans->priv->discont = FALSE;
  2136     gst_caps_replace (&trans->priv->sink_suggest, NULL);
       
  2137 
  1701 
  2138     GST_OBJECT_UNLOCK (trans);
  1702     GST_OBJECT_UNLOCK (trans);
  2139   } else {
  1703   } else {
  2140     /* We must make sure streaming has finished before resetting things
  1704     /* We must make sure streaming has finished before resetting things
  2141      * and calling the ::stop vfunc */
  1705      * and calling the ::stop vfunc */
  2148     if (bclass->passthrough_on_same_caps) {
  1712     if (bclass->passthrough_on_same_caps) {
  2149       gst_base_transform_set_passthrough (trans, FALSE);
  1713       gst_base_transform_set_passthrough (trans, FALSE);
  2150     }
  1714     }
  2151     gst_caps_replace (&trans->cache_caps1, NULL);
  1715     gst_caps_replace (&trans->cache_caps1, NULL);
  2152     gst_caps_replace (&trans->cache_caps2, NULL);
  1716     gst_caps_replace (&trans->cache_caps2, NULL);
  2153     gst_caps_replace (&trans->priv->sink_alloc, NULL);
       
  2154     gst_caps_replace (&trans->priv->sink_suggest, NULL);
       
  2155 
  1717 
  2156     if (trans->priv->pad_mode != GST_ACTIVATE_NONE && bclass->stop)
  1718     if (trans->priv->pad_mode != GST_ACTIVATE_NONE && bclass->stop)
  2157       result &= bclass->stop (trans);
  1719       result &= bclass->stop (trans);
  2158   }
  1720   }
  2159 
  1721 
  2220 gst_base_transform_set_passthrough (GstBaseTransform * trans,
  1782 gst_base_transform_set_passthrough (GstBaseTransform * trans,
  2221     gboolean passthrough)
  1783     gboolean passthrough)
  2222 {
  1784 {
  2223   GstBaseTransformClass *bclass;
  1785   GstBaseTransformClass *bclass;
  2224 
  1786 
  2225   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
  1787   g_return_if_fail (trans != NULL);
  2226 
  1788 
  2227   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1789   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  2228 
  1790 
  2229   GST_OBJECT_LOCK (trans);
  1791   GST_OBJECT_LOCK (trans);
  2230   if (passthrough == FALSE) {
  1792   if (passthrough == FALSE) {
  2255 gboolean
  1817 gboolean
  2256 gst_base_transform_is_passthrough (GstBaseTransform * trans)
  1818 gst_base_transform_is_passthrough (GstBaseTransform * trans)
  2257 {
  1819 {
  2258   gboolean result;
  1820   gboolean result;
  2259 
  1821 
  2260   g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
  1822   g_return_val_if_fail (trans != NULL, FALSE);
  2261 
  1823 
  2262   GST_OBJECT_LOCK (trans);
  1824   GST_OBJECT_LOCK (trans);
  2263   result = trans->passthrough;
  1825   result = trans->passthrough;
  2264   GST_OBJECT_UNLOCK (trans);
  1826   GST_OBJECT_UNLOCK (trans);
  2265 
  1827 
  2274  *
  1836  *
  2275  * Determines whether a non-writable buffer will be copied before passing
  1837  * Determines whether a non-writable buffer will be copied before passing
  2276  * to the transform_ip function.
  1838  * to the transform_ip function.
  2277  * <itemizedlist>
  1839  * <itemizedlist>
  2278  *   <listitem>Always TRUE if no transform function is implemented.</listitem>
  1840  *   <listitem>Always TRUE if no transform function is implemented.</listitem>
  2279  *   <listitem>Always FALSE if ONLY transform function is implemented.</listitem>
  1841  *   <listitem>Always FALSE if ONLY transform_ip function is implemented.</listitem>
  2280  * </itemizedlist>
  1842  * </itemizedlist>
  2281  *
  1843  *
  2282  * MT safe.
  1844  * MT safe.
  2283  */
  1845  */
  2284 #ifdef __SYMBIAN32__
  1846 #ifdef __SYMBIAN32__
  2288 void
  1850 void
  2289 gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place)
  1851 gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place)
  2290 {
  1852 {
  2291   GstBaseTransformClass *bclass;
  1853   GstBaseTransformClass *bclass;
  2292 
  1854 
  2293   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
  1855   g_return_if_fail (trans != NULL);
  2294 
  1856 
  2295   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  1857   bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
  2296 
  1858 
  2297   GST_OBJECT_LOCK (trans);
  1859   GST_OBJECT_LOCK (trans);
  2298 
  1860 
  2328 gboolean
  1890 gboolean
  2329 gst_base_transform_is_in_place (GstBaseTransform * trans)
  1891 gst_base_transform_is_in_place (GstBaseTransform * trans)
  2330 {
  1892 {
  2331   gboolean result;
  1893   gboolean result;
  2332 
  1894 
  2333   g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
  1895   g_return_val_if_fail (trans != NULL, FALSE);
  2334 
  1896 
  2335   GST_OBJECT_LOCK (trans);
  1897   GST_OBJECT_LOCK (trans);
  2336   result = trans->always_in_place;
  1898   result = trans->always_in_place;
  2337   GST_OBJECT_UNLOCK (trans);
  1899   GST_OBJECT_UNLOCK (trans);
  2338 
  1900 
  2342 /**
  1904 /**
  2343  * gst_base_transform_update_qos:
  1905  * gst_base_transform_update_qos:
  2344  * @trans: a #GstBaseTransform
  1906  * @trans: a #GstBaseTransform
  2345  * @proportion: the proportion
  1907  * @proportion: the proportion
  2346  * @diff: the diff against the clock
  1908  * @diff: the diff against the clock
  2347  * @timestamp: the timestamp of the buffer generating the QoS expressed in
  1909  * @timestamp: the timestamp of the buffer generating the QoS
  2348  * running_time.
  1910  *
  2349  *
  1911  * Set the QoS parameters in the transform.
  2350  * Set the QoS parameters in the transform. This function is called internally
  1912  *
  2351  * when a QOS event is received but subclasses can provide custom information
  1913  * Since: 0.10.5
  2352  * when needed.
       
  2353  *
  1914  *
  2354  * MT safe.
  1915  * MT safe.
  2355  *
       
  2356  * Since: 0.10.5
       
  2357  */
  1916  */
  2358 #ifdef __SYMBIAN32__
  1917 #ifdef __SYMBIAN32__
  2359 EXPORT_C
  1918 EXPORT_C
  2360 #endif
  1919 #endif
  2361 
  1920 
  2362 void
  1921 void
  2363 gst_base_transform_update_qos (GstBaseTransform * trans,
  1922 gst_base_transform_update_qos (GstBaseTransform * trans,
  2364     gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
  1923     gdouble proportion, GstClockTimeDiff diff, GstClockTime timestamp)
  2365 {
  1924 {
  2366 
  1925 
  2367   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
  1926   g_return_if_fail (trans != NULL);
  2368 
  1927 
  2369   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans,
  1928   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans,
  2370       "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
  1929       "qos: proportion: %lf, diff %" G_GINT64_FORMAT ", timestamp %"
  2371       GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
  1930       GST_TIME_FORMAT, proportion, diff, GST_TIME_ARGS (timestamp));
  2372 
  1931 
  2381  * @trans: a #GstBaseTransform
  1940  * @trans: a #GstBaseTransform
  2382  * @enabled: new state
  1941  * @enabled: new state
  2383  *
  1942  *
  2384  * Enable or disable QoS handling in the transform.
  1943  * Enable or disable QoS handling in the transform.
  2385  *
  1944  *
       
  1945  * Since: 0.10.5
       
  1946  *
  2386  * MT safe.
  1947  * MT safe.
  2387  *
       
  2388  * Since: 0.10.5
       
  2389  */
  1948  */
  2390 #ifdef __SYMBIAN32__
  1949 #ifdef __SYMBIAN32__
  2391 EXPORT_C
  1950 EXPORT_C
  2392 #endif
  1951 #endif
  2393 
  1952 
  2394 void
  1953 void
  2395 gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled)
  1954 gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled)
  2396 {
  1955 {
  2397   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
  1956   g_return_if_fail (trans != NULL);
  2398 
  1957 
  2399   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "enabled: %d", enabled);
  1958   GST_CAT_DEBUG_OBJECT (GST_CAT_QOS, trans, "enabled: %d", enabled);
  2400 
  1959 
  2401   GST_OBJECT_LOCK (trans);
  1960   GST_OBJECT_LOCK (trans);
  2402   trans->priv->qos_enabled = enabled;
  1961   trans->priv->qos_enabled = enabled;
  2409  *
  1968  *
  2410  * Queries if the transform will handle QoS.
  1969  * Queries if the transform will handle QoS.
  2411  *
  1970  *
  2412  * Returns: TRUE if QoS is enabled.
  1971  * Returns: TRUE if QoS is enabled.
  2413  *
  1972  *
       
  1973  * Since: 0.10.5
       
  1974  *
  2414  * MT safe.
  1975  * MT safe.
  2415  *
       
  2416  * Since: 0.10.5
       
  2417  */
  1976  */
  2418 #ifdef __SYMBIAN32__
  1977 #ifdef __SYMBIAN32__
  2419 EXPORT_C
  1978 EXPORT_C
  2420 #endif
  1979 #endif
  2421 
  1980 
  2422 gboolean
  1981 gboolean
  2423 gst_base_transform_is_qos_enabled (GstBaseTransform * trans)
  1982 gst_base_transform_is_qos_enabled (GstBaseTransform * trans)
  2424 {
  1983 {
  2425   gboolean result;
  1984   gboolean result;
  2426 
  1985 
  2427   g_return_val_if_fail (GST_IS_BASE_TRANSFORM (trans), FALSE);
  1986   g_return_val_if_fail (trans != NULL, FALSE);
  2428 
  1987 
  2429   GST_OBJECT_LOCK (trans);
  1988   GST_OBJECT_LOCK (trans);
  2430   result = trans->priv->qos_enabled;
  1989   result = trans->priv->qos_enabled;
  2431   GST_OBJECT_UNLOCK (trans);
  1990   GST_OBJECT_UNLOCK (trans);
  2432 
  1991 
  2436 /**
  1995 /**
  2437  * gst_base_transform_set_gap_aware:
  1996  * gst_base_transform_set_gap_aware:
  2438  * @trans: a #GstBaseTransform
  1997  * @trans: a #GstBaseTransform
  2439  * @gap_aware: New state
  1998  * @gap_aware: New state
  2440  *
  1999  *
  2441  * If @gap_aware is %FALSE (the default), output buffers will have the
  2000  * If @gap_aware is %FALSE (as it is by default) subclasses will never get
  2442  * %GST_BUFFER_FLAG_GAP flag unset.
  2001  * output buffers with the %GST_BUFFER_FLAG_GAP flag set.
  2443  *
  2002  *
  2444  * If set to %TRUE, the element must handle output buffers with this flag set
  2003  * If set to %TRUE elements must handle output buffers with this flag set
  2445  * correctly, i.e. it can assume that the buffer contains neutral data but must
  2004  * correctly, i.e. they can assume that the buffer contains neutral data
  2446  * unset the flag if the output is no neutral data.
  2005  * but must unset the flag if the output is no neutral data.
       
  2006  * Since: 0.10.16
  2447  *
  2007  *
  2448  * MT safe.
  2008  * MT safe.
  2449  *
       
  2450  * Since: 0.10.16
       
  2451  */
  2009  */
  2452 #ifdef __SYMBIAN32__
  2010 #ifdef __SYMBIAN32__
  2453 EXPORT_C
  2011 EXPORT_C
  2454 #endif
  2012 #endif
  2455 
  2013 
  2456 void
  2014 void
  2457 gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
  2015 gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
  2458 {
  2016 {
  2459   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
  2017   g_return_if_fail (trans != NULL);
  2460 
  2018 
  2461   GST_OBJECT_LOCK (trans);
  2019   GST_OBJECT_LOCK (trans);
  2462   trans->priv->gap_aware = gap_aware;
  2020   trans->priv->gap_aware = gap_aware;
  2463   GST_DEBUG_OBJECT (trans, "set gap aware %d", trans->priv->gap_aware);
  2021   GST_DEBUG_OBJECT (trans, "set gap aware %d", trans->priv->gap_aware);
  2464   GST_OBJECT_UNLOCK (trans);
  2022   GST_OBJECT_UNLOCK (trans);
  2465 }
  2023 }
  2466 
       
  2467 /**
       
  2468  * gst_base_transform_suggest:
       
  2469  * @trans: a #GstBaseTransform
       
  2470  * @caps: caps to suggest
       
  2471  * @size: buffer size to suggest
       
  2472  *
       
  2473  * Instructs @trans to suggest new @caps upstream. A copy of @caps will be
       
  2474  * taken.
       
  2475  *
       
  2476  * Since: 0.10.21
       
  2477  */
       
  2478 #ifdef __SYMBIAN32__
       
  2479 EXPORT_C
       
  2480 #endif
       
  2481 
       
  2482 void
       
  2483 gst_base_transform_suggest (GstBaseTransform * trans, GstCaps * caps,
       
  2484     guint size)
       
  2485 {
       
  2486   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
       
  2487 
       
  2488   GST_OBJECT_LOCK (trans->sinkpad);
       
  2489   if (trans->priv->sink_suggest)
       
  2490     gst_caps_unref (trans->priv->sink_suggest);
       
  2491   if (caps)
       
  2492     caps = gst_caps_copy (caps);
       
  2493   trans->priv->sink_suggest = caps;
       
  2494   trans->priv->size_suggest = size;
       
  2495   trans->priv->suggest_pending = TRUE;
       
  2496   GST_DEBUG_OBJECT (trans, "new suggest %" GST_PTR_FORMAT, caps);
       
  2497   GST_OBJECT_UNLOCK (trans->sinkpad);
       
  2498 }
       
  2499 
       
  2500 /**
       
  2501  * gst_base_transform_reconfigure:
       
  2502  * @trans: a #GstBaseTransform
       
  2503  *
       
  2504  * Instructs @trans to renegotiate a new downstream transform on the next
       
  2505  * buffer. This function is typically called after properties on the transform
       
  2506  * were set that influence the output format.
       
  2507  *
       
  2508  * Since: 0.10.21
       
  2509  */
       
  2510 #ifdef __SYMBIAN32__
       
  2511 EXPORT_C
       
  2512 #endif
       
  2513 
       
  2514 void
       
  2515 gst_base_transform_reconfigure (GstBaseTransform * trans)
       
  2516 {
       
  2517   g_return_if_fail (GST_IS_BASE_TRANSFORM (trans));
       
  2518 
       
  2519   GST_OBJECT_LOCK (trans);
       
  2520   GST_DEBUG_OBJECT (trans, "marking reconfigure");
       
  2521   trans->priv->reconfigure = TRUE;
       
  2522   gst_caps_replace (&trans->priv->sink_alloc, NULL);
       
  2523   GST_OBJECT_UNLOCK (trans);
       
  2524 }