mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 20:42:30 +00:00
controller: Use ordered GSequence instead of GList
This makes lookups and insertions O(log n) instead of always O(n) for insertions and O(n) in worst case for lookups. Fixes bug #582564.
This commit is contained in:
parent
e535c171d6
commit
10743802be
3 changed files with 136 additions and 165 deletions
|
@ -1,7 +1,7 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* gstinterpolation.c: Interpolation methods for dynamic properties
|
||||
*
|
||||
|
@ -35,49 +35,53 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
|||
|
||||
/* 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_node:
|
||||
* 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.
|
||||
*
|
||||
* Returns: the found #GList node or %NULL
|
||||
* Returns: the found #GSequenceIter or %NULL
|
||||
*/
|
||||
static GList *gst_interpolation_control_source_find_control_point_node
|
||||
static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
|
||||
(GstInterpolationControlSource * self, GstClockTime timestamp)
|
||||
{
|
||||
GList *prev_node = g_list_last (self->priv->values);
|
||||
GList *node;
|
||||
GSequenceIter *iter;
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* Check if we can start from the last requested value
|
||||
* to save some time */
|
||||
node = self->priv->values;
|
||||
if (self->priv->last_requested_value) {
|
||||
GstControlPoint *last_cp = self->priv->last_requested_value->data;
|
||||
if (!self->priv->values)
|
||||
return NULL;
|
||||
|
||||
if (timestamp > last_cp->timestamp)
|
||||
node = self->priv->last_requested_value;
|
||||
}
|
||||
iter =
|
||||
g_sequence_search (self->priv->values, ×tamp,
|
||||
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||
|
||||
/* iterate over timed value list */
|
||||
for (; node; node = g_list_next (node)) {
|
||||
cp = node->data;
|
||||
/* this timestamp is newer that the one we look for */
|
||||
if (timestamp < cp->timestamp) {
|
||||
/* get previous one again */
|
||||
prev_node = g_list_previous (node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* g_sequence_search() returns the iter where timestamp
|
||||
* would be inserted, i.e. the iter > timestamp, so
|
||||
* we need to get the previous one */
|
||||
iter = g_sequence_iter_prev (iter);
|
||||
|
||||
/* If we have something to return save it as a
|
||||
* potential start position for the next search */
|
||||
if (prev_node)
|
||||
self->priv->last_requested_value = prev_node;
|
||||
/* g_sequence_iter_prev () on the begin iter returns
|
||||
* the begin iter. Check if the prev iter is still
|
||||
* after our timestamp, in that case return NULL
|
||||
*/
|
||||
cp = g_sequence_get (iter);
|
||||
if (cp->timestamp > timestamp)
|
||||
return NULL;
|
||||
|
||||
return prev_node;
|
||||
/* If the iter is the end iter return NULL as no
|
||||
* data is linked to the end iter */
|
||||
return G_UNLIKELY (g_sequence_iter_is_end (iter)) ? NULL : iter;
|
||||
}
|
||||
|
||||
/* steps-like (no-)interpolation, default */
|
||||
|
@ -88,11 +92,11 @@ static inline GValue * \
|
|||
_interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
||||
{ \
|
||||
GValue *ret; \
|
||||
GList *node; \
|
||||
GSequenceIter *iter; \
|
||||
\
|
||||
if ((node = \
|
||||
gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
|
||||
GstControlPoint *cp = node->data; \
|
||||
if ((iter = \
|
||||
gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
|
||||
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) \
|
||||
|
@ -162,13 +166,13 @@ static inline GValue *
|
|||
_interpolate_none_get (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
GList *node;
|
||||
GSequenceIter *iter;
|
||||
GValue *ret;
|
||||
|
||||
if ((node =
|
||||
gst_interpolation_control_source_find_control_point_node (self,
|
||||
if ((iter =
|
||||
gst_interpolation_control_source_find_control_point_iter (self,
|
||||
timestamp))) {
|
||||
GstControlPoint *cp = node->data;
|
||||
GstControlPoint *cp = g_sequence_get (iter);
|
||||
|
||||
ret = &cp->value;
|
||||
} else {
|
||||
|
@ -300,13 +304,13 @@ static GstInterpolateMethod interpolate_none = {
|
|||
static inline GValue * \
|
||||
_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
||||
{ \
|
||||
GList *node; \
|
||||
GSequenceIter *iter; \
|
||||
GstControlPoint *cp; \
|
||||
\
|
||||
/* check if there is a value at the registered timestamp */ \
|
||||
if ((node = \
|
||||
gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
|
||||
cp = node->data; \
|
||||
if ((iter = \
|
||||
gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
|
||||
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) \
|
||||
|
@ -379,14 +383,14 @@ static inline GValue *
|
|||
_interpolate_trigger_get (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
GList *node;
|
||||
GSequenceIter *iter;
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* check if there is a value at the registered timestamp */
|
||||
if ((node =
|
||||
gst_interpolation_control_source_find_control_point_node (self,
|
||||
if ((iter =
|
||||
gst_interpolation_control_source_find_control_point_iter (self,
|
||||
timestamp))) {
|
||||
cp = node->data;
|
||||
cp = g_sequence_get (iter);
|
||||
if (timestamp == cp->timestamp) {
|
||||
return &cp->value;
|
||||
}
|
||||
|
@ -518,25 +522,26 @@ static GstInterpolateMethod interpolate_trigger = {
|
|||
static inline gboolean \
|
||||
_interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
||||
{ \
|
||||
GList *node; \
|
||||
GSequenceIter *iter; \
|
||||
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
||||
\
|
||||
node = gst_interpolation_control_source_find_control_point_node (self, timestamp); \
|
||||
if (node) { \
|
||||
cp1 = node->data; \
|
||||
node = g_list_next (node); \
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
if (iter) { \
|
||||
cp1 = g_sequence_get (iter); \
|
||||
iter = g_sequence_iter_next (iter); \
|
||||
iter = g_sequence_iter_is_end (iter) ? NULL : 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; \
|
||||
node = self->priv->values; \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
} \
|
||||
if (node) { \
|
||||
if (iter) { \
|
||||
gdouble slope; \
|
||||
g##vtype value1,value2; \
|
||||
\
|
||||
cp2 = node->data; \
|
||||
cp2 = g_sequence_get (iter); \
|
||||
\
|
||||
value1 = g_value_get_##vtype (&cp1->value); \
|
||||
value2 = g_value_get_##vtype (&cp2->value); \
|
||||
|
@ -655,21 +660,21 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
gdouble *b = g_new0 (gdouble, n); \
|
||||
gdouble *z = g_new0 (gdouble, n); \
|
||||
\
|
||||
GList *node; \
|
||||
GSequenceIter *iter; \
|
||||
GstControlPoint *cp; \
|
||||
GstClockTime x_prev, x, x_next; \
|
||||
g##vtype y_prev, y, y_next; \
|
||||
\
|
||||
/* Fill linear system of equations */ \
|
||||
node = self->priv->values; \
|
||||
cp = node->data; \
|
||||
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; \
|
||||
\
|
||||
node = node->next; \
|
||||
cp = node->data; \
|
||||
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); \
|
||||
|
@ -680,8 +685,8 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
y_prev = y; \
|
||||
x = x_next; \
|
||||
y = y_next; \
|
||||
node = node->next; \
|
||||
cp = node->data; \
|
||||
iter = g_sequence_iter_next (iter); \
|
||||
cp = g_sequence_get (iter); \
|
||||
x_next = cp->timestamp; \
|
||||
y_next = g_value_get_##vtype (&cp->value); \
|
||||
\
|
||||
|
@ -707,12 +712,12 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
\
|
||||
/* Save cache next in the GstControlPoint */ \
|
||||
\
|
||||
node = self->priv->values; \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
for (i = 0; i < n; i++) { \
|
||||
cp = node->data; \
|
||||
cp = g_sequence_get (iter); \
|
||||
cp->cache.cubic.h = h[i]; \
|
||||
cp->cache.cubic.z = z[i]; \
|
||||
node = node->next; \
|
||||
iter = g_sequence_iter_next (iter); \
|
||||
} \
|
||||
\
|
||||
/* Free our temporary arrays */ \
|
||||
|
@ -727,7 +732,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
static inline gboolean \
|
||||
_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
||||
{ \
|
||||
GList *node; \
|
||||
GSequenceIter *iter; \
|
||||
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
||||
\
|
||||
if (self->priv->nvalues <= 2) \
|
||||
|
@ -738,23 +743,24 @@ _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
|||
self->priv->valid_cache = TRUE; \
|
||||
} \
|
||||
\
|
||||
node = gst_interpolation_control_source_find_control_point_node (self, timestamp); \
|
||||
if (node) { \
|
||||
cp1 = node->data; \
|
||||
node = g_list_next (node); \
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
if (iter) { \
|
||||
cp1 = g_sequence_get (iter); \
|
||||
iter = g_sequence_iter_next (iter); \
|
||||
iter = g_sequence_iter_is_end (iter) ? NULL : 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; \
|
||||
node = self->priv->values; \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
} \
|
||||
if (node) { \
|
||||
if (iter) { \
|
||||
gdouble diff1, diff2; \
|
||||
g##vtype value1,value2; \
|
||||
gdouble out; \
|
||||
\
|
||||
cp2 = node->data; \
|
||||
cp2 = g_sequence_get (iter); \
|
||||
\
|
||||
value1 = g_value_get_##vtype (&cp1->value); \
|
||||
value2 = g_value_get_##vtype (&cp2->value); \
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
*
|
||||
* gstinterpolationcontrolsource.c: Control source that provides several
|
||||
* interpolation methods
|
||||
|
@ -89,13 +89,11 @@ gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
|
|||
g_value_unset (&self->priv->maximum_value);
|
||||
|
||||
if (self->priv->values) {
|
||||
g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
|
||||
g_list_free (self->priv->values);
|
||||
g_sequence_free (self->priv->values);
|
||||
self->priv->values = NULL;
|
||||
}
|
||||
|
||||
self->priv->nvalues = 0;
|
||||
self->priv->last_requested_value = NULL;
|
||||
self->priv->valid_cache = FALSE;
|
||||
}
|
||||
|
||||
|
@ -125,9 +123,8 @@ gst_interpolation_control_source_new (void)
|
|||
* Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
gst_interpolation_control_source_set_interpolation_mode
|
||||
(GstInterpolationControlSource * self, GstInterpolateMode mode)
|
||||
{
|
||||
gst_interpolation_control_source_set_interpolation_mode
|
||||
(GstInterpolationControlSource * self, GstInterpolateMode mode) {
|
||||
gboolean ret = TRUE;
|
||||
GstControlSource *csource = GST_CONTROL_SOURCE (self);
|
||||
|
||||
|
@ -416,44 +413,6 @@ gst_control_point_find (gconstpointer p1, gconstpointer p2)
|
|||
return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* _list_find_sorted_custom:
|
||||
*
|
||||
* This works like g_list_find_custom() with the difference that it expects the
|
||||
* list to be sorted in ascending order (0->MAX), stops when it the list-values
|
||||
* are bigger that what is searched for and optionaly delivers the last node
|
||||
* back in the @prev_node argument. This can be used to quickly insert a new
|
||||
* node at the correct position.
|
||||
*/
|
||||
static GList *
|
||||
_list_find_sorted_custom (GList * list, gconstpointer data, GCompareFunc func,
|
||||
GList ** prev_node)
|
||||
{
|
||||
GList *prev = list;
|
||||
gint cmp;
|
||||
|
||||
g_return_val_if_fail (func != NULL, list);
|
||||
|
||||
while (list) {
|
||||
cmp = func (list->data, data);
|
||||
switch (cmp) {
|
||||
case -1:
|
||||
prev = list;
|
||||
list = list->next;
|
||||
break;
|
||||
case 0:
|
||||
return list;
|
||||
case 1:
|
||||
if (prev_node)
|
||||
*prev_node = prev;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (prev_node)
|
||||
*prev_node = prev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GstControlPoint *
|
||||
_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
|
||||
GValue * value)
|
||||
|
@ -473,43 +432,38 @@ static void
|
|||
gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
|
||||
self, GstClockTime timestamp, GValue * value)
|
||||
{
|
||||
GList *node, *prev = self->priv->values;
|
||||
|
||||
/* check if we can shortcut and append */
|
||||
if ((node = g_list_last (self->priv->values))) {
|
||||
GstControlPoint *last_cp = node->data;
|
||||
|
||||
if (timestamp > last_cp->timestamp) {
|
||||
/* pass 'node' instead of list, and also deliberately ignore the result */
|
||||
node = g_list_append (node, _make_new_cp (self, timestamp, value));
|
||||
self->priv->nvalues++;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
GSequenceIter *iter;
|
||||
|
||||
/* check if a control point for the timestamp already exists */
|
||||
if ((node = _list_find_sorted_custom (self->priv->values, ×tamp,
|
||||
gst_control_point_find, &prev))) {
|
||||
/* update control point */
|
||||
GstControlPoint *cp = node->data;
|
||||
g_value_reset (&cp->value);
|
||||
g_value_copy (value, &cp->value);
|
||||
} else {
|
||||
/* sort new cp into the prop->values list */
|
||||
if (self->priv->values) {
|
||||
GList *new_list;
|
||||
|
||||
/* pass 'prev' instead of list */
|
||||
new_list = g_list_insert_sorted (prev,
|
||||
_make_new_cp (self, timestamp, value), gst_control_point_compare);
|
||||
if (self->priv->values == prev)
|
||||
self->priv->values = new_list;
|
||||
} else {
|
||||
self->priv->values = g_list_prepend (NULL,
|
||||
_make_new_cp (self, timestamp, value));
|
||||
/* iter contains the iter right *after* timestamp */
|
||||
if (self->priv->values) {
|
||||
iter =
|
||||
g_sequence_search (self->priv->values, ×tamp,
|
||||
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||
if (iter) {
|
||||
GSequenceIter *prev = g_sequence_iter_prev (iter);
|
||||
GstControlPoint *cp = g_sequence_get (prev);
|
||||
|
||||
/* If the timestamp is the same just update the control point value */
|
||||
if (cp->timestamp == timestamp) {
|
||||
/* update control point */
|
||||
g_value_reset (&cp->value);
|
||||
g_value_copy (value, &cp->value);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
self->priv->nvalues++;
|
||||
}
|
||||
|
||||
/* sort new cp into the prop->values list */
|
||||
if (!self->priv->values)
|
||||
self->priv->values =
|
||||
g_sequence_new ((GDestroyNotify) gst_control_point_free);
|
||||
|
||||
g_sequence_insert_sorted (self->priv->values, _make_new_cp (self, timestamp,
|
||||
value), (GCompareDataFunc) gst_control_point_compare, NULL);
|
||||
self->priv->nvalues++;
|
||||
|
||||
done:
|
||||
self->priv->valid_cache = FALSE;
|
||||
}
|
||||
|
@ -595,7 +549,7 @@ gboolean
|
|||
gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
GList *node;
|
||||
GSequenceIter *iter;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
|
||||
|
@ -603,15 +557,22 @@ gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
|||
|
||||
g_mutex_lock (self->lock);
|
||||
/* check if a control point for the timestamp exists */
|
||||
if ((node = g_list_find_custom (self->priv->values, ×tamp,
|
||||
gst_control_point_find))) {
|
||||
if (node == self->priv->last_requested_value)
|
||||
self->priv->last_requested_value = NULL;
|
||||
gst_control_point_free (node->data); /* free GstControlPoint */
|
||||
self->priv->values = g_list_delete_link (self->priv->values, node);
|
||||
self->priv->nvalues--;
|
||||
self->priv->valid_cache = FALSE;
|
||||
res = TRUE;
|
||||
if ((iter =
|
||||
g_sequence_search (self->priv->values, ×tamp,
|
||||
(GCompareDataFunc) gst_control_point_find, NULL))) {
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* Iter contains the iter right after timestamp, i.e.
|
||||
* we need to get the previous one and check the timestamp
|
||||
*/
|
||||
iter = g_sequence_iter_prev (iter);
|
||||
cp = g_sequence_get (iter);
|
||||
if (cp->timestamp == timestamp) {
|
||||
g_sequence_remove (iter);
|
||||
self->priv->nvalues--;
|
||||
self->priv->valid_cache = FALSE;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
|
@ -633,9 +594,7 @@ gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
|
|||
|
||||
g_mutex_lock (self->lock);
|
||||
/* free GstControlPoint structures */
|
||||
g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
|
||||
g_list_free (self->priv->values);
|
||||
self->priv->last_requested_value = NULL;
|
||||
g_sequence_free (self->priv->values);
|
||||
self->priv->values = NULL;
|
||||
self->priv->nvalues = 0;
|
||||
self->priv->valid_cache = FALSE;
|
||||
|
@ -643,6 +602,12 @@ gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
|
|||
g_mutex_unlock (self->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
_append_control_point (GstControlPoint * cp, GList ** l)
|
||||
{
|
||||
*l = g_list_prepend (*l, cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_get_all:
|
||||
* @self: the #GstInterpolationControlSource to get the list from
|
||||
|
@ -661,10 +626,11 @@ gst_interpolation_control_source_get_all (GstInterpolationControlSource * self)
|
|||
|
||||
g_mutex_lock (self->lock);
|
||||
if (self->priv->values)
|
||||
res = g_list_copy (self->priv->values);
|
||||
g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
|
||||
&res);
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return res;
|
||||
return g_list_reverse (res);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,9 +90,8 @@ struct _GstInterpolationControlSourcePrivate
|
|||
GValue maximum_value; /* max value for the handled property */
|
||||
GstInterpolateMode interpolation_mode;
|
||||
|
||||
GList *values; /* List of GstControlPoint */
|
||||
GSequence *values; /* List of GstControlPoint */
|
||||
gint nvalues; /* Number of control points */
|
||||
GList *last_requested_value; /* last search result, can be used for incremental searches */
|
||||
gboolean valid_cache;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue