libs/gst/controller/: Add a new private GstControlPoint struct which "inherits" from
authorSebastian Dröge <slomo@circular-chaos.org>
Thu, 17 May 2007 17:05:36 +0000 (17:05 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Thu, 17 May 2007 17:05:36 +0000 (17:05 +0000)
Original commit message from CVS:
reviewed by: Stefan Kost <ensonic@users.sf.net>
* 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.

ChangeLog
libs/gst/controller/gstcontroller.c
libs/gst/controller/gstcontroller.h
libs/gst/controller/gstcontrollerprivate.h
libs/gst/controller/gstinterpolation.c
tests/check/libs/controller.c

index 2e56000..f7a5818 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2007-05-17  Sebastian Dröge  <slomo@circular-chaos.org>
+
+       reviewed by: Stefan Kost <ensonic@users.sf.net>
+
+       * 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  <edward@fluendo.com>
 
        * gst/gstsegment.c:
index ce2e86b..3930ed2 100644 (file)
@@ -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, &timestamp,
-                  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, &timestamp,
-                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) {
index 6148451..9c64480 100644 (file)
@@ -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;
 
 
index 82c2da9..8bfd067 100644 (file)
@@ -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::<name> 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
    */
index a66fc48..c33442a 100644 (file)
@@ -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)); \
index befcc9b..91d5f49 100644 (file)
@@ -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);