⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gstbasetransform.c

📁 gnash 在pc和嵌入式下开发需要的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu> *                    2000 Wim Taymans <wtay@chello.be> *                    2005 Wim Taymans <wim@fluendo.com> *                    2005 Andy Wingo <wingo@fluendo.com> *                    2005 Thomas Vander Stichele <thomas at apestaart dot org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//** * SECTION:gstbasetransform * @short_description: Base class for simple transform filters * @see_also: #GstBaseSrc, #GstBaseSink * * This base class is for filter elements that process data. * * It provides for: * <itemizedlist> *   <listitem><para>one sinkpad and one srcpad</para></listitem> *   <listitem><para> *      Possible formats on sink and source pad implemented *      with custom transform_caps function. By default uses *      same format on sink and source. *   </para></listitem> *   <listitem><para>Handles state changes</para></listitem> *   <listitem><para>Does flushing</para></listitem> *   <listitem><para>Push mode</para></listitem> *   <listitem><para> *       Pull mode if the sub-class transform can operate on arbitrary data *    </para></listitem> * </itemizedlist> * * Use Cases: * <orderedlist> * <listitem> *   <itemizedlist><title>Passthrough mode</title> *   <listitem><para> *     Element has no interest in modifying the buffer. It may want to inspect it, *     in which case the element should have a transform_ip function. If there *     is no transform_ip function in passthrough mode, the buffer is pushed *     intact. *   </para></listitem> *   <listitem><para> *     On the GstBaseTransformClass is the passthrough_on_same_caps variable *     which will automatically set/unset passthrough based on whether the *     element negotiates the same caps on both pads. *   </para></listitem> *   <listitem><para> *     passthrough_on_same_caps on an element that doesn't implement a *     transform_caps function is useful for elements that only inspect data *     (such as level) *   </para></listitem> *   </itemizedlist> *   <itemizedlist> *   <title>Example elements</title> *     <listitem>Level</listitem> *     <listitem>Videoscale, audioconvert, ffmpegcolorspace, audioresample in *     certain modes.</listitem> *   </itemizedlist> * </listitem> * <listitem> *   <itemizedlist> *     <title>Modifications in-place - input buffer and output buffer are the *     same thing.</title> *   <listitem><para> *     The element must implement a transform_ip function. *   </para></listitem> *   <listitem><para> *     Output buffer size must <= input buffer size *   </para></listitem> *   <listitem><para> *     If the always_in_place flag is set, non-writable buffers will be copied *     and passed to the transform_ip function, otherwise a new buffer will be *     created and the transform function called. *   </para></listitem> *   <listitem><para> *     Incoming writable buffers will be passed to the transform_ip function *     immediately.  </para></listitem> *   <listitem><para> *     only implementing transform_ip and not transform implies always_in_place *     = TRUE *   </para></listitem> *   </itemizedlist> *   <itemizedlist> *   <title>Example elements</title> *     <listitem>Volume</listitem> *     <listitem>Audioconvert in certain modes (signed/unsigned *     conversion)</listitem> *     <listitem>ffmpegcolorspace in certain modes (endianness *     swapping)</listitem> *   </itemizedlist> *  </listitem> * <listitem> *   <itemizedlist> *   <title>Modifications only to the caps/metadata of a buffer</title> *   <listitem><para> *     The element does not require writable data, but non-writable buffers *     should be subbuffered so that the meta-information can be replaced. *   </para></listitem> *   <listitem><para> *     Elements wishing to operate in this mode should replace the *     prepare_output_buffer method to create subbuffers of the input buffer *     and set always_in_place to TRUE *   </para></listitem> *   </itemizedlist> *   <itemizedlist> *   <title>Example elements</title> *     <listitem>Capsfilter when setting caps on outgoing buffers that have *     none.</listitem> *     <listitem>identity when it is going to re-timestamp buffers by *     datarate.</listitem> *   </itemizedlist> * </listitem> * <listitem> *   <itemizedlist><title>Normal mode</title> *   <listitem><para> *     always_in_place flag is not set, or there is no transform_ip function *   </para></listitem> *   <listitem><para> *     Element will receive an input buffer and output buffer to operate on. *   </para></listitem> *   <listitem><para> *     Output buffer is allocated by calling the prepare_output_buffer function. *   </para></listitem> *   </itemizedlist> *   <itemizedlist> *   <title>Example elements</title> *     <listitem>Videoscale, ffmpegcolorspace, audioconvert when doing *     scaling/conversions</listitem> *   </itemizedlist> * </listitem> * <listitem> *   <itemizedlist><title>Special output buffer allocations</title> *   <listitem><para> *     Elements which need to do special allocation of their output buffers *     other than what gst_buffer_pad_alloc allows should implement a *     prepare_output_buffer method, which calls the parent implementation and *     passes the newly allocated buffer. *   </para></listitem> *   </itemizedlist> *   <itemizedlist> *   <title>Example elements</title> *     <listitem>efence</listitem> *   </itemizedlist> * </listitem> * </orderedlist> * * <itemizedlist><title>Sub-class settable flags on GstBaseTransform</title> * <listitem><para> *   <itemizedlist><title>passthrough</title> *     <listitem><para> *       Implies that in the current configuration, the sub-class is not *       interested in modifying the buffers. *     </para></listitem> *     <listitem><para> *       Elements which are always in passthrough mode whenever the same caps *       has been negotiated on both pads can set the class variable *       passthrough_on_same_caps to have this behaviour automatically. *     </para></listitem> *   </itemizedlist> * </para></listitem> * <listitem><para> *   <itemizedlist><title>always_in_place</title> *     <listitem><para> *       Determines whether a non-writable buffer will be copied before passing *       to the transform_ip function. *     </para></listitem> *     <listitem><para> *       Implied TRUE if no transform function is implemented. *     </para></listitem> *     <listitem><para> *       Implied FALSE if ONLY transform function is implemented. *     </para></listitem> *   </itemizedlist> * </para></listitem> * </itemizedlist> **/#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <stdlib.h>#include <string.h>#include "../../../gst/gst_private.h"#include "../../../gst/gst-i18n-lib.h"#include "gstbasetransform.h"#include <gst/gstmarshal.h>GST_DEBUG_CATEGORY_STATIC (gst_base_transform_debug);#define GST_CAT_DEFAULT gst_base_transform_debug/* BaseTransform signals and args */enum{  /* FILL ME */  LAST_SIGNAL};#define DEFAULT_PROP_QOS	FALSEenum{  PROP_0,  PROP_QOS};#define GST_BASE_TRANSFORM_GET_PRIVATE(obj)  \    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_TRANSFORM, GstBaseTransformPrivate))struct _GstBaseTransformPrivate{  /* QoS *//* with LOCK */  gboolean qos_enabled;  gdouble proportion;  GstClockTime earliest_time;  /* previous buffer had a discont */  gboolean discont;  GstActivateMode pad_mode;};static GstElementClass *parent_class = NULL;static void gst_base_transform_base_init (gpointer g_class);static void gst_base_transform_class_init (GstBaseTransformClass * klass);static void gst_base_transform_init (GstBaseTransform * trans,    GstBaseTransformClass * klass);static GstFlowReturn gst_base_transform_prepare_output_buffer (GstBaseTransform    * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf);GTypegst_base_transform_get_type (void){  static GType base_transform_type = 0;  if (!base_transform_type) {    static const GTypeInfo base_transform_info = {      sizeof (GstBaseTransformClass),      (GBaseInitFunc) gst_base_transform_base_init,      NULL,      (GClassInitFunc) gst_base_transform_class_init,      NULL,      NULL,      sizeof (GstBaseTransform),      0,      (GInstanceInitFunc) gst_base_transform_init,    };    base_transform_type = g_type_register_static (GST_TYPE_ELEMENT,        "GstBaseTransform", &base_transform_info, G_TYPE_FLAG_ABSTRACT);  }  return base_transform_type;}static void gst_base_transform_finalize (GObject * object);static void gst_base_transform_set_property (GObject * object, guint prop_id,    const GValue * value, GParamSpec * pspec);static void gst_base_transform_get_property (GObject * object, guint prop_id,    GValue * value, GParamSpec * pspec);static gboolean gst_base_transform_src_activate_pull (GstPad * pad,    gboolean active);static gboolean gst_base_transform_sink_activate_push (GstPad * pad,    gboolean active);static gboolean gst_base_transform_activate (GstBaseTransform * trans,    gboolean active);static gboolean gst_base_transform_get_unit_size (GstBaseTransform * trans,    GstCaps * caps, guint * size);static gboolean gst_base_transform_src_event (GstPad * pad, GstEvent * event);static gboolean gst_base_transform_src_eventfunc (GstBaseTransform * trans,    GstEvent * event);static gboolean gst_base_transform_sink_event (GstPad * pad, GstEvent * event);static gboolean gst_base_transform_sink_eventfunc (GstBaseTransform * trans,    GstEvent * event);static gboolean gst_base_transform_check_get_range (GstPad * pad);static GstFlowReturn gst_base_transform_getrange (GstPad * pad, guint64 offset,    guint length, GstBuffer ** buffer);static GstFlowReturn gst_base_transform_chain (GstPad * pad,    GstBuffer * buffer);static GstCaps *gst_base_transform_getcaps (GstPad * pad);static gboolean gst_base_transform_setcaps (GstPad * pad, GstCaps * caps);static GstFlowReturn gst_base_transform_buffer_alloc (GstPad * pad,    guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);/* static guint gst_base_transform_signals[LAST_SIGNAL] = { 0 }; */static voidgst_base_transform_base_init (gpointer g_class){  GST_DEBUG_CATEGORY_INIT (gst_base_transform_debug, "basetransform", 0,      "basetransform element");}static voidgst_base_transform_finalize (GObject * object){  GstBaseTransform *trans;  trans = GST_BASE_TRANSFORM (object);  g_mutex_free (trans->transform_lock);  G_OBJECT_CLASS (parent_class)->finalize (object);}static voidgst_base_transform_class_init (GstBaseTransformClass * klass){  GObjectClass *gobject_class;  gobject_class = G_OBJECT_CLASS (klass);  g_type_class_add_private (klass, sizeof (GstBaseTransformPrivate));  parent_class = g_type_class_peek_parent (klass);  gobject_class->set_property =      GST_DEBUG_FUNCPTR (gst_base_transform_set_property);  gobject_class->get_property =      GST_DEBUG_FUNCPTR (gst_base_transform_get_property);  g_object_class_install_property (gobject_class, PROP_QOS,      g_param_spec_boolean ("qos", "QoS", "handle QoS messages",          DEFAULT_PROP_QOS, G_PARAM_READWRITE));  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_transform_finalize);  klass->passthrough_on_same_caps = FALSE;  klass->event = GST_DEBUG_FUNCPTR (gst_base_transform_sink_eventfunc);  klass->src_event = GST_DEBUG_FUNCPTR (gst_base_transform_src_eventfunc);}static voidgst_base_transform_init (GstBaseTransform * trans,    GstBaseTransformClass * bclass){  GstPadTemplate *pad_template;  GST_DEBUG ("gst_base_transform_init");  trans->priv = GST_BASE_TRANSFORM_GET_PRIVATE (trans);  pad_template =      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");  g_return_if_fail (pad_template != NULL);  trans->sinkpad = gst_pad_new_from_template (pad_template, "sink");  gst_pad_set_getcaps_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));  gst_pad_set_setcaps_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));  gst_pad_set_event_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_sink_event));  gst_pad_set_chain_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_chain));  gst_pad_set_activatepush_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_sink_activate_push));  gst_pad_set_bufferalloc_function (trans->sinkpad,      GST_DEBUG_FUNCPTR (gst_base_transform_buffer_alloc));  gst_element_add_pad (GST_ELEMENT (trans), trans->sinkpad);  pad_template =      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");  g_return_if_fail (pad_template != NULL);  trans->srcpad = gst_pad_new_from_template (pad_template, "src");  gst_pad_set_getcaps_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_getcaps));  gst_pad_set_setcaps_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_setcaps));  gst_pad_set_event_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_src_event));  gst_pad_set_checkgetrange_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_check_get_range));  gst_pad_set_getrange_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_getrange));  gst_pad_set_activatepull_function (trans->srcpad,      GST_DEBUG_FUNCPTR (gst_base_transform_src_activate_pull));  gst_element_add_pad (GST_ELEMENT (trans), trans->srcpad);  trans->transform_lock = g_mutex_new ();  trans->delay_configure = FALSE;  trans->pending_configure = FALSE;  trans->priv->qos_enabled = DEFAULT_PROP_QOS;  trans->cache_caps1 = NULL;  trans->cache_caps2 = NULL;  trans->priv->pad_mode = GST_ACTIVATE_NONE;  trans->passthrough = FALSE;  if (bclass->transform == NULL) {    /* If no transform function, always_in_place is TRUE */    GST_DEBUG_OBJECT (trans, "setting in_place TRUE");    trans->always_in_place = TRUE;    if (bclass->transform_ip == NULL)      trans->passthrough = TRUE;  }}/* given @caps on the src or sink pad (given by @direction) * calculate the possible caps on the other pad. * * Returns new caps, unref after usage. */static GstCaps *gst_base_transform_transform_caps (GstBaseTransform * trans,    GstPadDirection direction, GstCaps * caps){  GstCaps *ret;  GstBaseTransformClass *klass;  klass = GST_BASE_TRANSFORM_GET_CLASS (trans);  /* if there is a custom transform function, use this */  if (klass->transform_caps) {    GstCaps *temp;    gint i;    /* start with empty caps */    ret = gst_caps_new_empty ();    GST_DEBUG_OBJECT (trans, "transform caps (direction = %d)", direction);    if (gst_caps_is_any (caps)) {      /* for any caps we still have to call the transform function */      GST_DEBUG_OBJECT (trans, "from: ANY");      temp = klass->transform_caps (trans, direction, caps);      GST_DEBUG_OBJECT (trans, "  to: %" GST_PTR_FORMAT, temp);      temp = gst_caps_make_writable (temp);      gst_caps_append (ret, temp);    } else {      /* we send caps with just one structure to the transform       * function as this is easier for the element */      for (i = 0; i < gst_caps_get_size (caps); i++) {        GstCaps *nth;        nth = gst_caps_copy_nth (caps, i);        GST_DEBUG_OBJECT (trans, "from[%d]: %" GST_PTR_FORMAT, i, nth);        temp = klass->transform_caps (trans, direction, nth);        gst_caps_unref (nth);        GST_DEBUG_OBJECT (trans, "  to[%d]: %" GST_PTR_FORMAT, i, temp);        temp = gst_caps_make_writable (temp);        /* FIXME: here we need to only append those structures, that are not yet         * in there         * gst_caps_append (ret, temp);         */        gst_caps_merge (ret, temp);      }      GST_DEBUG_OBJECT (trans, "merged: (%d)", gst_caps_get_size (ret));      /* now simplify caps         gst_caps_do_simplify (ret);         GST_DEBUG_OBJECT (trans, "simplified: (%d)", gst_caps_get_size (ret));       */    }  } else {    /* else use the identity transform */    ret = gst_caps_ref (caps);  }  GST_DEBUG_OBJECT (trans, "to: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (ret),      ret);  return ret;}static gbooleangst_base_transform_transform_size (GstBaseTransform * trans,    GstPadDirection direction, GstCaps * caps,    guint size, GstCaps * othercaps, guint * othersize){  guint inunitsize, outunitsize, units;  GstBaseTransformClass *klass;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -