2 * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
4 * gstdparam_smooth.c: Realtime smoothed dynamic parameter
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 #include <gst/gstinfo.h>
26 #include "dparam_smooth.h"
27 #include "dparammanager.h"
29 static void gst_dpsmooth_class_init (GstDParamSmoothClass *klass);
30 static void gst_dpsmooth_init (GstDParamSmooth *dparam);
31 static void gst_dpsmooth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
32 static void gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
33 static void gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info);
34 static void gst_dpsmooth_value_changed_float (GstDParam *dparam);
40 ARG_SLOPE_DELTA_FLOAT,
42 ARG_SLOPE_DELTA_INT64,
46 gst_dpsmooth_get_type(void) {
47 static GType dpsmooth_type = 0;
50 static const GTypeInfo dpsmooth_info = {
51 sizeof(GstDParamSmoothClass),
54 (GClassInitFunc)gst_dpsmooth_class_init,
57 sizeof(GstDParamSmooth),
59 (GInstanceInitFunc)gst_dpsmooth_init,
61 dpsmooth_type = g_type_register_static(GST_TYPE_DPARAM, "GstDParamSmooth", &dpsmooth_info, 0);
67 gst_dpsmooth_class_init (GstDParamSmoothClass *klass)
69 GObjectClass *gobject_class;
70 GstDParamSmoothClass *dpsmooth_class;
71 GstObjectClass *gstobject_class;
73 gobject_class = (GObjectClass*)klass;
74 dpsmooth_class = (GstDParamSmoothClass*)klass;
75 gstobject_class = (GstObjectClass*) klass;
77 gobject_class->get_property = gst_dpsmooth_get_property;
78 gobject_class->set_property = gst_dpsmooth_set_property;
80 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_UPDATE_PERIOD,
81 g_param_spec_int64("update_period",
82 "Update Period (nanoseconds)",
83 "Number of nanoseconds between updates",
84 0LL, G_MAXINT64, 2000000LL, G_PARAM_READWRITE));
86 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SLOPE_TIME,
87 g_param_spec_int64("slope_time",
88 "Slope Time (nanoseconds)",
89 "The time period to define slope_delta by",
90 0LL, G_MAXINT64, 10000000LL, G_PARAM_READWRITE));
92 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SLOPE_DELTA_FLOAT,
93 g_param_spec_float("slope_delta_float",
95 "The amount a float value can change for a given slope_time",
96 0.0F, G_MAXFLOAT, 0.2F, G_PARAM_READWRITE));
98 /*gstobject_class->save_thyself = gst_dparam_save_thyself; */
103 gst_dpsmooth_init (GstDParamSmooth *dpsmooth)
105 g_return_if_fail (dpsmooth != NULL);
110 * @type: the type that this dparam will store
112 * Returns: a new instance of GstDParam
115 gst_dpsmooth_new (GType type)
118 GstDParamSmooth *dpsmooth;
120 dpsmooth =g_object_new (gst_dpsmooth_get_type (), NULL);
121 dparam = GST_DPARAM(dpsmooth);
123 GST_DPARAM_TYPE(dparam) = type;
127 dparam->do_update_func = gst_dpsmooth_do_update_float;
128 g_signal_connect (G_OBJECT (dpsmooth), "value_changed", G_CALLBACK (gst_dpsmooth_value_changed_float), NULL);
132 /* we don't support this type here */
133 dparam->do_update_func = gst_dparam_do_update_default;
140 gst_dpsmooth_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
143 GstDParamSmooth *dpsmooth;
145 g_return_if_fail(GST_IS_DPSMOOTH(object));
147 dpsmooth = GST_DPSMOOTH(object);
148 dparam = GST_DPARAM(object);
150 GST_DPARAM_LOCK(dparam);
153 case ARG_UPDATE_PERIOD:
154 dpsmooth->update_period = g_value_get_int64 (value);
155 GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
159 dpsmooth->slope_time = g_value_get_int64 (value);
160 GST_DEBUG(GST_CAT_PARAMS, "dpsmooth->slope_time:%"
162 dpsmooth->slope_time);
163 GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
166 case ARG_SLOPE_DELTA_FLOAT:
167 dpsmooth->slope_delta_float = g_value_get_float (value);
168 GST_DPARAM_READY_FOR_UPDATE(dparam) = TRUE;
174 GST_DPARAM_UNLOCK(dparam);
178 gst_dpsmooth_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
181 GstDParamSmooth *dpsmooth;
183 g_return_if_fail(GST_IS_DPSMOOTH(object));
185 dpsmooth = GST_DPSMOOTH(object);
186 dparam = GST_DPARAM(object);
189 case ARG_UPDATE_PERIOD:
190 g_value_set_int64(value, dpsmooth->update_period);
193 g_value_set_int64(value, dpsmooth->slope_time);
195 case ARG_SLOPE_DELTA_FLOAT:
196 g_value_set_float (value, dpsmooth->slope_delta_float);
199 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
205 gst_dpsmooth_value_changed_float (GstDParam *dparam)
207 GstDParamSmooth *dpsmooth;
210 g_return_if_fail(GST_IS_DPSMOOTH(dparam));
211 dpsmooth = GST_DPSMOOTH(dparam);
213 if (GST_DPARAM_IS_LOG(dparam)){
214 dparam->value_float = log(dparam->value_float);
216 dpsmooth->start_float = dpsmooth->current_float;
217 dpsmooth->diff_float = dparam->value_float - dpsmooth->start_float;
219 time_ratio = ABS(dpsmooth->diff_float) / dpsmooth->slope_delta_float;
220 dpsmooth->duration_interp = (gint64)(time_ratio * (gfloat)dpsmooth->slope_time);
222 dpsmooth->need_interp_times = TRUE;
224 GST_DEBUG(GST_CAT_PARAMS, "%f to %f ratio:%f duration:%"
225 G_GINT64_FORMAT "\n",
226 dpsmooth->start_float, dparam->value_float, time_ratio, dpsmooth->duration_interp);
230 gst_dpsmooth_do_update_float (GstDParam *dparam, gint64 timestamp, GValue *value, GstDParamUpdateInfo update_info)
233 GstDParamSmooth *dpsmooth = GST_DPSMOOTH(dparam);
235 GST_DPARAM_LOCK(dparam);
237 if (dpsmooth->need_interp_times){
238 dpsmooth->start_interp = timestamp;
239 dpsmooth->end_interp = timestamp + dpsmooth->duration_interp;
240 dpsmooth->need_interp_times = FALSE;
243 if ((update_info == GST_DPARAM_UPDATE_FIRST) || (timestamp >= dpsmooth->end_interp)){
244 if (GST_DPARAM_IS_LOG(dparam)){
245 g_value_set_float(value, exp(dparam->value_float));
248 g_value_set_float(value, dparam->value_float);
250 dpsmooth->current_float = dparam->value_float;
252 GST_DEBUG(GST_CAT_PARAMS, "interp finished at %"
253 G_GINT64_FORMAT, timestamp);
255 GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
256 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp;
258 GST_DPARAM_READY_FOR_UPDATE(dparam) = FALSE;
259 GST_DPARAM_UNLOCK(dparam);
263 if (timestamp <= dpsmooth->start_interp){
264 if (GST_DPARAM_IS_LOG(dparam)){
265 g_value_set_float(value, exp(dpsmooth->start_float));
268 g_value_set_float(value, dpsmooth->start_float);
270 GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
271 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = dpsmooth->start_interp + dpsmooth->update_period;
273 GST_DEBUG(GST_CAT_PARAMS, "interp started at %" G_GINT64_FORMAT, timestamp);
275 GST_DPARAM_UNLOCK(dparam);
280 time_ratio = (gfloat)(timestamp - dpsmooth->start_interp) / (gfloat)dpsmooth->duration_interp;
282 GST_DEBUG(GST_CAT_PARAMS, "start:%" G_GINT64_FORMAT " current:%" G_GINT64_FORMAT " end:%" G_GINT64_FORMAT " ratio%f", dpsmooth->start_interp, timestamp, dpsmooth->end_interp, time_ratio);
283 GST_DEBUG(GST_CAT_PARAMS, "pre start:%f current:%f target:%f", dpsmooth->start_float, dpsmooth->current_float, dparam->value_float);
285 dpsmooth->current_float = dpsmooth->start_float + (dpsmooth->diff_float * time_ratio);
287 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = timestamp + dpsmooth->update_period;
288 if (GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) > dpsmooth->end_interp){
289 GST_DPARAM_NEXT_UPDATE_TIMESTAMP(dparam) = dpsmooth->end_interp;
292 GST_DPARAM_LAST_UPDATE_TIMESTAMP(dparam) = timestamp;
294 if (GST_DPARAM_IS_LOG(dparam)){
295 g_value_set_float(value, exp(dpsmooth->current_float));
298 g_value_set_float(value, dpsmooth->current_float);
301 GST_DEBUG(GST_CAT_PARAMS, "post start:%f current:%f target:%f", dpsmooth->start_float, dpsmooth->current_float, dparam->value_float);
303 GST_DPARAM_UNLOCK(dparam);