diff options
Diffstat (limited to 'libs/gst/controller/gstinterpolation.c')
-rw-r--r-- | libs/gst/controller/gstinterpolation.c | 811 |
1 files changed, 0 insertions, 811 deletions
diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c deleted file mode 100644 index 54ff60e..0000000 --- a/libs/gst/controller/gstinterpolation.c +++ /dev/null @@ -1,811 +0,0 @@ -/* GStreamer - * - * Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net> - * Copyright (C) 2007-2010 Sebastian Dröge <sebastian.droege@collabora.co.uk> - * - * gstinterpolation.c: Interpolation methods for dynamic properties - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "gstinterpolationcontrolsource.h" -#include "gstinterpolationcontrolsourceprivate.h" - -#define GST_CAT_DEFAULT controller_debug -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT); - -#define EMPTY(x) (x) - -/* common helper */ - -static gint -gst_control_point_find (gconstpointer p1, gconstpointer p2) -{ - GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp; - GstClockTime ct2 = *(GstClockTime *) p2; - - return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); -} - -/* - * gst_interpolation_control_source_find_control_point_iter: - * @self: the interpolation control source to search in - * @timestamp: the search key - * - * Find last value before given timestamp in control point list. - * If all values in the control point list come after the given - * timestamp or no values exist, %NULL is returned. - * - * Returns: the found #GSequenceIter or %NULL - */ -static GSequenceIter *gst_interpolation_control_source_find_control_point_iter - (GstInterpolationControlSource * self, GstClockTime timestamp) -{ - GSequenceIter *iter; - - if (!self->priv->values) - return NULL; - - iter = - g_sequence_search (self->priv->values, ×tamp, - (GCompareDataFunc) gst_control_point_find, NULL); - - /* g_sequence_search() returns the iter where timestamp - * would be inserted, i.e. the iter > timestamp, so - * we need to get the previous one. And of course, if - * there is no previous one, we return NULL. */ - if (g_sequence_iter_is_begin (iter)) - return NULL; - - return g_sequence_iter_prev (iter); -} - -/* steps-like (no-)interpolation, default */ -/* just returns the value for the most recent key-frame */ -static inline const GValue * -_interpolate_none_get (GstInterpolationControlSource * self, - GSequenceIter * iter) -{ - const GValue *ret; - - if (iter) { - GstControlPoint *cp = g_sequence_get (iter); - - ret = &cp->value; - } else { - ret = &self->priv->default_value; - } - return ret; -} - -#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \ -static inline const GValue * \ -_interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \ -{ \ - const GValue *ret; \ - \ - if (iter) { \ - GstControlPoint *cp = g_sequence_get (iter); \ - g##type ret_val = g_value_get_##type (&cp->value); \ - \ - if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \ - ret = &self->priv->minimum_value; \ - else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \ - ret = &self->priv->maximum_value; \ - else \ - ret = &cp->value; \ - } else { \ - ret = &self->priv->default_value; \ - } \ - return ret; \ -} - -#define DEFINE_NONE_GET(type,ctype,get_func) \ -static gboolean \ -interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \ -{ \ - const GValue *ret; \ - GSequenceIter *iter; \ - \ - g_mutex_lock (self->lock); \ - \ - iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \ - ret = get_func (self, iter); \ - g_value_copy (ret, value); \ - g_mutex_unlock (self->lock); \ - return TRUE; \ -} \ -\ -static gboolean \ -interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self, \ - GstClockTime timestamp, GstValueArray * value_array) \ -{ \ - gint i; \ - GstClockTime ts = timestamp; \ - GstClockTime next_ts = 0; \ - ctype *values = (ctype *) value_array->values; \ - const GValue *ret_val = NULL; \ - ctype ret = 0; \ - GSequenceIter *iter1 = NULL, *iter2 = NULL; \ - \ - g_mutex_lock (self->lock); \ - for(i = 0; i < value_array->nbsamples; i++) { \ - if (!ret_val || ts >= next_ts) { \ - iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \ - if (!iter1) { \ - if (G_LIKELY (self->priv->values)) \ - iter2 = g_sequence_get_begin_iter (self->priv->values); \ - else \ - iter2 = NULL; \ - } else { \ - iter2 = g_sequence_iter_next (iter1); \ - } \ - \ - if (iter2 && !g_sequence_iter_is_end (iter2)) { \ - GstControlPoint *cp; \ - \ - cp = g_sequence_get (iter2); \ - next_ts = cp->timestamp; \ - } else { \ - next_ts = GST_CLOCK_TIME_NONE; \ - } \ - \ - ret_val = get_func (self, iter1); \ - ret = g_value_get_##type (ret_val); \ - } \ - *values = ret; \ - ts += value_array->sample_interval; \ - values++; \ - } \ - g_mutex_unlock (self->lock); \ - return TRUE; \ -} - -DEFINE_NONE_GET_FUNC_COMPARABLE (int); -DEFINE_NONE_GET (int, gint, _interpolate_none_get_int); -DEFINE_NONE_GET_FUNC_COMPARABLE (uint); -DEFINE_NONE_GET (uint, guint, _interpolate_none_get_uint); -DEFINE_NONE_GET_FUNC_COMPARABLE (long); -DEFINE_NONE_GET (long, glong, _interpolate_none_get_long); -DEFINE_NONE_GET_FUNC_COMPARABLE (ulong); -DEFINE_NONE_GET (ulong, gulong, _interpolate_none_get_ulong); -DEFINE_NONE_GET_FUNC_COMPARABLE (int64); -DEFINE_NONE_GET (int64, gint64, _interpolate_none_get_int64); -DEFINE_NONE_GET_FUNC_COMPARABLE (uint64); -DEFINE_NONE_GET (uint64, guint64, _interpolate_none_get_uint64); -DEFINE_NONE_GET_FUNC_COMPARABLE (float); -DEFINE_NONE_GET (float, gfloat, _interpolate_none_get_float); -DEFINE_NONE_GET_FUNC_COMPARABLE (double); -DEFINE_NONE_GET (double, gdouble, _interpolate_none_get_double); - -DEFINE_NONE_GET (boolean, gboolean, _interpolate_none_get); -DEFINE_NONE_GET (enum, gint, _interpolate_none_get); -DEFINE_NONE_GET (string, const gchar *, _interpolate_none_get); - -static GstInterpolateMethod interpolate_none = { - (GstControlSourceGetValue) interpolate_none_get_int, - (GstControlSourceGetValueArray) interpolate_none_get_int_value_array, - (GstControlSourceGetValue) interpolate_none_get_uint, - (GstControlSourceGetValueArray) interpolate_none_get_uint_value_array, - (GstControlSourceGetValue) interpolate_none_get_long, - (GstControlSourceGetValueArray) interpolate_none_get_long_value_array, - (GstControlSourceGetValue) interpolate_none_get_ulong, - (GstControlSourceGetValueArray) interpolate_none_get_ulong_value_array, - (GstControlSourceGetValue) interpolate_none_get_int64, - (GstControlSourceGetValueArray) interpolate_none_get_int64_value_array, - (GstControlSourceGetValue) interpolate_none_get_uint64, - (GstControlSourceGetValueArray) interpolate_none_get_uint64_value_array, - (GstControlSourceGetValue) interpolate_none_get_float, - (GstControlSourceGetValueArray) interpolate_none_get_float_value_array, - (GstControlSourceGetValue) interpolate_none_get_double, - (GstControlSourceGetValueArray) interpolate_none_get_double_value_array, - (GstControlSourceGetValue) interpolate_none_get_boolean, - (GstControlSourceGetValueArray) interpolate_none_get_boolean_value_array, - (GstControlSourceGetValue) interpolate_none_get_enum, - (GstControlSourceGetValueArray) interpolate_none_get_enum_value_array, - (GstControlSourceGetValue) interpolate_none_get_string, - (GstControlSourceGetValueArray) interpolate_none_get_string_value_array -}; - -/* returns the default value of the property, except for times with specific values */ -/* needed for one-shot events, such as notes and triggers */ -static inline const GValue * -_interpolate_trigger_get (GstInterpolationControlSource * self, - GSequenceIter * iter, GstClockTime timestamp) -{ - GstControlPoint *cp; - - /* check if there is a value at the registered timestamp */ - if (iter) { - cp = g_sequence_get (iter); - if (timestamp == cp->timestamp) { - return &cp->value; - } - } - if (self->priv->nvalues > 0) - return &self->priv->default_value; - else - return NULL; -} - -#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \ -static inline const GValue * \ -_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \ -{ \ - GstControlPoint *cp; \ - \ - /* check if there is a value at the registered timestamp */ \ - if (iter) { \ - cp = g_sequence_get (iter); \ - if (timestamp == cp->timestamp) { \ - g##type ret = g_value_get_##type (&cp->value); \ - if (g_value_get_##type (&self->priv->minimum_value) > ret) \ - return &self->priv->minimum_value; \ - else if (g_value_get_##type (&self->priv->maximum_value) < ret) \ - return &self->priv->maximum_value; \ - else \ - return &cp->value; \ - } \ - } \ - \ - if (self->priv->nvalues > 0) \ - return &self->priv->default_value; \ - else \ - return NULL; \ -} - -#define DEFINE_TRIGGER_GET(type, ctype, get_func) \ -static gboolean \ -interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \ -{ \ - const GValue *ret; \ - GSequenceIter *iter; \ - \ - g_mutex_lock (self->lock); \ - \ - iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \ - ret = get_func (self, iter, timestamp); \ - if (!ret) { \ - g_mutex_unlock (self->lock); \ - return FALSE; \ - } \ - \ - g_value_copy (ret, value); \ - g_mutex_unlock (self->lock); \ - return TRUE; \ -} \ -\ -static gboolean \ -interpolate_trigger_get_##type##_value_array (GstInterpolationControlSource *self, \ - GstClockTime timestamp, GstValueArray * value_array) \ -{ \ - gint i; \ - GstClockTime ts = timestamp; \ - GstClockTime next_ts = 0; \ - ctype *values = (ctype *) value_array->values; \ - const GValue *ret_val = NULL; \ - ctype ret = 0; \ - GSequenceIter *iter1 = NULL, *iter2 = NULL; \ - gboolean triggered = FALSE; \ - \ - g_mutex_lock (self->lock); \ - for(i = 0; i < value_array->nbsamples; i++) { \ - if (!ret_val || ts >= next_ts) { \ - iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \ - if (!iter1) { \ - if (G_LIKELY (self->priv->values)) \ - iter2 = g_sequence_get_begin_iter (self->priv->values); \ - else \ - iter2 = NULL; \ - } else { \ - iter2 = g_sequence_iter_next (iter1); \ - } \ - \ - if (iter2 && !g_sequence_iter_is_end (iter2)) { \ - GstControlPoint *cp; \ - \ - cp = g_sequence_get (iter2); \ - next_ts = cp->timestamp; \ - } else { \ - next_ts = GST_CLOCK_TIME_NONE; \ - } \ - \ - ret_val = get_func (self, iter1, ts); \ - if (!ret_val) { \ - g_mutex_unlock (self->lock); \ - return FALSE; \ - } \ - ret = g_value_get_##type (ret_val); \ - triggered = TRUE; \ - } else if (triggered) { \ - ret_val = get_func (self, iter1, ts); \ - if (!ret_val) { \ - g_mutex_unlock (self->lock); \ - return FALSE; \ - } \ - ret = g_value_get_##type (ret_val); \ - triggered = FALSE; \ - } \ - *values = ret; \ - ts += value_array->sample_interval; \ - values++; \ - } \ - g_mutex_unlock (self->lock); \ - return TRUE; \ -} - -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int); -DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint); -DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long); -DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong); -DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64); -DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64); -DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float); -DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float); -DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double); -DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double); - -DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get); -DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get); -DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get); - -static GstInterpolateMethod interpolate_trigger = { - (GstControlSourceGetValue) interpolate_trigger_get_int, - (GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_uint, - (GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_long, - (GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_ulong, - (GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_int64, - (GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_uint64, - (GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_float, - (GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_double, - (GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_boolean, - (GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_enum, - (GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array, - (GstControlSourceGetValue) interpolate_trigger_get_string, - (GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array -}; - -/* linear interpolation */ -/* smoothes inbetween values */ -#define DEFINE_LINEAR_GET(vtype, round, convert) \ -static inline void \ -_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) \ -{ \ - if (GST_CLOCK_TIME_IS_VALID (timestamp2)) { \ - gdouble slope; \ - \ - slope = ((gdouble) convert (value2) - (gdouble) convert (value1)) / gst_guint64_to_gdouble (timestamp2 - timestamp1); \ - \ - if (round) \ - *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope + 0.5); \ - else \ - *ret = (g##vtype) (convert (value1) + gst_guint64_to_gdouble (timestamp - timestamp1) * slope); \ - } else { \ - *ret = value1; \ - } \ - *ret = CLAMP (*ret, min, max); \ -} \ -\ -static gboolean \ -interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \ -{ \ - g##vtype ret, min, max; \ - GSequenceIter *iter; \ - GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \ - \ - g_mutex_lock (self->lock); \ - \ - min = g_value_get_##vtype (&self->priv->minimum_value); \ - max = g_value_get_##vtype (&self->priv->maximum_value); \ - \ - iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \ - if (iter) { \ - cp1 = g_sequence_get (iter); \ - iter = g_sequence_iter_next (iter); \ - } else { \ - cp.timestamp = G_GUINT64_CONSTANT(0); \ - g_value_init (&cp.value, self->priv->type); \ - g_value_copy (&self->priv->default_value, &cp.value); \ - cp1 = &cp; \ - if (G_LIKELY (self->priv->values)) \ - iter = g_sequence_get_begin_iter (self->priv->values); \ - } \ - if (iter && !g_sequence_iter_is_end (iter)) \ - cp2 = g_sequence_get (iter); \ - \ - _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); \ - g_value_set_##vtype (value, ret); \ - g_mutex_unlock (self->lock); \ - if (cp1 == &cp) \ - g_value_unset (&cp.value); \ - return TRUE; \ -} \ -\ -static gboolean \ -interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \ - GstClockTime timestamp, GstValueArray * value_array) \ -{ \ - gint i; \ - GstClockTime ts = timestamp; \ - GstClockTime next_ts = 0; \ - g##vtype *values = (g##vtype *) value_array->values; \ - GSequenceIter *iter1, *iter2 = NULL; \ - GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \ - g##vtype val1 = 0, val2 = 0, min, max; \ - \ - g_mutex_lock (self->lock); \ - \ - cp.timestamp = G_GUINT64_CONSTANT(0); \ - g_value_init (&cp.value, self->priv->type); \ - g_value_copy (&self->priv->default_value, &cp.value); \ - \ - min = g_value_get_##vtype (&self->priv->minimum_value); \ - max = g_value_get_##vtype (&self->priv->maximum_value); \ - \ - for(i = 0; i < value_array->nbsamples; i++) { \ - if (timestamp >= next_ts) { \ - iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \ - if (!iter1) { \ - cp1 = &cp; \ - if (G_LIKELY (self->priv->values)) \ - iter2 = g_sequence_get_begin_iter (self->priv->values); \ - else \ - iter2 = NULL; \ - } else { \ - cp1 = g_sequence_get (iter1); \ - iter2 = g_sequence_iter_next (iter1); \ - } \ - \ - if (iter2 && !g_sequence_iter_is_end (iter2)) { \ - cp2 = g_sequence_get (iter2); \ - next_ts = cp2->timestamp; \ - } else { \ - next_ts = GST_CLOCK_TIME_NONE; \ - } \ - val1 = g_value_get_##vtype (&cp1->value); \ - if (cp2) \ - val2 = g_value_get_##vtype (&cp2->value); \ - } \ - _interpolate_linear_internal_##vtype (cp1->timestamp, val1, (cp2 ? cp2->timestamp : GST_CLOCK_TIME_NONE), (cp2 ? val2 : 0), ts, min, max, values); \ - ts += value_array->sample_interval; \ - values++; \ - } \ - g_mutex_unlock (self->lock); \ - g_value_unset (&cp.value); \ - return TRUE; \ -} - -DEFINE_LINEAR_GET (int, TRUE, EMPTY); -DEFINE_LINEAR_GET (uint, TRUE, EMPTY); -DEFINE_LINEAR_GET (long, TRUE, EMPTY); -DEFINE_LINEAR_GET (ulong, TRUE, EMPTY); -DEFINE_LINEAR_GET (int64, TRUE, EMPTY); -DEFINE_LINEAR_GET (uint64, TRUE, gst_guint64_to_gdouble); -DEFINE_LINEAR_GET (float, FALSE, EMPTY); -DEFINE_LINEAR_GET (double, FALSE, EMPTY); - -static GstInterpolateMethod interpolate_linear = { - (GstControlSourceGetValue) interpolate_linear_get_int, - (GstControlSourceGetValueArray) interpolate_linear_get_int_value_array, - (GstControlSourceGetValue) interpolate_linear_get_uint, - (GstControlSourceGetValueArray) interpolate_linear_get_uint_value_array, - (GstControlSourceGetValue) interpolate_linear_get_long, - (GstControlSourceGetValueArray) interpolate_linear_get_long_value_array, - (GstControlSourceGetValue) interpolate_linear_get_ulong, - (GstControlSourceGetValueArray) interpolate_linear_get_ulong_value_array, - (GstControlSourceGetValue) interpolate_linear_get_int64, - (GstControlSourceGetValueArray) interpolate_linear_get_int64_value_array, - (GstControlSourceGetValue) interpolate_linear_get_uint64, - (GstControlSourceGetValueArray) interpolate_linear_get_uint64_value_array, - (GstControlSourceGetValue) interpolate_linear_get_float, - (GstControlSourceGetValueArray) interpolate_linear_get_float_value_array, - (GstControlSourceGetValue) interpolate_linear_get_double, - (GstControlSourceGetValueArray) interpolate_linear_get_double_value_array, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL -}; - -/* square interpolation */ - -/* cubic interpolation */ - -/* The following functions implement a natural cubic spline interpolator. - * For details look at http://en.wikipedia.org/wiki/Spline_interpolation - * - * Instead of using a real matrix with n^2 elements for the linear system - * of equations we use three arrays o, p, q to hold the tridiagonal matrix - * as following to save memory: - * - * p[0] q[0] 0 0 0 - * o[1] p[1] q[1] 0 0 - * 0 o[2] p[2] q[2] . - * . . . . . - */ - -#define DEFINE_CUBIC_GET(vtype,round, convert) \ -static void \ -_interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \ -{ \ - gint i, n = self->priv->nvalues; \ - gdouble *o = g_new0 (gdouble, n); \ - gdouble *p = g_new0 (gdouble, n); \ - gdouble *q = g_new0 (gdouble, n); \ - \ - gdouble *h = g_new0 (gdouble, n); \ - gdouble *b = g_new0 (gdouble, n); \ - gdouble *z = g_new0 (gdouble, n); \ - \ - GSequenceIter *iter; \ - GstControlPoint *cp; \ - GstClockTime x, x_next; \ - g##vtype y_prev, y, y_next; \ - \ - /* Fill linear system of equations */ \ - iter = g_sequence_get_begin_iter (self->priv->values); \ - cp = g_sequence_get (iter); \ - x = cp->timestamp; \ - y = g_value_get_##vtype (&cp->value); \ - \ - p[0] = 1.0; \ - \ - iter = g_sequence_iter_next (iter); \ - cp = g_sequence_get (iter); \ - x_next = cp->timestamp; \ - y_next = g_value_get_##vtype (&cp->value); \ - h[0] = gst_guint64_to_gdouble (x_next - x); \ - \ - for (i = 1; i < n-1; i++) { \ - /* Shuffle x and y values */ \ - y_prev = y; \ - x = x_next; \ - y = y_next; \ - iter = g_sequence_iter_next (iter); \ - cp = g_sequence_get (iter); \ - x_next = cp->timestamp; \ - y_next = g_value_get_##vtype (&cp->value); \ - \ - h[i] = gst_guint64_to_gdouble (x_next - x); \ - o[i] = h[i-1]; \ - p[i] = 2.0 * (h[i-1] + h[i]); \ - q[i] = h[i]; \ - b[i] = convert (y_next - y) / h[i] - convert (y - y_prev) / h[i-1]; \ - } \ - p[n-1] = 1.0; \ - \ - /* Use Gauss elimination to set everything below the \ - * diagonal to zero */ \ - for (i = 1; i < n-1; i++) { \ - gdouble a = o[i] / p[i-1]; \ - p[i] -= a * q[i-1]; \ - b[i] -= a * b[i-1]; \ - } \ - \ - /* Solve everything else from bottom to top */ \ - for (i = n-2; i > 0; i--) \ - z[i] = (b[i] - q[i] * z[i+1]) / p[i]; \ - \ - /* Save cache next in the GstControlPoint */ \ - \ - iter = g_sequence_get_begin_iter (self->priv->values); \ - for (i = 0; i < n; i++) { \ - cp = g_sequence_get (iter); \ - cp->cache.cubic.h = h[i]; \ - cp->cache.cubic.z = z[i]; \ - iter = g_sequence_iter_next (iter); \ - } \ - \ - /* Free our temporary arrays */ \ - g_free (o); \ - g_free (p); \ - g_free (q); \ - g_free (h); \ - g_free (b); \ - g_free (z); \ -} \ -\ -static inline void \ -_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) \ -{ \ - if (!self->priv->valid_cache) { \ - _interpolate_cubic_update_cache_##vtype (self); \ - self->priv->valid_cache = TRUE; \ - } \ - \ - if (cp2) { \ - gdouble diff1, diff2; \ - gdouble out; \ - \ - diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \ - diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \ - \ - out = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \ - out += (convert (value2) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \ - out += (convert (value1) / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \ - \ - if (round) \ - *ret = (g##vtype) (out + 0.5); \ - else \ - *ret = (g##vtype) out; \ - } \ - else { \ - *ret = value1; \ - } \ - *ret = CLAMP (*ret, min, max); \ -} \ -\ -static gboolean \ -interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \ -{ \ - g##vtype ret, min, max; \ - GSequenceIter *iter; \ - GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \ - \ - if (self->priv->nvalues <= 2) \ - return interpolate_linear_get_##vtype (self, timestamp, value); \ - \ - g_mutex_lock (self->lock); \ - \ - min = g_value_get_##vtype (&self->priv->minimum_value); \ - max = g_value_get_##vtype (&self->priv->maximum_value); \ - \ - iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \ - if (iter) { \ - cp1 = g_sequence_get (iter); \ - iter = g_sequence_iter_next (iter); \ - } else { \ - cp.timestamp = G_GUINT64_CONSTANT(0); \ - g_value_init (&cp.value, self->priv->type); \ - g_value_copy (&self->priv->default_value, &cp.value); \ - cp1 = &cp; \ - if (G_LIKELY (self->priv->values)) \ - iter = g_sequence_get_begin_iter (self->priv->values); \ - } \ - if (iter && !g_sequence_iter_is_end (iter)) \ - cp2 = g_sequence_get (iter); \ - \ - _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); \ - g_value_set_##vtype (value, ret); \ - g_mutex_unlock (self->lock); \ - if (cp1 == &cp) \ - g_value_unset (&cp.value); \ - return TRUE; \ -} \ -\ -static gboolean \ -interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \ - GstClockTime timestamp, GstValueArray * value_array) \ -{ \ - gint i; \ - GstClockTime ts = timestamp; \ - GstClockTime next_ts = 0; \ - g##vtype *values = (g##vtype *) value_array->values; \ - GSequenceIter *iter1, *iter2 = NULL; \ - GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \ - g##vtype val1 = 0, val2 = 0, min, max; \ - \ - if (self->priv->nvalues <= 2) \ - return interpolate_linear_get_##vtype##_value_array (self, timestamp, value_array); \ - \ - g_mutex_lock (self->lock); \ - \ - cp.timestamp = G_GUINT64_CONSTANT(0); \ - g_value_init (&cp.value, self->priv->type); \ - g_value_copy (&self->priv->default_value, &cp.value); \ - \ - min = g_value_get_##vtype (&self->priv->minimum_value); \ - max = g_value_get_##vtype (&self->priv->maximum_value); \ - \ - for(i = 0; i < value_array->nbsamples; i++) { \ - if (timestamp >= next_ts) { \ - iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \ - if (!iter1) { \ - cp1 = &cp; \ - if (G_LIKELY (self->priv->values)) \ - iter2 = g_sequence_get_begin_iter (self->priv->values); \ - else \ - iter2 = NULL; \ - } else { \ - cp1 = g_sequence_get (iter1); \ - iter2 = g_sequence_iter_next (iter1); \ - } \ - \ - if (iter2 && !g_sequence_iter_is_end (iter2)) { \ - cp2 = g_sequence_get (iter2); \ - next_ts = cp2->timestamp; \ - } else { \ - next_ts = GST_CLOCK_TIME_NONE; \ - } \ - val1 = g_value_get_##vtype (&cp1->value); \ - if (cp2) \ - val2 = g_value_get_##vtype (&cp2->value); \ - } \ - _interpolate_cubic_get_##vtype (self, cp1, val1, cp2, val2, timestamp, min, max, values); \ - ts += value_array->sample_interval; \ - values++; \ - } \ - g_mutex_unlock (self->lock); \ - g_value_unset (&cp.value); \ - return TRUE; \ -} - -DEFINE_CUBIC_GET (int, TRUE, EMPTY); -DEFINE_CUBIC_GET (uint, TRUE, EMPTY); -DEFINE_CUBIC_GET (long, TRUE, EMPTY); -DEFINE_CUBIC_GET (ulong, TRUE, EMPTY); -DEFINE_CUBIC_GET (int64, TRUE, EMPTY); -DEFINE_CUBIC_GET (uint64, TRUE, gst_guint64_to_gdouble); -DEFINE_CUBIC_GET (float, FALSE, EMPTY); -DEFINE_CUBIC_GET (double, FALSE, EMPTY); - -static GstInterpolateMethod interpolate_cubic = { - (GstControlSourceGetValue) interpolate_cubic_get_int, - (GstControlSourceGetValueArray) interpolate_cubic_get_int_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_uint, - (GstControlSourceGetValueArray) interpolate_cubic_get_uint_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_long, - (GstControlSourceGetValueArray) interpolate_cubic_get_long_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_ulong, - (GstControlSourceGetValueArray) interpolate_cubic_get_ulong_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_int64, - (GstControlSourceGetValueArray) interpolate_cubic_get_int64_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_uint64, - (GstControlSourceGetValueArray) interpolate_cubic_get_uint64_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_float, - (GstControlSourceGetValueArray) interpolate_cubic_get_float_value_array, - (GstControlSourceGetValue) interpolate_cubic_get_double, - (GstControlSourceGetValueArray) interpolate_cubic_get_double_value_array, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL, - (GstControlSourceGetValue) NULL, - (GstControlSourceGetValueArray) NULL -}; - -/* register all interpolation methods */ -GstInterpolateMethod *priv_gst_interpolation_methods[] = { - &interpolate_none, - &interpolate_trigger, - &interpolate_linear, - &interpolate_cubic, - &interpolate_cubic -}; - -guint priv_gst_num_interpolation_methods = -G_N_ELEMENTS (priv_gst_interpolation_methods); |