From: Sebastian Dröge Date: Thu, 17 May 2007 17:05:36 +0000 (+0000) Subject: libs/gst/controller/: Add a new private GstControlPoint struct which "inherits" from X-Git-Tag: RELEASE-0_10_13~41 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b92d7dc076cce5b0e96d1c611bfbbd19574d0c55;p=platform%2Fupstream%2Fgstreamer.git libs/gst/controller/: Add a new private GstControlPoint struct which "inherits" from Original commit message from CVS: reviewed by: Stefan Kost * libs/gst/controller/gstcontroller.c: (gst_control_point_compare), (gst_control_point_find), (gst_controlled_property_new), (gst_control_point_free), (gst_controlled_property_free), (gst_controller_set), (gst_controller_set_from_list), (gst_controller_unset), (gst_controller_unset_all), (gst_controller_sync_values): * libs/gst/controller/gstcontroller.h: * libs/gst/controller/gstcontrollerprivate.h: * libs/gst/controller/gstinterpolation.c: (gst_controlled_property_find_control_point_node), (interpolate_none_get), (interpolate_trigger_get): Add a new private GstControlPoint struct which "inherits" from GstTimedValue to allow different interpolators to store internal values next to each control point. From the outside everything is still a GstControlPoint so we don't loose binary compatibility. Also fixup all the GValue handling to not leak GValues or list nodes. * tests/check/libs/controller.c: (GST_START_TEST): Free the list nodes and GValues in the controller_misc test. --- diff --git a/ChangeLog b/ChangeLog index 2e56000..f7a5818 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2007-05-17 Sebastian Dröge + + reviewed by: Stefan Kost + + * libs/gst/controller/gstcontroller.c: (gst_control_point_compare), + (gst_control_point_find), (gst_controlled_property_new), + (gst_control_point_free), (gst_controlled_property_free), + (gst_controller_set), (gst_controller_set_from_list), + (gst_controller_unset), (gst_controller_unset_all), + (gst_controller_sync_values): + * libs/gst/controller/gstcontroller.h: + * libs/gst/controller/gstcontrollerprivate.h: + * libs/gst/controller/gstinterpolation.c: + (gst_controlled_property_find_control_point_node), + (interpolate_none_get), (interpolate_trigger_get): + Add a new private GstControlPoint struct which "inherits" from + GstTimedValue to allow different interpolators to store internal + values next to each control point. From the outside everything is + still a GstControlPoint so we don't loose binary compatibility. + Also fixup all the GValue handling to not leak GValues or list nodes. + * tests/check/libs/controller.c: (GST_START_TEST): + Free the list nodes and GValues in the controller_misc test. + 2007-05-17 Edward Hervey * gst/gstsegment.c: diff --git a/libs/gst/controller/gstcontroller.c b/libs/gst/controller/gstcontroller.c index ce2e86b..3930ed2 100644 --- a/libs/gst/controller/gstcontroller.c +++ b/libs/gst/controller/gstcontroller.c @@ -92,7 +92,7 @@ struct _GstControllerPrivate /* imports from gst-interpolation.c */ extern GList - * gst_controlled_property_find_timed_value_node (GstControlledProperty * + * gst_controlled_property_find_control_point_node (GstControlledProperty * prop, GstClockTime timestamp); extern GstInterpolateMethod *interpolation_methods[]; extern guint num_interpolation_methods; @@ -127,18 +127,18 @@ on_object_controlled_property_changed (const GObject * object, GParamSpec * arg, /* helper */ /* - * gst_timed_value_compare: - * @p1: a pointer to a #GstTimedValue - * @p2: a pointer to a #GstTimedValue + * gst_control_point_compare: + * @p1: a pointer to a #GstControlPoint + * @p2: a pointer to a #GstControlPoint * - * Compare function for g_list operations that operates on two #GstTimedValue + * Compare function for g_list operations that operates on two #GstControlPoint * parameters. */ static gint -gst_timed_value_compare (gconstpointer p1, gconstpointer p2) +gst_control_point_compare (gconstpointer p1, gconstpointer p2) { - GstClockTime ct1 = ((GstTimedValue *) p1)->timestamp; - GstClockTime ct2 = ((GstTimedValue *) p2)->timestamp; + GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp; + GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp; return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); /* this does not produce an gint :( @@ -147,17 +147,17 @@ gst_timed_value_compare (gconstpointer p1, gconstpointer p2) } /* - * gst_timed_value_find: - * @p1: a pointer to a #GstTimedValue + * gst_control_point_find: + * @p1: a pointer to a #GstControlPoint * @p2: a pointer to a #GstClockTime * - * Compare function for g_list operations that operates on a #GstTimedValue and + * Compare function for g_list operations that operates on a #GstControlPoint and * a #GstClockTime. */ static gint -gst_timed_value_find (gconstpointer p1, gconstpointer p2) +gst_control_point_find (gconstpointer p1, gconstpointer p2) { - GstClockTime ct1 = ((GstTimedValue *) p1)->timestamp; + GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp; GstClockTime ct2 = *(GstClockTime *) p2; return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1)); @@ -373,7 +373,7 @@ 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 timed-val with timestamp=0 and value=default + /* 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 @@ -398,6 +398,23 @@ Error: } /* + * gst_control_point_free: + * @prop: the object to free + * + * Private method which frees all data allocated by a #GstControlPoint + * instance. + */ +static void +gst_control_point_free (GstControlPoint * cp) +{ + g_return_if_fail (cp); + + g_value_unset (&cp->value); + g_free (cp); +} + +/* + * gst_controlled_property_free: * @prop: the object to free * @@ -407,12 +424,15 @@ Error: static void gst_controlled_property_free (GstControlledProperty * prop) { - GList *node; - - for (node = prop->values; node; node = g_list_next (node)) { - g_free (node->data); - } + g_list_foreach (prop->values, (GFunc) gst_control_point_free, NULL); g_list_free (prop->values); + + g_value_unset (&prop->default_value); + g_value_unset (&prop->result_value); + g_value_unset (&prop->last_value.value); + if (G_IS_VALUE (&prop->live_value.value)) + g_value_unset (&prop->live_value.value); + g_free (prop); } @@ -723,22 +743,24 @@ 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) { - GstTimedValue *tv; + GstControlPoint *cp; GList *node; - /* check if a timed_value for the timestamp already exists */ + /* check if a control point for the timestamp already exists */ if ((node = g_list_find_custom (prop->values, ×tamp, - gst_timed_value_find))) { - tv = node->data; - memcpy (&tv->value, value, sizeof (GValue)); + gst_control_point_find))) { + cp = node->data; + g_value_reset (&cp->value); + g_value_copy (value, &cp->value); } else { - /* create a new GstTimedValue */ - tv = g_new (GstTimedValue, 1); - tv->timestamp = timestamp; - memcpy (&tv->value, value, sizeof (GValue)); + /* 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, tv, gst_timed_value_compare); + g_list_insert_sorted (prop->values, cp, gst_control_point_compare); } res = TRUE; } else { @@ -769,6 +791,7 @@ 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); @@ -779,9 +802,13 @@ gst_controller_set_from_list (GstController * self, gchar * property_name, tv = node->data; if (G_VALUE_TYPE (&tv->value) == prop->type) { if (GST_CLOCK_TIME_IS_VALID (tv->timestamp)) { - /* TODO copy the timed value or just link in? */ + 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, tv, gst_timed_value_compare); + g_list_insert_sorted (prop->values, cp, + gst_control_point_compare); res = TRUE; } else { g_warning ("GstTimedValued with invalid timestamp passed to %s " @@ -823,10 +850,10 @@ gst_controller_unset (GstController * self, gchar * property_name, if ((prop = gst_controller_find_controlled_property (self, property_name))) { GList *node; - /* check if a timed_value for the timestamp exists */ + /* check if a control point for the timestamp exists */ if ((node = g_list_find_custom (prop->values, ×tamp, - gst_timed_value_find))) { - g_free (node->data); /* free GstTimedValue */ + gst_control_point_find))) { + gst_control_point_free (node->data); /* free GstControlPoint */ prop->values = g_list_delete_link (prop->values, node); res = TRUE; } @@ -858,8 +885,8 @@ gst_controller_unset_all (GstController * self, gchar * property_name) g_mutex_lock (self->lock); if ((prop = gst_controller_find_controlled_property (self, property_name))) { - /* free GstTimedValue structures */ - g_list_foreach (prop->values, (GFunc) g_free, NULL); + /* free GstControlPoint structures */ + g_list_foreach (prop->values, (GFunc) gst_control_point_free, NULL); g_list_free (prop->values); prop->values = NULL; res = TRUE; @@ -963,14 +990,14 @@ gst_controller_sync_values (GstController * self, GstClockTime timestamp) live = FALSE; if (G_UNLIKELY (G_IS_VALUE (&prop->live_value.value))) { GList *lnode = - gst_controlled_property_find_timed_value_node (prop, timestamp); + gst_controlled_property_find_control_point_node (prop, timestamp); if (G_UNLIKELY (!lnode)) { GST_DEBUG (" no control changes in the queue"); live = TRUE; } else { - GstTimedValue *tv = lnode->data; + GstControlPoint *cp = lnode->data; - if (prop->live_value.timestamp < tv->timestamp) { + if (prop->live_value.timestamp < cp->timestamp) { g_value_unset (&prop->live_value.value); GST_DEBUG (" live value resetted"); } else if (prop->live_value.timestamp < timestamp) { diff --git a/libs/gst/controller/gstcontroller.h b/libs/gst/controller/gstcontroller.h index 6148451..9c64480 100644 --- a/libs/gst/controller/gstcontroller.h +++ b/libs/gst/controller/gstcontroller.h @@ -51,11 +51,6 @@ typedef struct _GstTimedValue { GstClockTime timestamp; /* timestamp of the value change */ GValue value; /* the new value */ - /* TODO what about storing the difference to next timestamp and value here - + make calculations slightly easier and faster - - determining the GType for the value_dif is not simple - e.g. if value is G_TYPE_UCHAR value_diff needs to be G_TYPE_INT - */ } GstTimedValue; diff --git a/libs/gst/controller/gstcontrollerprivate.h b/libs/gst/controller/gstcontrollerprivate.h index 82c2da9..8bfd067 100644 --- a/libs/gst/controller/gstcontrollerprivate.h +++ b/libs/gst/controller/gstcontrollerprivate.h @@ -66,6 +66,24 @@ typedef struct _GstInterpolateMethod } GstInterpolateMethod; /** + * GstControlPoint: + * + * a internal structure for value+time and various temporary + * values used for interpolation. This "inherits" from + * GstTimedValue. + */ +/* FIXME 0.11: This should be merged with GstTimedValue for 0.11 */ +typedef struct _GstControlPoint +{ + /* fields from GstTimedValue. DO NOT CHANGE! */ + GstClockTime timestamp; /* timestamp of the value change */ + GValue value; /* the new value */ + + /* internal fields */ + +} GstControlPoint; + +/** * GstControlledProperty: */ typedef struct _GstControlledProperty @@ -75,8 +93,8 @@ typedef struct _GstControlledProperty GType base; /* base-type of the handled property */ GValue default_value; /* default value for the handled property */ GValue result_value; /* result value location for the interpolation method */ - GstTimedValue last_value; /* the last value a _sink call wrote */ - GstTimedValue live_value; /* temporary value override for live input */ + GstControlPoint last_value; /* the last value a _sink call wrote */ + GstControlPoint live_value; /* temporary value override for live input */ gulong notify_handler_id; /* id of the notify:: signal handler */ GstInterpolateMode interpolation; /* Interpolation mode */ /* TODO instead of *method, have pointers to get() and get_value_array() here @@ -87,7 +105,7 @@ typedef struct _GstControlledProperty InterpolateGet get; InterpolateGetValueArray get_value_array; - GList *values; /* List of GstTimedValue */ + GList *values; /* List of GstControlPoint */ /* TODO keep the last search result to be able to continue GList *last_value; // last search result, can be used for incremental searches */ diff --git a/libs/gst/controller/gstinterpolation.c b/libs/gst/controller/gstinterpolation.c index a66fc48..c33442a 100644 --- a/libs/gst/controller/gstinterpolation.c +++ b/libs/gst/controller/gstinterpolation.c @@ -32,22 +32,22 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT); /* common helper */ /* - * gst_controlled_property_find_timed_value_node: + * gst_controlled_property_find_control_point_node: * @prop: the controlled property to search in * @timestamp: the search key * - * Find last value before given timestamp in timed value list. + * Find last value before given timestamp in control point list. * * Returns: the found #GList node or %NULL */ GList * -gst_controlled_property_find_timed_value_node (GstControlledProperty * prop, +gst_controlled_property_find_control_point_node (GstControlledProperty * prop, GstClockTime timestamp) { /* GList *prev_node = NULL; */ GList *prev_node = g_list_last (prop->values); GList *node; - GstTimedValue *tv; + GstControlPoint *cp; /* if((prop->last_value) && @@ -61,9 +61,9 @@ gst_controlled_property_find_timed_value_node (GstControlledProperty * prop, /* iterate over timed value list */ for (node = prop->values; node; node = g_list_next (node)) { - tv = node->data; + cp = node->data; /* this timestamp is newer that the one we look for */ - if (timestamp < tv->timestamp) { + if (timestamp < cp->timestamp) { /* get previous one again */ prev_node = g_list_previous (node); break; @@ -85,10 +85,11 @@ interpolate_none_get (GstControlledProperty * prop, GstClockTime timestamp) { GList *node; - if ((node = gst_controlled_property_find_timed_value_node (prop, timestamp))) { - GstTimedValue *tv = node->data; + if ((node = + gst_controlled_property_find_control_point_node (prop, timestamp))) { + GstControlPoint *cp = node->data; - return (&tv->value); + return (&cp->value); } return (&prop->default_value); } @@ -180,13 +181,13 @@ static GValue * interpolate_trigger_get (GstControlledProperty * prop, GstClockTime timestamp) { GList *node; - GstTimedValue *tv; + GstControlPoint *cp; /* check if there is a value at the registered timestamp */ for (node = prop->values; node; node = g_list_next (node)) { - tv = node->data; - if (timestamp == tv->timestamp) { - return (&tv->value); + cp = node->data; + if (timestamp == cp->timestamp) { + return (&cp->value); } } @@ -230,25 +231,25 @@ _interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime times { \ GList *node; \ \ - if ((node = gst_controlled_property_find_timed_value_node (prop, timestamp))) { \ - GstTimedValue *tv1, *tv2; \ + if ((node = gst_controlled_property_find_control_point_node (prop, timestamp))) { \ + GstControlPoint *cp1, *cp2; \ \ - tv1 = node->data; \ + cp1 = node->data; \ if ((node = g_list_next (node))) { \ gdouble timediff,valuediff; \ g##type value1,value2; \ \ - tv2 = node->data; \ + cp2 = node->data; \ \ - timediff = gst_guint64_to_gdouble (tv2->timestamp - tv1->timestamp); \ - value1 = g_value_get_##type (&tv1->value); \ - value2 = g_value_get_##type (&tv2->value); \ + 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); \ \ - return ((g##type) (value1 + valuediff * (gst_guint64_to_gdouble (timestamp - tv1->timestamp) / timediff))); \ + return ((g##type) (value1 + valuediff * (gst_guint64_to_gdouble (timestamp - cp1->timestamp) / timediff))); \ } \ else { \ - return (g_value_get_##type (&tv1->value)); \ + return (g_value_get_##type (&cp1->value)); \ } \ } \ return (g_value_get_##type (&prop->default_value)); \ diff --git a/tests/check/libs/controller.c b/tests/check/libs/controller.c index befcc9b..91d5f49 100644 --- a/tests/check/libs/controller.c +++ b/tests/check/libs/controller.c @@ -883,6 +883,8 @@ GST_START_TEST (controller_misc) fail_unless (gst_controller_set_from_list (ctrl, "ulong", list)); /* allocated GstTimedValue now belongs to the controller, but list not */ + g_value_unset (&tval->value); + g_free (tval); g_slist_free (list); g_object_unref (ctrl); gst_object_unref (elem);