From: Sebastian Dröge Date: Wed, 6 Jun 2007 14:01:56 +0000 (+0000) Subject: libs/gst/controller/: Factor out the 'set' logic into gst_controller_set_unlocked... X-Git-Tag: RELEASE-0_10_14~109 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c478fb4813c7b74a68e7ba5995001fad3a741536;p=platform%2Fupstream%2Fgstreamer.git libs/gst/controller/: Factor out the 'set' logic into gst_controller_set_unlocked for the gst_controller_set and gst_... Original commit message from CVS: * libs/gst/controller/gstcontroller.c: (gst_controlled_property_set_interpolation_mode), (gst_controlled_property_prepend_default), (gst_controlled_property_new), (gst_controller_set_unlocked), (gst_controller_set), (gst_controller_set_from_list), (gst_controller_unset), (gst_controller_unset_all): * libs/gst/controller/gstcontrollerprivate.h: * libs/gst/controller/gstinterpolation.c: Factor out the 'set' logic into gst_controller_set_unlocked for the gst_controller_set and gst_controller_set_from_list functions. To make life of the interpolators easier always add a control point at timestamp zero with the default value. In the linear interpolator make things more obvious by better variable naming (slope). Implement cubic interpolation mode (by using a natural cubic spline) and map the quadratic interpolation mode to this too (as quadratic doesn't make much sense, see discussion on the list). * tests/check/libs/controller.c: (GST_START_TEST), (gst_controller_suite): Add unit test for the cubic interpolation mode and check everywhere if the interpolation mode could be set as expected. --- diff --git a/ChangeLog b/ChangeLog index b14d172..a45286d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2007-06-06 Sebastian Dröge + + * libs/gst/controller/gstcontroller.c: + (gst_controlled_property_set_interpolation_mode), + (gst_controlled_property_prepend_default), + (gst_controlled_property_new), (gst_controller_set_unlocked), + (gst_controller_set), (gst_controller_set_from_list), + (gst_controller_unset), (gst_controller_unset_all): + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + Factor out the 'set' logic into gst_controller_set_unlocked for the + gst_controller_set and gst_controller_set_from_list functions. + + To make life of the interpolators easier always add a control point + at timestamp zero with the default value. + + In the linear interpolator make things more obvious by better variable + naming (slope). + + Implement cubic interpolation mode (by using a natural cubic spline) + and map the quadratic interpolation mode to this too (as quadratic + doesn't make much sense, see discussion on the list). + + * tests/check/libs/controller.c: (GST_START_TEST), + (gst_controller_suite): + Add unit test for the cubic interpolation mode and check everywhere + if the interpolation mode could be set as expected. + 2007-06-06 Tim-Philipp Müller * gst/gstparamspecs.c: (gst_param_spec_fraction_get_type): diff --git a/libs/gst/controller/gstcontroller.c b/libs/gst/controller/gstcontroller.c index 10de02b..d2b5008 100644 --- a/libs/gst/controller/gstcontroller.c +++ b/libs/gst/controller/gstcontroller.c @@ -1,6 +1,7 @@ /* GStreamer * * Copyright (C) <2005> Stefan Kost + * Copyright (C) 2007 Sebastian Dröge * * gstcontroller.c: dynamic parameter control subsystem * @@ -240,21 +241,40 @@ gst_controlled_property_set_interpolation_mode (GstControlledProperty * self, self->get = NULL; self->get_value_array = NULL; } - if (!self->get) { /* || !self->get_value_array) */ + if (!self->get || !self->get_value_array) { GST_WARNING ("incomplete implementation for type %lu/%lu:'%s'/'%s'", self->type, self->base, g_type_name (self->type), g_type_name (self->base)); res = FALSE; } + if (mode == GST_INTERPOLATE_QUADRATIC) { + GST_WARNING ("Quadratic interpolation mode is deprecated, using cubic" + "interpolation mode"); + } } else { /* TODO shouldn't this also get a GstInterpolateMethod *user_method for the case mode==GST_INTERPOLATE_USER */ res = FALSE; } + + self->valid_cache = FALSE; + return (res); } +static void +gst_controlled_property_prepend_default (GstControlledProperty * prop) +{ + GstControlPoint *cp = g_new0 (GstControlPoint, 1); + + cp->timestamp = 0; + g_value_init (&cp->value, prop->type); + g_value_copy (&prop->default_value, &cp->value); + prop->values = g_list_prepend (prop->values, cp); + prop->nvalues++; +} + /* * gst_controlled_property_new: * @object: for which object the controlled property should be set up @@ -374,13 +394,14 @@ gst_controlled_property_new (GObject * object, const gchar * name) GST_WARNING ("incomplete implementation for paramspec type '%s'", G_PARAM_SPEC_TYPE_NAME (pspec)); } - /* TODO what about adding a control point with timestamp=0 and value=default - * a bit easier for interpolators, example: - * first timestamp is at 5 - * requested value if for timestamp=3 - * LINEAR and Co. would need to interpolate from default value to value - * at timestamp 5 - */ + + prop->valid_cache = FALSE; + prop->nvalues = 0; + + /* Add a control point at timestamp 0 with the default value + * to make the life of interpolators easier. */ + gst_controlled_property_prepend_default (prop); + signal_name = g_alloca (8 + 1 + strlen (name)); g_sprintf (signal_name, "notify::%s", name); prop->notify_handler_id = @@ -718,6 +739,42 @@ gst_controller_remove_properties (GstController * self, ...) return (res); } +static gboolean +gst_controller_set_unlocked (GstController * self, GstControlledProperty * prop, + GstClockTime timestamp, GValue * value) +{ + gboolean res = FALSE; + + if (G_VALUE_TYPE (value) == prop->type) { + GstControlPoint *cp; + GList *node; + + /* check if a control point for the timestamp already exists */ + if ((node = g_list_find_custom (prop->values, ×tamp, + gst_control_point_find))) { + cp = node->data; + g_value_reset (&cp->value); + g_value_copy (value, &cp->value); + } else { + /* create a new GstControlPoint */ + cp = g_new0 (GstControlPoint, 1); + cp->timestamp = timestamp; + g_value_init (&cp->value, prop->type); + g_value_copy (value, &cp->value); + /* and sort it into the prop->values list */ + prop->values = + g_list_insert_sorted (prop->values, cp, gst_control_point_compare); + prop->nvalues++; + } + prop->valid_cache = FALSE; + res = TRUE; + } else { + GST_WARNING ("incompatible value type for property '%s'", prop->name); + } + + return res; +} + /** * gst_controller_set: * @self: the controller object which handles the properties @@ -743,30 +800,7 @@ gst_controller_set (GstController * self, gchar * property_name, g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, property_name))) { - if (G_VALUE_TYPE (value) == prop->type) { - GstControlPoint *cp; - GList *node; - - /* check if a control point for the timestamp already exists */ - if ((node = g_list_find_custom (prop->values, ×tamp, - gst_control_point_find))) { - cp = node->data; - g_value_reset (&cp->value); - g_value_copy (value, &cp->value); - } else { - /* create a new GstControlPoint */ - cp = g_new0 (GstControlPoint, 1); - cp->timestamp = timestamp; - g_value_init (&cp->value, prop->type); - g_value_copy (value, &cp->value); - /* and sort it into the prop->values list */ - prop->values = - g_list_insert_sorted (prop->values, cp, gst_control_point_compare); - } - res = TRUE; - } else { - GST_WARNING ("incompatible value type for property '%s'", prop->name); - } + res = gst_controller_set_unlocked (self, prop, timestamp, value); } g_mutex_unlock (self->lock); @@ -792,7 +826,6 @@ gst_controller_set_from_list (GstController * self, gchar * property_name, GstControlledProperty *prop; GSList *node; GstTimedValue *tv; - GstControlPoint *cp; g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE); g_return_val_if_fail (property_name, FALSE); @@ -801,22 +834,15 @@ gst_controller_set_from_list (GstController * self, gchar * property_name, if ((prop = gst_controller_find_controlled_property (self, property_name))) { for (node = timedvalues; node; node = g_slist_next (node)) { tv = node->data; - if (G_VALUE_TYPE (&tv->value) == prop->type) { - if (GST_CLOCK_TIME_IS_VALID (tv->timestamp)) { - cp = g_new0 (GstControlPoint, 1); - cp->timestamp = tv->timestamp; - g_value_init (&cp->value, prop->type); - g_value_copy (&tv->value, &cp->value); - prop->values = - g_list_insert_sorted (prop->values, cp, - gst_control_point_compare); - res = TRUE; - } else { - g_warning ("GstTimedValued with invalid timestamp passed to %s " - "for property '%s'", GST_FUNCTION, property_name); - } + if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) { + GST_WARNING ("GstTimedValued with invalid timestamp passed to %s " + "for property '%s'", GST_FUNCTION, property_name); + } else if (!G_IS_VALUE (&tv->value)) { + GST_WARNING ("GstTimedValued with invalid value passed to %s " + "for property '%s'", GST_FUNCTION, property_name); } else { - GST_WARNING ("incompatible value type for property '%s'", prop->name); + res = + gst_controller_set_unlocked (self, prop, tv->timestamp, &tv->value); } } } @@ -854,10 +880,20 @@ gst_controller_unset (GstController * self, gchar * property_name, /* check if a control point for the timestamp exists */ if ((node = g_list_find_custom (prop->values, ×tamp, gst_control_point_find))) { - if (node == prop->last_requested_value) - prop->last_requested_value = NULL; - gst_control_point_free (node->data); /* free GstControlPoint */ - prop->values = g_list_delete_link (prop->values, node); + GstControlPoint *cp = node->data; + + if (cp->timestamp == 0) { + /* Restore the default node */ + g_value_reset (&cp->value); + g_value_copy (&prop->default_value, &cp->value); + } else { + if (node == prop->last_requested_value) + prop->last_requested_value = NULL; + gst_control_point_free (node->data); /* free GstControlPoint */ + prop->values = g_list_delete_link (prop->values, node); + prop->nvalues--; + } + prop->valid_cache = FALSE; res = TRUE; } } @@ -893,6 +929,12 @@ gst_controller_unset_all (GstController * self, gchar * property_name) g_list_free (prop->values); prop->last_requested_value = NULL; prop->values = NULL; + prop->nvalues = 0; + prop->valid_cache = FALSE; + + /* Insert the default control point again */ + gst_controlled_property_prepend_default (prop); + res = TRUE; } g_mutex_unlock (self->lock); @@ -1146,8 +1188,8 @@ gst_controller_get_value_array (GstController * self, GstClockTime timestamp, * * Sets the given interpolation mode on the given property. * - * Quadratic, cubic and user interpolation is not yet available. - * + * User interpolation is not yet available and quadratic interpolation + * is deprecated and maps to cubic interpolation. * * Returns: %TRUE if the property is handled by the controller, %FALSE otherwise */ diff --git a/libs/gst/controller/gstcontrollerprivate.h b/libs/gst/controller/gstcontrollerprivate.h index 398ae67..0bd4cde 100644 --- a/libs/gst/controller/gstcontrollerprivate.h +++ b/libs/gst/controller/gstcontrollerprivate.h @@ -81,6 +81,14 @@ typedef struct _GstControlPoint /* internal fields */ + /* Caches for the interpolators */ + union { + struct { + gdouble h; + gdouble z; + } cubic; + } cache; + } GstControlPoint; /** @@ -106,10 +114,9 @@ typedef struct _GstControlledProperty InterpolateGetValueArray get_value_array; GList *values; /* List of GstControlPoint */ + gint nvalues; /* Number of control points */ GList *last_requested_value; /* last search result, can be used for incremental searches */ - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; + gboolean valid_cache; } GstControlledProperty; #define GST_CONTROLLED_PROPERTY(obj) ((GstControlledProperty *)(obj)) diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c index 76fa1e8..f1c6d93 100644 --- a/libs/gst/controller/gstinterpolation.c +++ b/libs/gst/controller/gstinterpolation.c @@ -1,6 +1,7 @@ /* GStreamer * * Copyright (C) <2005> Stefan Kost + * Copyright (C) 2007 Sebastian Dröge * * gstinterpolation.c: Interpolation methods for dynamic properties * @@ -284,17 +285,16 @@ _interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime times \ cp1 = node->data; \ if ((node = g_list_next (node))) { \ - gdouble timediff,valuediff; \ + gdouble slope; \ g##type value1,value2; \ \ cp2 = node->data; \ \ - timediff = gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \ value1 = g_value_get_##type (&cp1->value); \ value2 = g_value_get_##type (&cp2->value); \ - valuediff = (gdouble) (value2 - value1); \ + slope = (gdouble) (value2 - value1) / gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \ \ - return ((g##type) (value1 + valuediff * (gst_guint64_to_gdouble (timestamp - cp1->timestamp) / timediff))); \ + return ((g##type) (value1 + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope)); \ } \ else { \ return (g_value_get_##type (&cp1->value)); \ @@ -360,13 +360,205 @@ static GstInterpolateMethod interpolate_linear = { /* 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(type) \ +static void \ +_interpolate_cubic_update_cache_##type (GstControlledProperty *prop) \ +{ \ + gint i, n = prop->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); \ + \ + GList *node; \ + GstControlPoint *cp; \ + GstClockTime x_prev, x, x_next; \ + g##type y_prev, y, y_next; \ + \ + /* Fill linear system of equations */ \ + node = prop->values; \ + cp = node->data; \ + x = cp->timestamp; \ + y = g_value_get_##type (&cp->value); \ + \ + p[0] = 1.0; \ + \ + node = node->next; \ + cp = node->data; \ + x_next = cp->timestamp; \ + y_next = g_value_get_##type (&cp->value); \ + h[0] = x_next - x; \ + \ + for (i = 1; i < n-1; i++) { \ + /* Shuffle x and y values */ \ + x_prev = x; \ + y_prev = y; \ + x = x_next; \ + y = y_next; \ + node = node->next; \ + cp = node->data; \ + x_next = cp->timestamp; \ + y_next = g_value_get_##type (&cp->value); \ + \ + h[i] = x_next - x; \ + o[i] = h[i-1]; \ + p[i] = 2.0 * (h[i-1] + h[i]); \ + q[i] = h[i]; \ + b[i] = (y_next - y) / h[i] - (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 */ \ + \ + node = prop->values; \ + for (i = 0; i < n; i++) { \ + cp = node->data; \ + cp->cache.cubic.h = h[i]; \ + cp->cache.cubic.z = z[i]; \ + node = node->next; \ + } \ + \ + /* Free our temporary arrays */ \ + g_free (o); \ + g_free (p); \ + g_free (q); \ + g_free (h); \ + g_free (b); \ + g_free (z); \ +} \ +\ +static g##type \ +_interpolate_cubic_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ +{ \ + GList *node; \ + \ + if (prop->nvalues <= 2) \ + return _interpolate_linear_get_##type (prop, timestamp); \ + \ + if (!prop->valid_cache) { \ + _interpolate_cubic_update_cache_##type (prop); \ + prop->valid_cache = TRUE; \ + } \ + \ + if ((node = gst_controlled_property_find_control_point_node (prop, timestamp))) { \ + GstControlPoint *cp1, *cp2; \ + \ + cp1 = node->data; \ + if ((node = g_list_next (node))) { \ + gdouble diff1, diff2; \ + g##type value1,value2; \ + gdouble ret; \ + \ + cp2 = node->data; \ + \ + value1 = g_value_get_##type (&cp1->value); \ + value2 = g_value_get_##type (&cp2->value); \ + \ + diff1 = gst_guint64_to_gdouble (timestamp - cp1->timestamp); \ + diff2 = gst_guint64_to_gdouble (cp2->timestamp - timestamp); \ + \ + ret = (cp2->cache.cubic.z * diff1 * diff1 * diff1 + cp1->cache.cubic.z * diff2 * diff2 * diff2) / cp1->cache.cubic.h; \ + ret += (value2 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \ + ret += (value1 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \ + \ + return (g##type) ret; \ + } \ + else { \ + return (g_value_get_##type (&cp1->value)); \ + } \ + } \ + return (g_value_get_##type (&prop->default_value)); \ +} \ +\ +static GValue * \ +interpolate_cubic_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ +{ \ + g_value_set_##type (&prop->result_value,_interpolate_cubic_get_##type (prop,timestamp)); \ + return (&prop->result_value); \ +} \ +\ +static gboolean \ +interpolate_cubic_get_##type##_value_array (GstControlledProperty * prop, \ + GstClockTime timestamp, GstValueArray * value_array) \ +{ \ + gint i; \ + GstClockTime ts = timestamp; \ + g##type *values = (g##type *) value_array->values; \ + \ + for(i = 0; i < value_array->nbsamples; i++) { \ + *values = _interpolate_cubic_get_##type (prop, ts); \ + ts += value_array->sample_interval; \ + values++; \ + } \ + return (TRUE); \ +} + +DEFINE_CUBIC_GET (int); + +DEFINE_CUBIC_GET (uint); +DEFINE_CUBIC_GET (long); + +DEFINE_CUBIC_GET (ulong); +DEFINE_CUBIC_GET (float); +DEFINE_CUBIC_GET (double); + +static GstInterpolateMethod interpolate_cubic = { + interpolate_cubic_get_int, + interpolate_cubic_get_int_value_array, + interpolate_cubic_get_uint, + interpolate_cubic_get_uint_value_array, + interpolate_cubic_get_long, + interpolate_cubic_get_long_value_array, + interpolate_cubic_get_ulong, + interpolate_cubic_get_ulong_value_array, + interpolate_cubic_get_float, + interpolate_cubic_get_float_value_array, + interpolate_cubic_get_double, + interpolate_cubic_get_double_value_array, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + /* register all interpolation methods */ GstInterpolateMethod *interpolation_methods[] = { &interpolate_none, &interpolate_trigger, &interpolate_linear, - NULL, - NULL + &interpolate_cubic, + &interpolate_cubic }; guint num_interpolation_methods = G_N_ELEMENTS (interpolation_methods); diff --git a/tests/check/libs/controller.c b/tests/check/libs/controller.c index dd52ed2..b6cdc06 100644 --- a/tests/check/libs/controller.c +++ b/tests/check/libs/controller.c @@ -524,7 +524,8 @@ GST_START_TEST (controller_interpolate_none) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_NONE)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -567,8 +568,8 @@ GST_START_TEST (controller_interpolate_trigger) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", - GST_INTERPOLATE_TRIGGER); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_TRIGGER)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -612,7 +613,8 @@ GST_START_TEST (controller_interpolate_linear) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_LINEAR); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_LINEAR)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -638,6 +640,63 @@ GST_START_TEST (controller_interpolate_linear) GST_END_TEST; +/* test timed value handling with cubic interpolation */ +GST_START_TEST (controller_interpolate_cubic) +{ + GstController *ctrl; + GstElement *elem; + gboolean res; + GValue val_double = { 0, }; + + gst_controller_init (NULL, NULL); + + elem = gst_element_factory_make ("testmonosource", "test_source"); + + /* that property should exist and should be controllable */ + ctrl = gst_controller_new (G_OBJECT (elem), "double", NULL); + fail_unless (ctrl != NULL, NULL); + + /* set interpolation mode */ + fail_unless (gst_controller_set_interpolation_mode (ctrl, "double", + GST_INTERPOLATE_CUBIC)); + + /* set control values */ + g_value_init (&val_double, G_TYPE_DOUBLE); + g_value_set_double (&val_double, 0.0); + res = gst_controller_set (ctrl, "double", 0 * GST_SECOND, &val_double); + fail_unless (res, NULL); + g_value_set_double (&val_double, 5.0); + res = gst_controller_set (ctrl, "double", 1 * GST_SECOND, &val_double); + fail_unless (res, NULL); + g_value_set_double (&val_double, 2.0); + res = gst_controller_set (ctrl, "double", 2 * GST_SECOND, &val_double); + fail_unless (res, NULL); + g_value_set_double (&val_double, 8.0); + res = gst_controller_set (ctrl, "double", 4 * GST_SECOND, &val_double); + fail_unless (res, NULL); + + /* now pull in values for some timestamps */ + gst_controller_sync_values (ctrl, 0 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 0.0, NULL); + gst_controller_sync_values (ctrl, 1 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 5.0, NULL); + gst_controller_sync_values (ctrl, 2 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 2.0, NULL); + gst_controller_sync_values (ctrl, 3 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double > 2.0 && + GST_TEST_MONO_SOURCE (elem)->val_double < 8.0, NULL); + gst_controller_sync_values (ctrl, 4 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 8.0, NULL); + gst_controller_sync_values (ctrl, 5 * GST_SECOND); + fail_unless (GST_TEST_MONO_SOURCE (elem)->val_double == 8.0, NULL); + + GST_INFO ("controller->ref_count=%d", G_OBJECT (ctrl)->ref_count); + g_object_unref (ctrl); + gst_object_unref (elem); +} + +GST_END_TEST; + /* make sure we don't crash when someone sets an unsupported interpolation * mode */ GST_START_TEST (controller_interpolate_unimplemented) @@ -653,16 +712,9 @@ GST_START_TEST (controller_interpolate_unimplemented) ctrl = gst_controller_new (G_OBJECT (elem), "ulong", NULL); fail_unless (ctrl != NULL, NULL); - /* set unsupported interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_CUBIC); - - /* set another unsupported interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", - GST_INTERPOLATE_QUADRATIC); - /* set completely bogus interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", - (GstInterpolateMode) 93871); + fail_if (gst_controller_set_interpolation_mode (ctrl, "ulong", + (GstInterpolateMode) 93871)); g_object_unref (ctrl); gst_object_unref (elem); @@ -687,7 +739,8 @@ GST_START_TEST (controller_unset) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_NONE)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -743,7 +796,8 @@ GST_START_TEST (controller_unset_all) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_NONE); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_NONE)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -792,7 +846,8 @@ GST_START_TEST (controller_live) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_LINEAR); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_LINEAR)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -866,7 +921,8 @@ GST_START_TEST (controller_misc) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_LINEAR); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_LINEAR)); /* set control value */ tval = g_new0 (GstTimedValue, 1); @@ -876,7 +932,7 @@ GST_START_TEST (controller_misc) list = g_slist_append (list, tval); - ASSERT_WARNING (fail_if (gst_controller_set_from_list (ctrl, "ulong", list))); + fail_if (gst_controller_set_from_list (ctrl, "ulong", list)); /* try again with a valid stamp, should work now */ tval->timestamp = 0; @@ -989,7 +1045,8 @@ GST_START_TEST (controller_interpolate_linear_value_array) fail_unless (ctrl != NULL, NULL); /* set interpolation mode */ - gst_controller_set_interpolation_mode (ctrl, "ulong", GST_INTERPOLATE_LINEAR); + fail_unless (gst_controller_set_interpolation_mode (ctrl, "ulong", + GST_INTERPOLATE_LINEAR)); /* set control values */ g_value_init (&val_ulong, G_TYPE_ULONG); @@ -1041,6 +1098,7 @@ gst_controller_suite (void) tcase_add_test (tc, controller_interpolate_none); tcase_add_test (tc, controller_interpolate_trigger); tcase_add_test (tc, controller_interpolate_linear); + tcase_add_test (tc, controller_interpolate_cubic); tcase_add_test (tc, controller_interpolate_unimplemented); tcase_add_test (tc, controller_unset); tcase_add_test (tc, controller_unset_all);