]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blob - libs/gst/control/dparam_smooth.c
don't mix tabs and spaces
[glsdk/gstreamer0-10.git] / libs / gst / control / dparam_smooth.c
1 /* GStreamer
2  * Copyright (C) 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
3  *
4  * gstdparam_smooth.c: Realtime smoothed dynamic parameter
5  *
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.
10  *
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.
15  *
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.
20  */
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
26 #include <math.h>
27 #include <string.h>
28 #include <gst/gstinfo.h>
30 #include "dparam_smooth.h"
31 #include "dparammanager.h"
33 GST_DEBUG_CATEGORY_EXTERN (_gst_control_debug);
35 static void gst_dpsmooth_class_init (GstDParamSmoothClass * klass);
36 static void gst_dpsmooth_init (GstDParamSmooth * dparam);
37 static void gst_dpsmooth_set_property (GObject * object, guint prop_id,
38     const GValue * value, GParamSpec * pspec);
39 static void gst_dpsmooth_get_property (GObject * object, guint prop_id,
40     GValue * value, GParamSpec * pspec);
41 static void gst_dpsmooth_do_update_float (GstDParam * dparam, gint64 timestamp,
42     GValue * value, GstDParamUpdateInfo update_info);
43 static void gst_dpsmooth_value_changed_float (GstDParam * dparam);
44 static void gst_dpsmooth_do_update_double (GstDParam * dparam, gint64 timestamp,
45     GValue * value, GstDParamUpdateInfo update_info);
46 static void gst_dpsmooth_value_changed_double (GstDParam * dparam);
48 enum
49 {
50   ARG_0,
51   ARG_UPDATE_PERIOD,
52   ARG_SLOPE_TIME,
53   ARG_SLOPE_DELTA_FLOAT,
54   ARG_SLOPE_DELTA_DOUBLE,
55   ARG_SLOPE_DELTA_INT,
56   ARG_SLOPE_DELTA_INT64,
57 };
59 GType
60 gst_dpsmooth_get_type (void)
61 {
62   static GType dpsmooth_type = 0;
64   if (!dpsmooth_type) {
65     static const GTypeInfo dpsmooth_info = {
66       sizeof (GstDParamSmoothClass),
67       NULL,
68       NULL,
69       (GClassInitFunc) gst_dpsmooth_class_init,
70       NULL,
71       NULL,
72       sizeof (GstDParamSmooth),
73       0,
74       (GInstanceInitFunc) gst_dpsmooth_init,
75     };
77     dpsmooth_type =
78         g_type_register_static (GST_TYPE_DPARAM, "GstDParamSmooth",
79         &dpsmooth_info, 0);
80   }
81   return dpsmooth_type;
82 }
84 static void
85 gst_dpsmooth_class_init (GstDParamSmoothClass * klass)
86 {
87   GObjectClass *gobject_class;
88   GstDParamSmoothClass *dpsmooth_class;
89   GstObjectClass *gstobject_class;
91   gobject_class = (GObjectClass *) klass;
92   dpsmooth_class = (GstDParamSmoothClass *) klass;
93   gstobject_class = (GstObjectClass *) klass;
95   gobject_class->get_property = gst_dpsmooth_get_property;
96   gobject_class->set_property = gst_dpsmooth_set_property;
98   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_UPDATE_PERIOD,
99       g_param_spec_int64 ("update_period",
100           "Update Period (nanoseconds)",
101           "Number of nanoseconds between updates",
102           0LL, G_MAXINT64, 2000000LL, G_PARAM_READWRITE));
104   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SLOPE_TIME,
105       g_param_spec_int64 ("slope_time",
106           "Slope Time (nanoseconds)",
107           "The time period to define slope_delta by",
108           0LL, G_MAXINT64, 10000000LL, G_PARAM_READWRITE));
110   g_object_class_install_property (G_OBJECT_CLASS (klass),
111       ARG_SLOPE_DELTA_FLOAT,
112       g_param_spec_float ("slope_delta_float", "Slope Delta float",
113           "The amount a float value can change for a given slope_time",
114           0.0F, G_MAXFLOAT, 0.2F, G_PARAM_READWRITE));
116   g_object_class_install_property (G_OBJECT_CLASS (klass),
117       ARG_SLOPE_DELTA_DOUBLE,
118       g_param_spec_double ("slope_delta_double", "Slope Delta double",
119           "The amount a double value can change for a given slope_time",
120           0.0, G_MAXDOUBLE, 0.2, G_PARAM_READWRITE));
122   /*gstobject_class->save_thyself = gst_dparam_save_thyself; */
126 static void
127 gst_dpsmooth_init (GstDParamSmooth * dpsmooth)
129   g_return_if_fail (dpsmooth != NULL);
132 /**
133  * gst_dpsmooth_new:
134  * @type: the type that this dparam will store
135  *
136  * Returns: a new instance of GstDParam
137  */
138 GstDParam *
139 gst_dpsmooth_new (GType type)
141   GstDParam *dparam;
142   GstDParamSmooth *dpsmooth;
144   dpsmooth = g_object_new (gst_dpsmooth_get_type (), NULL);
145   dparam = GST_DPARAM (dpsmooth);
147   GST_DPARAM_TYPE (dparam) = type;
149   switch (type) {
150     case G_TYPE_FLOAT:{
151       dparam->do_update_func = gst_dpsmooth_do_update_float;
152       g_signal_connect (G_OBJECT (dpsmooth), "value_changed",
153           G_CALLBACK (gst_dpsmooth_value_changed_float), NULL);
154       break;
155     }
156     case G_TYPE_DOUBLE:{
157       dparam->do_update_func = gst_dpsmooth_do_update_double;
158       g_signal_connect (G_OBJECT (dpsmooth), "value_changed",
159           G_CALLBACK (gst_dpsmooth_value_changed_double), NULL);
160       break;
161     }
162     default:
163       /* we don't support this type here */
164       dparam->do_update_func = gst_dparam_do_update_default;
165       break;
166   }
167   return dparam;
170 static void
171 gst_dpsmooth_set_property (GObject * object, guint prop_id,
172     const GValue * value, GParamSpec * pspec)
174   GstDParam *dparam;
175   GstDParamSmooth *dpsmooth;
177   g_return_if_fail (GST_IS_DPSMOOTH (object));
179   dpsmooth = GST_DPSMOOTH (object);
180   dparam = GST_DPARAM (object);
182   GST_DPARAM_LOCK (dparam);
184   switch (prop_id) {
185     case ARG_UPDATE_PERIOD:
186       dpsmooth->update_period = g_value_get_int64 (value);
187       GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
188       break;
190     case ARG_SLOPE_TIME:
191       dpsmooth->slope_time = g_value_get_int64 (value);
192       GST_DEBUG ("dpsmooth->slope_time:%"
193           G_GINT64_FORMAT, dpsmooth->slope_time);
194       GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
195       break;
197     case ARG_SLOPE_DELTA_FLOAT:
198       dpsmooth->slope_delta_float = g_value_get_float (value);
199       GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
200       break;
202     case ARG_SLOPE_DELTA_DOUBLE:
203       dpsmooth->slope_delta_double = g_value_get_double (value);
204       GST_DPARAM_READY_FOR_UPDATE (dparam) = TRUE;
205       break;
207     default:
208       break;
209   }
210   GST_DPARAM_UNLOCK (dparam);
213 static void
214 gst_dpsmooth_get_property (GObject * object, guint prop_id, GValue * value,
215     GParamSpec * pspec)
217   GstDParam *dparam;
218   GstDParamSmooth *dpsmooth;
220   g_return_if_fail (GST_IS_DPSMOOTH (object));
222   dpsmooth = GST_DPSMOOTH (object);
223   dparam = GST_DPARAM (object);
225   switch (prop_id) {
226     case ARG_UPDATE_PERIOD:
227       g_value_set_int64 (value, dpsmooth->update_period);
228       break;
229     case ARG_SLOPE_TIME:
230       g_value_set_int64 (value, dpsmooth->slope_time);
231       break;
232     case ARG_SLOPE_DELTA_FLOAT:
233       g_value_set_float (value, dpsmooth->slope_delta_float);
234       break;
235     case ARG_SLOPE_DELTA_DOUBLE:
236       g_value_set_double (value, dpsmooth->slope_delta_double);
237       break;
238     default:
239       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
240       break;
241   }
244 static void
245 gst_dpsmooth_value_changed_float (GstDParam * dparam)
247   GstDParamSmooth *dpsmooth;
248   gfloat time_ratio;
250   g_return_if_fail (GST_IS_DPSMOOTH (dparam));
251   dpsmooth = GST_DPSMOOTH (dparam);
253   if (GST_DPARAM_IS_LOG (dparam)) {
254     dparam->value_float = log (dparam->value_float);
255   }
256   dpsmooth->start_float = dpsmooth->current_float;
257   dpsmooth->diff_float = dparam->value_float - dpsmooth->start_float;
259   time_ratio = ABS (dpsmooth->diff_float) / dpsmooth->slope_delta_float;
260   dpsmooth->duration_interp =
261       (gint64) (time_ratio * (gfloat) dpsmooth->slope_time);
263   dpsmooth->need_interp_times = TRUE;
265   GST_DEBUG ("%f to %f ratio:%f duration:%"
266       G_GINT64_FORMAT "\n",
267       dpsmooth->start_float, dparam->value_float, time_ratio,
268       dpsmooth->duration_interp);
271 static void
272 gst_dpsmooth_do_update_float (GstDParam * dparam, gint64 timestamp,
273     GValue * value, GstDParamUpdateInfo update_info)
275   gfloat time_ratio;
276   GstDParamSmooth *dpsmooth = GST_DPSMOOTH (dparam);
278   GST_DPARAM_LOCK (dparam);
280   if (dpsmooth->need_interp_times) {
281     dpsmooth->start_interp = timestamp;
282     dpsmooth->end_interp = timestamp + dpsmooth->duration_interp;
283     dpsmooth->need_interp_times = FALSE;
284   }
286   if ((update_info == GST_DPARAM_UPDATE_FIRST)
287       || (timestamp >= dpsmooth->end_interp)) {
288     if (GST_DPARAM_IS_LOG (dparam)) {
289       g_value_set_float (value, exp (dparam->value_float));
290     } else {
291       g_value_set_float (value, dparam->value_float);
292     }
293     dpsmooth->current_float = dparam->value_float;
295     GST_DEBUG ("interp finished at %" G_GINT64_FORMAT, timestamp);
297     GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
298     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = timestamp;
300     GST_DPARAM_READY_FOR_UPDATE (dparam) = FALSE;
301     GST_DPARAM_UNLOCK (dparam);
302     return;
303   }
305   if (timestamp <= dpsmooth->start_interp) {
306     if (GST_DPARAM_IS_LOG (dparam)) {
307       g_value_set_float (value, exp (dpsmooth->start_float));
308     } else {
309       g_value_set_float (value, dpsmooth->start_float);
310     }
311     GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
312     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
313         dpsmooth->start_interp + dpsmooth->update_period;
315     GST_DEBUG ("interp started at %" G_GINT64_FORMAT, timestamp);
317     GST_DPARAM_UNLOCK (dparam);
318     return;
320   }
322   time_ratio =
323       (gfloat) (timestamp -
324       dpsmooth->start_interp) / (gfloat) dpsmooth->duration_interp;
326   GST_DEBUG ("start:%" G_GINT64_FORMAT " current:%" G_GINT64_FORMAT " end:%"
327       G_GINT64_FORMAT " ratio%f", dpsmooth->start_interp, timestamp,
328       dpsmooth->end_interp, time_ratio);
329   GST_DEBUG ("pre  start:%f current:%f target:%f", dpsmooth->start_float,
330       dpsmooth->current_float, dparam->value_float);
332   dpsmooth->current_float =
333       dpsmooth->start_float + (dpsmooth->diff_float * time_ratio);
335   GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
336       timestamp + dpsmooth->update_period;
337   if (GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) > dpsmooth->end_interp) {
338     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = dpsmooth->end_interp;
339   }
341   GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
343   if (GST_DPARAM_IS_LOG (dparam)) {
344     g_value_set_float (value, exp (dpsmooth->current_float));
345   } else {
346     g_value_set_float (value, dpsmooth->current_float);
347   }
349   GST_DEBUG ("post start:%f current:%f target:%f", dpsmooth->start_float,
350       dpsmooth->current_float, dparam->value_float);
352   GST_DPARAM_UNLOCK (dparam);
355 static void
356 gst_dpsmooth_value_changed_double (GstDParam * dparam)
358   GstDParamSmooth *dpsmooth;
359   gdouble time_ratio;
361   g_return_if_fail (GST_IS_DPSMOOTH (dparam));
362   dpsmooth = GST_DPSMOOTH (dparam);
364   if (GST_DPARAM_IS_LOG (dparam)) {
365     dparam->value_double = log (dparam->value_double);
366   }
367   dpsmooth->start_double = dpsmooth->current_double;
368   dpsmooth->diff_double = dparam->value_double - dpsmooth->start_double;
370   time_ratio = ABS (dpsmooth->diff_double) / dpsmooth->slope_delta_double;
371   dpsmooth->duration_interp =
372       (gint64) (time_ratio * (gdouble) dpsmooth->slope_time);
374   dpsmooth->need_interp_times = TRUE;
376   GST_DEBUG ("%f to %f ratio:%f duration:%"
377       G_GINT64_FORMAT "\n",
378       dpsmooth->start_double, dparam->value_double, time_ratio,
379       dpsmooth->duration_interp);
382 static void
383 gst_dpsmooth_do_update_double (GstDParam * dparam, gint64 timestamp,
384     GValue * value, GstDParamUpdateInfo update_info)
386   gdouble time_ratio;
387   GstDParamSmooth *dpsmooth = GST_DPSMOOTH (dparam);
389   GST_DPARAM_LOCK (dparam);
391   if (dpsmooth->need_interp_times) {
392     dpsmooth->start_interp = timestamp;
393     dpsmooth->end_interp = timestamp + dpsmooth->duration_interp;
394     dpsmooth->need_interp_times = FALSE;
395   }
397   if ((update_info == GST_DPARAM_UPDATE_FIRST)
398       || (timestamp >= dpsmooth->end_interp)) {
399     if (GST_DPARAM_IS_LOG (dparam)) {
400       g_value_set_double (value, exp (dparam->value_double));
401     } else {
402       g_value_set_double (value, dparam->value_double);
403     }
404     dpsmooth->current_double = dparam->value_double;
406     GST_DEBUG ("interp finished at %" G_GINT64_FORMAT, timestamp);
408     GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
409     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = timestamp;
411     GST_DPARAM_READY_FOR_UPDATE (dparam) = FALSE;
412     GST_DPARAM_UNLOCK (dparam);
413     return;
414   }
416   if (timestamp <= dpsmooth->start_interp) {
417     if (GST_DPARAM_IS_LOG (dparam)) {
418       g_value_set_double (value, exp (dpsmooth->start_double));
419     } else {
420       g_value_set_double (value, dpsmooth->start_double);
421     }
422     GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
423     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
424         dpsmooth->start_interp + dpsmooth->update_period;
426     GST_DEBUG ("interp started at %" G_GINT64_FORMAT, timestamp);
428     GST_DPARAM_UNLOCK (dparam);
429     return;
431   }
433   time_ratio =
434       (gdouble) (timestamp -
435       dpsmooth->start_interp) / (gdouble) dpsmooth->duration_interp;
437   GST_DEBUG ("start:%" G_GINT64_FORMAT " current:%" G_GINT64_FORMAT " end:%"
438       G_GINT64_FORMAT " ratio%f", dpsmooth->start_interp, timestamp,
439       dpsmooth->end_interp, time_ratio);
440   GST_DEBUG ("pre  start:%f current:%f target:%f", dpsmooth->start_double,
441       dpsmooth->current_double, dparam->value_double);
443   dpsmooth->current_double =
444       dpsmooth->start_double + (dpsmooth->diff_double * time_ratio);
446   GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) =
447       timestamp + dpsmooth->update_period;
448   if (GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) > dpsmooth->end_interp) {
449     GST_DPARAM_NEXT_UPDATE_TIMESTAMP (dparam) = dpsmooth->end_interp;
450   }
452   GST_DPARAM_LAST_UPDATE_TIMESTAMP (dparam) = timestamp;
454   if (GST_DPARAM_IS_LOG (dparam)) {
455     g_value_set_double (value, exp (dpsmooth->current_double));
456   } else {
457     g_value_set_double (value, dpsmooth->current_double);
458   }
460   GST_DEBUG ("post start:%f current:%f target:%f", dpsmooth->start_double,
461       dpsmooth->current_double, dparam->value_double);
463   GST_DPARAM_UNLOCK (dparam);