mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +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
|
/* GStreamer
|
||||||
*
|
*
|
||||||
* Copyright (C) <2005> Stefan Kost <ensonic at users dot sf dot net>
|
* 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
|
* gstinterpolation.c: Interpolation methods for dynamic properties
|
||||||
*
|
*
|
||||||
|
@ -35,49 +35,53 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
/* common helper */
|
/* 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
|
* @self: the interpolation control source to search in
|
||||||
* @timestamp: the search key
|
* @timestamp: the search key
|
||||||
*
|
*
|
||||||
* Find last value before given timestamp in control point list.
|
* 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)
|
(GstInterpolationControlSource * self, GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GList *prev_node = g_list_last (self->priv->values);
|
GSequenceIter *iter;
|
||||||
GList *node;
|
|
||||||
GstControlPoint *cp;
|
GstControlPoint *cp;
|
||||||
|
|
||||||
/* Check if we can start from the last requested value
|
if (!self->priv->values)
|
||||||
* to save some time */
|
return NULL;
|
||||||
node = self->priv->values;
|
|
||||||
if (self->priv->last_requested_value) {
|
|
||||||
GstControlPoint *last_cp = self->priv->last_requested_value->data;
|
|
||||||
|
|
||||||
if (timestamp > last_cp->timestamp)
|
iter =
|
||||||
node = self->priv->last_requested_value;
|
g_sequence_search (self->priv->values, ×tamp,
|
||||||
}
|
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||||
|
|
||||||
/* iterate over timed value list */
|
/* g_sequence_search() returns the iter where timestamp
|
||||||
for (; node; node = g_list_next (node)) {
|
* would be inserted, i.e. the iter > timestamp, so
|
||||||
cp = node->data;
|
* we need to get the previous one */
|
||||||
/* this timestamp is newer that the one we look for */
|
iter = g_sequence_iter_prev (iter);
|
||||||
if (timestamp < cp->timestamp) {
|
|
||||||
/* get previous one again */
|
|
||||||
prev_node = g_list_previous (node);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we have something to return save it as a
|
/* g_sequence_iter_prev () on the begin iter returns
|
||||||
* potential start position for the next search */
|
* the begin iter. Check if the prev iter is still
|
||||||
if (prev_node)
|
* after our timestamp, in that case return NULL
|
||||||
self->priv->last_requested_value = prev_node;
|
*/
|
||||||
|
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 */
|
/* steps-like (no-)interpolation, default */
|
||||||
|
@ -88,11 +92,11 @@ static inline GValue * \
|
||||||
_interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
_interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
||||||
{ \
|
{ \
|
||||||
GValue *ret; \
|
GValue *ret; \
|
||||||
GList *node; \
|
GSequenceIter *iter; \
|
||||||
\
|
\
|
||||||
if ((node = \
|
if ((iter = \
|
||||||
gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
|
gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
|
||||||
GstControlPoint *cp = node->data; \
|
GstControlPoint *cp = g_sequence_get (iter); \
|
||||||
g##type ret_val = g_value_get_##type (&cp->value); \
|
g##type ret_val = g_value_get_##type (&cp->value); \
|
||||||
\
|
\
|
||||||
if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
|
if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
|
||||||
|
@ -162,13 +166,13 @@ static inline GValue *
|
||||||
_interpolate_none_get (GstInterpolationControlSource * self,
|
_interpolate_none_get (GstInterpolationControlSource * self,
|
||||||
GstClockTime timestamp)
|
GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GList *node;
|
GSequenceIter *iter;
|
||||||
GValue *ret;
|
GValue *ret;
|
||||||
|
|
||||||
if ((node =
|
if ((iter =
|
||||||
gst_interpolation_control_source_find_control_point_node (self,
|
gst_interpolation_control_source_find_control_point_iter (self,
|
||||||
timestamp))) {
|
timestamp))) {
|
||||||
GstControlPoint *cp = node->data;
|
GstControlPoint *cp = g_sequence_get (iter);
|
||||||
|
|
||||||
ret = &cp->value;
|
ret = &cp->value;
|
||||||
} else {
|
} else {
|
||||||
|
@ -300,13 +304,13 @@ static GstInterpolateMethod interpolate_none = {
|
||||||
static inline GValue * \
|
static inline GValue * \
|
||||||
_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
|
||||||
{ \
|
{ \
|
||||||
GList *node; \
|
GSequenceIter *iter; \
|
||||||
GstControlPoint *cp; \
|
GstControlPoint *cp; \
|
||||||
\
|
\
|
||||||
/* check if there is a value at the registered timestamp */ \
|
/* check if there is a value at the registered timestamp */ \
|
||||||
if ((node = \
|
if ((iter = \
|
||||||
gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
|
gst_interpolation_control_source_find_control_point_iter (self, timestamp))) { \
|
||||||
cp = node->data; \
|
cp = g_sequence_get (iter); \
|
||||||
if (timestamp == cp->timestamp) { \
|
if (timestamp == cp->timestamp) { \
|
||||||
g##type ret = g_value_get_##type (&cp->value); \
|
g##type ret = g_value_get_##type (&cp->value); \
|
||||||
if (g_value_get_##type (&self->priv->minimum_value) > ret) \
|
if (g_value_get_##type (&self->priv->minimum_value) > ret) \
|
||||||
|
@ -379,14 +383,14 @@ static inline GValue *
|
||||||
_interpolate_trigger_get (GstInterpolationControlSource * self,
|
_interpolate_trigger_get (GstInterpolationControlSource * self,
|
||||||
GstClockTime timestamp)
|
GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GList *node;
|
GSequenceIter *iter;
|
||||||
GstControlPoint *cp;
|
GstControlPoint *cp;
|
||||||
|
|
||||||
/* check if there is a value at the registered timestamp */
|
/* check if there is a value at the registered timestamp */
|
||||||
if ((node =
|
if ((iter =
|
||||||
gst_interpolation_control_source_find_control_point_node (self,
|
gst_interpolation_control_source_find_control_point_iter (self,
|
||||||
timestamp))) {
|
timestamp))) {
|
||||||
cp = node->data;
|
cp = g_sequence_get (iter);
|
||||||
if (timestamp == cp->timestamp) {
|
if (timestamp == cp->timestamp) {
|
||||||
return &cp->value;
|
return &cp->value;
|
||||||
}
|
}
|
||||||
|
@ -518,25 +522,26 @@ static GstInterpolateMethod interpolate_trigger = {
|
||||||
static inline gboolean \
|
static inline gboolean \
|
||||||
_interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
_interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
||||||
{ \
|
{ \
|
||||||
GList *node; \
|
GSequenceIter *iter; \
|
||||||
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
||||||
\
|
\
|
||||||
node = gst_interpolation_control_source_find_control_point_node (self, timestamp); \
|
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||||
if (node) { \
|
if (iter) { \
|
||||||
cp1 = node->data; \
|
cp1 = g_sequence_get (iter); \
|
||||||
node = g_list_next (node); \
|
iter = g_sequence_iter_next (iter); \
|
||||||
|
iter = g_sequence_iter_is_end (iter) ? NULL : iter; \
|
||||||
} else { \
|
} else { \
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->priv->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->priv->default_value, &cp.value); \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
node = self->priv->values; \
|
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||||
} \
|
} \
|
||||||
if (node) { \
|
if (iter) { \
|
||||||
gdouble slope; \
|
gdouble slope; \
|
||||||
g##vtype value1,value2; \
|
g##vtype value1,value2; \
|
||||||
\
|
\
|
||||||
cp2 = node->data; \
|
cp2 = g_sequence_get (iter); \
|
||||||
\
|
\
|
||||||
value1 = g_value_get_##vtype (&cp1->value); \
|
value1 = g_value_get_##vtype (&cp1->value); \
|
||||||
value2 = g_value_get_##vtype (&cp2->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 *b = g_new0 (gdouble, n); \
|
||||||
gdouble *z = g_new0 (gdouble, n); \
|
gdouble *z = g_new0 (gdouble, n); \
|
||||||
\
|
\
|
||||||
GList *node; \
|
GSequenceIter *iter; \
|
||||||
GstControlPoint *cp; \
|
GstControlPoint *cp; \
|
||||||
GstClockTime x_prev, x, x_next; \
|
GstClockTime x_prev, x, x_next; \
|
||||||
g##vtype y_prev, y, y_next; \
|
g##vtype y_prev, y, y_next; \
|
||||||
\
|
\
|
||||||
/* Fill linear system of equations */ \
|
/* Fill linear system of equations */ \
|
||||||
node = self->priv->values; \
|
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||||
cp = node->data; \
|
cp = g_sequence_get (iter); \
|
||||||
x = cp->timestamp; \
|
x = cp->timestamp; \
|
||||||
y = g_value_get_##vtype (&cp->value); \
|
y = g_value_get_##vtype (&cp->value); \
|
||||||
\
|
\
|
||||||
p[0] = 1.0; \
|
p[0] = 1.0; \
|
||||||
\
|
\
|
||||||
node = node->next; \
|
iter = g_sequence_iter_next (iter); \
|
||||||
cp = node->data; \
|
cp = g_sequence_get (iter); \
|
||||||
x_next = cp->timestamp; \
|
x_next = cp->timestamp; \
|
||||||
y_next = g_value_get_##vtype (&cp->value); \
|
y_next = g_value_get_##vtype (&cp->value); \
|
||||||
h[0] = gst_guint64_to_gdouble (x_next - x); \
|
h[0] = gst_guint64_to_gdouble (x_next - x); \
|
||||||
|
@ -680,8 +685,8 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
||||||
y_prev = y; \
|
y_prev = y; \
|
||||||
x = x_next; \
|
x = x_next; \
|
||||||
y = y_next; \
|
y = y_next; \
|
||||||
node = node->next; \
|
iter = g_sequence_iter_next (iter); \
|
||||||
cp = node->data; \
|
cp = g_sequence_get (iter); \
|
||||||
x_next = cp->timestamp; \
|
x_next = cp->timestamp; \
|
||||||
y_next = g_value_get_##vtype (&cp->value); \
|
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 */ \
|
/* 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++) { \
|
for (i = 0; i < n; i++) { \
|
||||||
cp = node->data; \
|
cp = g_sequence_get (iter); \
|
||||||
cp->cache.cubic.h = h[i]; \
|
cp->cache.cubic.h = h[i]; \
|
||||||
cp->cache.cubic.z = z[i]; \
|
cp->cache.cubic.z = z[i]; \
|
||||||
node = node->next; \
|
iter = g_sequence_iter_next (iter); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
/* Free our temporary arrays */ \
|
/* Free our temporary arrays */ \
|
||||||
|
@ -727,7 +732,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
||||||
static inline gboolean \
|
static inline gboolean \
|
||||||
_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, g##vtype *ret) \
|
||||||
{ \
|
{ \
|
||||||
GList *node; \
|
GSequenceIter *iter; \
|
||||||
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
GstControlPoint *cp1 = NULL, *cp2, cp={0,}; \
|
||||||
\
|
\
|
||||||
if (self->priv->nvalues <= 2) \
|
if (self->priv->nvalues <= 2) \
|
||||||
|
@ -738,23 +743,24 @@ _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
||||||
self->priv->valid_cache = TRUE; \
|
self->priv->valid_cache = TRUE; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
node = gst_interpolation_control_source_find_control_point_node (self, timestamp); \
|
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||||
if (node) { \
|
if (iter) { \
|
||||||
cp1 = node->data; \
|
cp1 = g_sequence_get (iter); \
|
||||||
node = g_list_next (node); \
|
iter = g_sequence_iter_next (iter); \
|
||||||
|
iter = g_sequence_iter_is_end (iter) ? NULL : iter; \
|
||||||
} else { \
|
} else { \
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->priv->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->priv->default_value, &cp.value); \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
node = self->priv->values; \
|
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||||
} \
|
} \
|
||||||
if (node) { \
|
if (iter) { \
|
||||||
gdouble diff1, diff2; \
|
gdouble diff1, diff2; \
|
||||||
g##vtype value1,value2; \
|
g##vtype value1,value2; \
|
||||||
gdouble out; \
|
gdouble out; \
|
||||||
\
|
\
|
||||||
cp2 = node->data; \
|
cp2 = g_sequence_get (iter); \
|
||||||
\
|
\
|
||||||
value1 = g_value_get_##vtype (&cp1->value); \
|
value1 = g_value_get_##vtype (&cp1->value); \
|
||||||
value2 = g_value_get_##vtype (&cp2->value); \
|
value2 = g_value_get_##vtype (&cp2->value); \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* GStreamer
|
/* 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
|
* gstinterpolationcontrolsource.c: Control source that provides several
|
||||||
* interpolation methods
|
* interpolation methods
|
||||||
|
@ -89,13 +89,11 @@ gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
|
||||||
g_value_unset (&self->priv->maximum_value);
|
g_value_unset (&self->priv->maximum_value);
|
||||||
|
|
||||||
if (self->priv->values) {
|
if (self->priv->values) {
|
||||||
g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
|
g_sequence_free (self->priv->values);
|
||||||
g_list_free (self->priv->values);
|
|
||||||
self->priv->values = NULL;
|
self->priv->values = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->priv->nvalues = 0;
|
self->priv->nvalues = 0;
|
||||||
self->priv->last_requested_value = NULL;
|
|
||||||
self->priv->valid_cache = FALSE;
|
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
|
* Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_interpolation_control_source_set_interpolation_mode
|
gst_interpolation_control_source_set_interpolation_mode
|
||||||
(GstInterpolationControlSource * self, GstInterpolateMode mode)
|
(GstInterpolationControlSource * self, GstInterpolateMode mode) {
|
||||||
{
|
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
GstControlSource *csource = GST_CONTROL_SOURCE (self);
|
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));
|
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 *
|
static GstControlPoint *
|
||||||
_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
|
_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
|
||||||
GValue * value)
|
GValue * value)
|
||||||
|
@ -473,43 +432,38 @@ static void
|
||||||
gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
|
gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
|
||||||
self, GstClockTime timestamp, GValue * value)
|
self, GstClockTime timestamp, GValue * value)
|
||||||
{
|
{
|
||||||
GList *node, *prev = self->priv->values;
|
GSequenceIter *iter;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if a control point for the timestamp already exists */
|
/* 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 */
|
/* iter contains the iter right *after* timestamp */
|
||||||
new_list = g_list_insert_sorted (prev,
|
if (self->priv->values) {
|
||||||
_make_new_cp (self, timestamp, value), gst_control_point_compare);
|
iter =
|
||||||
if (self->priv->values == prev)
|
g_sequence_search (self->priv->values, ×tamp,
|
||||||
self->priv->values = new_list;
|
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||||
} else {
|
if (iter) {
|
||||||
self->priv->values = g_list_prepend (NULL,
|
GSequenceIter *prev = g_sequence_iter_prev (iter);
|
||||||
_make_new_cp (self, timestamp, value));
|
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:
|
done:
|
||||||
self->priv->valid_cache = FALSE;
|
self->priv->valid_cache = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -595,7 +549,7 @@ gboolean
|
||||||
gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
||||||
GstClockTime timestamp)
|
GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GList *node;
|
GSequenceIter *iter;
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 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);
|
g_mutex_lock (self->lock);
|
||||||
/* check if a control point for the timestamp exists */
|
/* check if a control point for the timestamp exists */
|
||||||
if ((node = g_list_find_custom (self->priv->values, ×tamp,
|
if ((iter =
|
||||||
gst_control_point_find))) {
|
g_sequence_search (self->priv->values, ×tamp,
|
||||||
if (node == self->priv->last_requested_value)
|
(GCompareDataFunc) gst_control_point_find, NULL))) {
|
||||||
self->priv->last_requested_value = NULL;
|
GstControlPoint *cp;
|
||||||
gst_control_point_free (node->data); /* free GstControlPoint */
|
|
||||||
self->priv->values = g_list_delete_link (self->priv->values, node);
|
/* Iter contains the iter right after timestamp, i.e.
|
||||||
self->priv->nvalues--;
|
* we need to get the previous one and check the timestamp
|
||||||
self->priv->valid_cache = FALSE;
|
*/
|
||||||
res = TRUE;
|
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);
|
g_mutex_unlock (self->lock);
|
||||||
|
|
||||||
|
@ -633,9 +594,7 @@ gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
|
||||||
|
|
||||||
g_mutex_lock (self->lock);
|
g_mutex_lock (self->lock);
|
||||||
/* free GstControlPoint structures */
|
/* free GstControlPoint structures */
|
||||||
g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
|
g_sequence_free (self->priv->values);
|
||||||
g_list_free (self->priv->values);
|
|
||||||
self->priv->last_requested_value = NULL;
|
|
||||||
self->priv->values = NULL;
|
self->priv->values = NULL;
|
||||||
self->priv->nvalues = 0;
|
self->priv->nvalues = 0;
|
||||||
self->priv->valid_cache = FALSE;
|
self->priv->valid_cache = FALSE;
|
||||||
|
@ -643,6 +602,12 @@ gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
|
||||||
g_mutex_unlock (self->lock);
|
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:
|
* gst_interpolation_control_source_get_all:
|
||||||
* @self: the #GstInterpolationControlSource to get the list from
|
* @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);
|
g_mutex_lock (self->lock);
|
||||||
if (self->priv->values)
|
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);
|
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 */
|
GValue maximum_value; /* max value for the handled property */
|
||||||
GstInterpolateMode interpolation_mode;
|
GstInterpolateMode interpolation_mode;
|
||||||
|
|
||||||
GList *values; /* List of GstControlPoint */
|
GSequence *values; /* List of GstControlPoint */
|
||||||
gint nvalues; /* Number of control points */
|
gint nvalues; /* Number of control points */
|
||||||
GList *last_requested_value; /* last search result, can be used for incremental searches */
|
|
||||||
gboolean valid_cache;
|
gboolean valid_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue