mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
controlsources: refactor interpolation control source
Move most of the code to a GstTimedValueControlSource. Split out the trigger 'interpolation mode' to a new control source class. Move tests and examples to new api. Update docs. Fixes #610338
This commit is contained in:
parent
9c3c0fb251
commit
2c7a8b924a
17 changed files with 1653 additions and 1084 deletions
|
@ -55,8 +55,10 @@
|
|||
element properties over time.
|
||||
</para>
|
||||
|
||||
<xi:include href="xml/gsttimedvaluecontrolsource.xml" />
|
||||
<xi:include href="xml/gstinterpolationcontrolsource.xml" />
|
||||
<xi:include href="xml/gstlfocontrolsource.xml" />
|
||||
<xi:include href="xml/gsttriggercontrolsource.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="gstreamer-dataprotocol">
|
||||
|
|
|
@ -53,22 +53,22 @@ gst_dp_version_get_type
|
|||
# control source classes
|
||||
|
||||
<SECTION>
|
||||
<FILE>gstinterpolationcontrolsource</FILE>
|
||||
<TITLE>GstInterpolationControlSource</TITLE>
|
||||
<INCLUDE>libs/controller/gstinterpolationcontrolsource.h</INCLUDE>
|
||||
GstInterpolationControlSource
|
||||
GstInterpolateMode
|
||||
gst_interpolation_control_source_new
|
||||
gst_interpolation_control_source_set
|
||||
gst_interpolation_control_source_set_from_list
|
||||
gst_interpolation_control_source_set_interpolation_mode
|
||||
gst_interpolation_control_source_get_all
|
||||
gst_interpolation_control_source_unset
|
||||
gst_interpolation_control_source_unset_all
|
||||
gst_interpolation_control_source_get_count
|
||||
<FILE>gsttimedvaluecontrolsource</FILE>
|
||||
<TITLE>GstTimedValueControlSource</TITLE>
|
||||
<INCLUDE>libs/controller/gsttimedvaluecontrolsource.h</INCLUDE>
|
||||
GstTimedValueControlSource
|
||||
gst_timed_value_control_source_find_control_point_iter
|
||||
gst_timed_value_control_source_set
|
||||
gst_timed_value_control_source_set_from_list
|
||||
gst_timed_value_control_source_get_all
|
||||
gst_timed_value_control_source_unset
|
||||
gst_timed_value_control_source_unset_all
|
||||
gst_timed_value_control_source_get_count
|
||||
gst_timed_value_control_source_get_base_value_type
|
||||
gst_timed_value_control_invalidate_cache
|
||||
<SUBSECTION Standard>
|
||||
GstInterpolationControlSourceClass
|
||||
GstInterpolationControlSourcePrivate
|
||||
GstTimedValueControlSourceClass
|
||||
GstTimedValueControlSourcePrivate
|
||||
GST_INTERPOLATION_CONTROL_SOURCE
|
||||
GST_IS_INTERPOLATION_CONTROL_SOURCE
|
||||
GST_INTERPOLATION_CONTROL_SOURCE_CLASS
|
||||
|
@ -76,6 +76,27 @@ GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
|
|||
GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
|
||||
GST_TYPE_INTERPOLATION_CONTROL_SOURCE
|
||||
<SUBSECTION Private>
|
||||
gst_timed_value_control_source_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gstinterpolationcontrolsource</FILE>
|
||||
<TITLE>GstInterpolationControlSource</TITLE>
|
||||
<INCLUDE>libs/controller/gstinterpolationcontrolsource.h</INCLUDE>
|
||||
GstInterpolationControlSource
|
||||
GstInterpolateMode
|
||||
gst_interpolation_control_source_new
|
||||
gst_interpolation_control_source_set_interpolation_mode
|
||||
<SUBSECTION Standard>
|
||||
GstInterpolationControlSourceClass
|
||||
GstInterpolationControlSourcePrivate
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE
|
||||
GST_IS_TIMED_VALUE_CONTROL_SOURCE
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_CLASS
|
||||
GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS
|
||||
GST_TYPE_TIMED_VALUE_CONTROL_SOURCE
|
||||
<SUBSECTION Private>
|
||||
gst_interpolation_control_source_get_type
|
||||
</SECTION>
|
||||
|
||||
|
@ -101,6 +122,25 @@ gst_lfo_control_source_get_type
|
|||
gst_lfo_waveform_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gsttriggercontrolsource</FILE>
|
||||
<TITLE>GstTriggerControlSource</TITLE>
|
||||
<INCLUDE>libs/controller/gsttriggercontrolsource.h</INCLUDE>
|
||||
GstTriggerControlSource
|
||||
gst_trigger_control_source_new
|
||||
<SUBSECTION Standard>
|
||||
GstTriggerControlSourceClass
|
||||
GstTriggerControlSourcePrivate
|
||||
GST_TRIGGER_CONTROL_SOURCE
|
||||
GST_IS_TRIGGER_CONTROL_SOURCE
|
||||
GST_TRIGGER_CONTROL_SOURCE_CLASS
|
||||
GST_IS_TRIGGER_CONTROL_SOURCE_CLASS
|
||||
GST_TRIGGER_CONTROL_SOURCE_GET_CLASS
|
||||
GST_TYPE_TRIGGER_CONTROL_SOURCE
|
||||
<SUBSECTION Private>
|
||||
gst_trigger_control_source_get_type
|
||||
</SECTION>
|
||||
|
||||
# base classes
|
||||
|
||||
<SECTION>
|
||||
|
|
|
@ -18,11 +18,15 @@ gst_push_src_get_type
|
|||
|
||||
% controller
|
||||
|
||||
#include <gst/controller/gsttimedvaluecontrolsource.h>
|
||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||
#include <gst/controller/gstlfocontrolsource.h>
|
||||
#include <gst/controller/gsttriggercontrolsource.h>
|
||||
|
||||
gst_timed_value_control_source_get_type
|
||||
gst_interpolation_control_source_get_type
|
||||
gst_lfo_control_source_get_type
|
||||
gst_trigger_control_source_get_type
|
||||
|
||||
% net
|
||||
|
||||
|
|
|
@ -447,4 +447,8 @@ The 0.11 porting guide
|
|||
properties fetch the value array. Also GstValueArray is gone. The fields of
|
||||
GstValueArray are now passed directly to gst_object_get_value_array as
|
||||
arguments.
|
||||
|
||||
|
||||
GstInterpolationControlSource has been split. There is a new
|
||||
GstTimedValueControlSource baseclass and 2 sub classes:
|
||||
GstInterpolationControlSource and GstTriggerControlSource. The API for setting
|
||||
and getting the timestamps is in GstTimedValueControlSource.
|
||||
|
|
|
@ -121,8 +121,8 @@
|
|||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* Set the control values
|
||||
* gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
|
||||
* gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
|
||||
* gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1);
|
||||
* gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* start your pipeline
|
||||
|
|
|
@ -2,7 +2,9 @@ lib_LTLIBRARIES = libgstcontroller-@GST_MAJORMINOR@.la
|
|||
|
||||
libgstcontroller_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/controller
|
||||
libgstcontroller_@GST_MAJORMINOR@_include_HEADERS = \
|
||||
gsttimedvaluecontrolsource.h \
|
||||
gstinterpolationcontrolsource.h \
|
||||
gsttriggercontrolsource.h \
|
||||
gstlfocontrolsource.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
|
@ -10,8 +12,10 @@ noinst_HEADERS = \
|
|||
gstlfocontrolsourceprivate.h
|
||||
|
||||
libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
|
||||
gsttimedvaluecontrolsource.c \
|
||||
gstinterpolation.c \
|
||||
gstinterpolationcontrolsource.c \
|
||||
gsttriggercontrolsource.c \
|
||||
gstlfocontrolsource.c
|
||||
|
||||
libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
|
||||
|
|
|
@ -33,55 +33,10 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
|||
|
||||
#define EMPTY(x) (x)
|
||||
|
||||
/* 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_iter:
|
||||
* @self: the interpolation control source to search in
|
||||
* @timestamp: the search key
|
||||
*
|
||||
* Find last value before given timestamp in control point list.
|
||||
* If all values in the control point list come after the given
|
||||
* timestamp or no values exist, %NULL is returned.
|
||||
*
|
||||
* Returns: the found #GSequenceIter or %NULL
|
||||
*/
|
||||
static GSequenceIter *gst_interpolation_control_source_find_control_point_iter
|
||||
(GstInterpolationControlSource * self, GstClockTime timestamp)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
if (!self->priv->values)
|
||||
return NULL;
|
||||
|
||||
iter =
|
||||
g_sequence_search (self->priv->values, ×tamp,
|
||||
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||
|
||||
/* g_sequence_search() returns the iter where timestamp
|
||||
* would be inserted, i.e. the iter > timestamp, so
|
||||
* we need to get the previous one. And of course, if
|
||||
* there is no previous one, we return NULL. */
|
||||
if (g_sequence_iter_is_begin (iter))
|
||||
return NULL;
|
||||
|
||||
return g_sequence_iter_prev (iter);
|
||||
}
|
||||
|
||||
/* steps-like (no-)interpolation, default */
|
||||
/* just returns the value for the most recent key-frame */
|
||||
static inline const GValue *
|
||||
_interpolate_none_get (GstInterpolationControlSource * self,
|
||||
GSequenceIter * iter)
|
||||
_interpolate_none_get (GstTimedValueControlSource * self, GSequenceIter * iter)
|
||||
{
|
||||
const GValue *ret;
|
||||
|
||||
|
@ -90,14 +45,14 @@ _interpolate_none_get (GstInterpolationControlSource * self,
|
|||
|
||||
ret = &cp->value;
|
||||
} else {
|
||||
ret = &self->priv->default_value;
|
||||
ret = &self->default_value;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
|
||||
static inline const GValue * \
|
||||
_interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \
|
||||
_interpolate_none_get_##type (GstTimedValueControlSource *self, GSequenceIter *iter) \
|
||||
{ \
|
||||
const GValue *ret; \
|
||||
\
|
||||
|
@ -105,28 +60,28 @@ _interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter
|
|||
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) \
|
||||
ret = &self->priv->minimum_value; \
|
||||
else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
|
||||
ret = &self->priv->maximum_value; \
|
||||
if (g_value_get_##type (&self->minimum_value) > ret_val) \
|
||||
ret = &self->minimum_value; \
|
||||
else if (g_value_get_##type (&self->maximum_value) < ret_val) \
|
||||
ret = &self->maximum_value; \
|
||||
else \
|
||||
ret = &cp->value; \
|
||||
} else { \
|
||||
ret = &self->priv->default_value; \
|
||||
ret = &self->default_value; \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define DEFINE_NONE_GET(type,ctype,get_func) \
|
||||
static gboolean \
|
||||
interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
interpolate_none_get_##type (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
{ \
|
||||
const GValue *ret; \
|
||||
GSequenceIter *iter; \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
|
||||
ret = get_func (self, iter); \
|
||||
g_value_copy (ret, value); \
|
||||
g_mutex_unlock (self->lock); \
|
||||
|
@ -134,7 +89,7 @@ interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime t
|
|||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self, \
|
||||
interpolate_none_get_##type##_value_array (GstTimedValueControlSource *self, \
|
||||
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||
{ \
|
||||
guint i; \
|
||||
|
@ -148,10 +103,10 @@ interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self,
|
|||
g_mutex_lock (self->lock); \
|
||||
for(i = 0; i < n_values; i++) { \
|
||||
if (!ret_val || ts >= next_ts) { \
|
||||
iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
|
||||
iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
|
||||
if (!iter1) { \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||
else \
|
||||
iter2 = NULL; \
|
||||
} else { \
|
||||
|
@ -224,178 +179,6 @@ static GstInterpolateMethod interpolate_none = {
|
|||
(GstControlSourceGetValueArray) interpolate_none_get_string_value_array
|
||||
};
|
||||
|
||||
/* returns the default value of the property, except for times with specific values */
|
||||
/* needed for one-shot events, such as notes and triggers */
|
||||
static inline const GValue *
|
||||
_interpolate_trigger_get (GstInterpolationControlSource * self,
|
||||
GSequenceIter * iter, GstClockTime timestamp)
|
||||
{
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* check if there is a value at the registered timestamp */
|
||||
if (iter) {
|
||||
cp = g_sequence_get (iter);
|
||||
if (timestamp == cp->timestamp) {
|
||||
return &cp->value;
|
||||
}
|
||||
}
|
||||
if (self->priv->nvalues > 0)
|
||||
return &self->priv->default_value;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
|
||||
static inline const GValue * \
|
||||
_interpolate_trigger_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
|
||||
{ \
|
||||
GstControlPoint *cp; \
|
||||
\
|
||||
/* check if there is a value at the registered timestamp */ \
|
||||
if (iter) { \
|
||||
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) \
|
||||
return &self->priv->minimum_value; \
|
||||
else if (g_value_get_##type (&self->priv->maximum_value) < ret) \
|
||||
return &self->priv->maximum_value; \
|
||||
else \
|
||||
return &cp->value; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (self->priv->nvalues > 0) \
|
||||
return &self->priv->default_value; \
|
||||
else \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define DEFINE_TRIGGER_GET(type, ctype, get_func) \
|
||||
static gboolean \
|
||||
interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
{ \
|
||||
const GValue *ret; \
|
||||
GSequenceIter *iter; \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
ret = get_func (self, iter, timestamp); \
|
||||
if (!ret) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
\
|
||||
g_value_copy (ret, value); \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_trigger_get_##type##_value_array (GstInterpolationControlSource *self, \
|
||||
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||
{ \
|
||||
guint i; \
|
||||
GstClockTime ts = timestamp; \
|
||||
GstClockTime next_ts = 0; \
|
||||
ctype *values = (ctype *) _values; \
|
||||
const GValue *ret_val = NULL; \
|
||||
ctype ret = 0; \
|
||||
GSequenceIter *iter1 = NULL, *iter2 = NULL; \
|
||||
gboolean triggered = FALSE; \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
for(i = 0; i < n_values; i++) { \
|
||||
if (!ret_val || ts >= next_ts) { \
|
||||
iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
|
||||
if (!iter1) { \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
||||
else \
|
||||
iter2 = NULL; \
|
||||
} else { \
|
||||
iter2 = g_sequence_iter_next (iter1); \
|
||||
} \
|
||||
\
|
||||
if (iter2 && !g_sequence_iter_is_end (iter2)) { \
|
||||
GstControlPoint *cp; \
|
||||
\
|
||||
cp = g_sequence_get (iter2); \
|
||||
next_ts = cp->timestamp; \
|
||||
} else { \
|
||||
next_ts = GST_CLOCK_TIME_NONE; \
|
||||
} \
|
||||
\
|
||||
ret_val = get_func (self, iter1, ts); \
|
||||
if (!ret_val) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
ret = g_value_get_##type (ret_val); \
|
||||
triggered = TRUE; \
|
||||
} else if (triggered) { \
|
||||
ret_val = get_func (self, iter1, ts); \
|
||||
if (!ret_val) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
ret = g_value_get_##type (ret_val); \
|
||||
triggered = FALSE; \
|
||||
} \
|
||||
*values = ret; \
|
||||
ts += interval; \
|
||||
values++; \
|
||||
} \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return TRUE; \
|
||||
}
|
||||
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
|
||||
DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
|
||||
DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
|
||||
DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
|
||||
DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
|
||||
DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
|
||||
DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
|
||||
DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
|
||||
DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
|
||||
|
||||
DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
|
||||
DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
|
||||
DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
|
||||
|
||||
static GstInterpolateMethod interpolate_trigger = {
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_int,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_uint,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_long,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_ulong,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_int64,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_uint64,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_float,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_double,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_boolean,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_enum,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array,
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_string,
|
||||
(GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array
|
||||
};
|
||||
|
||||
/* linear interpolation */
|
||||
/* smoothes inbetween values */
|
||||
|
@ -419,7 +202,7 @@ _interpolate_linear_internal_##vtype (GstClockTime timestamp1, g##vtype value1,
|
|||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
interpolate_linear_get_##vtype (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
{ \
|
||||
g##vtype ret, min, max; \
|
||||
GSequenceIter *iter; \
|
||||
|
@ -427,20 +210,20 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
|||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
||||
min = g_value_get_##vtype (&self->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->maximum_value); \
|
||||
\
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
|
||||
if (iter) { \
|
||||
cp1 = g_sequence_get (iter); \
|
||||
iter = g_sequence_iter_next (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); \
|
||||
g_value_init (&cp.value, self->type); \
|
||||
g_value_copy (&self->default_value, &cp.value); \
|
||||
cp1 = &cp; \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter = g_sequence_get_begin_iter (self->values); \
|
||||
} \
|
||||
if (iter && !g_sequence_iter_is_end (iter)) \
|
||||
cp2 = g_sequence_get (iter); \
|
||||
|
@ -454,7 +237,7 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
|||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *self, \
|
||||
interpolate_linear_get_##vtype##_value_array (GstTimedValueControlSource *self, \
|
||||
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||
{ \
|
||||
guint i; \
|
||||
|
@ -468,19 +251,19 @@ interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *sel
|
|||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||
g_value_init (&cp.value, self->priv->type); \
|
||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
||||
g_value_init (&cp.value, self->type); \
|
||||
g_value_copy (&self->default_value, &cp.value); \
|
||||
\
|
||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
||||
min = g_value_get_##vtype (&self->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->maximum_value); \
|
||||
\
|
||||
for(i = 0; i < n_values; i++) { \
|
||||
if (timestamp >= next_ts) { \
|
||||
iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
|
||||
iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
|
||||
if (!iter1) { \
|
||||
cp1 = &cp; \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||
else \
|
||||
iter2 = NULL; \
|
||||
} else { \
|
||||
|
@ -560,9 +343,9 @@ static GstInterpolateMethod interpolate_linear = {
|
|||
|
||||
#define DEFINE_CUBIC_GET(vtype,round, convert) \
|
||||
static void \
|
||||
_interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
||||
_interpolate_cubic_update_cache_##vtype (GstTimedValueControlSource *self) \
|
||||
{ \
|
||||
gint i, n = self->priv->nvalues; \
|
||||
gint i, n = self->nvalues; \
|
||||
gdouble *o = g_new0 (gdouble, n); \
|
||||
gdouble *p = g_new0 (gdouble, n); \
|
||||
gdouble *q = g_new0 (gdouble, n); \
|
||||
|
@ -577,7 +360,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
g##vtype y_prev, y, y_next; \
|
||||
\
|
||||
/* Fill linear system of equations */ \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
iter = g_sequence_get_begin_iter (self->values); \
|
||||
cp = g_sequence_get (iter); \
|
||||
x = cp->timestamp; \
|
||||
y = g_value_get_##vtype (&cp->value); \
|
||||
|
@ -622,7 +405,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
\
|
||||
/* Save cache next in the GstControlPoint */ \
|
||||
\
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
iter = g_sequence_get_begin_iter (self->values); \
|
||||
for (i = 0; i < n; i++) { \
|
||||
cp = g_sequence_get (iter); \
|
||||
cp->cache.cubic.h = h[i]; \
|
||||
|
@ -640,11 +423,11 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
|||
} \
|
||||
\
|
||||
static inline void \
|
||||
_interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
|
||||
_interpolate_cubic_get_##vtype (GstTimedValueControlSource *self, GstControlPoint *cp1, g##vtype value1, GstControlPoint *cp2, g##vtype value2, GstClockTime timestamp, g##vtype min, g##vtype max, g##vtype *ret) \
|
||||
{ \
|
||||
if (!self->priv->valid_cache) { \
|
||||
if (!self->valid_cache) { \
|
||||
_interpolate_cubic_update_cache_##vtype (self); \
|
||||
self->priv->valid_cache = TRUE; \
|
||||
self->valid_cache = TRUE; \
|
||||
} \
|
||||
\
|
||||
if (cp2) { \
|
||||
|
@ -670,31 +453,31 @@ _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlP
|
|||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
interpolate_cubic_get_##vtype (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
{ \
|
||||
g##vtype ret, min, max; \
|
||||
GSequenceIter *iter; \
|
||||
GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
|
||||
\
|
||||
if (self->priv->nvalues <= 2) \
|
||||
if (self->nvalues <= 2) \
|
||||
return interpolate_linear_get_##vtype (self, timestamp, value); \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
||||
min = g_value_get_##vtype (&self->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->maximum_value); \
|
||||
\
|
||||
iter = gst_interpolation_control_source_find_control_point_iter (self, timestamp); \
|
||||
iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
|
||||
if (iter) { \
|
||||
cp1 = g_sequence_get (iter); \
|
||||
iter = g_sequence_iter_next (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); \
|
||||
g_value_init (&cp.value, self->type); \
|
||||
g_value_copy (&self->default_value, &cp.value); \
|
||||
cp1 = &cp; \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter = g_sequence_get_begin_iter (self->values); \
|
||||
} \
|
||||
if (iter && !g_sequence_iter_is_end (iter)) \
|
||||
cp2 = g_sequence_get (iter); \
|
||||
|
@ -708,7 +491,7 @@ interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime
|
|||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self, \
|
||||
interpolate_cubic_get_##vtype##_value_array (GstTimedValueControlSource *self, \
|
||||
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||
{ \
|
||||
guint i; \
|
||||
|
@ -719,25 +502,25 @@ interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self
|
|||
GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
|
||||
g##vtype val1 = 0, val2 = 0, min, max; \
|
||||
\
|
||||
if (self->priv->nvalues <= 2) \
|
||||
if (self->nvalues <= 2) \
|
||||
return interpolate_linear_get_##vtype##_value_array (self, timestamp, interval, n_values, values); \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||
g_value_init (&cp.value, self->priv->type); \
|
||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
||||
g_value_init (&cp.value, self->type); \
|
||||
g_value_copy (&self->default_value, &cp.value); \
|
||||
\
|
||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
||||
min = g_value_get_##vtype (&self->minimum_value); \
|
||||
max = g_value_get_##vtype (&self->maximum_value); \
|
||||
\
|
||||
for(i = 0; i < n_values; i++) { \
|
||||
if (timestamp >= next_ts) { \
|
||||
iter1 = gst_interpolation_control_source_find_control_point_iter (self, ts); \
|
||||
iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
|
||||
if (!iter1) { \
|
||||
cp1 = &cp; \
|
||||
if (G_LIKELY (self->priv->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||
else \
|
||||
iter2 = NULL; \
|
||||
} else { \
|
||||
|
@ -801,7 +584,6 @@ static GstInterpolateMethod interpolate_cubic = {
|
|||
/* register all interpolation methods */
|
||||
GstInterpolateMethod *priv_gst_interpolation_methods[] = {
|
||||
&interpolate_none,
|
||||
&interpolate_trigger,
|
||||
&interpolate_linear,
|
||||
&interpolate_cubic,
|
||||
&interpolate_cubic
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
* To use #GstInterpolationControlSource get a new instance by calling
|
||||
* gst_interpolation_control_source_new(), bind it to a #GParamSpec, select a interpolation mode with
|
||||
* gst_interpolation_control_source_set_interpolation_mode() and set some control points by calling
|
||||
* gst_interpolation_control_source_set().
|
||||
* gst_timed_value_control_source_set().
|
||||
*
|
||||
* All functions are MT-safe.
|
||||
*
|
||||
|
@ -48,54 +48,17 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#define _do_init \
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, "timeline value interpolating control source")
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "interpolation control source", 0, \
|
||||
"timeline value interpolating control source")
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstInterpolationControlSource,
|
||||
gst_interpolation_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
|
||||
gst_interpolation_control_source, GST_TYPE_TIMED_VALUE_CONTROL_SOURCE,
|
||||
_do_init);
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
struct _GstInterpolationControlSourcePrivate
|
||||
{
|
||||
g_return_if_fail (cp);
|
||||
|
||||
g_value_unset (&cp->value);
|
||||
g_slice_free (GstControlPoint, cp);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
|
||||
{
|
||||
GstControlSource *csource = (GstControlSource *) self;
|
||||
|
||||
csource->get_value = NULL;
|
||||
csource->get_value_array = NULL;
|
||||
|
||||
self->priv->type = self->priv->base = G_TYPE_INVALID;
|
||||
|
||||
if (G_IS_VALUE (&self->priv->default_value))
|
||||
g_value_unset (&self->priv->default_value);
|
||||
if (G_IS_VALUE (&self->priv->minimum_value))
|
||||
g_value_unset (&self->priv->minimum_value);
|
||||
if (G_IS_VALUE (&self->priv->maximum_value))
|
||||
g_value_unset (&self->priv->maximum_value);
|
||||
|
||||
if (self->priv->values) {
|
||||
g_sequence_free (self->priv->values);
|
||||
self->priv->values = NULL;
|
||||
}
|
||||
|
||||
self->priv->nvalues = 0;
|
||||
self->priv->valid_cache = FALSE;
|
||||
}
|
||||
GstInterpolateMode interpolation_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_new:
|
||||
|
@ -142,561 +105,115 @@ gst_interpolation_control_source_set_interpolation_mode (
|
|||
"interpolation mode");
|
||||
}
|
||||
|
||||
if (mode == GST_INTERPOLATE_USER) {
|
||||
GST_WARNING ("User interpolation mode is not implemented yet");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
switch (self->priv->base) {
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
|
||||
switch (gst_timed_value_control_source_get_base_value_type (
|
||||
(GstTimedValueControlSource *) self)) {
|
||||
case G_TYPE_INT:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_int_value_array;
|
||||
break;
|
||||
case G_TYPE_UINT:{
|
||||
case G_TYPE_UINT:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_uint_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_LONG:{
|
||||
case G_TYPE_LONG:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_long_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ULONG:{
|
||||
case G_TYPE_ULONG:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_ulong_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_INT64:{
|
||||
case G_TYPE_INT64:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_int64_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_UINT64:{
|
||||
case G_TYPE_UINT64:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_uint64_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_FLOAT:{
|
||||
case G_TYPE_FLOAT:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_float_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_DOUBLE:{
|
||||
case G_TYPE_DOUBLE:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_double_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_BOOLEAN:{
|
||||
case G_TYPE_BOOLEAN:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_boolean_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ENUM:{
|
||||
case G_TYPE_ENUM:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_enum_value_array;
|
||||
break;
|
||||
}
|
||||
case G_TYPE_STRING:{
|
||||
case G_TYPE_STRING:
|
||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
|
||||
csource->get_value_array =
|
||||
priv_gst_interpolation_methods[mode]->get_string_value_array;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Incomplete implementation */
|
||||
if (!ret || !csource->get_value || !csource->get_value_array) {
|
||||
gst_interpolation_control_source_reset (self);
|
||||
if (!csource->get_value || !csource->get_value_array) {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
self->priv->valid_cache = FALSE;
|
||||
gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
|
||||
csource);
|
||||
self->priv->interpolation_mode = mode;
|
||||
|
||||
g_mutex_unlock (self->lock);
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_interpolation_control_source_bind (GstControlSource * source,
|
||||
gst_interpolation_control_source_bind (GstControlSource * csource,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GType type, base;
|
||||
GstInterpolationControlSource *self =
|
||||
(GstInterpolationControlSource *) source;
|
||||
gboolean ret = TRUE;
|
||||
if (GST_CONTROL_SOURCE_CLASS
|
||||
(gst_interpolation_control_source_parent_class)->bind (csource, pspec)) {
|
||||
GstInterpolationControlSource *self =
|
||||
GST_INTERPOLATION_CONTROL_SOURCE (csource);
|
||||
|
||||
/* get the fundamental base type */
|
||||
self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||
while ((type = g_type_parent (type)))
|
||||
base = type;
|
||||
|
||||
self->priv->base = base;
|
||||
/* restore type */
|
||||
type = self->priv->type;
|
||||
|
||||
if (!gst_interpolation_control_source_set_interpolation_mode (self,
|
||||
self->priv->interpolation_mode))
|
||||
return FALSE;
|
||||
|
||||
switch (base) {
|
||||
case G_TYPE_INT:{
|
||||
GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_int (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_UINT:{
|
||||
GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_uint (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_LONG:{
|
||||
GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_long (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ULONG:{
|
||||
GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_ulong (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_INT64:{
|
||||
GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_int64 (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_UINT64:{
|
||||
GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_uint64 (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_FLOAT:{
|
||||
GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_float (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_DOUBLE:{
|
||||
GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_double (&self->priv->default_value, tpspec->default_value);
|
||||
g_value_init (&self->priv->minimum_value, type);
|
||||
g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->priv->maximum_value, type);
|
||||
g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_BOOLEAN:{
|
||||
GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_boolean (&self->priv->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ENUM:{
|
||||
GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_enum (&self->priv->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_STRING:{
|
||||
GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
|
||||
|
||||
g_value_init (&self->priv->default_value, type);
|
||||
g_value_set_string (&self->priv->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GST_WARNING ("incomplete implementation for paramspec type '%s'",
|
||||
G_PARAM_SPEC_TYPE_NAME (pspec));
|
||||
ret = FALSE;
|
||||
break;
|
||||
if (gst_interpolation_control_source_set_interpolation_mode (self,
|
||||
self->priv->interpolation_mode))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
self->priv->valid_cache = FALSE;
|
||||
self->priv->nvalues = 0;
|
||||
} else {
|
||||
gst_interpolation_control_source_reset (self);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 #GstControlPoint
|
||||
* parameters.
|
||||
*/
|
||||
static gint
|
||||
gst_control_point_compare (gconstpointer p1, gconstpointer p2)
|
||||
{
|
||||
GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
|
||||
GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
|
||||
|
||||
return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 #GstControlPoint and
|
||||
* a #GstClockTime.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
static GstControlPoint *
|
||||
_make_new_cp (GstInterpolationControlSource * self, GstClockTime timestamp,
|
||||
const GValue * value)
|
||||
{
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* create a new GstControlPoint */
|
||||
cp = g_slice_new0 (GstControlPoint);
|
||||
cp->timestamp = timestamp;
|
||||
g_value_init (&cp->value, self->priv->type);
|
||||
g_value_copy (value, &cp->value);
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
|
||||
self, GstClockTime timestamp, const GValue * value)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
/* check if a control point for the timestamp already exists */
|
||||
|
||||
/* iter contains the iter right *after* timestamp */
|
||||
if (G_LIKELY (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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self->priv->values =
|
||||
g_sequence_new ((GDestroyNotify) gst_control_point_free);
|
||||
}
|
||||
|
||||
/* sort new cp into the prop->values list */
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_set:
|
||||
* @self: the #GstInterpolationControlSource object
|
||||
* @timestamp: the time the control-change is scheduled for
|
||||
* @value: the control-value
|
||||
*
|
||||
* Set the value of given controller-handled property at a certain time.
|
||||
*
|
||||
* Returns: FALSE if the values couldn't be set, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_interpolation_control_source_set (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp, const GValue * value)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
|
||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||
g_return_val_if_fail (G_IS_VALUE (value), FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (value) == self->priv->type, FALSE);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
gst_interpolation_control_source_set_internal (self, timestamp, value);
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_set_from_list:
|
||||
* @self: the #GstInterpolationControlSource object
|
||||
* @timedvalues: (transfer none) (element-type GstController.TimedValue): a list
|
||||
* with #GstTimedValue items
|
||||
*
|
||||
* Sets multiple timed values at once.
|
||||
*
|
||||
* Returns: FALSE if the values couldn't be set, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_interpolation_control_source_set_from_list (GstInterpolationControlSource *
|
||||
self, const GSList * timedvalues)
|
||||
{
|
||||
const GSList *node;
|
||||
GstTimedValue *tv;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
|
||||
|
||||
for (node = timedvalues; node; node = g_slist_next (node)) {
|
||||
tv = node->data;
|
||||
if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
|
||||
GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
|
||||
GST_FUNCTION);
|
||||
} else if (!G_IS_VALUE (&tv->value)) {
|
||||
GST_WARNING ("GstTimedValued with invalid value passed to %s",
|
||||
GST_FUNCTION);
|
||||
} else if (G_VALUE_TYPE (&tv->value) != self->priv->type) {
|
||||
GST_WARNING ("incompatible value type for property");
|
||||
} else {
|
||||
g_mutex_lock (self->lock);
|
||||
gst_interpolation_control_source_set_internal (self, tv->timestamp,
|
||||
&tv->value);
|
||||
g_mutex_unlock (self->lock);
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_unset:
|
||||
* @self: the #GstInterpolationControlSource object
|
||||
* @timestamp: the time the control-change should be removed from
|
||||
*
|
||||
* Used to remove the value of given controller-handled property at a certain
|
||||
* time.
|
||||
*
|
||||
* Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), FALSE);
|
||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
/* check if a control point for the timestamp exists */
|
||||
if (G_LIKELY (self->priv->values) && (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);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_unset_all:
|
||||
* @self: the #GstInterpolationControlSource object
|
||||
*
|
||||
* Used to remove all time-stamped values of given controller-handled property
|
||||
*
|
||||
*/
|
||||
void
|
||||
gst_interpolation_control_source_unset_all (GstInterpolationControlSource *
|
||||
self)
|
||||
{
|
||||
g_return_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self));
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
/* free GstControlPoint structures */
|
||||
if (self->priv->values) {
|
||||
g_sequence_free (self->priv->values);
|
||||
self->priv->values = NULL;
|
||||
}
|
||||
self->priv->nvalues = 0;
|
||||
self->priv->valid_cache = FALSE;
|
||||
|
||||
g_mutex_unlock (self->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
_append_control_point (GstControlPoint * cp, GQueue * res)
|
||||
{
|
||||
g_queue_push_tail (res, cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_get_all:
|
||||
* @self: the #GstInterpolationControlSource to get the list from
|
||||
*
|
||||
* Returns a read-only copy of the list of #GstTimedValue for the given property.
|
||||
* Free the list after done with it.
|
||||
*
|
||||
* Returns: (transfer container) (element-type GstController.TimedValue): a copy
|
||||
* of the list, or %NULL if the property isn't handled by the controller
|
||||
*/
|
||||
GList *
|
||||
gst_interpolation_control_source_get_all (GstInterpolationControlSource * self)
|
||||
{
|
||||
GQueue res = G_QUEUE_INIT;
|
||||
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
if (G_LIKELY (self->priv->values))
|
||||
g_sequence_foreach (self->priv->values, (GFunc) _append_control_point,
|
||||
&res);
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return res.head;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_interpolation_control_source_get_count:
|
||||
* @self: the #GstInterpolationControlSource to get the number of values from
|
||||
*
|
||||
* Returns the number of control points that are set.
|
||||
*
|
||||
* Returns: the number of control points that are set.
|
||||
*
|
||||
*/
|
||||
gint
|
||||
gst_interpolation_control_source_get_count (GstInterpolationControlSource *
|
||||
self)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 0);
|
||||
return self->priv->nvalues;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_init (GstInterpolationControlSource * self)
|
||||
{
|
||||
self->lock = g_mutex_new ();
|
||||
self->priv =
|
||||
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
|
||||
GstInterpolationControlSourcePrivate);
|
||||
self->priv->interpolation_mode = GST_INTERPOLATE_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_finalize (GObject * obj)
|
||||
{
|
||||
GstInterpolationControlSource *self = GST_INTERPOLATION_CONTROL_SOURCE (obj);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
gst_interpolation_control_source_reset (self);
|
||||
g_mutex_unlock (self->lock);
|
||||
g_mutex_free (self->lock);
|
||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_dispose (GObject * obj)
|
||||
{
|
||||
G_OBJECT_CLASS (parent_class)->dispose (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
|
||||
* klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
g_type_class_add_private (klass,
|
||||
sizeof (GstInterpolationControlSourcePrivate));
|
||||
|
||||
gobject_class->finalize = gst_interpolation_control_source_finalize;
|
||||
gobject_class->dispose = gst_interpolation_control_source_dispose;
|
||||
csource_class->bind = gst_interpolation_control_source_bind;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/gstcontrolsource.h>
|
||||
#include <gst/controller/gsttimedvaluecontrolsource.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -51,23 +51,18 @@ typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSour
|
|||
/**
|
||||
* GstInterpolateMode:
|
||||
* @GST_INTERPOLATE_NONE: steps-like interpolation, default
|
||||
* @GST_INTERPOLATE_TRIGGER: returns the default value of the property,
|
||||
* except for times with specific values
|
||||
* @GST_INTERPOLATE_LINEAR: linear interpolation
|
||||
* @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
|
||||
* @GST_INTERPOLATE_CUBIC: cubic interpolation
|
||||
* @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
|
||||
*
|
||||
* The various interpolation modes available.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GST_INTERPOLATE_NONE,
|
||||
GST_INTERPOLATE_TRIGGER,
|
||||
GST_INTERPOLATE_LINEAR,
|
||||
GST_INTERPOLATE_QUADRATIC,
|
||||
GST_INTERPOLATE_CUBIC,
|
||||
GST_INTERPOLATE_USER
|
||||
GST_INTERPOLATE_CUBIC
|
||||
} GstInterpolateMode;
|
||||
|
||||
/**
|
||||
|
@ -76,17 +71,15 @@ typedef enum
|
|||
* The instance structure of #GstControlSource.
|
||||
*/
|
||||
struct _GstInterpolationControlSource {
|
||||
GstControlSource parent;
|
||||
GstTimedValueControlSource parent;
|
||||
|
||||
/* <private> */
|
||||
GMutex *lock;
|
||||
/*< private >*/
|
||||
GstInterpolationControlSourcePrivate *priv;
|
||||
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstInterpolationControlSourceClass {
|
||||
GstControlSourceClass parent_class;
|
||||
GstTimedValueControlSourceClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
|
@ -101,16 +94,6 @@ GstInterpolationControlSource *
|
|||
gboolean gst_interpolation_control_source_set_interpolation_mode
|
||||
(GstInterpolationControlSource *self,
|
||||
GstInterpolateMode mode);
|
||||
gboolean gst_interpolation_control_source_set (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp,
|
||||
const GValue * value);
|
||||
gboolean gst_interpolation_control_source_set_from_list (GstInterpolationControlSource * self,
|
||||
const GSList * timedvalues);
|
||||
gboolean gst_interpolation_control_source_unset (GstInterpolationControlSource * self,
|
||||
GstClockTime timestamp);
|
||||
void gst_interpolation_control_source_unset_all (GstInterpolationControlSource *self);
|
||||
GList * gst_interpolation_control_source_get_all (GstInterpolationControlSource * self);
|
||||
gint gst_interpolation_control_source_get_count (GstInterpolationControlSource * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -80,21 +80,6 @@ typedef struct _GstControlPoint
|
|||
|
||||
} GstControlPoint;
|
||||
|
||||
struct _GstInterpolationControlSourcePrivate
|
||||
{
|
||||
GType type; /* type of the handled property */
|
||||
GType base; /* base-type of the handled property */
|
||||
|
||||
GValue default_value; /* default value for the handled property */
|
||||
GValue minimum_value; /* min value for the handled property */
|
||||
GValue maximum_value; /* max value for the handled property */
|
||||
GstInterpolateMode interpolation_mode;
|
||||
|
||||
GSequence *values; /* List of GstControlPoint */
|
||||
gint nvalues; /* Number of control points */
|
||||
gboolean valid_cache;
|
||||
};
|
||||
|
||||
extern GstInterpolateMethod *priv_gst_interpolation_methods[];
|
||||
extern guint priv_gst_num_interpolation_methods;
|
||||
|
||||
|
|
603
libs/gst/controller/gsttimedvaluecontrolsource.c
Normal file
603
libs/gst/controller/gsttimedvaluecontrolsource.c
Normal file
|
@ -0,0 +1,603 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
* 2011 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttimedvaluecontrolsource.c: Base class for timeed value based control
|
||||
* sources
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gsttimedvaluecontrolsource
|
||||
* @short_description: timed value control source base class
|
||||
*
|
||||
* Base class for #GstContrlSources that use time-stamped values.
|
||||
*
|
||||
* When overriding bind, chain up first to give this bind implementation a
|
||||
* chance to setup things.
|
||||
*
|
||||
* All functions are MT-safe.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstinterpolationcontrolsource.h"
|
||||
#include "gstinterpolationcontrolsourceprivate.h"
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT controller_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
#define _do_init \
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "timed value control source", 0, \
|
||||
"timed value control source base class")
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstTimedValueControlSource,
|
||||
gst_timed_value_control_source, GST_TYPE_CONTROL_SOURCE, _do_init);
|
||||
|
||||
/*
|
||||
* 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_slice_free (GstControlPoint, cp);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_timed_value_control_source_reset (GstTimedValueControlSource * self)
|
||||
{
|
||||
GstControlSource *csource = (GstControlSource *) self;
|
||||
|
||||
csource->get_value = NULL;
|
||||
csource->get_value_array = NULL;
|
||||
|
||||
self->type = self->base = G_TYPE_INVALID;
|
||||
|
||||
if (G_IS_VALUE (&self->default_value))
|
||||
g_value_unset (&self->default_value);
|
||||
if (G_IS_VALUE (&self->minimum_value))
|
||||
g_value_unset (&self->minimum_value);
|
||||
if (G_IS_VALUE (&self->maximum_value))
|
||||
g_value_unset (&self->maximum_value);
|
||||
|
||||
if (self->values) {
|
||||
g_sequence_free (self->values);
|
||||
self->values = NULL;
|
||||
}
|
||||
|
||||
self->nvalues = 0;
|
||||
self->valid_cache = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_timed_value_control_source_bind (GstControlSource * source,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GType type, base;
|
||||
GstTimedValueControlSource *self = (GstTimedValueControlSource *) source;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
/* get the fundamental base type */
|
||||
self->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||
while ((type = g_type_parent (type)))
|
||||
base = type;
|
||||
|
||||
self->base = base;
|
||||
/* restore type */
|
||||
type = self->type;
|
||||
|
||||
switch (base) {
|
||||
case G_TYPE_INT:{
|
||||
GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_int (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_int (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_int (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_UINT:{
|
||||
GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_uint (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_uint (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_uint (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_LONG:{
|
||||
GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_long (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_long (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_long (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ULONG:{
|
||||
GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_ulong (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_ulong (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_ulong (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_INT64:{
|
||||
GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_int64 (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_int64 (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_int64 (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_UINT64:{
|
||||
GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_uint64 (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_uint64 (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_uint64 (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_FLOAT:{
|
||||
GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_float (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_float (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_float (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_DOUBLE:{
|
||||
GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_double (&self->default_value, tpspec->default_value);
|
||||
g_value_init (&self->minimum_value, type);
|
||||
g_value_set_double (&self->minimum_value, tpspec->minimum);
|
||||
g_value_init (&self->maximum_value, type);
|
||||
g_value_set_double (&self->maximum_value, tpspec->maximum);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_BOOLEAN:{
|
||||
GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_boolean (&self->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_ENUM:{
|
||||
GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_enum (&self->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
case G_TYPE_STRING:{
|
||||
GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
|
||||
|
||||
g_value_init (&self->default_value, type);
|
||||
g_value_set_string (&self->default_value, tpspec->default_value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GST_WARNING ("incomplete implementation for paramspec type '%s'",
|
||||
G_PARAM_SPEC_TYPE_NAME (pspec));
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
self->valid_cache = FALSE;
|
||||
self->nvalues = 0;
|
||||
} else {
|
||||
gst_timed_value_control_source_reset (self);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 #GstControlPoint
|
||||
* parameters.
|
||||
*/
|
||||
static gint
|
||||
gst_control_point_compare (gconstpointer p1, gconstpointer p2)
|
||||
{
|
||||
GstClockTime ct1 = ((GstControlPoint *) p1)->timestamp;
|
||||
GstClockTime ct2 = ((GstControlPoint *) p2)->timestamp;
|
||||
|
||||
return ((ct1 < ct2) ? -1 : ((ct1 == ct2) ? 0 : 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 #GstControlPoint and
|
||||
* a #GstClockTime.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
static GstControlPoint *
|
||||
_make_new_cp (GstTimedValueControlSource * self, GstClockTime timestamp,
|
||||
const GValue * value)
|
||||
{
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* create a new GstControlPoint */
|
||||
cp = g_slice_new0 (GstControlPoint);
|
||||
cp->timestamp = timestamp;
|
||||
g_value_init (&cp->value, self->type);
|
||||
g_value_copy (value, &cp->value);
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_timed_value_control_source_set_internal (GstTimedValueControlSource *
|
||||
self, GstClockTime timestamp, const GValue * value)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
/* check if a control point for the timestamp already exists */
|
||||
|
||||
/* iter contains the iter right *after* timestamp */
|
||||
if (G_LIKELY (self->values)) {
|
||||
iter =
|
||||
g_sequence_search (self->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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self->values = g_sequence_new ((GDestroyNotify) gst_control_point_free);
|
||||
}
|
||||
|
||||
/* sort new cp into the prop->values list */
|
||||
g_sequence_insert_sorted (self->values, _make_new_cp (self, timestamp,
|
||||
value), (GCompareDataFunc) gst_control_point_compare, NULL);
|
||||
self->nvalues++;
|
||||
|
||||
done:
|
||||
self->valid_cache = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_find_control_point_iter:
|
||||
* @self: the control source to search in
|
||||
* @timestamp: the search key
|
||||
*
|
||||
* Find last value before given timestamp in control point list.
|
||||
* If all values in the control point list come after the given
|
||||
* timestamp or no values exist, %NULL is returned.
|
||||
*
|
||||
* For use in control source implementations.
|
||||
*
|
||||
* Returns: the found #GSequenceIter or %NULL
|
||||
*/
|
||||
GSequenceIter *gst_timed_value_control_source_find_control_point_iter
|
||||
(GstTimedValueControlSource * self, GstClockTime timestamp)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
if (!self->values)
|
||||
return NULL;
|
||||
|
||||
iter =
|
||||
g_sequence_search (self->values, ×tamp,
|
||||
(GCompareDataFunc) gst_control_point_find, NULL);
|
||||
|
||||
/* g_sequence_search() returns the iter where timestamp
|
||||
* would be inserted, i.e. the iter > timestamp, so
|
||||
* we need to get the previous one. And of course, if
|
||||
* there is no previous one, we return NULL. */
|
||||
if (g_sequence_iter_is_begin (iter))
|
||||
return NULL;
|
||||
|
||||
return g_sequence_iter_prev (iter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_set:
|
||||
* @self: the #GstTimedValueControlSource object
|
||||
* @timestamp: the time the control-change is scheduled for
|
||||
* @value: the control-value
|
||||
*
|
||||
* Set the value of given controller-handled property at a certain time.
|
||||
*
|
||||
* Returns: FALSE if the values couldn't be set, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_timed_value_control_source_set (GstTimedValueControlSource * self,
|
||||
GstClockTime timestamp, const GValue * value)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
|
||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||
g_return_val_if_fail (G_IS_VALUE (value), FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (value) == self->type, FALSE);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
gst_timed_value_control_source_set_internal (self, timestamp, value);
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_set_from_list:
|
||||
* @self: the #GstTimedValueControlSource object
|
||||
* @timedvalues: (transfer none) (element-type GstController.TimedValue): a list
|
||||
* with #GstTimedValue items
|
||||
*
|
||||
* Sets multiple timed values at once.
|
||||
*
|
||||
* Returns: FALSE if the values couldn't be set, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_timed_value_control_source_set_from_list (GstTimedValueControlSource *
|
||||
self, const GSList * timedvalues)
|
||||
{
|
||||
const GSList *node;
|
||||
GstTimedValue *tv;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
|
||||
|
||||
for (node = timedvalues; node; node = g_slist_next (node)) {
|
||||
tv = node->data;
|
||||
if (!GST_CLOCK_TIME_IS_VALID (tv->timestamp)) {
|
||||
GST_WARNING ("GstTimedValued with invalid timestamp passed to %s",
|
||||
GST_FUNCTION);
|
||||
} else if (!G_IS_VALUE (&tv->value)) {
|
||||
GST_WARNING ("GstTimedValued with invalid value passed to %s",
|
||||
GST_FUNCTION);
|
||||
} else if (G_VALUE_TYPE (&tv->value) != self->type) {
|
||||
GST_WARNING ("incompatible value type for property");
|
||||
} else {
|
||||
g_mutex_lock (self->lock);
|
||||
gst_timed_value_control_source_set_internal (self, tv->timestamp,
|
||||
&tv->value);
|
||||
g_mutex_unlock (self->lock);
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_unset:
|
||||
* @self: the #GstTimedValueControlSource object
|
||||
* @timestamp: the time the control-change should be removed from
|
||||
*
|
||||
* Used to remove the value of given controller-handled property at a certain
|
||||
* time.
|
||||
*
|
||||
* Returns: FALSE if the value couldn't be unset (i.e. not found, TRUE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
|
||||
GstClockTime timestamp)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), FALSE);
|
||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
/* check if a control point for the timestamp exists */
|
||||
if (G_LIKELY (self->values) && (iter =
|
||||
g_sequence_search (self->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->nvalues--;
|
||||
self->valid_cache = FALSE;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_unset_all:
|
||||
* @self: the #GstTimedValueControlSource object
|
||||
*
|
||||
* Used to remove all time-stamped values of given controller-handled property
|
||||
*
|
||||
*/
|
||||
void
|
||||
gst_timed_value_control_source_unset_all (GstTimedValueControlSource * self)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
/* free GstControlPoint structures */
|
||||
if (self->values) {
|
||||
g_sequence_free (self->values);
|
||||
self->values = NULL;
|
||||
}
|
||||
self->nvalues = 0;
|
||||
self->valid_cache = FALSE;
|
||||
|
||||
g_mutex_unlock (self->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
_append_control_point (GstControlPoint * cp, GQueue * res)
|
||||
{
|
||||
g_queue_push_tail (res, cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_get_all:
|
||||
* @self: the #GstTimedValueControlSource to get the list from
|
||||
*
|
||||
* Returns a read-only copy of the list of #GstTimedValue for the given property.
|
||||
* Free the list after done with it.
|
||||
*
|
||||
* Returns: (transfer container) (element-type GstController.TimedValue): a copy
|
||||
* of the list, or %NULL if the property isn't handled by the controller
|
||||
*/
|
||||
GList *
|
||||
gst_timed_value_control_source_get_all (GstTimedValueControlSource * self)
|
||||
{
|
||||
GQueue res = G_QUEUE_INIT;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), NULL);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
if (G_LIKELY (self->values))
|
||||
g_sequence_foreach (self->values, (GFunc) _append_control_point, &res);
|
||||
g_mutex_unlock (self->lock);
|
||||
|
||||
return res.head;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_get_count:
|
||||
* @self: the #GstTimedValueControlSource to get the number of values from
|
||||
*
|
||||
* Get the number of control points that are set.
|
||||
*
|
||||
* Returns: the number of control points that are set.
|
||||
*/
|
||||
gint
|
||||
gst_timed_value_control_source_get_count (GstTimedValueControlSource * self)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self), 0);
|
||||
return self->nvalues;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_source_get_base_value_type:
|
||||
* @self: the #GstTimedValueControlSource
|
||||
*
|
||||
* Get the base #GType of the property value.
|
||||
*
|
||||
* Returns: the #GType, %G_TYPE_INVALID if not yet known.
|
||||
*/
|
||||
GType
|
||||
gst_timed_value_control_source_get_base_value_type (GstTimedValueControlSource *
|
||||
self)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self),
|
||||
G_TYPE_INVALID);
|
||||
return self->base;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_timed_value_control_invalidate_cache:
|
||||
* @self: the #GstTimedValueControlSource
|
||||
*
|
||||
* Reset the controlled value cache.
|
||||
*/
|
||||
void
|
||||
gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self)
|
||||
{
|
||||
g_return_if_fail (GST_IS_TIMED_VALUE_CONTROL_SOURCE (self));
|
||||
self->valid_cache = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_timed_value_control_source_init (GstTimedValueControlSource * self)
|
||||
{
|
||||
self->lock = g_mutex_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
gst_timed_value_control_source_finalize (GObject * obj)
|
||||
{
|
||||
GstTimedValueControlSource *self = GST_TIMED_VALUE_CONTROL_SOURCE (obj);
|
||||
|
||||
g_mutex_lock (self->lock);
|
||||
gst_timed_value_control_source_reset (self);
|
||||
g_mutex_unlock (self->lock);
|
||||
g_mutex_free (self->lock);
|
||||
|
||||
G_OBJECT_CLASS (gst_timed_value_control_source_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_timed_value_control_source_class_init (GstTimedValueControlSourceClass
|
||||
* klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gst_timed_value_control_source_finalize;
|
||||
csource_class->bind = gst_timed_value_control_source_bind;
|
||||
}
|
114
libs/gst/controller/gsttimedvaluecontrolsource.h
Normal file
114
libs/gst/controller/gsttimedvaluecontrolsource.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* 2011 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttimedvaluecontrolsource.h: Base class for timeed value based control
|
||||
* sources
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_TIMED_VALUE_CONTROL_SOURCE_H__
|
||||
#define __GST_TIMED_VALUE_CONTROL_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/gstcontrolsource.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_TIMED_VALUE_CONTROL_SOURCE \
|
||||
(gst_timed_value_control_source_get_type ())
|
||||
#define GST_TIMED_VALUE_CONTROL_SOURCE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSource))
|
||||
#define GST_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
|
||||
#define GST_IS_TIMED_VALUE_CONTROL_SOURCE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
|
||||
#define GST_IS_TIMED_VALUE_CONTROL_SOURCE_CLASS(vtable) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE))
|
||||
#define GST_TIMED_VALUE_CONTROL_SOURCE_GET_CLASS(inst) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, GstTimedValueControlSourceClass))
|
||||
|
||||
typedef struct _GstTimedValueControlSource GstTimedValueControlSource;
|
||||
typedef struct _GstTimedValueControlSourceClass GstTimedValueControlSourceClass;
|
||||
typedef struct _GstTimedValueControlSourcePrivate GstTimedValueControlSourcePrivate;
|
||||
|
||||
/**
|
||||
* GstTimedValueControlSource:
|
||||
*
|
||||
* The instance structure of #GstControlSource.
|
||||
*/
|
||||
struct _GstTimedValueControlSource {
|
||||
GstControlSource parent;
|
||||
|
||||
/*< protected >*/
|
||||
GMutex *lock;
|
||||
|
||||
GType type; /* type of the handled property */
|
||||
GType base; /* base-type of the handled property */
|
||||
|
||||
GValue default_value; /* default value for the handled property */
|
||||
GValue minimum_value; /* min value for the handled property */
|
||||
GValue maximum_value; /* max value for the handled property */
|
||||
|
||||
GSequence *values; /* List of GstControlPoint */
|
||||
gint nvalues; /* Number of control points */
|
||||
gboolean valid_cache;
|
||||
|
||||
GstTimedValueControlSourcePrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstTimedValueControlSourceClass {
|
||||
GstControlSourceClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
#define GST_TIMED_VALUE_CONTROL_SOURCE_LOCK(o) \
|
||||
g_mutex_lock(((GstTimedValueControlSource *)o)->lock)
|
||||
#define GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK(o) \
|
||||
g_mutex_unlock(((GstTimedValueControlSource *)o)->lock)
|
||||
|
||||
GType gst_timed_value_control_source_get_type (void);
|
||||
|
||||
/* Functions */
|
||||
|
||||
GSequenceIter * gst_timed_value_control_source_find_control_point_iter (
|
||||
GstTimedValueControlSource * self,
|
||||
GstClockTime timestamp);
|
||||
|
||||
gboolean gst_timed_value_control_source_set (GstTimedValueControlSource * self,
|
||||
GstClockTime timestamp,
|
||||
const GValue * value);
|
||||
gboolean gst_timed_value_control_source_set_from_list (GstTimedValueControlSource * self,
|
||||
const GSList * timedvalues);
|
||||
gboolean gst_timed_value_control_source_unset (GstTimedValueControlSource * self,
|
||||
GstClockTime timestamp);
|
||||
void gst_timed_value_control_source_unset_all (GstTimedValueControlSource *self);
|
||||
GList * gst_timed_value_control_source_get_all (GstTimedValueControlSource * self);
|
||||
gint gst_timed_value_control_source_get_count (GstTimedValueControlSource * self);
|
||||
GType gst_timed_value_control_source_get_base_value_type (
|
||||
GstTimedValueControlSource * self);
|
||||
void gst_timed_value_control_invalidate_cache (GstTimedValueControlSource * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TIMED_VALUE_CONTROL_SOURCE_H__ */
|
404
libs/gst/controller/gsttriggercontrolsource.c
Normal file
404
libs/gst/controller/gsttriggercontrolsource.c
Normal file
|
@ -0,0 +1,404 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
* 2011 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttriggercontrolsource.c: Control source that provides some values at time-
|
||||
* stamps
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gsttriggercontrolsource
|
||||
* @short_description: interpolation control source
|
||||
*
|
||||
* #GstTriggerControlSource is a #GstControlSource, that returns values from user-given
|
||||
* control points. It allows for a tolerance on the time-stamps.
|
||||
*
|
||||
* To use #GstTriggerControlSource get a new instance by calling
|
||||
* gst_trigger_control_source_new(), bind it to a #GParamSpec and set some
|
||||
* control points by calling gst_timed_value_control_source_set().
|
||||
*
|
||||
* All functions are MT-safe.
|
||||
*/
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gsttriggercontrolsource.h"
|
||||
#include "gstinterpolationcontrolsourceprivate.h"
|
||||
#include "gst/glib-compat-private.h"
|
||||
|
||||
#define GST_CAT_DEFAULT controller_debug
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_TOLERANCE = 1,
|
||||
};
|
||||
|
||||
#define _do_init \
|
||||
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "trigger control source", 0, \
|
||||
"timeline value trigger control source")
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstTriggerControlSource, gst_trigger_control_source,
|
||||
GST_TYPE_TIMED_VALUE_CONTROL_SOURCE, _do_init);
|
||||
|
||||
struct _GstTriggerControlSourcePrivate
|
||||
{
|
||||
gint64 tolerance;
|
||||
};
|
||||
|
||||
/* control point accessors */
|
||||
|
||||
/* returns the default value of the property, except for times with specific values */
|
||||
/* needed for one-shot events, such as notes and triggers */
|
||||
static inline const GValue *
|
||||
_interpolate_trigger_get (GstTimedValueControlSource * self,
|
||||
GSequenceIter * iter, GstClockTime timestamp)
|
||||
{
|
||||
GstControlPoint *cp;
|
||||
|
||||
/* check if there is a value at the registered timestamp */
|
||||
if (iter) {
|
||||
gint64 tolerance = ((GstTriggerControlSource *) self)->priv->tolerance;
|
||||
cp = g_sequence_get (iter);
|
||||
if (GST_CLOCK_DIFF (cp->timestamp, timestamp) <= tolerance) {
|
||||
return &cp->value;
|
||||
} else {
|
||||
if ((iter = g_sequence_iter_next (iter))) {
|
||||
cp = g_sequence_get (iter);
|
||||
if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) {
|
||||
return &cp->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self->nvalues > 0)
|
||||
return &self->default_value;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define DEFINE_TRIGGER_GET_FUNC_COMPARABLE(type) \
|
||||
static inline const GValue * \
|
||||
_interpolate_trigger_get_##type (GstTimedValueControlSource *self, GSequenceIter *iter, GstClockTime timestamp) \
|
||||
{ \
|
||||
GstControlPoint *cp; \
|
||||
\
|
||||
/* check if there is a value at the registered timestamp */ \
|
||||
if (iter) { \
|
||||
gint64 tolerance = ((GstTriggerControlSource *)self)->priv->tolerance; \
|
||||
gboolean found = FALSE; \
|
||||
cp = g_sequence_get (iter); \
|
||||
if (GST_CLOCK_DIFF (cp->timestamp,timestamp) <= tolerance ) { \
|
||||
found = TRUE; \
|
||||
} else { \
|
||||
if ((iter = g_sequence_iter_next (iter))) { \
|
||||
cp = g_sequence_get (iter); \
|
||||
if (GST_CLOCK_DIFF (timestamp, cp->timestamp) <= tolerance) { \
|
||||
found = TRUE; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (found) { \
|
||||
g##type ret = g_value_get_##type (&cp->value); \
|
||||
if (g_value_get_##type (&self->minimum_value) > ret) \
|
||||
return &self->minimum_value; \
|
||||
else if (g_value_get_##type (&self->maximum_value) < ret) \
|
||||
return &self->maximum_value; \
|
||||
else \
|
||||
return &cp->value; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (self->nvalues > 0) \
|
||||
return &self->default_value; \
|
||||
else \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define DEFINE_TRIGGER_GET(type, ctype, get_func) \
|
||||
static gboolean \
|
||||
interpolate_trigger_get_##type (GstTimedValueControlSource *self, GstClockTime timestamp, GValue *value) \
|
||||
{ \
|
||||
const GValue *ret; \
|
||||
GSequenceIter *iter; \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
\
|
||||
iter = gst_timed_value_control_source_find_control_point_iter (self, timestamp); \
|
||||
ret = get_func (self, iter, timestamp); \
|
||||
if (!ret) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
\
|
||||
g_value_copy (ret, value); \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return TRUE; \
|
||||
} \
|
||||
\
|
||||
static gboolean \
|
||||
interpolate_trigger_get_##type##_value_array (GstTimedValueControlSource *self, \
|
||||
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||
{ \
|
||||
guint i; \
|
||||
GstClockTime ts = timestamp; \
|
||||
GstClockTime next_ts = 0; \
|
||||
ctype *values = (ctype *) _values; \
|
||||
const GValue *ret_val = NULL; \
|
||||
ctype ret = 0; \
|
||||
GSequenceIter *iter1 = NULL, *iter2 = NULL; \
|
||||
gboolean triggered = FALSE; \
|
||||
\
|
||||
g_mutex_lock (self->lock); \
|
||||
for(i = 0; i < n_values; i++) { \
|
||||
if (!ret_val || ts >= next_ts) { \
|
||||
iter1 = gst_timed_value_control_source_find_control_point_iter (self, ts); \
|
||||
if (!iter1) { \
|
||||
if (G_LIKELY (self->values)) \
|
||||
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||
else \
|
||||
iter2 = NULL; \
|
||||
} else { \
|
||||
iter2 = g_sequence_iter_next (iter1); \
|
||||
} \
|
||||
\
|
||||
if (iter2 && !g_sequence_iter_is_end (iter2)) { \
|
||||
GstControlPoint *cp; \
|
||||
\
|
||||
cp = g_sequence_get (iter2); \
|
||||
next_ts = cp->timestamp; \
|
||||
} else { \
|
||||
next_ts = GST_CLOCK_TIME_NONE; \
|
||||
} \
|
||||
\
|
||||
ret_val = get_func (self, iter1, ts); \
|
||||
if (!ret_val) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
ret = g_value_get_##type (ret_val); \
|
||||
triggered = TRUE; \
|
||||
} else if (triggered) { \
|
||||
ret_val = get_func (self, iter1, ts); \
|
||||
if (!ret_val) { \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return FALSE; \
|
||||
} \
|
||||
ret = g_value_get_##type (ret_val); \
|
||||
triggered = FALSE; \
|
||||
} \
|
||||
*values = ret; \
|
||||
ts += interval; \
|
||||
values++; \
|
||||
} \
|
||||
g_mutex_unlock (self->lock); \
|
||||
return TRUE; \
|
||||
}
|
||||
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int);
|
||||
DEFINE_TRIGGER_GET (int, gint, _interpolate_trigger_get_int);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint);
|
||||
DEFINE_TRIGGER_GET (uint, guint, _interpolate_trigger_get_uint);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (long);
|
||||
DEFINE_TRIGGER_GET (long, glong, _interpolate_trigger_get_long);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (ulong);
|
||||
DEFINE_TRIGGER_GET (ulong, gulong, _interpolate_trigger_get_ulong);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (int64);
|
||||
DEFINE_TRIGGER_GET (int64, gint64, _interpolate_trigger_get_int64);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (uint64);
|
||||
DEFINE_TRIGGER_GET (uint64, guint64, _interpolate_trigger_get_uint64);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (float);
|
||||
DEFINE_TRIGGER_GET (float, gfloat, _interpolate_trigger_get_float);
|
||||
DEFINE_TRIGGER_GET_FUNC_COMPARABLE (double);
|
||||
DEFINE_TRIGGER_GET (double, gdouble, _interpolate_trigger_get_double);
|
||||
|
||||
DEFINE_TRIGGER_GET (boolean, gboolean, _interpolate_trigger_get);
|
||||
DEFINE_TRIGGER_GET (enum, gint, _interpolate_trigger_get);
|
||||
DEFINE_TRIGGER_GET (string, const gchar *, _interpolate_trigger_get);
|
||||
|
||||
/**
|
||||
* gst_trigger_control_source_new:
|
||||
*
|
||||
* This returns a new, unbound #GstTriggerControlSource.
|
||||
*
|
||||
* Returns: a new, unbound #GstTriggerControlSource.
|
||||
*/
|
||||
GstTriggerControlSource *
|
||||
gst_trigger_control_source_new (void)
|
||||
{
|
||||
return g_object_newv (GST_TYPE_TRIGGER_CONTROL_SOURCE, 0, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_trigger_control_source_bind (GstControlSource * csource, GParamSpec * pspec)
|
||||
{
|
||||
if (GST_CONTROL_SOURCE_CLASS
|
||||
(gst_trigger_control_source_parent_class)->bind (csource, pspec)) {
|
||||
gboolean ret = TRUE;
|
||||
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (csource);
|
||||
switch (gst_timed_value_control_source_get_base_value_type (
|
||||
(GstTimedValueControlSource *) csource)) {
|
||||
case G_TYPE_INT:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_int;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_int_value_array;
|
||||
break;
|
||||
case G_TYPE_UINT:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_uint;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_uint_value_array;
|
||||
break;
|
||||
case G_TYPE_LONG:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_long;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_long_value_array;
|
||||
break;
|
||||
case G_TYPE_ULONG:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_ulong;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_ulong_value_array;
|
||||
break;
|
||||
case G_TYPE_INT64:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_int64;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_int64_value_array;
|
||||
break;
|
||||
case G_TYPE_UINT64:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_uint64;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_uint64_value_array;
|
||||
break;
|
||||
case G_TYPE_FLOAT:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_float;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_float_value_array;
|
||||
break;
|
||||
case G_TYPE_DOUBLE:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_double;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_double_value_array;
|
||||
break;
|
||||
case G_TYPE_BOOLEAN:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_boolean;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_boolean_value_array;
|
||||
break;
|
||||
case G_TYPE_ENUM:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_enum;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_enum_value_array;
|
||||
break;
|
||||
case G_TYPE_STRING:
|
||||
csource->get_value =
|
||||
(GstControlSourceGetValue) interpolate_trigger_get_string;
|
||||
csource->get_value_array = (GstControlSourceGetValueArray)
|
||||
interpolate_trigger_get_string_value_array;
|
||||
break;
|
||||
default:
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Incomplete implementation */
|
||||
if (!csource->get_value || !csource->get_value_array) {
|
||||
ret = FALSE;
|
||||
}
|
||||
gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
|
||||
csource);
|
||||
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (csource);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_trigger_control_source_init (GstTriggerControlSource * self)
|
||||
{
|
||||
self->priv =
|
||||
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_TRIGGER_CONTROL_SOURCE,
|
||||
GstTriggerControlSourcePrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_trigger_control_source_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TOLERANCE:
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
|
||||
self->priv->tolerance = g_value_get_int64 (value);
|
||||
GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_trigger_control_source_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTriggerControlSource *self = GST_TRIGGER_CONTROL_SOURCE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TOLERANCE:
|
||||
g_value_set_int64 (value, self->priv->tolerance);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_trigger_control_source_class_init (GstTriggerControlSourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GstTriggerControlSourcePrivate));
|
||||
|
||||
gobject_class->set_property = gst_trigger_control_source_set_property;
|
||||
gobject_class->get_property = gst_trigger_control_source_get_property;
|
||||
|
||||
csource_class->bind = gst_trigger_control_source_bind;
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_TOLERANCE,
|
||||
g_param_spec_int64 ("tolerance", "Tolerance",
|
||||
"Amount of ns a control time can be off to still trigger",
|
||||
0, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
}
|
83
libs/gst/controller/gsttriggercontrolsource.h
Normal file
83
libs/gst/controller/gsttriggercontrolsource.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
|
||||
* 2011 Stefan Sauer <ensonic@users.sf.net>
|
||||
*
|
||||
* gsttriggercontrolsource.h: Control source that provides some values at time-
|
||||
* stamps
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GST_TRIGGER_CONTROL_SOURCE_H__
|
||||
#define __GST_TRIGGER_CONTROL_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <gst/controller/gsttimedvaluecontrolsource.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_TRIGGER_CONTROL_SOURCE \
|
||||
(gst_trigger_control_source_get_type ())
|
||||
#define GST_TRIGGER_CONTROL_SOURCE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSource))
|
||||
#define GST_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
|
||||
#define GST_IS_TRIGGER_CONTROL_SOURCE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRIGGER_CONTROL_SOURCE))
|
||||
#define GST_IS_TRIGGER_CONTROL_SOURCE_CLASS(vtable) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_TRIGGER_CONTROL_SOURCE))
|
||||
#define GST_TRIGGER_CONTROL_SOURCE_GET_CLASS(inst) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_TRIGGER_CONTROL_SOURCE, GstTriggerControlSourceClass))
|
||||
|
||||
#define GST_TYPE_TRIGGER_WAVEFORM (gst_trigger_waveform_get_type ())
|
||||
|
||||
typedef struct _GstTriggerControlSource GstTriggerControlSource;
|
||||
typedef struct _GstTriggerControlSourceClass GstTriggerControlSourceClass;
|
||||
typedef struct _GstTriggerControlSourcePrivate GstTriggerControlSourcePrivate;
|
||||
|
||||
/**
|
||||
* GstTriggerControlSource:
|
||||
*
|
||||
* The instance structure of #GstControlSource.
|
||||
*/
|
||||
struct _GstTriggerControlSource {
|
||||
GstTimedValueControlSource parent;
|
||||
|
||||
/*< private >*/
|
||||
GstTriggerControlSourcePrivate *priv;
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
struct _GstTriggerControlSourceClass {
|
||||
GstTimedValueControlSourceClass parent_class;
|
||||
|
||||
/*< private >*/
|
||||
gpointer _gst_reserved[GST_PADDING];
|
||||
};
|
||||
|
||||
GType gst_trigger_control_source_get_type (void);
|
||||
|
||||
/* Functions */
|
||||
|
||||
GstTriggerControlSource *gst_trigger_control_source_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_TRIGGER_CONTROL_SOURCE_H__ */
|
|
@ -126,7 +126,8 @@ main (gint argc, gchar * argv[])
|
|||
|
||||
for (i = 0; i < NUM_CP; i++) {
|
||||
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
|
||||
gst_interpolation_control_source_set (csource, i * tick, &freq);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
|
||||
i * tick, &freq);
|
||||
}
|
||||
|
||||
ct = gst_util_get_timestamp ();
|
||||
|
@ -143,7 +144,8 @@ main (gint argc, gchar * argv[])
|
|||
for (i = 0; i < 100; i++) {
|
||||
j = g_random_int_range (0, NUM_CP - 1);
|
||||
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
|
||||
gst_interpolation_control_source_set (csource, j * tick, &freq);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
|
||||
j * tick, &freq);
|
||||
}
|
||||
|
||||
ct = gst_util_get_timestamp ();
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <gst/check/gstcheck.h>
|
||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||
#include <gst/controller/gstlfocontrolsource.h>
|
||||
#include <gst/controller/gsttriggercontrolsource.h>
|
||||
|
||||
/* LOCAL TEST ELEMENT */
|
||||
|
||||
|
@ -396,6 +397,24 @@ GST_START_TEST (controller_param_twice)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
/* tests if we can run controller methods against any GObject */
|
||||
GST_START_TEST (controller_any_gobject)
|
||||
{
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
|
||||
elem = gst_element_factory_make ("bin", "test_elem");
|
||||
|
||||
/* that element is not controllable */
|
||||
res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
|
||||
/* Syncing should still succeed as there's nothing to sync */
|
||||
fail_unless (res == TRUE, NULL);
|
||||
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* tests if we cleanup properly */
|
||||
GST_START_TEST (controller_controlsource_refcounts)
|
||||
{
|
||||
|
@ -466,10 +485,12 @@ GST_START_TEST (controller_controlsource_empty2)
|
|||
/* set control values */
|
||||
g_value_init (&val, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val, 0);
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND, &val);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource,
|
||||
0 * GST_SECOND, &val);
|
||||
|
||||
/* ... and unset the value */
|
||||
gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
|
||||
gst_timed_value_control_source_unset ((GstTimedValueControlSource *) csource,
|
||||
0 * GST_SECOND);
|
||||
|
||||
/* don't fail on empty control point lists */
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
|
@ -502,22 +523,23 @@ GST_START_TEST (controller_interpolate_none)
|
|||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_NONE));
|
||||
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 0);
|
||||
|
||||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 1);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 2);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
|
@ -534,64 +556,6 @@ GST_START_TEST (controller_interpolate_none)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test timed value handling in trigger mode */
|
||||
GST_START_TEST (controller_interpolate_trigger)
|
||||
{
|
||||
GstInterpolationControlSource *csource;
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
GValue val_ulong = { 0, };
|
||||
|
||||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||
|
||||
/* Get interpolation control source */
|
||||
csource = gst_interpolation_control_source_new ();
|
||||
|
||||
fail_unless (csource != NULL);
|
||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||
GST_CONTROL_SOURCE (csource)));
|
||||
|
||||
/* set interpolation mode */
|
||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_TRIGGER));
|
||||
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
0 * GST_SECOND, &val_ulong));
|
||||
|
||||
/* set control values */
|
||||
g_value_set_ulong (&val_ulong, 50);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
|
||||
/* now pull in values for some timestamps */
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
0 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
1 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
2 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
|
||||
g_object_unref (csource);
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test timed value handling with linear interpolation */
|
||||
GST_START_TEST (controller_interpolate_linear)
|
||||
{
|
||||
|
@ -616,14 +580,12 @@ GST_START_TEST (controller_interpolate_linear)
|
|||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
@ -665,24 +627,20 @@ GST_START_TEST (controller_interpolate_cubic)
|
|||
/* set control values */
|
||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||
g_value_set_double (&val_double, 0.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_double (&val_double, 5.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_double (&val_double, 2.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_double (&val_double, 8.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 4 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
@ -731,14 +689,12 @@ GST_START_TEST (controller_interpolate_cubic_too_few_cp)
|
|||
/* set 2 control values */
|
||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||
g_value_set_double (&val_double, 0.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_double (&val_double, 4.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
@ -809,19 +765,16 @@ GST_START_TEST (controller_interpolation_unset)
|
|||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 50);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* verify values */
|
||||
|
@ -833,7 +786,8 @@ GST_START_TEST (controller_interpolation_unset)
|
|||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
|
||||
/* unset second */
|
||||
res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
|
||||
res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* verify value again */
|
||||
|
@ -843,12 +797,14 @@ GST_START_TEST (controller_interpolation_unset)
|
|||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
|
||||
/* unset all values, reset and try to unset again */
|
||||
fail_unless (gst_interpolation_control_source_unset (csource,
|
||||
0 * GST_SECOND));
|
||||
fail_unless (gst_interpolation_control_source_unset (csource,
|
||||
2 * GST_SECOND));
|
||||
gst_interpolation_control_source_unset_all (csource);
|
||||
fail_if (gst_interpolation_control_source_unset (csource, 2 * GST_SECOND));
|
||||
fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
|
||||
*) csource, 0 * GST_SECOND));
|
||||
fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
|
||||
*) csource, 2 * GST_SECOND));
|
||||
gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
|
||||
csource);
|
||||
fail_if (gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND));
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
|
@ -881,14 +837,12 @@ GST_START_TEST (controller_interpolation_unset_all)
|
|||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* verify values */
|
||||
|
@ -898,7 +852,8 @@ GST_START_TEST (controller_interpolation_unset_all)
|
|||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
|
||||
/* unset all */
|
||||
gst_interpolation_control_source_unset_all (csource);
|
||||
gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
|
||||
csource);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
|
@ -936,14 +891,12 @@ GST_START_TEST (controller_interpolation_linear_value_array)
|
|||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* now pull in values for some timestamps */
|
||||
|
@ -987,14 +940,12 @@ GST_START_TEST (controller_interpolation_linear_invalid_values)
|
|||
/* set control values */
|
||||
g_value_init (&val_float, G_TYPE_FLOAT);
|
||||
g_value_set_float (&val_float, 200.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_float);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_float);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_float (&val_float, -200.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
|
||||
&val_float);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 4 * GST_SECOND, &val_float);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
@ -1056,14 +1007,12 @@ GST_START_TEST (controller_interpolation_linear_default_values)
|
|||
|
||||
/* set control values */
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 3 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 3 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* now pull in values for some timestamps */
|
||||
|
@ -1079,20 +1028,20 @@ GST_START_TEST (controller_interpolation_linear_default_values)
|
|||
|
||||
/* set control values */
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* unset the old ones */
|
||||
res = gst_interpolation_control_source_unset (csource, 1 * GST_SECOND);
|
||||
res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 1 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
res = gst_interpolation_control_source_unset (csource, 3 * GST_SECOND);
|
||||
res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 3 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
/* now pull in values for some timestamps */
|
||||
|
@ -1143,14 +1092,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
|
|||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
@ -1158,14 +1105,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
|
|||
/* set control values */
|
||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||
g_value_set_double (&val_double, 2.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource2, 0 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource2, 0 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_double (&val_double, 4.0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource2, 2 * GST_SECOND,
|
||||
&val_double);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource2, 2 * GST_SECOND, &val_double);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (G_OBJECT (csource2));
|
||||
|
@ -1289,11 +1234,13 @@ GST_START_TEST (controller_interpolation_set_from_list)
|
|||
|
||||
list = g_slist_append (list, tval);
|
||||
|
||||
fail_if (gst_interpolation_control_source_set_from_list (csource, list));
|
||||
fail_if (gst_timed_value_control_source_set_from_list (
|
||||
(GstTimedValueControlSource *) csource, list));
|
||||
|
||||
/* try again with a valid stamp, should work now */
|
||||
tval->timestamp = 0;
|
||||
fail_unless (gst_interpolation_control_source_set_from_list (csource, list));
|
||||
fail_unless (gst_timed_value_control_source_set_from_list (
|
||||
(GstTimedValueControlSource *) csource, list));
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
|
@ -1306,6 +1253,119 @@ GST_START_TEST (controller_interpolation_set_from_list)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
/* test linear interpolation for ts < first control point */
|
||||
GST_START_TEST (controller_interpolate_linear_before_ts0)
|
||||
{
|
||||
GstInterpolationControlSource *csource;
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
GValue val_ulong = { 0, };
|
||||
|
||||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||
|
||||
/* Get interpolation control source */
|
||||
csource = gst_interpolation_control_source_new ();
|
||||
|
||||
fail_unless (csource != NULL);
|
||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||
GST_CONTROL_SOURCE (csource)));
|
||||
|
||||
/* set interpolation mode */
|
||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_LINEAR));
|
||||
|
||||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 4 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
/* now pull in values for some timestamps after first control point */
|
||||
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
|
||||
/* now pull in values for some timestamps before first control point */
|
||||
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test control-point handling in interpolation control source */
|
||||
GST_START_TEST (controller_interpolation_cp_count)
|
||||
{
|
||||
GstInterpolationControlSource *csource;
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
GValue val_ulong = { 0, };
|
||||
|
||||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||
|
||||
/* Get interpolation control source */
|
||||
csource = gst_interpolation_control_source_new ();
|
||||
|
||||
fail_unless (csource != NULL);
|
||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||
GST_CONTROL_SOURCE (csource)));
|
||||
|
||||
/* set interpolation mode */
|
||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_NONE));
|
||||
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 0);
|
||||
|
||||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 1);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 2);
|
||||
|
||||
/* now unset control values */
|
||||
res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 1);
|
||||
|
||||
res = gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_timed_value_control_source_get_count (
|
||||
(GstTimedValueControlSource *) csource) == 0);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test lfo control source with sine waveform */
|
||||
GST_START_TEST (controller_lfo_sine)
|
||||
{
|
||||
|
@ -1720,28 +1780,10 @@ GST_START_TEST (controller_lfo_none)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
/* tests if we can run helper methods against any GObject */
|
||||
GST_START_TEST (controller_helper_any_gobject)
|
||||
/* test timed value handling in trigger mode */
|
||||
GST_START_TEST (controller_trigger_exact)
|
||||
{
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
|
||||
elem = gst_element_factory_make ("bin", "test_elem");
|
||||
|
||||
/* that element is not controllable */
|
||||
res = gst_object_sync_values (GST_OBJECT (elem), 0LL);
|
||||
/* Syncing should still succeed as there's nothing to sync */
|
||||
fail_unless (res == TRUE, NULL);
|
||||
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test linear interpolation for ts < first control point */
|
||||
GST_START_TEST (controller_interpolate_linear_before_ts0)
|
||||
{
|
||||
GstInterpolationControlSource *csource;
|
||||
GstTriggerControlSource *csource;
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
GValue val_ulong = { 0, };
|
||||
|
@ -1749,54 +1791,50 @@ GST_START_TEST (controller_interpolate_linear_before_ts0)
|
|||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||
|
||||
/* Get interpolation control source */
|
||||
csource = gst_interpolation_control_source_new ();
|
||||
csource = gst_trigger_control_source_new ();
|
||||
|
||||
fail_unless (csource != NULL);
|
||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||
GST_CONTROL_SOURCE (csource)));
|
||||
|
||||
/* set interpolation mode */
|
||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_LINEAR));
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
0 * GST_SECOND, &val_ulong));
|
||||
|
||||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 50);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
/* now pull in values for some timestamps after first control point */
|
||||
/* now pull in values for some timestamps */
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
0 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
1 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
fail_unless (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
2 * GST_SECOND, &val_ulong));
|
||||
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 3 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 4 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
|
||||
/* now pull in values for some timestamps before first control point */
|
||||
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
|
||||
g_object_unref (csource);
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
/* test control-point handling in interpolation control source */
|
||||
GST_START_TEST (controller_interpolation_cp_count)
|
||||
GST_START_TEST (controller_trigger_tolerance)
|
||||
{
|
||||
GstInterpolationControlSource *csource;
|
||||
GstTriggerControlSource *csource;
|
||||
GstElement *elem;
|
||||
gboolean res;
|
||||
GValue val_ulong = { 0, };
|
||||
|
@ -1804,44 +1842,42 @@ GST_START_TEST (controller_interpolation_cp_count)
|
|||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||
|
||||
/* Get interpolation control source */
|
||||
csource = gst_interpolation_control_source_new ();
|
||||
csource = gst_trigger_control_source_new ();
|
||||
|
||||
fail_unless (csource != NULL);
|
||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||
GST_CONTROL_SOURCE (csource)));
|
||||
|
||||
/* set interpolation mode */
|
||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||
GST_INTERPOLATE_NONE));
|
||||
g_object_set (csource, "tolerance", G_GINT64_CONSTANT (10), NULL);
|
||||
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||
0 * GST_SECOND, &val_ulong));
|
||||
|
||||
/* set control values */
|
||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||
g_value_set_ulong (&val_ulong, 0);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
||||
&val_ulong);
|
||||
g_value_set_ulong (&val_ulong, 50);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 0 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
|
||||
g_value_set_ulong (&val_ulong, 100);
|
||||
res =
|
||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
||||
&val_ulong);
|
||||
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||
csource, 2 * GST_SECOND, &val_ulong);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 2);
|
||||
|
||||
/* now unset control values */
|
||||
res = gst_interpolation_control_source_unset (csource, 2 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
|
||||
|
||||
res = gst_interpolation_control_source_unset (csource, 0 * GST_SECOND);
|
||||
fail_unless (res, NULL);
|
||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
|
||||
/* now pull in values for some timestamps */
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND + 5);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 1 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 0);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND - 5);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
|
||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||
|
||||
g_object_unref (csource);
|
||||
|
||||
gst_object_unref (elem);
|
||||
}
|
||||
|
||||
|
@ -1863,11 +1899,11 @@ gst_controller_suite (void)
|
|||
tcase_add_test (tc, controller_new_okay1);
|
||||
tcase_add_test (tc, controller_new_okay2);
|
||||
tcase_add_test (tc, controller_param_twice);
|
||||
tcase_add_test (tc, controller_any_gobject);
|
||||
tcase_add_test (tc, controller_controlsource_refcounts);
|
||||
tcase_add_test (tc, controller_controlsource_empty1);
|
||||
tcase_add_test (tc, controller_controlsource_empty2);
|
||||
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_cubic_too_few_cp);
|
||||
|
@ -1879,6 +1915,8 @@ gst_controller_suite (void)
|
|||
tcase_add_test (tc, controller_interpolation_linear_default_values);
|
||||
tcase_add_test (tc, controller_interpolate_linear_disabled);
|
||||
tcase_add_test (tc, controller_interpolation_set_from_list);
|
||||
tcase_add_test (tc, controller_interpolate_linear_before_ts0);
|
||||
tcase_add_test (tc, controller_interpolation_cp_count);
|
||||
tcase_add_test (tc, controller_lfo_sine);
|
||||
tcase_add_test (tc, controller_lfo_sine_timeshift);
|
||||
tcase_add_test (tc, controller_lfo_square);
|
||||
|
@ -1886,9 +1924,8 @@ gst_controller_suite (void)
|
|||
tcase_add_test (tc, controller_lfo_rsaw);
|
||||
tcase_add_test (tc, controller_lfo_triangle);
|
||||
tcase_add_test (tc, controller_lfo_none);
|
||||
tcase_add_test (tc, controller_helper_any_gobject);
|
||||
tcase_add_test (tc, controller_interpolate_linear_before_ts0);
|
||||
tcase_add_test (tc, controller_interpolation_cp_count);
|
||||
tcase_add_test (tc, controller_trigger_exact);
|
||||
tcase_add_test (tc, controller_trigger_tolerance);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -66,18 +66,23 @@ main (gint argc, gchar ** argv)
|
|||
/* set control values */
|
||||
g_value_init (&vol, G_TYPE_DOUBLE);
|
||||
g_value_set_double (&vol, 0.0);
|
||||
gst_interpolation_control_source_set (csource1, 0 * GST_SECOND, &vol);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource1,
|
||||
0 * GST_SECOND, &vol);
|
||||
g_value_set_double (&vol, 1.0);
|
||||
gst_interpolation_control_source_set (csource1, 5 * GST_SECOND, &vol);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource1,
|
||||
5 * GST_SECOND, &vol);
|
||||
|
||||
g_object_unref (csource1);
|
||||
|
||||
g_value_set_double (&vol, 220.0);
|
||||
gst_interpolation_control_source_set (csource2, 0 * GST_SECOND, &vol);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
|
||||
0 * GST_SECOND, &vol);
|
||||
g_value_set_double (&vol, 3520.0);
|
||||
gst_interpolation_control_source_set (csource2, 3 * GST_SECOND, &vol);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
|
||||
3 * GST_SECOND, &vol);
|
||||
g_value_set_double (&vol, 440.0);
|
||||
gst_interpolation_control_source_set (csource2, 6 * GST_SECOND, &vol);
|
||||
gst_timed_value_control_source_set ((GstTimedValueControlSource *) csource2,
|
||||
6 * GST_SECOND, &vol);
|
||||
|
||||
g_object_unref (csource2);
|
||||
|
||||
|
|
Loading…
Reference in a new issue