Branch data Line data Source code
1 : : /* GStreamer
2 : : *
3 : : * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
4 : : * Copyright (C) 2007-2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5 : : *
6 : : * gstinterpolation.c: Interpolation methods for dynamic properties
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 : : */
23 : :
24 : : #ifdef HAVE_CONFIG_H
25 : : # include "config.h"
26 : : #endif
27 : :
28 : : #include "gstinterpolationcontrolsource.h"
29 : : #include "gstinterpolationcontrolsourceprivate.h"
30 : :
31 : : #define GST_CAT_DEFAULT controller_debug
32 : : GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
33 : :
34 : : #define EMPTY(x) (x)
35 : :
36 : : /* common helper */
37 : :
38 : : static gint
39 : 125 : gst_control_point_find (gconstpointer p1, gconstpointer p2)
40 : : {
41 : 125 : GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
42 : 125 : GstClockTime ct2 = *(GstClockTime *) p2;
43 : :
44 [ + + ]: 125 : return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
45 : : }
46 : :
47 : : /*
48 : : * gst_interpolation_control_source_find_control_point_iter:
49 : : * @self: the interpolation control source to search in
50 : : * @timestamp: the search key
51 : : *
52 : : * Find last value before given timestamp in control point list.
53 : : * If all values in the control point list come after the given
54 : : * timestamp or no values exist, %NULL is returned.
55 : : *
56 : : * Returns: the found #GSequenceIter or %NULL
57 : : */
58 : 75 : static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
59 : : (GstInterpolationControlSource * self, GstClockTime timestamp)
60 : : {
61 : : GSequenceIter *iter;
62 : :
63 [ + + ]: 75 : if (!self->priv->values)
64 : 3 : return NULL;
65 : :
66 : 72 : iter =
67 : 72 : g_sequence_search (self->priv->values, ×tamp,
68 : : (GCompareDataFunc) gst_control_point_find, NULL);
69 : :
70 : : /* g_sequence_search() returns the iter where timestamp
71 : : * would be inserted, i.e. the iter > timestamp, so
72 : : * we need to get the previous one. And of course, if
73 : : * there is no previous one, we return NULL. */
74 [ + + ]: 72 : if (g_sequence_iter_is_begin (iter))
75 : 4 : return NULL;
76 : :
77 : 75 : return g_sequence_iter_prev (iter);
78 : : }
79 : :
80 : : /* steps-like (no-)interpolation, default */
81 : : /* just returns the value for the most recent key-frame */
82 : : static inline const GValue *
83 : 0 : _interpolate_none_get (GstInterpolationControlSource * self,
84 : : GSequenceIter * iter)
85 : : {
86 : : const GValue *ret;
87 : :
88 [ # # ]: 0 : if (iter) {
89 : 0 : GstControlPoint *cp = g_sequence_get (iter);
90 : :
91 : 0 : ret = &cp->value;
92 : : } else {
93 : 0 : ret = &self->priv->default_value;
94 : : }
95 : 0 : return ret;
96 : : }
97 : :
98 : : #define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
99 : : static inline const GValue * \
100 : : _interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \
101 : : { \
102 : : const GValue *ret; \
103 : : \
104 : : if (iter) { \
105 : : GstControlPoint *cp = g_sequence_get (iter); \
106 : : g##type ret_val = g_value_get_##type (&cp->value); \
107 : : \
108 : : if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
109 : : ret = &self->priv->minimum_value; \
110 : : else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
111 : : ret = &self->priv->maximum_value; \
112 : : else \
113 : : ret = &cp->value; \
114 : : } else { \
115 : : ret = &self->priv->default_value; \
116 : : } \
117 : : return ret; \
118 : : }
119 : :
120 : : #define DEFINE_NONE_GET(type,ctype,get_func) \
121 : : static gboolean \
122 : : interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
123 : : { \
124 : : const GValue *ret; \
125 : : GSequenceIter *iter; \
126 : : \
127 : : g_mutex_lock (self->lock); \
128 : : \
129 : : iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
130 : : ret = get_func (self, iter); \
131 : : g_value_copy (ret, value); \
132 : : g_mutex_unlock (self->lock); \
133 : : return TRUE; \
134 : : } \
135 : : \
136 : : static gboolean \
137 : : interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self, \
138 : : GstClockTime timestamp, GstValueArray * value_array) \
139 : : { \
140 : : gint i; \
141 : : GstClockTime ts = timestamp; \
142 : : GstClockTime next_ts = 0; \
143 : : ctype *values = (ctype *) value_array->values; \
144 : : const GValue *ret_val = NULL; \
145 : : ctype ret = 0; \
146 : : GSequenceIter *iter1 = NULL, *iter2 = NULL; \
147 : : \
148 : : g_mutex_lock (self->lock); \
149 : : for(i = 0; i < value_array->nbsamples; i++) { \
150 : : if (!ret_val || ts >= next_ts) { \
151 : : iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
152 : : if (!iter1) { \
153 : : if (G_LIKELY (self->priv->values)) \
154 : : iter2 = g_sequence_get_begin_iter (self->priv->values); \
155 : : else \
156 : : iter2 = NULL; \
157 : : } else { \
158 : : iter2 = g_sequence_iter_next (iter1); \
159 : : } \
160 : : \
161 : : if (iter2 && !g_sequence_iter_is_end (iter2)) { \
162 : : GstControlPoint *cp; \
163 : : \
164 : : cp = g_sequence_get (iter2); \
165 : : next_ts = cp->timestamp; \
166 : : } else { \
167 : : next_ts = GST_CLOCK_TIME_NONE; \
168 : : } \
169 : : \
170 : : ret_val = get_func (self, iter1); \
171 : : ret = g_value_get_##type (ret_val); \
172 : : } \
173 : : *values = ret; \
174 : : ts += value_array->sample_interval; \
175 : : values++; \
176 : : } \
177 : : g_mutex_unlock (self->lock); \
178 : : return TRUE; \
179 : : }
180 : :
181 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (int);
[ # # ]
182 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (int, gint, _interpolate_none_get_int);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
183 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (uint);
[ # # ]
184 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (uint, guint, _interpolate_none_get_uint);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
185 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (long);
[ # # ]
186 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (long, glong, _interpolate_none_get_long);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
187 [ + + ][ - + ]: 13 : DEFINE_NONE_GET_FUNC_COMPARABLE (ulong);
[ - + ]
188 [ # # ][ # # ]: 13 : DEFINE_NONE_GET (ulong, gulong, _interpolate_none_get_ulong);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
189 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (int64);
[ # # ]
190 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (int64, gint64, _interpolate_none_get_int64);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
191 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (uint64);
[ # # ]
192 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (uint64, guint64, _interpolate_none_get_uint64);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
193 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (float);
[ # # ]
194 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (float, gfloat, _interpolate_none_get_float);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
195 [ # # ][ # # ]: 0 : DEFINE_NONE_GET_FUNC_COMPARABLE (double);
[ # # ]
196 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (double, gdouble, _interpolate_none_get_double);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
197 : :
198 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (boolean, gboolean, _interpolate_none_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
199 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (enum, gint, _interpolate_none_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
200 [ # # ][ # # ]: 0 : DEFINE_NONE_GET (string, const gchar *, _interpolate_none_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
201 : :
202 : : static GstInterpolateMethod interpolate_none = {
203 : : (GstControlSourceGetValue) interpolate_none_get_int,
204 : : (GstControlSourceGetValueArray) interpolate_none_get_int_value_array,
205 : : (GstControlSourceGetValue) interpolate_none_get_uint,
206 : : (GstControlSourceGetValueArray) interpolate_none_get_uint_value_array,
207 : : (GstControlSourceGetValue) interpolate_none_get_long,
208 : : (GstControlSourceGetValueArray) interpolate_none_get_long_value_array,
209 : : (GstControlSourceGetValue) interpolate_none_get_ulong,
210 : : (GstControlSourceGetValueArray) interpolate_none_get_ulong_value_array,
211 : : (GstControlSourceGetValue) interpolate_none_get_int64,
212 : : (GstControlSourceGetValueArray) interpolate_none_get_int64_value_array,
213 : : (GstControlSourceGetValue) interpolate_none_get_uint64,
214 : : (GstControlSourceGetValueArray) interpolate_none_get_uint64_value_array,
215 : : (GstControlSourceGetValue) interpolate_none_get_float,
216 : : (GstControlSourceGetValueArray) interpolate_none_get_float_value_array,
217 : : (GstControlSourceGetValue) interpolate_none_get_double,
218 : : (GstControlSourceGetValueArray) interpolate_none_get_double_value_array,
219 : : (GstControlSourceGetValue) interpolate_none_get_boolean,
220 : : (GstControlSourceGetValueArray) interpolate_none_get_boolean_value_array,
221 : : (GstControlSourceGetValue) interpolate_none_get_enum,
222 : : (GstControlSourceGetValueArray) interpolate_none_get_enum_value_array,
223 : : (GstControlSourceGetValue) interpolate_none_get_string,
224 : : (GstControlSourceGetValueArray) interpolate_none_get_string_value_array
225 : : };
226 : :
227 : : /* returns the default value of the property, except for times with specific values */
228 : : /* needed for one-shot events, such as notes and triggers */
229 : : static inline const GValue *
230 : 0 : _interpolate_trigger_get (GstInterpolationControlSource * self,
231 : : GSequenceIter * iter, GstClockTime timestamp)
232 : : {
233 : : GstControlPoint *cp;
234 : :
235 : : /* check if there is a value at the registered timestamp */
236 [ # # ]: 0 : if (iter) {
237 : 0 : cp = g_sequence_get (iter);
238 [ # # ]: 0 : if (timestamp == cp->timestamp) {
239 : 0 : return &cp->value;
240 : : }
241 : : }
242 [ # # ]: 0 : if (self->priv->nvalues > 0)
243 : 0 : return &self->priv->default_value;
244 : : else
245 : 0 : return NULL;
246 : : }
247 : :
248 : : #define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
249 : : static inline const GValue * \
250 : : _interpolate_trigger_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
251 : : { \
252 : : GstControlPoint *cp; \
253 : : \
254 : : /* check if there is a value at the registered timestamp */ \
255 : : if (iter) { \
256 : : cp = g_sequence_get (iter); \
257 : : if (timestamp == cp->timestamp) { \
258 : : g##type ret = g_value_get_##type (&cp->value); \
259 : : if (g_value_get_##type (&self->priv->minimum_value) > ret) \
260 : : return &self->priv->minimum_value; \
261 : : else if (g_value_get_##type (&self->priv->maximum_value) < ret) \
262 : : return &self->priv->maximum_value; \
263 : : else \
264 : : return &cp->value; \
265 : : } \
266 : : } \
267 : : \
268 : : if (self->priv->nvalues > 0) \
269 : : return &self->priv->default_value; \
270 : : else \
271 : : return NULL; \
272 : : }
273 : :
274 : : #define DEFINE_TRIGGER_GET(type, ctype, get_func) \
275 : : static gboolean \
276 : : interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
277 : : { \
278 : : const GValue *ret; \
279 : : GSequenceIter *iter; \
280 : : \
281 : : g_mutex_lock (self->lock); \
282 : : \
283 : : iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
284 : : ret = get_func (self, iter, timestamp); \
285 : : if (!ret) { \
286 : : g_mutex_unlock (self->lock); \
287 : : return FALSE; \
288 : : } \
289 : : \
290 : : g_value_copy (ret, value); \
291 : : g_mutex_unlock (self->lock); \
292 : : return TRUE; \
293 : : } \
294 : : \
295 : : static gboolean \
296 : : interpolate_trigger_get_##type##_value_array (GstInterpolationControlSource *self, \
297 : : GstClockTime timestamp, GstValueArray * value_array) \
298 : : { \
299 : : gint i; \
300 : : GstClockTime ts = timestamp; \
301 : : GstClockTime next_ts = 0; \
302 : : ctype *values = (ctype *) value_array->values; \
303 : : const GValue *ret_val = NULL; \
304 : : ctype ret = 0; \
305 : : GSequenceIter *iter1 = NULL, *iter2 = NULL; \
306 : : gboolean triggered = FALSE; \
307 : : \
308 : : g_mutex_lock (self->lock); \
309 : : for(i = 0; i < value_array->nbsamples; i++) { \
310 : : if (!ret_val || ts >= next_ts) { \
311 : : iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
312 : : if (!iter1) { \
313 : : if (G_LIKELY (self->priv->values)) \
314 : : iter2 = g_sequence_get_begin_iter (self->priv->values); \
315 : : else \
316 : : iter2 = NULL; \
317 : : } else { \
318 : : iter2 = g_sequence_iter_next (iter1); \
319 : : } \
320 : : \
321 : : if (iter2 && !g_sequence_iter_is_end (iter2)) { \
322 : : GstControlPoint *cp; \
323 : : \
324 : : cp = g_sequence_get (iter2); \
325 : : next_ts = cp->timestamp; \
326 : : } else { \
327 : : next_ts = GST_CLOCK_TIME_NONE; \
328 : : } \
329 : : \
330 : : ret_val = get_func (self, iter1, ts); \
331 : : if (!ret_val) { \
332 : : g_mutex_unlock (self->lock); \
333 : : return FALSE; \
334 : : } \
335 : : ret = g_value_get_##type (ret_val); \
336 : : triggered = TRUE; \
337 : : } else if (triggered) { \
338 : : ret_val = get_func (self, iter1, ts); \
339 : : if (!ret_val) { \
340 : : g_mutex_unlock (self->lock); \
341 : : return FALSE; \
342 : : } \
343 : : ret = g_value_get_##type (ret_val); \
344 : : triggered = FALSE; \
345 : : } \
346 : : *values = ret; \
347 : : ts += value_array->sample_interval; \
348 : : values++; \
349 : : } \
350 : : g_mutex_unlock (self->lock); \
351 : : return TRUE; \
352 : : }
353 : :
354 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
[ # # ][ # # ]
[ # # ]
355 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
356 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
[ # # ][ # # ]
[ # # ]
357 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
358 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
[ # # ][ # # ]
[ # # ]
359 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
360 [ + + ][ + + ]: 7 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
[ - + ][ - + ]
[ + + ]
361 [ # # ][ # # ]: 7 : DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ]
362 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
[ # # ][ # # ]
[ # # ]
363 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
364 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
[ # # ][ # # ]
[ # # ]
365 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
366 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
[ # # ][ # # ]
[ # # ]
367 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
368 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
[ # # ][ # # ]
[ # # ]
369 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
370 : :
371 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
372 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
373 [ # # ][ # # ]: 0 : DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
374 : :
375 : : static GstInterpolateMethod interpolate_trigger = {
376 : : (GstControlSourceGetValue) interpolate_trigger_get_int,
377 : : (GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array,
378 : : (GstControlSourceGetValue) interpolate_trigger_get_uint,
379 : : (GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array,
380 : : (GstControlSourceGetValue) interpolate_trigger_get_long,
381 : : (GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array,
382 : : (GstControlSourceGetValue) interpolate_trigger_get_ulong,
383 : : (GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array,
384 : : (GstControlSourceGetValue) interpolate_trigger_get_int64,
385 : : (GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array,
386 : : (GstControlSourceGetValue) interpolate_trigger_get_uint64,
387 : : (GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array,
388 : : (GstControlSourceGetValue) interpolate_trigger_get_float,
389 : : (GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array,
390 : : (GstControlSourceGetValue) interpolate_trigger_get_double,
391 : : (GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array,
392 : : (GstControlSourceGetValue) interpolate_trigger_get_boolean,
393 : : (GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array,
394 : : (GstControlSourceGetValue) interpolate_trigger_get_enum,
395 : : (GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array,
396 : : (GstControlSourceGetValue) interpolate_trigger_get_string,
397 : : (GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array
398 : : };
399 : :
400 : : /* linear interpolation */
401 : : /* smoothes inbetween values */
402 : : #define DEFINE_LINEAR_GET(vtype, round, convert) \
403 : : static inline void \
404 : : _interpolate_linear_internal_##vtype (GstClockTime timestamp1, g##vtype value1, GstClockTime timestamp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
405 : : { \
406 : : if (GST_CLOCK_TIME_IS_VALID (timestamp2)) { \
407 : : gdouble slope; \
408 : : \
409 : : slope = ((gdouble) convert (value2) - (gdouble) convert (value1)) / gst_guint64_to_gdouble (timestamp2 - timestamp1); \
410 : : \
411 : : if (round) \
412 : : *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope + 0.5); \
413 : : else \
414 : : *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope); \
415 : : } else { \
416 : : *ret = value1; \
417 : : } \
418 : : *ret = CLAMP (*ret, min, max); \
419 : : } \
420 : : \
421 : : static gboolean \
422 : : interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
423 : : { \
424 : : g##vtype ret, min, max; \
425 : : GSequenceIter *iter; \
426 : : GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
427 : : \
428 : : g_mutex_lock (self->lock); \
429 : : \
430 : : min = g_value_get_##vtype (&self->priv->minimum_value); \
431 : : max = g_value_get_##vtype (&self->priv->maximum_value); \
432 : : \
433 : : iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
434 : : if (iter) { \
435 : : cp1 = g_sequence_get (iter); \
436 : : iter = g_sequence_iter_next (iter); \
437 : : } else { \
438 : : cp.timestamp = G_GUINT64_CONSTANT(0); \
439 : : g_value_init (&cp.value, self->priv->type); \
440 : : g_value_copy (&self->priv->default_value, &cp.value); \
441 : : cp1 = &cp; \
442 : : if (G_LIKELY (self->priv->values)) \
443 : : iter = g_sequence_get_begin_iter (self->priv->values); \
444 : : } \
445 : : if (iter && !g_sequence_iter_is_end (iter)) \
446 : : cp2 = g_sequence_get (iter); \
447 : : \
448 : : _interpolate_linear_internal_##vtype (cp1->timestamp, g_value_get_##vtype (&cp1->value), (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), (cp2 ? g_value_get_##vtype (&cp2->value) : 0), timestamp, min, max, &ret); \
449 : : g_value_set_##vtype (value, ret); \
450 : : g_mutex_unlock (self->lock); \
451 : : if (cp1 == &cp) \
452 : : g_value_unset (&cp.value); \
453 : : return TRUE; \
454 : : } \
455 : : \
456 : : static gboolean \
457 : : interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \
458 : : GstClockTime timestamp, GstValueArray * value_array) \
459 : : { \
460 : : gint i; \
461 : : GstClockTime ts = timestamp; \
462 : : GstClockTime next_ts = 0; \
463 : : g##vtype *values = (g##vtype *) value_array->values; \
464 : : GSequenceIter *iter1, *iter2 = NULL; \
465 : : GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
466 : : g##vtype val1 = 0, val2 = 0, min, max; \
467 : : \
468 : : g_mutex_lock (self->lock); \
469 : : \
470 : : cp.timestamp = G_GUINT64_CONSTANT(0); \
471 : : g_value_init (&cp.value, self->priv->type); \
472 : : g_value_copy (&self->priv->default_value, &cp.value); \
473 : : \
474 : : min = g_value_get_##vtype (&self->priv->minimum_value); \
475 : : max = g_value_get_##vtype (&self->priv->maximum_value); \
476 : : \
477 : : for(i = 0; i < value_array->nbsamples; i++) { \
478 : : if (timestamp >= next_ts) { \
479 : : iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
480 : : if (!iter1) { \
481 : : cp1 = &cp; \
482 : : if (G_LIKELY (self->priv->values)) \
483 : : iter2 = g_sequence_get_begin_iter (self->priv->values); \
484 : : else \
485 : : iter2 = NULL; \
486 : : } else { \
487 : : cp1 = g_sequence_get (iter1); \
488 : : iter2 = g_sequence_iter_next (iter1); \
489 : : } \
490 : : \
491 : : if (iter2 && !g_sequence_iter_is_end (iter2)) { \
492 : : cp2 = g_sequence_get (iter2); \
493 : : next_ts = cp2->timestamp; \
494 : : } else { \
495 : : next_ts = GST_CLOCK_TIME_NONE; \
496 : : } \
497 : : val1 = g_value_get_##vtype (&cp1->value); \
498 : : if (cp2) \
499 : : val2 = g_value_get_##vtype (&cp2->value); \
500 : : } \
501 : : _interpolate_linear_internal_##vtype (cp1->timestamp, val1, (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), (cp2 ? val2 : 0), ts, min, max, values); \
502 : : ts += value_array->sample_interval; \
503 : : values++; \
504 : : } \
505 : : g_mutex_unlock (self->lock); \
506 : : g_value_unset (&cp.value); \
507 : : return TRUE; \
508 : : }
509 : :
510 [ # # ][ # # ]: 0 : DEFINE_LINEAR_GET (int, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
511 [ # # ][ # # ]: 0 : DEFINE_LINEAR_GET (uint, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
512 [ # # ][ # # ]: 0 : DEFINE_LINEAR_GET (long, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
513 [ + + ][ - + ]: 61 : DEFINE_LINEAR_GET (ulong, TRUE, EMPTY);
[ # # ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + - ]
514 [ # # ][ # # ]: 0 : DEFINE_LINEAR_GET (int64, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
515 [ # # ][ # # ]: 0 : DEFINE_LINEAR_GET (uint64, TRUE, gst_guint64_to_gdouble);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
516 [ # # ][ # # ]: 12 : DEFINE_LINEAR_GET (float, FALSE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
[ # # ][ + - ]
[ + + ][ + + ]
[ + + ][ - + ]
[ + + ][ + + ]
[ + + ]
517 [ # # ][ # # ]: 30 : DEFINE_LINEAR_GET (double, FALSE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
[ # # ][ + - ]
[ + + ][ + + ]
[ + + ][ - + ]
[ + + ][ - + ]
[ - + ]
518 : :
519 : : static GstInterpolateMethod interpolate_linear = {
520 : : (GstControlSourceGetValue) interpolate_linear_get_int,
521 : : (GstControlSourceGetValueArray) interpolate_linear_get_int_value_array,
522 : : (GstControlSourceGetValue) interpolate_linear_get_uint,
523 : : (GstControlSourceGetValueArray) interpolate_linear_get_uint_value_array,
524 : : (GstControlSourceGetValue) interpolate_linear_get_long,
525 : : (GstControlSourceGetValueArray) interpolate_linear_get_long_value_array,
526 : : (GstControlSourceGetValue) interpolate_linear_get_ulong,
527 : : (GstControlSourceGetValueArray) interpolate_linear_get_ulong_value_array,
528 : : (GstControlSourceGetValue) interpolate_linear_get_int64,
529 : : (GstControlSourceGetValueArray) interpolate_linear_get_int64_value_array,
530 : : (GstControlSourceGetValue) interpolate_linear_get_uint64,
531 : : (GstControlSourceGetValueArray) interpolate_linear_get_uint64_value_array,
532 : : (GstControlSourceGetValue) interpolate_linear_get_float,
533 : : (GstControlSourceGetValueArray) interpolate_linear_get_float_value_array,
534 : : (GstControlSourceGetValue) interpolate_linear_get_double,
535 : : (GstControlSourceGetValueArray) interpolate_linear_get_double_value_array,
536 : : (GstControlSourceGetValue) NULL,
537 : : (GstControlSourceGetValueArray) NULL,
538 : : (GstControlSourceGetValue) NULL,
539 : : (GstControlSourceGetValueArray) NULL,
540 : : (GstControlSourceGetValue) NULL,
541 : : (GstControlSourceGetValueArray) NULL
542 : : };
543 : :
544 : : /* square interpolation */
545 : :
546 : : /* cubic interpolation */
547 : :
548 : : /* The following functions implement a natural cubic spline interpolator.
549 : : * For details look at http://en.wikipedia.org/wiki/Spline_interpolation
550 : : *
551 : : * Instead of using a real matrix with n^2 elements for the linear system
552 : : * of equations we use three arrays o, p, q to hold the tridiagonal matrix
553 : : * as following to save memory:
554 : : *
555 : : * p[0] q[0] 0 0 0
556 : : * o[1] p[1] q[1] 0 0
557 : : * 0 o[2] p[2] q[2] .
558 : : * . . . . .
559 : : */
560 : :
561 : : #define DEFINE_CUBIC_GET(vtype,round, convert) \
562 : : static void \
563 : : _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
564 : : { \
565 : : gint i, n = self->priv->nvalues; \
566 : : gdouble *o = g_new0 (gdouble, n); \
567 : : gdouble *p = g_new0 (gdouble, n); \
568 : : gdouble *q = g_new0 (gdouble, n); \
569 : : \
570 : : gdouble *h = g_new0 (gdouble, n); \
571 : : gdouble *b = g_new0 (gdouble, n); \
572 : : gdouble *z = g_new0 (gdouble, n); \
573 : : \
574 : : GSequenceIter *iter; \
575 : : GstControlPoint *cp; \
576 : : GstClockTime x, x_next; \
577 : : g##vtype y_prev, y, y_next; \
578 : : \
579 : : /* Fill linear system of equations */ \
580 : : iter = g_sequence_get_begin_iter (self->priv->values); \
581 : : cp = g_sequence_get (iter); \
582 : : x = cp->timestamp; \
583 : : y = g_value_get_##vtype (&cp->value); \
584 : : \
585 : : p[0] = 1.0; \
586 : : \
587 : : iter = g_sequence_iter_next (iter); \
588 : : cp = g_sequence_get (iter); \
589 : : x_next = cp->timestamp; \
590 : : y_next = g_value_get_##vtype (&cp->value); \
591 : : h[0] = gst_guint64_to_gdouble (x_next - x); \
592 : : \
593 : : for (i = 1; i < n-1; i++) { \
594 : : /* Shuffle x and y values */ \
595 : : y_prev = y; \
596 : : x = x_next; \
597 : : y = y_next; \
598 : : iter = g_sequence_iter_next (iter); \
599 : : cp = g_sequence_get (iter); \
600 : : x_next = cp->timestamp; \
601 : : y_next = g_value_get_##vtype (&cp->value); \
602 : : \
603 : : h[i] = gst_guint64_to_gdouble (x_next - x); \
604 : : o[i] = h[i-1]; \
605 : : p[i] = 2.0 * (h[i-1] + h[i]); \
606 : : q[i] = h[i]; \
607 : : b[i] = convert (y_next - y) / h[i] - convert (y - y_prev) / h[i-1]; \
608 : : } \
609 : : p[n-1] = 1.0; \
610 : : \
611 : : /* Use Gauss elimination to set everything below the \
612 : : * diagonal to zero */ \
613 : : for (i = 1; i < n-1; i++) { \
614 : : gdouble a = o[i] / p[i-1]; \
615 : : p[i] -= a * q[i-1]; \
616 : : b[i] -= a * b[i-1]; \
617 : : } \
618 : : \
619 : : /* Solve everything else from bottom to top */ \
620 : : for (i = n-2; i > 0; i--) \
621 : : z[i] = (b[i] - q[i] * z[i+1]) / p[i]; \
622 : : \
623 : : /* Save cache next in the GstControlPoint */ \
624 : : \
625 : : iter = g_sequence_get_begin_iter (self->priv->values); \
626 : : for (i = 0; i < n; i++) { \
627 : : cp = g_sequence_get (iter); \
628 : : cp->cache.cubic.h = h[i]; \
629 : : cp->cache.cubic.z = z[i]; \
630 : : iter = g_sequence_iter_next (iter); \
631 : : } \
632 : : \
633 : : /* Free our temporary arrays */ \
634 : : g_free (o); \
635 : : g_free (p); \
636 : : g_free (q); \
637 : : g_free (h); \
638 : : g_free (b); \
639 : : g_free (z); \
640 : : } \
641 : : \
642 : : static inline void \
643 : : _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
644 : : { \
645 : : if (!self->priv->valid_cache) { \
646 : : _interpolate_cubic_update_cache_##vtype (self); \
647 : : self->priv->valid_cache = TRUE; \
648 : : } \
649 : : \
650 : : if (cp2) { \
651 : : gdouble diff1, diff2; \
652 : : gdouble out; \
653 : : \
654 : : diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \
655 : : diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \
656 : : \
657 : : out = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \
658 : : out += (convert (value2) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \
659 : : out += (convert (value1) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \
660 : : \
661 : : if (round) \
662 : : *ret = (g##vtype) (out + 0.5); \
663 : : else \
664 : : *ret = (g##vtype) out; \
665 : : } \
666 : : else { \
667 : : *ret = value1; \
668 : : } \
669 : : *ret = CLAMP (*ret, min, max); \
670 : : } \
671 : : \
672 : : static gboolean \
673 : : interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
674 : : { \
675 : : g##vtype ret, min, max; \
676 : : GSequenceIter *iter; \
677 : : GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
678 : : \
679 : : if (self->priv->nvalues <= 2) \
680 : : return interpolate_linear_get_##vtype (self, timestamp, value); \
681 : : \
682 : : g_mutex_lock (self->lock); \
683 : : \
684 : : min = g_value_get_##vtype (&self->priv->minimum_value); \
685 : : max = g_value_get_##vtype (&self->priv->maximum_value); \
686 : : \
687 : : iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
688 : : if (iter) { \
689 : : cp1 = g_sequence_get (iter); \
690 : : iter = g_sequence_iter_next (iter); \
691 : : } else { \
692 : : cp.timestamp = G_GUINT64_CONSTANT(0); \
693 : : g_value_init (&cp.value, self->priv->type); \
694 : : g_value_copy (&self->priv->default_value, &cp.value); \
695 : : cp1 = &cp; \
696 : : if (G_LIKELY (self->priv->values)) \
697 : : iter = g_sequence_get_begin_iter (self->priv->values); \
698 : : } \
699 : : if (iter && !g_sequence_iter_is_end (iter)) \
700 : : cp2 = g_sequence_get (iter); \
701 : : \
702 : : _interpolate_cubic_get_##vtype (self, cp1, g_value_get_##vtype (&cp1->value), cp2, (cp2 ? g_value_get_##vtype (&cp2->value) : 0), timestamp, min, max, &ret); \
703 : : g_value_set_##vtype (value, ret); \
704 : : g_mutex_unlock (self->lock); \
705 : : if (cp1 == &cp) \
706 : : g_value_unset (&cp.value); \
707 : : return TRUE; \
708 : : } \
709 : : \
710 : : static gboolean \
711 : : interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \
712 : : GstClockTime timestamp, GstValueArray * value_array) \
713 : : { \
714 : : gint i; \
715 : : GstClockTime ts = timestamp; \
716 : : GstClockTime next_ts = 0; \
717 : : g##vtype *values = (g##vtype *) value_array->values; \
718 : : GSequenceIter *iter1, *iter2 = NULL; \
719 : : GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
720 : : g##vtype val1 = 0, val2 = 0, min, max; \
721 : : \
722 : : if (self->priv->nvalues <= 2) \
723 : : return interpolate_linear_get_##vtype##_value_array (self, timestamp, value_array); \
724 : : \
725 : : g_mutex_lock (self->lock); \
726 : : \
727 : : cp.timestamp = G_GUINT64_CONSTANT(0); \
728 : : g_value_init (&cp.value, self->priv->type); \
729 : : g_value_copy (&self->priv->default_value, &cp.value); \
730 : : \
731 : : min = g_value_get_##vtype (&self->priv->minimum_value); \
732 : : max = g_value_get_##vtype (&self->priv->maximum_value); \
733 : : \
734 : : for(i = 0; i < value_array->nbsamples; i++) { \
735 : : if (timestamp >= next_ts) { \
736 : : iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
737 : : if (!iter1) { \
738 : : cp1 = &cp; \
739 : : if (G_LIKELY (self->priv->values)) \
740 : : iter2 = g_sequence_get_begin_iter (self->priv->values); \
741 : : else \
742 : : iter2 = NULL; \
743 : : } else { \
744 : : cp1 = g_sequence_get (iter1); \
745 : : iter2 = g_sequence_iter_next (iter1); \
746 : : } \
747 : : \
748 : : if (iter2 && !g_sequence_iter_is_end (iter2)) { \
749 : : cp2 = g_sequence_get (iter2); \
750 : : next_ts = cp2->timestamp; \
751 : : } else { \
752 : : next_ts = GST_CLOCK_TIME_NONE; \
753 : : } \
754 : : val1 = g_value_get_##vtype (&cp1->value); \
755 : : if (cp2) \
756 : : val2 = g_value_get_##vtype (&cp2->value); \
757 : : } \
758 : : _interpolate_cubic_get_##vtype (self, cp1, val1, cp2, val2, timestamp, min, max, values); \
759 : : ts += value_array->sample_interval; \
760 : : values++; \
761 : : } \
762 : : g_mutex_unlock (self->lock); \
763 : : g_value_unset (&cp.value); \
764 : : return TRUE; \
765 : : }
766 : :
767 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (int, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
768 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (uint, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
769 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (long, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
770 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (ulong, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
771 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (int64, TRUE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
772 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (uint64, TRUE, gst_guint64_to_gdouble);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
773 [ # # ][ # # ]: 0 : DEFINE_CUBIC_GET (float, FALSE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
774 [ # # ][ # # ]: 26 : DEFINE_CUBIC_GET (double, FALSE, EMPTY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ][ + - ]
[ # # ][ + - ]
[ + + ][ + + ]
[ - + ][ + + ]
[ + + ][ - + ]
[ - + ][ + + ]
[ + + ][ + + ]
[ + + ]
775 : :
776 : : static GstInterpolateMethod interpolate_cubic = {
777 : : (GstControlSourceGetValue) interpolate_cubic_get_int,
778 : : (GstControlSourceGetValueArray) interpolate_cubic_get_int_value_array,
779 : : (GstControlSourceGetValue) interpolate_cubic_get_uint,
780 : : (GstControlSourceGetValueArray) interpolate_cubic_get_uint_value_array,
781 : : (GstControlSourceGetValue) interpolate_cubic_get_long,
782 : : (GstControlSourceGetValueArray) interpolate_cubic_get_long_value_array,
783 : : (GstControlSourceGetValue) interpolate_cubic_get_ulong,
784 : : (GstControlSourceGetValueArray) interpolate_cubic_get_ulong_value_array,
785 : : (GstControlSourceGetValue) interpolate_cubic_get_int64,
786 : : (GstControlSourceGetValueArray) interpolate_cubic_get_int64_value_array,
787 : : (GstControlSourceGetValue) interpolate_cubic_get_uint64,
788 : : (GstControlSourceGetValueArray) interpolate_cubic_get_uint64_value_array,
789 : : (GstControlSourceGetValue) interpolate_cubic_get_float,
790 : : (GstControlSourceGetValueArray) interpolate_cubic_get_float_value_array,
791 : : (GstControlSourceGetValue) interpolate_cubic_get_double,
792 : : (GstControlSourceGetValueArray) interpolate_cubic_get_double_value_array,
793 : : (GstControlSourceGetValue) NULL,
794 : : (GstControlSourceGetValueArray) NULL,
795 : : (GstControlSourceGetValue) NULL,
796 : : (GstControlSourceGetValueArray) NULL,
797 : : (GstControlSourceGetValue) NULL,
798 : : (GstControlSourceGetValueArray) NULL
799 : : };
800 : :
801 : : /* register all interpolation methods */
802 : : GstInterpolateMethod *priv_gst_interpolation_methods[] = {
803 : : &interpolate_none,
804 : : &interpolate_trigger,
805 : : &interpolate_linear,
806 : : &interpolate_cubic,
807 : : &interpolate_cubic
808 : : };
809 : :
810 : : guint priv_gst_num_interpolation_methods =
811 : : G_N_ELEMENTS (priv_gst_interpolation_methods);
|