]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/blob - libs/gst/controller/gstinterpolationcontrolsource.c
8f7d1d86f6fe1f67ee4cde96cb139ea5cf24965a
[glsdk/gstreamer0-10.git] / libs / gst / controller / gstinterpolationcontrolsource.c
1 /* GStreamer
2  *
3  * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
4  *
5  * gstinterpolationcontrolsource.c: Control source that provides several
6  *                                  interpolation methods
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
24 /**
25  * SECTION:gstinterpolationcontrolsource
26  * @short_description: interpolation control source
27  *
28  * #GstInterpolationControlSource is a #GstControlSource, that interpolates values between user-given
29  * control points. It supports several interpolation modes and property types.
30  *
31  * To use #GstInterpolationControlSource get a new instance by calling
32  * gst_interpolation_control_source_new(), bind it to a #GParamSpec, select a interpolation mode with
33  * gst_interpolation_control_source_set_interpolation_mode() and set some control points by calling
34  * gst_interpolation_control_source_set().
35  *
36  * All functions are MT-safe.
37  *
38  */
40 #include <glib-object.h>
41 #include <gst/gst.h>
43 #include "gstcontrolsource.h"
44 #include "gstinterpolationcontrolsource.h"
45 #include "gstinterpolationcontrolsourceprivate.h"
47 #define GST_CAT_DEFAULT controller_debug
48 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
50 G_DEFINE_TYPE (GstInterpolationControlSource, gst_interpolation_control_source,
51     GST_TYPE_CONTROL_SOURCE);
53 static GObjectClass *parent_class = NULL;
55 /*
56  * gst_control_point_free:
57  * @prop: the object to free
58  *
59  * Private method which frees all data allocated by a #GstControlPoint
60  * instance.
61  */
62 static void
63 gst_control_point_free (GstControlPoint * cp)
64 {
65   g_return_if_fail (cp);
67   g_value_unset (&cp->value);
68   g_slice_free (GstControlPoint, cp);
69 }
71 static void
72 gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
73 {
74   GstControlSource *csource = (GstControlSource *) self;
76   csource->get_value = NULL;
77   csource->get_value_array = NULL;
79   self->priv->type = self->priv->base = G_TYPE_INVALID;
81   if (G_IS_VALUE (&self->priv->default_value))
82     g_value_unset (&self->priv->default_value);
83   if (G_IS_VALUE (&self->priv->minimum_value))
84     g_value_unset (&self->priv->minimum_value);
85   if (G_IS_VALUE (&self->priv->maximum_value))
86     g_value_unset (&self->priv->maximum_value);
88   if (self->priv->values) {
89     g_sequence_free (self->priv->values);
90     self->priv->values = NULL;
91   }
93   self->priv->nvalues = 0;
94   self->priv->valid_cache = FALSE;
95 }
97 /**
98  * gst_interpolation_control_source_new:
99  *
100  * This returns a new, unbound #GstInterpolationControlSource.
101  *
102  * Returns: a new, unbound #GstInterpolationControlSource.
103  */
104 GstInterpolationControlSource *
105 gst_interpolation_control_source_new (void)
107   return g_object_newv (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, 0, NULL);
110 /**
111  * gst_interpolation_control_source_set_interpolation_mode:
112  * @self: the #GstInterpolationControlSource object
113  * @mode: interpolation mode
114  *
115  * Sets the given interpolation mode.
116  *
117  * <note><para>User interpolation is not yet available and quadratic interpolation
118  * is deprecated and maps to cubic interpolation.</para></note>
119  *
120  * Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
121  */
122 /* *INDENT-OFF* */
123 gboolean
124 gst_interpolation_control_source_set_interpolation_mode (
125     GstInterpolationControlSource * self, GstInterpolateMode mode)
126 /* *INDENT-ON* */
128   gboolean ret = TRUE;
129   GstControlSource *csource = GST_CONTROL_SOURCE (self);
131   if (mode >= priv_gst_num_interpolation_methods
132       || priv_gst_interpolation_methods[mode] == NULL) {
133     GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
134     return FALSE;
135   }
137   if (mode == GST_INTERPOLATE_QUADRATIC) {
138     GST_WARNING ("Quadratic interpolation mode is deprecated, using cubic"
139         "interpolation mode");
140   }
142   if (mode == GST_INTERPOLATE_USER) {
143     GST_WARNING ("User interpolation mode is not implemented yet");
144     return FALSE;
145   }
147   g_mutex_lock (self->lock);
148   switch (self->priv->base) {
149     case G_TYPE_INT:
150       csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
151       csource->get_value_array =
152           priv_gst_interpolation_methods[mode]->get_int_value_array;
153       break;
154     case G_TYPE_UINT:{
155       csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
156       csource->get_value_array =
157           priv_gst_interpolation_methods[mode]->get_uint_value_array;
158       break;
159     }
160     case G_TYPE_LONG:{
161       csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
162       csource->get_value_array =
163           priv_gst_interpolation_methods[mode]->get_long_value_array;
164       break;
165     }
166     case G_TYPE_ULONG:{
167       csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
168       csource->get_value_array =
169           priv_gst_interpolation_methods[mode]->get_ulong_value_array;
170       break;
171     }
172     case G_TYPE_INT64:{
173       csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
174       csource->get_value_array =
175           priv_gst_interpolation_methods[mode]->get_int64_value_array;
176       break;
177     }
178     case G_TYPE_UINT64:{
179       csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
180       csource->get_value_array =
181           priv_gst_interpolation_methods[mode]->get_uint64_value_array;
182       break;
183     }
184     case G_TYPE_FLOAT:{
185       csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
186       csource->get_value_array =
187           priv_gst_interpolation_methods[mode]->get_float_value_array;
188       break;
189     }
190     case G_TYPE_DOUBLE:{
191       csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
192       csource->get_value_array =
193           priv_gst_interpolation_methods[mode]->get_double_value_array;
194       break;
195     }
196     case G_TYPE_BOOLEAN:{
197       csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
198       csource->get_value_array =
199           priv_gst_interpolation_methods[mode]->get_boolean_value_array;
200       break;
201     }
202     case G_TYPE_ENUM:{
203       csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
204       csource->get_value_array =
205           priv_gst_interpolation_methods[mode]->get_enum_value_array;
206       break;
207     }
208     case G_TYPE_STRING:{
209       csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
210       csource->get_value_array =
211           priv_gst_interpolation_methods[mode]->get_string_value_array;
212       break;
213     }
214     default:
215       ret = FALSE;
216       break;
217   }
219   /* Incomplete implementation */
220   if (!ret || !csource->get_value || !csource->get_value_array) {
221     gst_interpolation_control_source_reset (self);
222     ret = FALSE;
223   }
225   self->priv->valid_cache = FALSE;
226   self->priv->interpolation_mode = mode;
228   g_mutex_unlock (self->lock);
230   return ret;
233 static gboolean
234 gst_interpolation_control_source_bind (GstControlSource * source,
235     GParamSpec * pspec)
237   GType type, base;
238   GstInterpolationControlSource *self =
239       (GstInterpolationControlSource *) source;
240   gboolean ret = TRUE;
242   /* get the fundamental base type */
243   self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
244   while ((type = g_type_parent (type)))
245     base = type;
247   self->priv->base = base;
248   /* restore type */
249   type = self->priv->type;
251   if (!gst_interpolation_control_source_set_interpolation_mode (self,
252           self->priv->interpolation_mode))
253     return FALSE;
255   switch (base) {
256     case G_TYPE_INT:{
257       GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
259       g_value_init (&self->priv->default_value, type);
260       g_value_set_int (&self->priv->default_value, tpspec->default_value);
261       g_value_init (&self->priv->minimum_value, type);
262       g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
263       g_value_init (&self->priv->maximum_value, type);
264       g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
265       break;
266     }
267     case G_TYPE_UINT:{
268       GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
270       g_value_init (&self->priv->default_value, type);
271       g_value_set_uint (&self->priv->default_value, tpspec->default_value);
272       g_value_init (&self->priv->minimum_value, type);
273       g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
274       g_value_init (&self->priv->maximum_value, type);
275       g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
276       break;
277     }
278     case G_TYPE_LONG:{
279       GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
281       g_value_init (&self->priv->default_value, type);
282       g_value_set_long (&self->priv->default_value, tpspec->default_value);
283       g_value_init (&self->priv->minimum_value, type);
284       g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
285       g_value_init (&self->priv->maximum_value, type);
286       g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
287       break;
288     }
289     case G_TYPE_ULONG:{
290       GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
292       g_value_init (&self->priv->default_value, type);
293       g_value_set_ulong (&self->priv->default_value, tpspec->default_value);
294       g_value_init (&self->priv->minimum_value, type);
295       g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
296       g_value_init (&self->priv->maximum_value, type);
297       g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
298       break;
299     }
300     case G_TYPE_INT64:{
301       GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
303       g_value_init (&self->priv->default_value, type);
304       g_value_set_int64 (&self->priv->default_value, tpspec->default_value);
305       g_value_init (&self->priv->minimum_value, type);
306       g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
307       g_value_init (&self->priv->maximum_value, type);
308       g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
309       break;
310     }
311     case G_TYPE_UINT64:{
312       GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
314       g_value_init (&self->priv->default_value, type);
315       g_value_set_uint64 (&self->priv->default_value, tpspec->default_value);
316       g_value_init (&self->priv->minimum_value, type);
317       g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
318       g_value_init (&self->priv->maximum_value, type);
319       g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
320       break;
321     }
322     case G_TYPE_FLOAT:{
323       GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
325       g_value_init (&self->priv->default_value, type);
326       g_value_set_float (&self->priv->default_value, tpspec->default_value);
327       g_value_init (&self->priv->minimum_value, type);
328       g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
329       g_value_init (&self->priv->maximum_value, type);
330       g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
331       break;
332     }
333     case G_TYPE_DOUBLE:{
334       GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
336       g_value_init (&self->priv->default_value, type);
337       g_value_set_double (&self->priv->default_value, tpspec->default_value);
338       g_value_init (&self->priv->minimum_value, type);
339       g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
340       g_value_init (&self->priv->maximum_value, type);
341       g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
342       break;
343     }
344     case G_TYPE_BOOLEAN:{
345       GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
347       g_value_init (&self->priv->default_value, type);
348       g_value_set_boolean (&self->priv->default_value, tpspec->default_value);
349       break;
350     }
351     case G_TYPE_ENUM:{
352       GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
354       g_value_init (&self->priv->default_value, type);
355       g_value_set_enum (&self->priv->default_value, tpspec->default_value);
356       break;
357     }
358     case G_TYPE_STRING:{
359       GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
361       g_value_init (&self->priv->default_value, type);
362       g_value_set_string (&self->priv->default_value, tpspec->default_value);
363       break;
364     }
365     default:
366       GST_WARNING ("incomplete implementation for paramspec type '%s'",
367           G_PARAM_SPEC_TYPE_NAME (pspec));
368       ret = FALSE;
369       break;
370   }
372   if (ret) {
373     self->priv->valid_cache = FALSE;
374     self->priv->nvalues = 0;
375   } else {
376     gst_interpolation_control_source_reset (self);
377   }
379   return ret;
382 /*
383  * gst_control_point_compare:
384  * @p1: a pointer to a #GstControlPoint
385  * @p2: a pointer to a #GstControlPoint
386  *
387  * Compare function for g_list operations that operates on two #GstControlPoint
388  * parameters.
389  */
390 static gint
391 gst_control_point_compare (gconstpointer p1, gconstpointer p2)
393   GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
394   GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
396   return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
399 /*
400  * gst_control_point_find:
401  * @p1: a pointer to a #GstControlPoint
402  * @p2: a pointer to a #GstClockTime
403  *
404  * Compare function for g_list operations that operates on a #GstControlPoint and
405  * a #GstClockTime.
406  */
407 static gint
408 gst_control_point_find (gconstpointer p1, gconstpointer p2)
410   GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
411   GstClockTime ct2 = *(GstClockTime *) p2;
413   return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
416 static GstControlPoint *
417 _make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
418     const GValue * value)
420   GstControlPoint *cp;
422   /* create a new GstControlPoint */
423   cp = g_slice_new0 (GstControlPoint);
424   cp->timestamp = timestamp;
425   g_value_init (&cp->value, self->priv->type);
426   g_value_copy (value, &cp->value);
428   return cp;
431 static void
432 gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
433     self, GstClockTime timestamp, const GValue * value)
435   GSequenceIter *iter;
437   /* check if a control point for the timestamp already exists */
439   /* iter contains the iter right *after* timestamp */
440   if (G_LIKELY (self->priv->values)) {
441     iter =
442         g_sequence_search (self->priv->values, &timestamp,
443         (GCompareDataFunc) gst_control_point_find, NULL);
444     if (iter) {
445       GSequenceIter *prev = g_sequence_iter_prev (iter);
446       GstControlPoint *cp = g_sequence_get (prev);
448       /* If the timestamp is the same just update the control point value */
449       if (cp->timestamp == timestamp) {
450         /* update control point */
451         g_value_reset (&cp->value);
452         g_value_copy (value, &cp->value);
453         goto done;
454       }
455     }
456   } else {
457     self->priv->values =
458         g_sequence_new ((GDestroyNotify) gst_control_point_free);
459   }
461   /* sort new cp into the prop->values list */
462   g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
463           value), (GCompareDataFunc) gst_control_point_compare, NULL);
464   self->priv->nvalues++;
466 done:
467   self->priv->valid_cache = FALSE;
471 /**
472  * gst_interpolation_control_source_set:
473  * @self: the #GstInterpolationControlSource object
474  * @timestamp: the time the control-change is scheduled for
475  * @value: the control-value
476  *
477  * Set the value of given controller-handled property at a certain time.
478  *
479  * Returns: FALSE if the values couldn't be set, TRUE otherwise.
480  */
481 gboolean
482 gst_interpolation_control_source_set (GstInterpolationControlSource * self,
483     GstClockTime timestamp, const GValue * value)
485   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
486   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
487   g_return_val_if_fail (G_IS_VALUE (value), FALSE);
488   g_return_val_if_fail (G_VALUE_TYPE (value) == self->priv->type, FALSE);
490   g_mutex_lock (self->lock);
491   gst_interpolation_control_source_set_internal (self, timestamp, value);
492   g_mutex_unlock (self->lock);
494   return TRUE;
497 /**
498  * gst_interpolation_control_source_set_from_list:
499  * @self: the #GstInterpolationControlSource object
500  * @timedvalues: a list with #GstTimedValue items
501  *
502  * Sets multiple timed values at once.
503  *
504  * Returns: FALSE if the values couldn't be set, TRUE otherwise.
505  */
506 gboolean
507 gst_interpolation_control_source_set_from_list (GstInterpolationControlSource *
508     self, const GSList * timedvalues)
510   const GSList *node;
511   GstTimedValue *tv;
512   gboolean res = FALSE;
514   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
516   for (node = timedvalues; node; node = g_slist_next (node)) {
517     tv = node->data;
518     if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
519       GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
520           GST_FUNCTION);
521     } else if (!G_IS_VALUE (&tv->value)) {
522       GST_WARNING ("GstTimedValued with invalid value passed to %s",
523           GST_FUNCTION);
524     } else if (G_VALUE_TYPE (&tv->value) != self->priv->type) {
525       GST_WARNING ("incompatible value type for property");
526     } else {
527       g_mutex_lock (self->lock);
528       gst_interpolation_control_source_set_internal (self, tv->timestamp,
529           &tv->value);
530       g_mutex_unlock (self->lock);
531       res = TRUE;
532     }
533   }
534   return res;
537 /**
538  * gst_interpolation_control_source_unset:
539  * @self: the #GstInterpolationControlSource object
540  * @timestamp: the time the control-change should be removed from
541  *
542  * Used to remove the value of given controller-handled property at a certain
543  * time.
544  *
545  * Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
546  */
547 gboolean
548 gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
549     GstClockTime timestamp)
551   GSequenceIter *iter;
552   gboolean res = FALSE;
554   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
555   g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
557   g_mutex_lock (self->lock);
558   /* check if a control point for the timestamp exists */
559   if (G_LIKELY (self->priv->values) && (iter =
560           g_sequence_search (self->priv->values, &timestamp,
561               (GCompareDataFunc) gst_control_point_find, NULL))) {
562     GstControlPoint *cp;
564     /* Iter contains the iter right after timestamp, i.e.
565      * we need to get the previous one and check the timestamp
566      */
567     iter = g_sequence_iter_prev (iter);
568     cp = g_sequence_get (iter);
569     if (cp->timestamp == timestamp) {
570       g_sequence_remove (iter);
571       self->priv->nvalues--;
572       self->priv->valid_cache = FALSE;
573       res = TRUE;
574     }
575   }
576   g_mutex_unlock (self->lock);
578   return res;
581 /**
582  * gst_interpolation_control_source_unset_all:
583  * @self: the #GstInterpolationControlSource object
584  *
585  * Used to remove all time-stamped values of given controller-handled property
586  *
587  */
588 void
589 gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
590     self)
592   g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
594   g_mutex_lock (self->lock);
595   /* free GstControlPoint structures */
596   if (self->priv->values) {
597     g_sequence_free (self->priv->values);
598     self->priv->values = NULL;
599   }
600   self->priv->nvalues = 0;
601   self->priv->valid_cache = FALSE;
603   g_mutex_unlock (self->lock);
606 static void
607 _append_control_point (GstControlPoint * cp, GList ** l)
609   *l = g_list_prepend (*l, cp);
612 /**
613  * gst_interpolation_control_source_get_all:
614  * @self: the #GstInterpolationControlSource to get the list from
615  *
616  * Returns a read-only copy of the list of #GstTimedValue for the given property.
617  * Free the list after done with it.
618  *
619  * Returns: a copy of the list, or %NULL if the property isn't handled by the controller
620  */
621 GList *
622 gst_interpolation_control_source_get_all (GstInterpolationControlSource * self)
624   GList *res = NULL;
626   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
628   g_mutex_lock (self->lock);
629   if (G_LIKELY (self->priv->values))
630     g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
631         &res);
632   g_mutex_unlock (self->lock);
634   return g_list_reverse (res);
637 /**
638  * gst_interpolation_control_source_get_count:
639  * @self: the #GstInterpolationControlSource to get the number of values from
640  *
641  * Returns the number of control points that are set.
642  *
643  * Returns: the number of control points that are set.
644  *
645  */
646 gint
647 gst_interpolation_control_source_get_count (GstInterpolationControlSource *
648     self)
650   g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 0);
651   return self->priv->nvalues;
655 static void
656 gst_interpolation_control_source_init (GstInterpolationControlSource * self)
658   self->lock = g_mutex_new ();
659   self->priv =
660       G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
661       GstInterpolationControlSourcePrivate);
662   self->priv->interpolation_mode = GST_INTERPOLATE_NONE;
665 static void
666 gst_interpolation_control_source_finalize (GObject * obj)
668   GstInterpolationControlSource *self = GST_INTERPOLATION_CONTROL_SOURCE (obj);
670   g_mutex_lock (self->lock);
671   gst_interpolation_control_source_reset (self);
672   g_mutex_unlock (self->lock);
673   g_mutex_free (self->lock);
674   G_OBJECT_CLASS (parent_class)->finalize (obj);
677 static void
678 gst_interpolation_control_source_dispose (GObject * obj)
680   G_OBJECT_CLASS (parent_class)->dispose (obj);
683 static void
684 gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
685     * klass)
687   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
688   GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
690   parent_class = g_type_class_peek_parent (klass);
691   g_type_class_add_private (klass,
692       sizeof (GstInterpolationControlSourcePrivate));
694   gobject_class->finalize = gst_interpolation_control_source_finalize;
695   gobject_class->dispose = gst_interpolation_control_source_dispose;
696   csource_class->bind = gst_interpolation_control_source_bind;