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

📄 gstcontroller.c

📁 GStreamer是一个开源的多媒体框架库。利用它
💻 C
📖 第 1 页 / 共 3 页
字号:
/* GStreamer * * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net> * * gstcontroller.c: dynamic parameter control subsystem * * 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:gstcontroller * @short_description: dynamic parameter control subsystem * * The controller subsystem offers a lightweight way to adjust gobject * properties over stream-time. It works by using time-stamped value pairs that * are queued for element-properties. At run-time the elements continously pull * values changes for the current stream-time. * * What needs to be changed in a #GstElement? * Very little - it is just two steps to make a plugin controllable! * <orderedlist> *   <listitem><para> *     mark gobject-properties paramspecs that make sense to be controlled, *     by GST_PARAM_CONTROLLABLE. *   </para></listitem> *   <listitem><para> *     when processing data (get, chain, loop function) at the beginning call *     gst_object_sync_values(element,timestamp). *     This will made the controller to update all gobject properties that are under *     control with the current values based on timestamp. *   </para></listitem> * </orderedlist> * * What needs to be done in applications? * Again its not a lot to change. * <orderedlist> *   <listitem><para> *     first put some properties under control, by calling *     controller = g_object_control_properties(object, "prop1", "prop2",...); *   </para></listitem> *   <listitem><para> *     set how the controller will smooth inbetween values. *     gst_controller_set_interpolation_mode(controller,"prop1",mode); *   </para></listitem> *   <listitem><para> *     set key values *     gst_controller_set (controller, "prop1" ,0 * GST_SECOND, value1); *     gst_controller_set (controller, "prop1" ,1 * GST_SECOND, value2); *   </para></listitem> *   <listitem><para> *     start your pipeline *   </para></listitem> * </orderedlist> */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "gstcontrollerprivate.h"#include "gstcontroller.h"#define GST_CAT_DEFAULT gst_controller_debugGST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);static GObjectClass *parent_class = NULL;GQuark __gst_controller_key;/* property ids */enum{  PROP_CONTROL_RATE = 1};struct _GstControllerPrivate{  GstClockTime control_rate;  GstClockTime last_sync;};/* imports from gst-interpolation.c */extern GList    * gst_controlled_property_find_control_point_node (GstControlledProperty *    prop, GstClockTime timestamp);extern GstInterpolateMethod *interpolation_methods[];extern guint num_interpolation_methods;/* callbacks */voidon_object_controlled_property_changed (const GObject * object, GParamSpec * arg,    gpointer user_data){  GstControlledProperty *prop = GST_CONTROLLED_PROPERTY (user_data);  GstController *ctrl;  GST_LOG ("notify for '%s'", prop->name);  ctrl = g_object_get_qdata (G_OBJECT (object), __gst_controller_key);  g_return_if_fail (ctrl);  if (g_mutex_trylock (ctrl->lock)) {    if (!G_IS_VALUE (&prop->live_value.value)) {      g_value_init (&prop->live_value.value, prop->type);    }    g_object_get_property (G_OBJECT (object), prop->name,        &prop->live_value.value);    prop->live_value.timestamp = prop->last_value.timestamp;    g_mutex_unlock (ctrl->lock);    GST_DEBUG ("-> is live update : ts=%" G_GUINT64_FORMAT,        prop->live_value.timestamp);  }}/* helper *//* * gst_control_point_compare: * @p1: a pointer to a #GstControlPoint * @p2: a pointer to a #GstControlPoint * * Compare function for g_list operations that operates on two #GstControlPoint * parameters. */static gintgst_control_point_compare (gconstpointer p1, gconstpointer p2){  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;  GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));/* this does not produce an gint :(  return ((ct1 - ct2));*/}/* * gst_control_point_find: * @p1: a pointer to a #GstControlPoint * @p2: a pointer to a #GstClockTime * * Compare function for g_list operations that operates on a #GstControlPoint and * a #GstClockTime. */static gintgst_control_point_find (gconstpointer p1, gconstpointer p2){  GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;  GstClockTime ct2 = *(GstClockTime *) p2;  return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));/* this does not produce an gint :(  return ((ct1 - ct2));*/}/* * gst_controlled_property_set_interpolation_mode: * @self: the controlled property object to change * @mode: the new interpolation mode * * Sets the given Interpolation mode for the controlled property and activates * the respective interpolation hooks. * * Returns: %TRUE for success */static gbooleangst_controlled_property_set_interpolation_mode (GstControlledProperty * self,    GstInterpolateMode mode){  gboolean res = TRUE;  if (mode >= num_interpolation_methods || interpolation_methods[mode] == NULL) {    GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);    return FALSE;  }  self->interpolation = mode;  if (mode != GST_INTERPOLATE_USER) {    switch (self->base) {      case G_TYPE_INT:        self->get = interpolation_methods[mode]->get_int;        self->get_value_array =            interpolation_methods[mode]->get_int_value_array;        break;      case G_TYPE_UINT:        self->get = interpolation_methods[mode]->get_uint;        self->get_value_array =            interpolation_methods[mode]->get_uint_value_array;        break;      case G_TYPE_LONG:        self->get = interpolation_methods[mode]->get_long;        self->get_value_array =            interpolation_methods[mode]->get_long_value_array;        break;      case G_TYPE_ULONG:        self->get = interpolation_methods[mode]->get_ulong;        self->get_value_array =            interpolation_methods[mode]->get_ulong_value_array;        break;      case G_TYPE_FLOAT:        self->get = interpolation_methods[mode]->get_float;        self->get_value_array =            interpolation_methods[mode]->get_float_value_array;        break;      case G_TYPE_DOUBLE:        self->get = interpolation_methods[mode]->get_double;        self->get_value_array =            interpolation_methods[mode]->get_double_value_array;        break;      case G_TYPE_BOOLEAN:        self->get = interpolation_methods[mode]->get_boolean;        self->get_value_array =            interpolation_methods[mode]->get_boolean_value_array;        break;      case G_TYPE_ENUM:        self->get = interpolation_methods[mode]->get_uint;        self->get_value_array =            interpolation_methods[mode]->get_enum_value_array;        break;      case G_TYPE_STRING:        self->get = interpolation_methods[mode]->get_string;        self->get_value_array =            interpolation_methods[mode]->get_string_value_array;        break;      default:        self->get = NULL;        self->get_value_array = NULL;    }    if (!self->get) {           /* || !self->get_value_array) */      GST_WARNING ("incomplete implementation for type %lu/%lu:'%s'/'%s'",          self->type, self->base,          g_type_name (self->type), g_type_name (self->base));      res = FALSE;    }  } else {    /* TODO shouldn't this also get a GstInterpolateMethod *user_method       for the case mode==GST_INTERPOLATE_USER     */    res = FALSE;  }  return (res);}/* * gst_controlled_property_new: * @object: for which object the controlled property should be set up * @name: the name of the property to be controlled * * Private method which initializes the fields of a new controlled property * structure. * * Returns: a freshly allocated structure or %NULL */static GstControlledProperty *gst_controlled_property_new (GObject * object, const gchar * name){  GstControlledProperty *prop = NULL;  GParamSpec *pspec;  GST_INFO ("trying to put property '%s' under control", name);  /* check if the object has a property of that name */  if ((pspec =          g_object_class_find_property (G_OBJECT_GET_CLASS (object), name))) {    GST_DEBUG ("  psec->flags : 0x%08x", pspec->flags);    /* check if this param is witable */    g_return_val_if_fail ((pspec->flags & G_PARAM_WRITABLE), NULL);    /* check if property is controlable */    g_return_val_if_fail ((pspec->flags & GST_PARAM_CONTROLLABLE), NULL);    /* check if this param is not construct-only */    g_return_val_if_fail (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY), NULL);    /* TODO do sanity checks       we don't control some pspec->value_type:       G_TYPE_PARAM_BOXED       G_TYPE_PARAM_ENUM       G_TYPE_PARAM_FLAGS       G_TYPE_PARAM_OBJECT       G_TYPE_PARAM_PARAM       G_TYPE_PARAM_POINTER       G_TYPE_PARAM_STRING     */    if ((prop = g_new0 (GstControlledProperty, 1))) {      gchar *signal_name;      GType base;      prop->name = pspec->name; /* so we don't use the same mem twice */      prop->type = G_PARAM_SPEC_VALUE_TYPE (pspec);      /* get the fundamental base type */      prop->base = prop->type;      while ((base = g_type_parent (prop->base))) {        prop->base = base;      }      /* initialize mode specific accessor callbacks */      if (!gst_controlled_property_set_interpolation_mode (prop,              GST_INTERPOLATE_NONE))        goto Error;      /* prepare our gvalues */      g_value_init (&prop->default_value, prop->type);      g_value_init (&prop->result_value, prop->type);      g_value_init (&prop->last_value.value, prop->type);      switch (prop->base) {        case G_TYPE_INT:{          GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);          g_value_set_int (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_UINT:{          GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);          g_value_set_uint (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_LONG:{          GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);          g_value_set_long (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_ULONG:{          GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);          g_value_set_ulong (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_FLOAT:{          GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);          g_value_set_float (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_DOUBLE:{          GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);          g_value_set_double (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_BOOLEAN:{          GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);          g_value_set_boolean (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_ENUM:{          GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);          g_value_set_enum (&prop->default_value, tpspec->default_value);        }          break;        case G_TYPE_STRING:{          GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);          g_value_set_string (&prop->default_value, tpspec->default_value);        }          break;        default:          GST_WARNING ("incomplete implementation for paramspec type '%s'",              G_PARAM_SPEC_TYPE_NAME (pspec));      }      /* TODO what about adding a control point with timestamp=0 and value=default       * a bit easier for interpolators, example:       * first timestamp is at 5       * requested value if for timestamp=3       * LINEAR and Co. would need to interpolate from default value to value       * at timestamp 5       */      signal_name = g_alloca (8 + 1 + strlen (name));      g_sprintf (signal_name, "notify::%s", name);      prop->notify_handler_id =          g_signal_connect (object, signal_name,          G_CALLBACK (on_object_controlled_property_changed), (gpointer) prop);    }  } else {    GST_WARNING ("class '%s' has no property '%s'", G_OBJECT_TYPE_NAME (object),        name);  }  return (prop);Error:  if (prop)    g_free (prop);  return (NULL);}/* * gst_control_point_free: * @prop: the object to free * * Private method which frees all data allocated by a #GstControlPoint * instance. */static voidgst_control_point_free (GstControlPoint * cp){  g_return_if_fail (cp);  g_value_unset (&cp->value);  g_free (cp);}/* * gst_controlled_property_free: * @prop: the object to free * * Private method which frees all data allocated by a #GstControlledProperty * instance. */static voidgst_controlled_property_free (GstControlledProperty * prop){  g_list_foreach (prop->values, (GFunc) gst_control_point_free, NULL);  g_list_free (prop->values);  g_value_unset (&prop->default_value);  g_value_unset (&prop->result_value);  g_value_unset (&prop->last_value.value);  if (G_IS_VALUE (&prop->live_value.value))    g_value_unset (&prop->live_value.value);  g_free (prop);}/* * gst_controller_find_controlled_property: * @self: the controller object to search for a property in * @name: the gobject property name to look for * * Searches the list of properties under control. *

⌨️ 快捷键说明

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