From: Steve Baker Date: Sun, 7 Oct 2001 09:49:41 +0000 (+0000) Subject: dparams lives here X-Git-Tag: BRANCH-EVENTS1-200110161-ROOT~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dbb97e0055903dbac541ba2f323da5bc5786113a;p=platform%2Fupstream%2Fgstreamer.git dparams lives here Original commit message from CVS: dparams lives here --- diff --git a/libs/control/Makefile.am b/libs/control/Makefile.am index 00086b4..bb72125 100644 --- a/libs/control/Makefile.am +++ b/libs/control/Makefile.am @@ -2,9 +2,20 @@ filterdir = $(libdir)/gst filter_LTLIBRARIES = libgstcontrol.la -libgstcontrol_la_SOURCES = gstdplinearinterp.c +libgstcontrol_la_SOURCES = \ + gstcontrol.c \ + gstdparammanager.c \ + gstdparam.c \ + gstdplinearinterp.c + libgstcontrolincludedir = $(includedir)/gst/libs/control -libgstcontrolinclude_HEADERS = gstcontrol.h gstdplinearinterp.h +libgstcontrolinclude_HEADERS = \ + gstcontrol.h \ + gstdparammanager.h \ + gstdparam.h \ + gstdplinearinterp.h + +libgstcontrol_la_LIBADD = -lm CFLAGS += -O2 $(FOMIT_FRAME_POINTER) -finline-functions -ffast-math diff --git a/libs/control/gstcontrol.c b/libs/control/gstcontrol.c new file mode 100644 index 0000000..9be5095 --- /dev/null +++ b/libs/control/gstcontrol.c @@ -0,0 +1,22 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstcontrol.c: GStreamer control utility library + * + * 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. + */ + +#include "gstcontrol.h" diff --git a/libs/control/gstcontrol.h b/libs/control/gstcontrol.h index b079e6d..764f37b 100644 --- a/libs/control/gstcontrol.h +++ b/libs/control/gstcontrol.h @@ -1,2 +1,41 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstcontrol.h: GStreamer control utility library + * + * 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. + */ + +#ifndef __GST_CONTROL_H__ +#define __GST_CONTROL_H__ -#include \ No newline at end of file +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#include + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_CONTROL_H__ */ diff --git a/libs/control/gstdparam.c b/libs/control/gstdparam.c new file mode 100644 index 0000000..665b66d --- /dev/null +++ b/libs/control/gstdparam.c @@ -0,0 +1,368 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparam.c: Dynamic Parameter functionality + * + * 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. + */ + +#include +#include +#include + +#include "gstdparam.h" +#include "gstdparammanager.h" + +static void gst_dparam_class_init (GstDParamClass *klass); +static void gst_dparam_init (GstDParam *dparam); + +static void gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp); +static GValue** gst_dparam_get_point_realtime (GstDParam *dparam, gint64 timestamp); + +GType +gst_dparam_get_type(void) { + static GType dparam_type = 0; + + if (!dparam_type) { + static const GTypeInfo dparam_info = { + sizeof(GstDParamClass), + NULL, + NULL, + (GClassInitFunc)gst_dparam_class_init, + NULL, + NULL, + sizeof(GstDParam), + 0, + (GInstanceInitFunc)gst_dparam_init, + }; + dparam_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParam", &dparam_info, 0); + } + return dparam_type; +} + +static void +gst_dparam_class_init (GstDParamClass *klass) +{ + GObjectClass *gobject_class; + GstDParamClass *dparam_class; + GstObjectClass *gstobject_class; + + gobject_class = (GObjectClass*)klass; + dparam_class = (GstDParamClass*)klass; + gstobject_class = (GstObjectClass*) klass; + + //gstobject_class->save_thyself = gst_dparam_save_thyself; + +} + +static void +gst_dparam_init (GstDParam *dparam) +{ + g_return_if_fail (dparam != NULL); + GST_DPARAM_VALUE(dparam) = NULL; + GST_DPARAM_TYPE(dparam) = 0; + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)=0LL; + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)=0LL; + GST_DPARAM_READY_FOR_UPDATE(dparam)=FALSE; + dparam->lock = g_mutex_new (); +} + +/** + * gst_dparam_new: + * @type: the type that this dparam will store + * + * Returns: a new instance of GstDParam + */ +GstDParam* +gst_dparam_new (GType type) +{ + GstDParam *dparam; + + dparam = g_object_new (gst_dparam_get_type (), NULL); + dparam->do_update_func = gst_dparam_do_update_realtime; + dparam->get_point_func = gst_dparam_get_point_realtime; + + dparam->point = gst_dparam_new_value_array(type, 0); + GST_DPARAM_TYPE(dparam) = type; + + return dparam; +} + +/** + * gst_dparam_attach + * @dparam: GstDParam instance + * @parent: the GstDParamManager that this dparam belongs to + * + */ +void +gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec) +{ + + g_return_if_fail (dparam != NULL); + g_return_if_fail (GST_IS_DPARAM (dparam)); + g_return_if_fail (GST_DPARAM_PARENT (dparam) == NULL); + g_return_if_fail (parent != NULL); + g_return_if_fail (G_IS_OBJECT (parent)); + g_return_if_fail (GST_IS_DPMAN (parent)); + g_return_if_fail ((gpointer)dparam != (gpointer)parent); + g_return_if_fail (value != NULL); + g_return_if_fail (spec != NULL); + g_return_if_fail (GST_DPARAM_TYPE(dparam) == G_VALUE_TYPE(value)); + + GST_DPARAM_NAME(dparam) = spec->dparam_name; + GST_DPARAM_VALUE(dparam) = value; + GST_DPARAM_SPEC(dparam) = spec; + gst_object_set_parent (GST_OBJECT (dparam), parent); +} + +/** + * gst_dparam_new_value_array + * @type: the type of the first GValue in the array + * @...: the type of other GValues in the array + * + * The list of types should be terminated with a 0. + * If the type of a value is not yet known then use G_TYPE_NONE . + * + * Returns: an newly created array of GValues + */ +GValue** +gst_dparam_new_value_array(GType type, ...) +{ + GValue **point; + GValue *value; + guint x; + guint values_length = 0; + va_list var_args; + GType each_type; + + va_start (var_args, type); + each_type = type; + while (each_type){ + values_length++; + each_type = va_arg (var_args, GType); + } + va_end (var_args); + + point = g_new0(GValue*,values_length + 1); + + va_start (var_args, type); + each_type = type; + for (x=0 ; x < values_length ; x++){ + value = g_new0(GValue,1); + if (each_type != G_TYPE_NONE){ + g_value_init(value, each_type); + } + point[x] = value; + each_type = va_arg (var_args, GType); + } + point[values_length] = NULL; + va_end (var_args); + + GST_DEBUG(GST_CAT_PARAMS, "array with %d values created\n", values_length); + + return point; +} + +void +gst_dparam_set_value_from_string(GValue *value, const gchar *value_str) +{ + + g_return_if_fail(value != NULL); + g_return_if_fail(value_str != NULL); + + GST_DEBUG(GST_CAT_PARAMS, "parsing '%s' to type %s\n", value_str, g_type_name(G_VALUE_TYPE(value))); + + switch (G_VALUE_TYPE(value)) { + case G_TYPE_STRING: + g_value_set_string(value, g_strdup(value_str)); + break; + case G_TYPE_ENUM: + case G_TYPE_INT: { + gint i; + sscanf (value_str, "%d", &i); + g_value_set_int(value, i); + break; + } + case G_TYPE_UINT: { + guint i; + sscanf (value_str, "%u", &i); + g_value_set_uint(value, i); + break; + } + case G_TYPE_LONG: { + glong i; + sscanf (value_str, "%ld", &i); + g_value_set_long(value, i); + break; + } + case G_TYPE_ULONG: { + gulong i; + sscanf (value_str, "%lu", &i); + g_value_set_ulong(value, i); + break; + } + case G_TYPE_BOOLEAN: { + gboolean i = FALSE; + if (!strncmp ("true", value_str, 4)) i = TRUE; + g_value_set_boolean(value, i); + break; + } + case G_TYPE_CHAR: { + gchar i; + sscanf (value_str, "%c", &i); + g_value_set_char(value, i); + break; + } + case G_TYPE_UCHAR: { + guchar i; + sscanf (value_str, "%c", &i); + g_value_set_uchar(value, i); + break; + } + case G_TYPE_FLOAT: { + gfloat i; + sscanf (value_str, "%f", &i); + g_value_set_float(value, i); + break; + } + case G_TYPE_DOUBLE: { + gfloat i; + sscanf (value_str, "%g", &i); + g_value_set_double(value, (gdouble)i); + break; + } + default: + break; + } +} + +static void +gst_dparam_do_update_realtime (GstDParam *dparam, gint64 timestamp) +{ + GST_DPARAM_LOCK(dparam); + GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE; + GST_DEBUG(GST_CAT_PARAMS, "updating value for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam); + g_value_copy(dparam->point[0], GST_DPARAM_VALUE(dparam)); + GST_DPARAM_UNLOCK(dparam); +} + +static GValue** +gst_dparam_get_point_realtime (GstDParam *dparam, gint64 timestamp) +{ + GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam); + return dparam->point; +} + +/********************** + * GstDParamSmooth + **********************/ + +static void gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp); +static GValue** gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp); + +/** + * gst_dparam_smooth_new: + * @type: the type that this dparam will store + * + * Returns: a new instance of GstDParamSmooth + */ +GstDParam* +gst_dparam_smooth_new (GType type) +{ + GstDParam *dparam; + + dparam = g_object_new (gst_dparam_get_type (), NULL); + + dparam->do_update_func = gst_dparam_do_update_smooth; + dparam->get_point_func = gst_dparam_get_point_smooth; + + dparam->point = gst_dparam_new_value_array(type, type, G_TYPE_FLOAT, 0); + GST_DPARAM_TYPE(dparam) = type; + + return dparam; +} + +static void +gst_dparam_do_update_smooth (GstDParam *dparam, gint64 timestamp) +{ + gint64 time_diff; + gfloat time_ratio; + + time_diff = MIN(GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam), + timestamp - GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam)); + + time_ratio = (gfloat)time_diff / g_value_get_float(dparam->point[2]); + + GST_DPARAM_LOCK(dparam); + + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam); + while(GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp){ + GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) += GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam); + } + GST_DEBUG(GST_CAT_PARAMS, "last:%lld current:%lld next:%lld\n", + GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam), timestamp, GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam)); + + + switch (G_VALUE_TYPE(GST_DPARAM_VALUE(dparam))){ + case G_TYPE_FLOAT: { + gfloat current, target, max_change, current_diff, final_val; + + target = g_value_get_float(dparam->point[0]); + current = g_value_get_float(GST_DPARAM_VALUE(dparam)); + max_change = time_ratio * g_value_get_float(dparam->point[1]); + + GST_DEBUG(GST_CAT_PARAMS, "target:%f current:%f max_change:%f \n", + target, current, max_change); + + if (dparam->spec->is_log){ + gfloat current_log; + current_log = log(current); + current_diff = ABS(current_log - log(target)); + if (current_diff > max_change) + final_val = (target < current) ? exp(current_log-max_change) : exp(current_log+max_change); + else + final_val = target; + } + else { + current_diff = ABS (current - target); + if (current_diff > max_change) + final_val = (target < current) ? current-max_change : current+max_change; + else + final_val = target; + } + + GST_DPARAM_READY_FOR_UPDATE(dparam) = (current_diff > max_change); + g_value_set_float(GST_DPARAM_VALUE(dparam), final_val); + + break; + } + default: + break; + } + + + //GST_DEBUG(GST_CAT_PARAMS, "smooth update for %s(%p): %f\n", + // GST_DPARAM_NAME (dparam),dparam, g_value_get_float(GST_DPARAM_VALUE(dparam))); + + GST_DPARAM_UNLOCK(dparam); +} + +static GValue** +gst_dparam_get_point_smooth (GstDParam *dparam, gint64 timestamp) +{ + GST_DEBUG(GST_CAT_PARAMS, "getting point for %s(%p)\n",GST_DPARAM_NAME (dparam),dparam); + return dparam->point; +} diff --git a/libs/control/gstdparam.h b/libs/control/gstdparam.h new file mode 100644 index 0000000..72d5fad --- /dev/null +++ b/libs/control/gstdparam.h @@ -0,0 +1,146 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparam.h: Dynamic Parameter functionality + * + * 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. + */ + +#ifndef __GST_DPARAM_H__ +#define __GST_DPARAM_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GST_TYPE_DPARAM (gst_dparam_get_type ()) +#define GST_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPARAM,GstDParam)) +#define GST_DPARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPARAM,GstDParam)) +#define GST_IS_DPARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPARAM)) +#define GST_IS_DPARAM_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPARAM)) + +#define GST_DPARAM_NAME(dparam) (GST_OBJECT_NAME(dparam)) +#define GST_DPARAM_PARENT(dparam) (GST_OBJECT_PARENT(dparam)) +#define GST_DPARAM_VALUE(dparam) ((dparam)->value) +#define GST_DPARAM_SPEC(dparam) ((dparam)->spec) +#define GST_DPARAM_TYPE(dparam) ((dparam)->type) + +#define GST_DPARAM_LOCK(dparam) (g_mutex_lock((dparam)->lock)) +#define GST_DPARAM_UNLOCK(dparam) (g_mutex_unlock((dparam)->lock)) + +#define GST_DPARAM_READY_FOR_UPDATE(dparam) ((dparam)->ready_for_update) +#define GST_DPARAM_DEFAULT_UPDATE_PERIOD(dparam) ((dparam)->default_update_period) +#define GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) ((dparam)->next_update_timestamp) +#define GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) ((dparam)->last_update_timestamp) + +#define GST_DPARAM_GET_POINT(dparam, timestamp) \ + ((dparam->get_point_func)(dparam, timestamp)) + +#define GST_DPARAM_FIND_POINT(dparam, timestamp, search_flag) \ + ((dparam->find_point_func)(dparam, data, search_flag)) + +#define GST_DPARAM_DO_UPDATE(dparam, timestamp) \ + ((dparam->do_update_func)(dparam, timestamp)) + +#define GST_DPARAM_INSERT_POINT(dparam, timestamp) \ + ((dparam->insert_point_func)(dparam, timestamp)) + +#define GST_DPARAM_REMOVE_POINT(dparam, data) \ + ((dparam->remove_point_func)(dparam, data)) + +typedef enum { + GST_DPARAM_CLOSEST, + GST_DPARAM_CLOSEST_AFTER, + GST_DPARAM_CLOSEST_BEFORE, + GST_DPARAM_EXACT, +} GstDParamSearchFlag; + +typedef enum { + GST_DPARAM_NOT_FOUND = 0, + GST_DPARAM_FOUND_EXACT, + GST_DPARAM_FOUND_CLOSEST, +} GstDParamSearchResult; + +typedef struct _GstDParam GstDParam; +typedef struct _GstDParamClass GstDParamClass; +typedef struct _GstDParamSpec GstDParamSpec; + +typedef GValue** (*GstDParamInsertPointFunction) (GstDParam *dparam, guint64 timestamp); +typedef void (*GstDParamRemovePointFunction) (GstDParam *dparam, GValue** point); +typedef GValue** (*GstDParamGetPointFunction) (GstDParam *dparam, gint64 timestamp); +typedef GstDParamSearchResult (*GstDParamFindPointFunction) (GstDParam *dparam, gint64 *timestamp, GstDParamSearchFlag search_flag); + +typedef void (*GstDParamDoUpdateFunction) (GstDParam *dparam, gint64 timestamp); + +struct _GstDParam { + GstObject object; + + GstDParamGetPointFunction get_point_func; + GstDParamFindPointFunction find_point_func; + + GstDParamDoUpdateFunction do_update_func; + + GstDParamInsertPointFunction insert_point_func; + GstDParamRemovePointFunction remove_point_func; + + GMutex *lock; + GValue *value; + GstDParamSpec *spec; + GValue **point; + GType type; + gint64 last_update_timestamp; + gint64 next_update_timestamp; + gint64 default_update_period; + gboolean ready_for_update; +}; + +struct _GstDParamClass { + GstObjectClass parent_class; + + /* signal callbacks */ +}; + +struct _GstDParamSpec { + gchar *dparam_name; + gchar *unit_name; + GValue *min_val; + GValue *max_val; + GValue *default_val; + gboolean is_log; + gboolean is_rate; +}; + +GType gst_dparam_get_type (void); +GstDParam* gst_dparam_new (GType type); +void gst_dparam_attach (GstDParam *dparam, GstObject *parent, GValue *value, GstDParamSpec *spec); +GValue** gst_dparam_new_value_array(GType type, ...); +void gst_dparam_set_value_from_string(GValue *value, const gchar *value_str); + +/********************** + * GstDParamSmooth + **********************/ + +GstDParam* gst_dparam_smooth_new (GType type); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_DPARAM_H__ */ diff --git a/libs/control/gstdparammanager.c b/libs/control/gstdparammanager.c new file mode 100644 index 0000000..efba373 --- /dev/null +++ b/libs/control/gstdparammanager.c @@ -0,0 +1,760 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparammanager.c: Dynamic Parameter group functionality + * + * 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. + */ + +#include "gstdparammanager.h" +#include +#include + +static GHashTable *_element_registry; + +static void gst_dpman_class_init (GstDParamManagerClass *klass); +static void gst_dpman_init (GstDParamManager *dpman); +static GstDParamWrapper* gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method); +static GstDParamWrapper* gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name); +static void gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman); +static void gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman); +static guint gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp); +static guint gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp); +static guint gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count); + +GType +gst_dpman_get_type (void) +{ + static GType dpman_type = 0; + + if (!dpman_type) { + static const GTypeInfo dpman_info = { + sizeof(GstDParamManagerClass), + NULL, + NULL, + (GClassInitFunc)gst_dpman_class_init, + NULL, + NULL, + sizeof(GstDParamManager), + 0, + (GInstanceInitFunc)gst_dpman_init, + }; + dpman_type = g_type_register_static(GST_TYPE_OBJECT, "GstDParamManager", &dpman_info, 0); + } + return dpman_type; +} + +static void +gst_dpman_class_init (GstDParamManagerClass *klass) +{ + GstObjectClass *gstobject_class; + GObjectClass *gobject_class; + + gstobject_class = (GstObjectClass*) klass; + gobject_class = (GObjectClass*) klass; + + klass->modes = g_hash_table_new(g_str_hash,g_str_equal); + _element_registry = g_hash_table_new(NULL,NULL); + + gst_dpman_register_mode (klass, "synchronous", + gst_dpman_preprocess_synchronous, gst_dpman_process_noop, NULL, NULL); + gst_dpman_register_mode (klass, "asynchronous", + gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL); + gst_dpman_register_mode (klass, "disabled", + gst_dpman_preprocess_noop, gst_dpman_process_noop, NULL, NULL); + +} + +static void +gst_dpman_init (GstDParamManager *dpman) +{ + GST_DPMAN_DPARAMS(dpman) = g_hash_table_new(g_str_hash,g_str_equal); + GST_DPMAN_DPARAMS_LIST(dpman) = NULL; + GST_DPMAN_NAME(dpman) = NULL; + GST_DPMAN_PARENT(dpman) = NULL; + GST_DPMAN_MODE_NAME(dpman) = NULL; + GST_DPMAN_MODE(dpman) = NULL; + GST_DPMAN_MODE_DATA(dpman) = NULL; + GST_DPMAN_RATE(dpman) = 0; +} + +/** + * gst_dpman_new: + * @name: name of the GstDParamManager instance + * @parent: element which created this instance + * + * Returns: a new instance of GstDParamManager + */ +GstDParamManager* +gst_dpman_new (gchar *name, GstElement *parent) +{ + GstDParamManager *dpman; + + g_return_val_if_fail (name != NULL, NULL); + + dpman = g_object_new (gst_dpman_get_type (), NULL); + gst_object_set_name (GST_OBJECT (dpman), name); + gst_dpman_set_parent(dpman, parent); + + gst_dpman_set_mode(dpman, "disabled"); + + return dpman; +} + +/** + * gst_dpman_add_required_dparam_callback: + * @dpman: GstDParamManager instance + * @dparam_name: a parameter name unique to this GstDParamManager + * @type: the GValue type that this parameter will store + * @update_func: callback to update the element with the new value + * @update_data: will be included in the call to update_func + * + * Returns: true if it was successfully added + */ +gboolean +gst_dpman_add_required_dparam_callback (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + GstDPMUpdateFunction update_func, + gpointer update_data) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (update_func != NULL, FALSE); + + dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_CALLBACK); + + g_return_val_if_fail (dpwrap != NULL, FALSE); + + GST_DEBUG(GST_CAT_PARAMS,"adding required callback dparam '%s' of type %s\n", dparam_name, g_type_name(type)); + + dpwrap->update_func = update_func; + dpwrap->update_data = update_data; + + return TRUE; +} + +/** + * gst_dpman_add_required_dparam_direct: + * @dpman: GstDParamManager instance + * @dparam_name: a parameter name unique to this GstDParamManager + * @type: the GValue type that this parameter will store + * @update_data: pointer to the member to be updated + * + * Returns: true if it was successfully added + */ +gboolean +gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + gpointer update_data) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (update_data != NULL, FALSE); + + dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_DIRECT); + + g_return_val_if_fail (dpwrap != NULL, FALSE); + + GST_DEBUG(GST_CAT_PARAMS,"adding required direct dparam '%s' of type %s\n", dparam_name, g_type_name(type)); + + dpwrap->update_data = update_data; + + return TRUE; +} + +/** + * gst_dpman_add_required_dparam_array: + * @dpman: GstDParamManager instance + * @dparam_name: a parameter name unique to this GstDParamManager + * @type: the GValue type that this parameter will store + * @update_data: pointer to where the array will be stored + * + * Returns: true if it was successfully added + */ +gboolean +gst_dpman_add_required_dparam_array (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + gpointer update_data) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (update_data != NULL, FALSE); + + dpwrap = gst_dpman_new_wrapper(dpman, dparam_name, type, GST_DPMAN_ARRAY); + + g_return_val_if_fail (dpwrap != NULL, FALSE); + + GST_DEBUG(GST_CAT_PARAMS,"adding required array dparam '%s' of type %s\n", dparam_name, g_type_name(type)); + + dpwrap->update_data = update_data; + + return TRUE; +} + +/** + * gst_dpman_remove_required_dparam: + * @dpman: GstDParamManager instance + * @dparam_name: the name of an existing parameter + * + */ +void +gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name) +{ + GstDParamWrapper* dpwrap; + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (dparam_name != NULL); + + dpwrap = gst_dpman_get_wrapper(dpman, dparam_name); + + g_return_if_fail(dpwrap != NULL); + g_return_if_fail(dpwrap->dparam == NULL); + + GST_DEBUG(GST_CAT_PARAMS, "removing required dparam: %s\n", dparam_name); + + g_hash_table_remove(GST_DPMAN_DPARAMS(dpman), dparam_name); + GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_remove(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap); + + g_free(dpwrap->value); + g_free(dpwrap); +} + +/** + * gst_dpman_attach_dparam: + * @dpman: GstDParamManager instance + * @dparam_name: a name previously added with gst_dpman_add_required_dparam + * @dparam: GstDParam instance to attach + * + * Returns: true if it was successfully attached + */ +gboolean +gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (dparam_name != NULL, FALSE); + g_return_val_if_fail (dparam != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPARAM (dparam), FALSE); + g_return_val_if_fail (dparam != NULL, FALSE); + + dpwrap = gst_dpman_get_wrapper(dpman, dparam_name); + + g_return_val_if_fail(dpwrap != NULL, FALSE); + g_return_val_if_fail(dpwrap->value != NULL, FALSE); + + dpwrap->dparam = dparam; + gst_dparam_attach(dparam, GST_OBJECT(dpman), dpwrap->value, dpwrap->spec); + + return TRUE; +} + +/** + * gst_dpman_dettach_dparam: + * @dpman: GstDParamManager instance + * @dparam_name: the name of a parameter with a previously attached GstDParam + * + */ +void +gst_dpman_dettach_dparam (GstDParamManager *dpman, gchar *dparam_name) +{ + GstDParamWrapper* dpwrap; + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (dparam_name != NULL); + + dpwrap = gst_dpman_get_wrapper(dpman, dparam_name); + + g_return_if_fail(dpwrap); + + GST_DPARAM_VALUE(dpwrap->dparam) = NULL; + GST_DPARAM_NAME(dpwrap->dparam) = NULL; + gst_object_unparent (GST_OBJECT(dpwrap->dparam)); + + dpwrap->dparam = NULL; + +} + +/** + * gst_dpman_get_dparam: + * @dpman: GstDParamManager instance + * @name: the name of an existing dparam instance + * + * Returns: the dparam with the given name - or NULL otherwise + */ +GstDParam * +gst_dpman_get_dparam (GstDParamManager *dpman, gchar *name) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + g_return_val_if_fail (name != NULL, NULL); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name); + g_return_val_if_fail (dpwrap != NULL, NULL); + + return dpwrap->dparam; +} + +/** + * gst_dpman_get_dparam_type: + * @dpman: GstDParamManager instance + * @name: the name of dparam + * + * Returns: the type that this dparam requires/uses + */ +GType +gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, 0); + g_return_val_if_fail (GST_IS_DPMAN (dpman), 0); + g_return_val_if_fail (name != NULL, 0); + + dpwrap = g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), name); + g_return_val_if_fail (dpwrap != NULL, 0); + + return G_VALUE_TYPE(dpwrap->value); +} + +GstDParamSpec** +gst_dpman_list_dparam_specs(GstDParamManager *dpman) +{ + GstDParamWrapper* dpwrap; + GSList *dpwraps; + GstDParamSpec** dparam_specs; + guint x = 0; + + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + + dpwraps = GST_DPMAN_DPARAMS_LIST(dpman); + + dparam_specs = g_new0(GstDParamSpec*, g_slist_length(dpwraps) + 1); + + while (dpwraps){ + dpwrap = (GstDParamWrapper*)dpwraps->data; + dparam_specs[x++] = dpwrap->spec; + dpwraps = g_slist_next(dpwraps); + } + return dparam_specs; +} + +GstDParamSpec* +gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + g_return_val_if_fail (dparam_name != NULL, NULL); + + dpwrap = gst_dpman_get_wrapper(dpman, dparam_name); + return dpwrap->spec; +} + +void +gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name) +{ + +} + +/** + * gst_dpman_register_mode + * @klass: GstDParamManagerClass class instance + * @modename: the unique name of the new mode + * @preprocessfunc: the function which will be called before each buffer is processed + * @processfunc: the function which may be called throughout the processing of a buffer + * @setupfunc: the function which initialises the mode when activated + * @teardownfunc: the function which frees any resources the mode uses + * + */ +void +gst_dpman_register_mode (GstDParamManagerClass *klass, + gchar *modename, + GstDPMModePreProcessFunction preprocessfunc, + GstDPMModeProcessFunction processfunc, + GstDPMModeSetupFunction setupfunc, + GstDPMModeTeardownFunction teardownfunc) +{ + GstDPMMode *mode; + + g_return_if_fail (klass != NULL); + g_return_if_fail (modename != NULL); + g_return_if_fail (GST_IS_DPMAN_CLASS (klass)); + + mode = g_new0(GstDPMMode,1); + + mode->preprocessfunc = preprocessfunc; + mode->processfunc = processfunc; + mode->setupfunc = setupfunc; + mode->teardownfunc = teardownfunc; + + g_hash_table_insert(klass->modes, modename, mode); + GST_DEBUG(GST_CAT_PARAMS, "mode '%s' registered\n", modename); +} + +/** + * gst_dpman_set_mode + * @dpman: GstDParamManager instance + * @modename: the name of the mode to use + * + * Returns: TRUE if the mode was set, FALSE otherwise + */ +gboolean +gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename) +{ + GstDPMMode *mode=NULL; + GstDParamManagerClass *oclass; + + g_return_val_if_fail (dpman != NULL, FALSE); + g_return_val_if_fail (GST_IS_DPMAN (dpman), FALSE); + g_return_val_if_fail (modename != NULL, FALSE); + + oclass = (GstDParamManagerClass*)(G_OBJECT_GET_CLASS(dpman)); + + mode = g_hash_table_lookup(oclass->modes, modename); + g_return_val_if_fail (mode != NULL, FALSE); + GST_DEBUG(GST_CAT_PARAMS, "setting mode to %s\n", modename); + if (GST_DPMAN_MODE(dpman) && GST_DPMAN_TEARDOWNFUNC(dpman)){ + GST_DPMAN_TEARDOWNFUNC(dpman)(dpman); + } + + GST_DPMAN_MODE(dpman) = mode; + + if (GST_DPMAN_SETUPFUNC(dpman)){ + GST_DPMAN_SETUPFUNC(dpman)(dpman); + } + + return TRUE; +} + +/** + * gst_dpman_set_parent + * @dpman: GstDParamManager instance + * @parent: the element that this GstDParamManager belongs to + * + */ +void +gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent) +{ + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (parent != NULL); + g_return_if_fail (GST_IS_ELEMENT (parent)); + + g_hash_table_insert(_element_registry, parent, dpman); + gst_object_set_parent (GST_OBJECT (dpman), GST_OBJECT(parent)); + g_signal_connect(G_OBJECT(parent), "state_change", + G_CALLBACK (gst_dpman_state_change), dpman); +} + +/** + * gst_dpman_get_manager + * @parent: the element that the desired GstDParamManager belongs to + * + * Returns: the GstDParamManager which belongs to this element or NULL + * if it doesn't exist + */ +GstDParamManager * +gst_dpman_get_manager (GstElement *parent) +{ + GstDParamManager *dpman; + g_return_val_if_fail (parent != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (parent), NULL); + + dpman = (GstDParamManager*)g_hash_table_lookup(_element_registry, parent); + g_return_val_if_fail (dpman != NULL, NULL); + return dpman; +} + +/** + * gst_dpman_set_rate_change_pad + * @dpman: GstDParamManager instance + * @pad: the pad which may have a "rate" caps property + * + */ +void +gst_dpman_set_rate_change_pad(GstDParamManager *dpman, GstPad *pad) +{ + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + + g_signal_connect(G_OBJECT(pad), "caps_changed", + G_CALLBACK (gst_dpman_caps_changed), dpman); +} + +static GstDParamWrapper* +gst_dpman_get_wrapper(GstDParamManager *dpman, gchar *dparam_name) +{ + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + g_return_val_if_fail (dparam_name != NULL, NULL); + + return g_hash_table_lookup(GST_DPMAN_DPARAMS(dpman), dparam_name); +} + +static GstDParamWrapper* +gst_dpman_new_wrapper(GstDParamManager *dpman, gchar *dparam_name, GType type, GstDPMUpdateMethod update_method) +{ + GstDParamWrapper* dpwrap; + + g_return_val_if_fail (dpman != NULL, NULL); + g_return_val_if_fail (GST_IS_DPMAN (dpman), NULL); + g_return_val_if_fail (dparam_name != NULL, NULL); + + g_return_val_if_fail(gst_dpman_get_wrapper(dpman, dparam_name) == NULL, NULL); + + dpwrap = g_new0(GstDParamWrapper,1); + dpwrap->update_method = update_method; + dpwrap->value = g_new0(GValue,1); + g_value_init(dpwrap->value, type); + + dpwrap->spec = g_new0(GstDParamSpec,1); + dpwrap->spec->dparam_name = dparam_name; + dpwrap->spec->min_val = g_new0(GValue,1); + dpwrap->spec->max_val = g_new0(GValue,1); + dpwrap->spec->default_val = g_new0(GValue,1); + g_value_init(dpwrap->spec->min_val, type); + g_value_init(dpwrap->spec->max_val, type); + g_value_init(dpwrap->spec->default_val, type); + + g_hash_table_insert(GST_DPMAN_DPARAMS(dpman), dparam_name, dpwrap); + GST_DPMAN_DPARAMS_LIST(dpman) = g_slist_append(GST_DPMAN_DPARAMS_LIST(dpman), dpwrap); + + return dpwrap; +} + + +static void +gst_dpman_state_change (GstElement *element, gint state, GstDParamManager *dpman) +{ + GSList *dwraps; + GstDParam *dparam; + GstDParamWrapper *dpwrap; + + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + + if (state == GST_STATE_PLAYING){ + GST_DEBUG(GST_CAT_PARAMS, "initialising params\n"); + + // force all params to be updated + dwraps = GST_DPMAN_DPARAMS_LIST(dpman); + while (dwraps){ + dpwrap = (GstDParamWrapper*)dwraps->data; + dparam = dpwrap->dparam; + + if (dparam){ + GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE; + if (dparam->spec){ + g_value_copy(dparam->spec->default_val, GST_DPARAM_VALUE(dparam)); + } + } + dwraps = g_slist_next(dwraps); + } + } +} + +static void +gst_dpman_caps_changed (GstPad *pad, GstCaps *caps, GstDParamManager *dpman) +{ + g_return_if_fail (caps != NULL); + g_return_if_fail (dpman != NULL); + g_return_if_fail (GST_IS_DPMAN (dpman)); + + GST_DPMAN_RATE(dpman) = gst_caps_get_int (caps, "rate"); + + GST_DEBUG(GST_CAT_PARAMS, "got caps change %d\n", GST_DPMAN_RATE(dpman)); +} + +static guint +gst_dpman_preprocess_synchronous(GstDParamManager *dpman, guint frames, gint64 timestamp) +{ + GSList *dwraps; + GstDParam *dparam; + GstDParamWrapper *dpwrap; + guint x; + + g_return_val_if_fail (dpman != NULL, frames); + g_return_val_if_fail (GST_IS_DPMAN (dpman), frames); + + // now check whether any passive dparams are ready for an update + dwraps = GST_DPMAN_DPARAMS_LIST(dpman); + while (dwraps){ + dpwrap = (GstDParamWrapper*)dwraps->data; + dparam = dpwrap->dparam; + + if (dparam && (GST_DPARAM_READY_FOR_UPDATE(dparam) && + (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) <= timestamp))){ + + // this will make dpwrap->value contain the latest value. + // now we just need to get it to the element + GST_DPARAM_DO_UPDATE(dparam, timestamp); + + switch (dpwrap->update_method) { + + // direct method - set the value directly in the struct of the element + case GST_DPMAN_DIRECT: + GST_DEBUG(GST_CAT_PARAMS, "doing direct update\n"); + switch (G_VALUE_TYPE(dpwrap->value)){ + case G_TYPE_CHAR: + *(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value); + break; + case G_TYPE_UCHAR: + *(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value); + break; + case G_TYPE_BOOLEAN: + *(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value); + break; + case G_TYPE_INT: + *(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value); + break; + case G_TYPE_UINT: + *(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value); + break; + case G_TYPE_LONG: + *(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value); + break; + case G_TYPE_ULONG: + *(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value); + break; + case G_TYPE_FLOAT: + *(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value); + break; + case G_TYPE_DOUBLE: + *(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value); + break; + case G_TYPE_POINTER: + *(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value); + break; + default: + break; + } + break; + + // callback method - call the element's callback so it can do what it likes + case GST_DPMAN_CALLBACK: + GST_DEBUG(GST_CAT_PARAMS, "doing callback update\n"); + GST_DPMAN_DO_UPDATE(dpwrap); + break; + + // array method - generate an array of the right size + // with each value being the same (in synchronous update mode) + case GST_DPMAN_ARRAY: + GST_DEBUG(GST_CAT_PARAMS, "doing array update\n"); + switch (G_VALUE_TYPE(dpwrap->value)){ + case G_TYPE_CHAR: + (gchar*)dpwrap->update_data = g_new(gchar, frames); + *(gchar*)dpwrap->update_data = g_value_get_char(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gchar*)dpwrap->update_data)[x] = *(gchar*)dpwrap->update_data; + break; + case G_TYPE_UCHAR: + (guchar*)dpwrap->update_data = g_new(guchar, frames); + *(guchar*)dpwrap->update_data = g_value_get_uchar(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((guchar*)dpwrap->update_data)[x] = *(guchar*)dpwrap->update_data; + break; + case G_TYPE_BOOLEAN: + (gboolean*)dpwrap->update_data = g_new(gboolean, frames); + *(gboolean*)dpwrap->update_data = g_value_get_boolean(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gboolean*)dpwrap->update_data)[x] = *(gboolean*)dpwrap->update_data; + break; + case G_TYPE_INT: + (gint*)dpwrap->update_data = g_new(gint, frames); + *(gint*)dpwrap->update_data = g_value_get_int(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gint*)dpwrap->update_data)[x] = *(gint*)dpwrap->update_data; + break; + case G_TYPE_UINT: + (guint*)dpwrap->update_data = g_new(guint, frames); + *(guint*)dpwrap->update_data = g_value_get_uint(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((guint*)dpwrap->update_data)[x] = *(guint*)dpwrap->update_data; + break; + case G_TYPE_LONG: + (glong*)dpwrap->update_data = g_new(glong, frames); + *(glong*)dpwrap->update_data = g_value_get_long(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((glong*)dpwrap->update_data)[x] = *(glong*)dpwrap->update_data; + break; + case G_TYPE_ULONG: + (gulong*)dpwrap->update_data = g_new(gulong, frames); + *(gulong*)dpwrap->update_data = g_value_get_ulong(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gulong*)dpwrap->update_data)[x] = *(gulong*)dpwrap->update_data; + break; + case G_TYPE_FLOAT: + (gfloat*)dpwrap->update_data = g_new(gfloat, frames); + *(gfloat*)dpwrap->update_data = g_value_get_float(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gfloat*)dpwrap->update_data)[x] = *(gfloat*)dpwrap->update_data; + break; + case G_TYPE_DOUBLE: + (gdouble*)dpwrap->update_data = g_new(gdouble, frames); + *(gdouble*)dpwrap->update_data = g_value_get_double(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gdouble*)dpwrap->update_data)[x] = *(gdouble*)dpwrap->update_data; + break; + case G_TYPE_POINTER: + (gpointer*)dpwrap->update_data = g_new(gpointer, frames); + *(gpointer*)dpwrap->update_data = g_value_get_pointer(dpwrap->value); + for (x = 1 ; x < frames ; x++) + ((gpointer*)dpwrap->update_data)[x] = *(gpointer*)dpwrap->update_data; + break; + default: + break; + } + break; + default: + break; + } + } + dwraps = g_slist_next(dwraps); + } + return frames; +} + +static guint +gst_dpman_preprocess_noop(GstDParamManager *dpman, guint frames, gint64 timestamp) +{ + return frames; +} + +static guint +gst_dpman_process_noop(GstDParamManager *dpman, guint frame_count) +{ + return 0; +} + diff --git a/libs/control/gstdparammanager.h b/libs/control/gstdparammanager.h new file mode 100644 index 0000000..e8799e6 --- /dev/null +++ b/libs/control/gstdparammanager.h @@ -0,0 +1,163 @@ +/* GStreamer + * Copyright (C) 2001 Steve Baker + * + * gstdparammanager.h: Dynamic Parameter group functionality + * + * 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. + */ + +#ifndef __GST_DPMAN_H__ +#define __GST_DPMAN_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GST_TYPE_DPMAN (gst_dpman_get_type ()) +#define GST_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DPMAN,GstDParamManager)) +#define GST_DPMAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DPMAN,GstDParamManager)) +#define GST_IS_DPMAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DPMAN)) +#define GST_IS_DPMAN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DPMAN)) + +#define GST_DPMAN_NAME(dpman) (GST_OBJECT_NAME(dpman)) +#define GST_DPMAN_PARENT(dpman) (GST_OBJECT_PARENT(dpman)) +#define GST_DPMAN_DPARAMS(dpman) ((dpman)->dparams) +#define GST_DPMAN_DPARAMS_LIST(dpman) ((dpman)->dparams_list) + +#define GST_DPMAN_MODE_NAME(dpman) ((dpman)->mode_name) +#define GST_DPMAN_MODE(dpman) ((dpman)->mode) +#define GST_DPMAN_MODE_DATA(dpman) ((dpman)->mode_data) +#define GST_DPMAN_RATE(dpman) ((dpman)->rate) + +typedef enum { + GST_DPMAN_CALLBACK, + GST_DPMAN_DIRECT, + GST_DPMAN_ARRAY, +} GstDPMUpdateMethod; + +typedef struct _GstDParamManager GstDParamManager; +typedef struct _GstDParamManagerClass GstDParamManagerClass; +typedef struct _GstDPMMode GstDPMMode; +typedef struct _GstDParamWrapper GstDParamWrapper; + +typedef guint (*GstDPMModePreProcessFunction) (GstDParamManager *dpman, guint frames, gint64 timestamp); +typedef guint (*GstDPMModeProcessFunction) (GstDParamManager *dpman, guint frame_count); +typedef void (*GstDPMModeSetupFunction) (GstDParamManager *dpman); +typedef void (*GstDPMModeTeardownFunction) (GstDParamManager *dpman); + +typedef void (*GstDPMUpdateFunction) (GValue *value, gpointer data); + +struct _GstDParamManager { + GstObject object; + + GHashTable *dparams; + GSList *dparams_list; + + gchar *mode_name; + GstDPMMode* mode; + gpointer mode_data; + + gint64 timestamp; + guint rate; +}; + +struct _GstDParamManagerClass { + GstObjectClass parent_class; + + GHashTable *modes; + /* signal callbacks */ +}; + +struct _GstDPMMode { + GstDPMModePreProcessFunction preprocessfunc; + GstDPMModeProcessFunction processfunc; + GstDPMModeSetupFunction setupfunc; + GstDPMModeTeardownFunction teardownfunc; +}; + +struct _GstDParamWrapper { + GstDParamSpec* spec; + GValue *value; + GstDParam *dparam; + GstDPMUpdateMethod update_method; + gpointer update_data; + GstDPMUpdateFunction update_func; +}; + +#define GST_DPMAN_PREPROCESSFUNC(dpman) (((dpman)->mode)->preprocessfunc) +#define GST_DPMAN_PROCESSFUNC(dpman) (((dpman)->mode)->processfunc) +#define GST_DPMAN_SETUPFUNC(dpman) (((dpman)->mode)->setupfunc) +#define GST_DPMAN_TEARDOWNFUNC(dpman) (((dpman)->mode)->teardownfunc) + +#define GST_DPMAN_PREPROCESS(dpman, buffer_size, timestamp) \ + (GST_DPMAN_PREPROCESSFUNC(dpman)(dpman, buffer_size, timestamp)) + +#define GST_DPMAN_PROCESS(dpman, frame_count) \ + (GST_DPMAN_PROCESSFUNC(dpman)(dpman, frame_count)) + +#define GST_DPMAN_PROCESS_COUNTDOWN(dpman, frame_countdown, frame_count) \ + (frame_countdown-- || \ + (frame_countdown = GST_DPMAN_PROCESS(dpman, frame_count))) + +#define GST_DPMAN_DO_UPDATE(dpwrap) ((dpwrap->update_func)(dpwrap->value, dpwrap->update_data)) + +GType gst_dpman_get_type (void); +GstDParamManager* gst_dpman_new (gchar *name, GstElement *parent); +void gst_dpman_set_parent (GstDParamManager *dpman, GstElement *parent); +GstDParamManager* gst_dpman_get_manager (GstElement *parent); + +gboolean gst_dpman_add_required_dparam_callback (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + GstDPMUpdateFunction update_func, + gpointer update_data); +gboolean gst_dpman_add_required_dparam_direct (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + gpointer update_data); +gboolean gst_dpman_add_required_dparam_array (GstDParamManager *dpman, + gchar *dparam_name, + GType type, + gpointer update_data); +void gst_dpman_remove_required_dparam (GstDParamManager *dpman, gchar *dparam_name); +gboolean gst_dpman_attach_dparam (GstDParamManager *dpman, gchar *dparam_name, GstDParam *dparam); +void gst_dpman_dettach_dparam (GstDParamManager *dpman, gchar *dparam_name); +GstDParam* gst_dpman_get_dparam(GstDParamManager *dpman, gchar *name); +GType gst_dpman_get_dparam_type (GstDParamManager *dpman, gchar *name); + +GstDParamSpec** gst_dpman_list_dparam_specs(GstDParamManager *dpman); +GstDParamSpec* gst_dpman_get_dparam_spec (GstDParamManager *dpman, gchar *dparam_name); +void gst_dpman_dparam_spec_has_changed (GstDParamManager *dpman, gchar *dparam_name); + +void gst_dpman_set_rate_change_pad(GstDParamManager *dpman, GstPad *pad); + +gboolean gst_dpman_set_mode(GstDParamManager *dpman, gchar *modename); +void gst_dpman_register_mode (GstDParamManagerClass *klass, + gchar *modename, + GstDPMModePreProcessFunction preprocessfunc, + GstDPMModeProcessFunction processfunc, + GstDPMModeSetupFunction setupfunc, + GstDPMModeTeardownFunction teardownfunc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_DPMAN_H__ */ diff --git a/libs/control/gstdplinearinterp.c b/libs/control/gstdplinearinterp.c index cae255b..2444165 100644 --- a/libs/control/gstdplinearinterp.c +++ b/libs/control/gstdplinearinterp.c @@ -21,7 +21,6 @@ #include "gstdplinearinterp.h" - static void gst_dp_linint_class_init (GstDParamClass *klass); static void gst_dp_linint_base_class_init (GstDParamClass *klass); static void gst_dp_linint_init (GstDParam *dp_linint); diff --git a/libs/control/gstdplinearinterp.h b/libs/control/gstdplinearinterp.h index 73f43f9..fa1a7dc 100644 --- a/libs/control/gstdplinearinterp.h +++ b/libs/control/gstdplinearinterp.h @@ -24,7 +24,7 @@ #define __GST_DP_LININT_H__ #include -#include +#include "gstdparam.h" #ifdef __cplusplus extern "C" {