mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +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.
|
element properties over time.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="xml/gsttimedvaluecontrolsource.xml" />
|
||||||
<xi:include href="xml/gstinterpolationcontrolsource.xml" />
|
<xi:include href="xml/gstinterpolationcontrolsource.xml" />
|
||||||
<xi:include href="xml/gstlfocontrolsource.xml" />
|
<xi:include href="xml/gstlfocontrolsource.xml" />
|
||||||
|
<xi:include href="xml/gsttriggercontrolsource.xml" />
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="gstreamer-dataprotocol">
|
<chapter id="gstreamer-dataprotocol">
|
||||||
|
|
|
@ -53,22 +53,22 @@ gst_dp_version_get_type
|
||||||
# control source classes
|
# control source classes
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>gstinterpolationcontrolsource</FILE>
|
<FILE>gsttimedvaluecontrolsource</FILE>
|
||||||
<TITLE>GstInterpolationControlSource</TITLE>
|
<TITLE>GstTimedValueControlSource</TITLE>
|
||||||
<INCLUDE>libs/controller/gstinterpolationcontrolsource.h</INCLUDE>
|
<INCLUDE>libs/controller/gsttimedvaluecontrolsource.h</INCLUDE>
|
||||||
GstInterpolationControlSource
|
GstTimedValueControlSource
|
||||||
GstInterpolateMode
|
gst_timed_value_control_source_find_control_point_iter
|
||||||
gst_interpolation_control_source_new
|
gst_timed_value_control_source_set
|
||||||
gst_interpolation_control_source_set
|
gst_timed_value_control_source_set_from_list
|
||||||
gst_interpolation_control_source_set_from_list
|
gst_timed_value_control_source_get_all
|
||||||
gst_interpolation_control_source_set_interpolation_mode
|
gst_timed_value_control_source_unset
|
||||||
gst_interpolation_control_source_get_all
|
gst_timed_value_control_source_unset_all
|
||||||
gst_interpolation_control_source_unset
|
gst_timed_value_control_source_get_count
|
||||||
gst_interpolation_control_source_unset_all
|
gst_timed_value_control_source_get_base_value_type
|
||||||
gst_interpolation_control_source_get_count
|
gst_timed_value_control_invalidate_cache
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
GstInterpolationControlSourceClass
|
GstTimedValueControlSourceClass
|
||||||
GstInterpolationControlSourcePrivate
|
GstTimedValueControlSourcePrivate
|
||||||
GST_INTERPOLATION_CONTROL_SOURCE
|
GST_INTERPOLATION_CONTROL_SOURCE
|
||||||
GST_IS_INTERPOLATION_CONTROL_SOURCE
|
GST_IS_INTERPOLATION_CONTROL_SOURCE
|
||||||
GST_INTERPOLATION_CONTROL_SOURCE_CLASS
|
GST_INTERPOLATION_CONTROL_SOURCE_CLASS
|
||||||
|
@ -76,6 +76,27 @@ GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
|
||||||
GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
|
GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
|
||||||
GST_TYPE_INTERPOLATION_CONTROL_SOURCE
|
GST_TYPE_INTERPOLATION_CONTROL_SOURCE
|
||||||
<SUBSECTION Private>
|
<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
|
gst_interpolation_control_source_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
@ -101,6 +122,25 @@ gst_lfo_control_source_get_type
|
||||||
gst_lfo_waveform_get_type
|
gst_lfo_waveform_get_type
|
||||||
</SECTION>
|
</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
|
# base classes
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
|
|
|
@ -18,11 +18,15 @@ gst_push_src_get_type
|
||||||
|
|
||||||
% controller
|
% controller
|
||||||
|
|
||||||
|
#include <gst/controller/gsttimedvaluecontrolsource.h>
|
||||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||||
#include <gst/controller/gstlfocontrolsource.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_interpolation_control_source_get_type
|
||||||
gst_lfo_control_source_get_type
|
gst_lfo_control_source_get_type
|
||||||
|
gst_trigger_control_source_get_type
|
||||||
|
|
||||||
% net
|
% net
|
||||||
|
|
||||||
|
|
|
@ -447,4 +447,8 @@ The 0.11 porting guide
|
||||||
properties fetch the value array. Also GstValueArray is gone. The fields of
|
properties fetch the value array. Also GstValueArray is gone. The fields of
|
||||||
GstValueArray are now passed directly to gst_object_get_value_array as
|
GstValueArray are now passed directly to gst_object_get_value_array as
|
||||||
arguments.
|
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>
|
* </para></listitem>
|
||||||
* <listitem><para>
|
* <listitem><para>
|
||||||
* Set the control values
|
* Set the control values
|
||||||
* gst_interpolation_control_source_set (csource,0 * GST_SECOND, value1);
|
* gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,0 * GST_SECOND, value1);
|
||||||
* gst_interpolation_control_source_set (csource,1 * GST_SECOND, value2);
|
* gst_timed_value_control_source_set ((GstTimedValueControlSource *)csource,1 * GST_SECOND, value2);
|
||||||
* </para></listitem>
|
* </para></listitem>
|
||||||
* <listitem><para>
|
* <listitem><para>
|
||||||
* start your pipeline
|
* 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@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/controller
|
||||||
libgstcontroller_@GST_MAJORMINOR@_include_HEADERS = \
|
libgstcontroller_@GST_MAJORMINOR@_include_HEADERS = \
|
||||||
|
gsttimedvaluecontrolsource.h \
|
||||||
gstinterpolationcontrolsource.h \
|
gstinterpolationcontrolsource.h \
|
||||||
|
gsttriggercontrolsource.h \
|
||||||
gstlfocontrolsource.h
|
gstlfocontrolsource.h
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
|
@ -10,8 +12,10 @@ noinst_HEADERS = \
|
||||||
gstlfocontrolsourceprivate.h
|
gstlfocontrolsourceprivate.h
|
||||||
|
|
||||||
libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
|
libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
|
||||||
|
gsttimedvaluecontrolsource.c \
|
||||||
gstinterpolation.c \
|
gstinterpolation.c \
|
||||||
gstinterpolationcontrolsource.c \
|
gstinterpolationcontrolsource.c \
|
||||||
|
gsttriggercontrolsource.c \
|
||||||
gstlfocontrolsource.c
|
gstlfocontrolsource.c
|
||||||
|
|
||||||
libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
|
libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
|
||||||
|
|
|
@ -33,55 +33,10 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
#define EMPTY(x) (x)
|
#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 */
|
/* steps-like (no-)interpolation, default */
|
||||||
/* just returns the value for the most recent key-frame */
|
/* just returns the value for the most recent key-frame */
|
||||||
static inline const GValue *
|
static inline const GValue *
|
||||||
_interpolate_none_get (GstInterpolationControlSource * self,
|
_interpolate_none_get (GstTimedValueControlSource * self, GSequenceIter * iter)
|
||||||
GSequenceIter * iter)
|
|
||||||
{
|
{
|
||||||
const GValue *ret;
|
const GValue *ret;
|
||||||
|
|
||||||
|
@ -90,14 +45,14 @@ _interpolate_none_get (GstInterpolationControlSource * self,
|
||||||
|
|
||||||
ret = &cp->value;
|
ret = &cp->value;
|
||||||
} else {
|
} else {
|
||||||
ret = &self->priv->default_value;
|
ret = &self->default_value;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
|
#define DEFINE_NONE_GET_FUNC_COMPARABLE(type) \
|
||||||
static inline const GValue * \
|
static inline const GValue * \
|
||||||
_interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter *iter) \
|
_interpolate_none_get_##type (GstTimedValueControlSource *self, GSequenceIter *iter) \
|
||||||
{ \
|
{ \
|
||||||
const GValue *ret; \
|
const GValue *ret; \
|
||||||
\
|
\
|
||||||
|
@ -105,28 +60,28 @@ _interpolate_none_get_##type (GstInterpolationControlSource *self, GSequenceIter
|
||||||
GstControlPoint *cp = g_sequence_get (iter); \
|
GstControlPoint *cp = g_sequence_get (iter); \
|
||||||
g##type ret_val = g_value_get_##type (&cp->value); \
|
g##type ret_val = g_value_get_##type (&cp->value); \
|
||||||
\
|
\
|
||||||
if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
|
if (g_value_get_##type (&self->minimum_value) > ret_val) \
|
||||||
ret = &self->priv->minimum_value; \
|
ret = &self->minimum_value; \
|
||||||
else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
|
else if (g_value_get_##type (&self->maximum_value) < ret_val) \
|
||||||
ret = &self->priv->maximum_value; \
|
ret = &self->maximum_value; \
|
||||||
else \
|
else \
|
||||||
ret = &cp->value; \
|
ret = &cp->value; \
|
||||||
} else { \
|
} else { \
|
||||||
ret = &self->priv->default_value; \
|
ret = &self->default_value; \
|
||||||
} \
|
} \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_NONE_GET(type,ctype,get_func) \
|
#define DEFINE_NONE_GET(type,ctype,get_func) \
|
||||||
static gboolean \
|
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; \
|
const GValue *ret; \
|
||||||
GSequenceIter *iter; \
|
GSequenceIter *iter; \
|
||||||
\
|
\
|
||||||
g_mutex_lock (self->lock); \
|
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); \
|
ret = get_func (self, iter); \
|
||||||
g_value_copy (ret, value); \
|
g_value_copy (ret, value); \
|
||||||
g_mutex_unlock (self->lock); \
|
g_mutex_unlock (self->lock); \
|
||||||
|
@ -134,7 +89,7 @@ interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime t
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static gboolean \
|
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) \
|
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||||
{ \
|
{ \
|
||||||
guint i; \
|
guint i; \
|
||||||
|
@ -148,10 +103,10 @@ interpolate_none_get_##type##_value_array (GstInterpolationControlSource *self,
|
||||||
g_mutex_lock (self->lock); \
|
g_mutex_lock (self->lock); \
|
||||||
for(i = 0; i < n_values; i++) { \
|
for(i = 0; i < n_values; i++) { \
|
||||||
if (!ret_val || ts >= next_ts) { \
|
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 (!iter1) { \
|
||||||
if (G_LIKELY (self->priv->values)) \
|
if (G_LIKELY (self->values)) \
|
||||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||||
else \
|
else \
|
||||||
iter2 = NULL; \
|
iter2 = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
|
@ -224,178 +179,6 @@ static GstInterpolateMethod interpolate_none = {
|
||||||
(GstControlSourceGetValueArray) interpolate_none_get_string_value_array
|
(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 */
|
/* linear interpolation */
|
||||||
/* smoothes inbetween values */
|
/* smoothes inbetween values */
|
||||||
|
@ -419,7 +202,7 @@ _interpolate_linear_internal_##vtype (GstClockTime timestamp1, g##vtype value1,
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static gboolean \
|
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; \
|
g##vtype ret, min, max; \
|
||||||
GSequenceIter *iter; \
|
GSequenceIter *iter; \
|
||||||
|
@ -427,20 +210,20 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
||||||
\
|
\
|
||||||
g_mutex_lock (self->lock); \
|
g_mutex_lock (self->lock); \
|
||||||
\
|
\
|
||||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
min = g_value_get_##vtype (&self->minimum_value); \
|
||||||
max = g_value_get_##vtype (&self->priv->maximum_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) { \
|
if (iter) { \
|
||||||
cp1 = g_sequence_get (iter); \
|
cp1 = g_sequence_get (iter); \
|
||||||
iter = g_sequence_iter_next (iter); \
|
iter = g_sequence_iter_next (iter); \
|
||||||
} else { \
|
} else { \
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->default_value, &cp.value); \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
if (G_LIKELY (self->priv->values)) \
|
if (G_LIKELY (self->values)) \
|
||||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
iter = g_sequence_get_begin_iter (self->values); \
|
||||||
} \
|
} \
|
||||||
if (iter && !g_sequence_iter_is_end (iter)) \
|
if (iter && !g_sequence_iter_is_end (iter)) \
|
||||||
cp2 = g_sequence_get (iter); \
|
cp2 = g_sequence_get (iter); \
|
||||||
|
@ -454,7 +237,7 @@ interpolate_linear_get_##vtype (GstInterpolationControlSource *self, GstClockTim
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static gboolean \
|
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) \
|
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||||
{ \
|
{ \
|
||||||
guint i; \
|
guint i; \
|
||||||
|
@ -468,19 +251,19 @@ interpolate_linear_get_##vtype##_value_array (GstInterpolationControlSource *sel
|
||||||
g_mutex_lock (self->lock); \
|
g_mutex_lock (self->lock); \
|
||||||
\
|
\
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->default_value, &cp.value); \
|
||||||
\
|
\
|
||||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
min = g_value_get_##vtype (&self->minimum_value); \
|
||||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
max = g_value_get_##vtype (&self->maximum_value); \
|
||||||
\
|
\
|
||||||
for(i = 0; i < n_values; i++) { \
|
for(i = 0; i < n_values; i++) { \
|
||||||
if (timestamp >= next_ts) { \
|
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) { \
|
if (!iter1) { \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
if (G_LIKELY (self->priv->values)) \
|
if (G_LIKELY (self->values)) \
|
||||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||||
else \
|
else \
|
||||||
iter2 = NULL; \
|
iter2 = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
|
@ -560,9 +343,9 @@ static GstInterpolateMethod interpolate_linear = {
|
||||||
|
|
||||||
#define DEFINE_CUBIC_GET(vtype,round, convert) \
|
#define DEFINE_CUBIC_GET(vtype,round, convert) \
|
||||||
static void \
|
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 *o = g_new0 (gdouble, n); \
|
||||||
gdouble *p = g_new0 (gdouble, n); \
|
gdouble *p = g_new0 (gdouble, n); \
|
||||||
gdouble *q = 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; \
|
g##vtype y_prev, y, y_next; \
|
||||||
\
|
\
|
||||||
/* Fill linear system of equations */ \
|
/* 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); \
|
cp = g_sequence_get (iter); \
|
||||||
x = cp->timestamp; \
|
x = cp->timestamp; \
|
||||||
y = g_value_get_##vtype (&cp->value); \
|
y = g_value_get_##vtype (&cp->value); \
|
||||||
|
@ -622,7 +405,7 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
||||||
\
|
\
|
||||||
/* Save cache next in the GstControlPoint */ \
|
/* 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++) { \
|
for (i = 0; i < n; i++) { \
|
||||||
cp = g_sequence_get (iter); \
|
cp = g_sequence_get (iter); \
|
||||||
cp->cache.cubic.h = h[i]; \
|
cp->cache.cubic.h = h[i]; \
|
||||||
|
@ -640,11 +423,11 @@ _interpolate_cubic_update_cache_##vtype (GstInterpolationControlSource *self) \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static inline void \
|
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); \
|
_interpolate_cubic_update_cache_##vtype (self); \
|
||||||
self->priv->valid_cache = TRUE; \
|
self->valid_cache = TRUE; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (cp2) { \
|
if (cp2) { \
|
||||||
|
@ -670,31 +453,31 @@ _interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstControlP
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static gboolean \
|
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; \
|
g##vtype ret, min, max; \
|
||||||
GSequenceIter *iter; \
|
GSequenceIter *iter; \
|
||||||
GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
|
GstControlPoint *cp1, *cp2 = NULL, cp = {0, }; \
|
||||||
\
|
\
|
||||||
if (self->priv->nvalues <= 2) \
|
if (self->nvalues <= 2) \
|
||||||
return interpolate_linear_get_##vtype (self, timestamp, value); \
|
return interpolate_linear_get_##vtype (self, timestamp, value); \
|
||||||
\
|
\
|
||||||
g_mutex_lock (self->lock); \
|
g_mutex_lock (self->lock); \
|
||||||
\
|
\
|
||||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
min = g_value_get_##vtype (&self->minimum_value); \
|
||||||
max = g_value_get_##vtype (&self->priv->maximum_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) { \
|
if (iter) { \
|
||||||
cp1 = g_sequence_get (iter); \
|
cp1 = g_sequence_get (iter); \
|
||||||
iter = g_sequence_iter_next (iter); \
|
iter = g_sequence_iter_next (iter); \
|
||||||
} else { \
|
} else { \
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->default_value, &cp.value); \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
if (G_LIKELY (self->priv->values)) \
|
if (G_LIKELY (self->values)) \
|
||||||
iter = g_sequence_get_begin_iter (self->priv->values); \
|
iter = g_sequence_get_begin_iter (self->values); \
|
||||||
} \
|
} \
|
||||||
if (iter && !g_sequence_iter_is_end (iter)) \
|
if (iter && !g_sequence_iter_is_end (iter)) \
|
||||||
cp2 = g_sequence_get (iter); \
|
cp2 = g_sequence_get (iter); \
|
||||||
|
@ -708,7 +491,7 @@ interpolate_cubic_get_##vtype (GstInterpolationControlSource *self, GstClockTime
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
static gboolean \
|
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) \
|
GstClockTime timestamp, GstClockTime interval, guint n_values, gpointer _values) \
|
||||||
{ \
|
{ \
|
||||||
guint i; \
|
guint i; \
|
||||||
|
@ -719,25 +502,25 @@ interpolate_cubic_get_##vtype##_value_array (GstInterpolationControlSource *self
|
||||||
GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
|
GstControlPoint *cp1 = NULL, *cp2 = NULL, cp = {0, }; \
|
||||||
g##vtype val1 = 0, val2 = 0, min, max; \
|
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); \
|
return interpolate_linear_get_##vtype##_value_array (self, timestamp, interval, n_values, values); \
|
||||||
\
|
\
|
||||||
g_mutex_lock (self->lock); \
|
g_mutex_lock (self->lock); \
|
||||||
\
|
\
|
||||||
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
cp.timestamp = G_GUINT64_CONSTANT(0); \
|
||||||
g_value_init (&cp.value, self->priv->type); \
|
g_value_init (&cp.value, self->type); \
|
||||||
g_value_copy (&self->priv->default_value, &cp.value); \
|
g_value_copy (&self->default_value, &cp.value); \
|
||||||
\
|
\
|
||||||
min = g_value_get_##vtype (&self->priv->minimum_value); \
|
min = g_value_get_##vtype (&self->minimum_value); \
|
||||||
max = g_value_get_##vtype (&self->priv->maximum_value); \
|
max = g_value_get_##vtype (&self->maximum_value); \
|
||||||
\
|
\
|
||||||
for(i = 0; i < n_values; i++) { \
|
for(i = 0; i < n_values; i++) { \
|
||||||
if (timestamp >= next_ts) { \
|
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) { \
|
if (!iter1) { \
|
||||||
cp1 = &cp; \
|
cp1 = &cp; \
|
||||||
if (G_LIKELY (self->priv->values)) \
|
if (G_LIKELY (self->values)) \
|
||||||
iter2 = g_sequence_get_begin_iter (self->priv->values); \
|
iter2 = g_sequence_get_begin_iter (self->values); \
|
||||||
else \
|
else \
|
||||||
iter2 = NULL; \
|
iter2 = NULL; \
|
||||||
} else { \
|
} else { \
|
||||||
|
@ -801,7 +584,6 @@ static GstInterpolateMethod interpolate_cubic = {
|
||||||
/* register all interpolation methods */
|
/* register all interpolation methods */
|
||||||
GstInterpolateMethod *priv_gst_interpolation_methods[] = {
|
GstInterpolateMethod *priv_gst_interpolation_methods[] = {
|
||||||
&interpolate_none,
|
&interpolate_none,
|
||||||
&interpolate_trigger,
|
|
||||||
&interpolate_linear,
|
&interpolate_linear,
|
||||||
&interpolate_cubic,
|
&interpolate_cubic,
|
||||||
&interpolate_cubic
|
&interpolate_cubic
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
* To use #GstInterpolationControlSource get a new instance by calling
|
* 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_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_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.
|
* All functions are MT-safe.
|
||||||
*
|
*
|
||||||
|
@ -48,54 +48,17 @@
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
#define _do_init \
|
#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,
|
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;
|
struct _GstInterpolationControlSourcePrivate
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
GstInterpolateMode interpolation_mode;
|
||||||
|
};
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_interpolation_control_source_new:
|
* gst_interpolation_control_source_new:
|
||||||
|
@ -142,561 +105,115 @@ gst_interpolation_control_source_set_interpolation_mode (
|
||||||
"interpolation mode");
|
"interpolation mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == GST_INTERPOLATE_USER) {
|
GST_TIMED_VALUE_CONTROL_SOURCE_LOCK (self);
|
||||||
GST_WARNING ("User interpolation mode is not implemented yet");
|
switch (gst_timed_value_control_source_get_base_value_type (
|
||||||
return FALSE;
|
(GstTimedValueControlSource *) self)) {
|
||||||
}
|
|
||||||
|
|
||||||
g_mutex_lock (self->lock);
|
|
||||||
switch (self->priv->base) {
|
|
||||||
case G_TYPE_INT:
|
case G_TYPE_INT:
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_int;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_int_value_array;
|
priv_gst_interpolation_methods[mode]->get_int_value_array;
|
||||||
break;
|
break;
|
||||||
case G_TYPE_UINT:{
|
case G_TYPE_UINT:
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_uint_value_array;
|
priv_gst_interpolation_methods[mode]->get_uint_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_LONG:
|
||||||
case G_TYPE_LONG:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_long;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_long_value_array;
|
priv_gst_interpolation_methods[mode]->get_long_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_ULONG:
|
||||||
case G_TYPE_ULONG:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_ulong;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_ulong_value_array;
|
priv_gst_interpolation_methods[mode]->get_ulong_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_INT64:
|
||||||
case G_TYPE_INT64:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_int64;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_int64_value_array;
|
priv_gst_interpolation_methods[mode]->get_int64_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_UINT64:
|
||||||
case G_TYPE_UINT64:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_uint64;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_uint64_value_array;
|
priv_gst_interpolation_methods[mode]->get_uint64_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_FLOAT:
|
||||||
case G_TYPE_FLOAT:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_float;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_float_value_array;
|
priv_gst_interpolation_methods[mode]->get_float_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_DOUBLE:
|
||||||
case G_TYPE_DOUBLE:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_double;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_double_value_array;
|
priv_gst_interpolation_methods[mode]->get_double_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_BOOLEAN:
|
||||||
case G_TYPE_BOOLEAN:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_boolean;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_boolean_value_array;
|
priv_gst_interpolation_methods[mode]->get_boolean_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_ENUM:
|
||||||
case G_TYPE_ENUM:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_enum;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_enum_value_array;
|
priv_gst_interpolation_methods[mode]->get_enum_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
case G_TYPE_STRING:
|
||||||
case G_TYPE_STRING:{
|
|
||||||
csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
|
csource->get_value = priv_gst_interpolation_methods[mode]->get_string;
|
||||||
csource->get_value_array =
|
csource->get_value_array =
|
||||||
priv_gst_interpolation_methods[mode]->get_string_value_array;
|
priv_gst_interpolation_methods[mode]->get_string_value_array;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Incomplete implementation */
|
/* Incomplete implementation */
|
||||||
if (!ret || !csource->get_value || !csource->get_value_array) {
|
if (!csource->get_value || !csource->get_value_array) {
|
||||||
gst_interpolation_control_source_reset (self);
|
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
gst_timed_value_control_invalidate_cache ((GstTimedValueControlSource *)
|
||||||
self->priv->valid_cache = FALSE;
|
csource);
|
||||||
self->priv->interpolation_mode = mode;
|
self->priv->interpolation_mode = mode;
|
||||||
|
|
||||||
g_mutex_unlock (self->lock);
|
GST_TIMED_VALUE_CONTROL_SOURCE_UNLOCK (self);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_interpolation_control_source_bind (GstControlSource * source,
|
gst_interpolation_control_source_bind (GstControlSource * csource,
|
||||||
GParamSpec * pspec)
|
GParamSpec * pspec)
|
||||||
{
|
{
|
||||||
GType type, base;
|
if (GST_CONTROL_SOURCE_CLASS
|
||||||
GstInterpolationControlSource *self =
|
(gst_interpolation_control_source_parent_class)->bind (csource, pspec)) {
|
||||||
(GstInterpolationControlSource *) source;
|
GstInterpolationControlSource *self =
|
||||||
gboolean ret = TRUE;
|
GST_INTERPOLATION_CONTROL_SOURCE (csource);
|
||||||
|
|
||||||
/* get the fundamental base type */
|
if (gst_interpolation_control_source_set_interpolation_mode (self,
|
||||||
self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
self->priv->interpolation_mode))
|
||||||
while ((type = g_type_parent (type)))
|
return TRUE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
if (ret) {
|
|
||||||
self->priv->valid_cache = FALSE;
|
|
||||||
self->priv->nvalues = 0;
|
|
||||||
} else {
|
|
||||||
gst_interpolation_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 (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
|
static void
|
||||||
gst_interpolation_control_source_init (GstInterpolationControlSource * self)
|
gst_interpolation_control_source_init (GstInterpolationControlSource * self)
|
||||||
{
|
{
|
||||||
self->lock = g_mutex_new ();
|
|
||||||
self->priv =
|
self->priv =
|
||||||
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
|
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
|
||||||
GstInterpolationControlSourcePrivate);
|
GstInterpolationControlSourcePrivate);
|
||||||
self->priv->interpolation_mode = GST_INTERPOLATE_NONE;
|
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
|
static void
|
||||||
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
|
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
|
||||||
* klass)
|
* klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
||||||
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
|
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
|
||||||
g_type_class_add_private (klass,
|
g_type_class_add_private (klass,
|
||||||
sizeof (GstInterpolationControlSourcePrivate));
|
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;
|
csource_class->bind = gst_interpolation_control_source_bind;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
|
||||||
#include <gst/gstcontrolsource.h>
|
#include <gst/controller/gsttimedvaluecontrolsource.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -51,23 +51,18 @@ typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSour
|
||||||
/**
|
/**
|
||||||
* GstInterpolateMode:
|
* GstInterpolateMode:
|
||||||
* @GST_INTERPOLATE_NONE: steps-like interpolation, default
|
* @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_LINEAR: linear interpolation
|
||||||
* @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
|
* @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
|
||||||
* @GST_INTERPOLATE_CUBIC: cubic interpolation
|
* @GST_INTERPOLATE_CUBIC: cubic interpolation
|
||||||
* @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
|
|
||||||
*
|
*
|
||||||
* The various interpolation modes available.
|
* The various interpolation modes available.
|
||||||
*/
|
*/
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GST_INTERPOLATE_NONE,
|
GST_INTERPOLATE_NONE,
|
||||||
GST_INTERPOLATE_TRIGGER,
|
|
||||||
GST_INTERPOLATE_LINEAR,
|
GST_INTERPOLATE_LINEAR,
|
||||||
GST_INTERPOLATE_QUADRATIC,
|
GST_INTERPOLATE_QUADRATIC,
|
||||||
GST_INTERPOLATE_CUBIC,
|
GST_INTERPOLATE_CUBIC
|
||||||
GST_INTERPOLATE_USER
|
|
||||||
} GstInterpolateMode;
|
} GstInterpolateMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,17 +71,15 @@ typedef enum
|
||||||
* The instance structure of #GstControlSource.
|
* The instance structure of #GstControlSource.
|
||||||
*/
|
*/
|
||||||
struct _GstInterpolationControlSource {
|
struct _GstInterpolationControlSource {
|
||||||
GstControlSource parent;
|
GstTimedValueControlSource parent;
|
||||||
|
|
||||||
/* <private> */
|
/*< private >*/
|
||||||
GMutex *lock;
|
|
||||||
GstInterpolationControlSourcePrivate *priv;
|
GstInterpolationControlSourcePrivate *priv;
|
||||||
|
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstInterpolationControlSourceClass {
|
struct _GstInterpolationControlSourceClass {
|
||||||
GstControlSourceClass parent_class;
|
GstTimedValueControlSourceClass parent_class;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
|
@ -101,16 +94,6 @@ GstInterpolationControlSource *
|
||||||
gboolean gst_interpolation_control_source_set_interpolation_mode
|
gboolean gst_interpolation_control_source_set_interpolation_mode
|
||||||
(GstInterpolationControlSource *self,
|
(GstInterpolationControlSource *self,
|
||||||
GstInterpolateMode mode);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -80,21 +80,6 @@ typedef struct _GstControlPoint
|
||||||
|
|
||||||
} 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 GstInterpolateMethod *priv_gst_interpolation_methods[];
|
||||||
extern guint priv_gst_num_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++) {
|
for (i = 0; i < NUM_CP; i++) {
|
||||||
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
|
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 ();
|
ct = gst_util_get_timestamp ();
|
||||||
|
@ -143,7 +144,8 @@ main (gint argc, gchar * argv[])
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
j = g_random_int_range (0, NUM_CP - 1);
|
j = g_random_int_range (0, NUM_CP - 1);
|
||||||
g_value_set_double (&freq, g_random_double_range (50.0, 3000.0));
|
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 ();
|
ct = gst_util_get_timestamp ();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <gst/check/gstcheck.h>
|
#include <gst/check/gstcheck.h>
|
||||||
#include <gst/controller/gstinterpolationcontrolsource.h>
|
#include <gst/controller/gstinterpolationcontrolsource.h>
|
||||||
#include <gst/controller/gstlfocontrolsource.h>
|
#include <gst/controller/gstlfocontrolsource.h>
|
||||||
|
#include <gst/controller/gsttriggercontrolsource.h>
|
||||||
|
|
||||||
/* LOCAL TEST ELEMENT */
|
/* LOCAL TEST ELEMENT */
|
||||||
|
|
||||||
|
@ -396,6 +397,24 @@ GST_START_TEST (controller_param_twice)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 */
|
/* tests if we cleanup properly */
|
||||||
GST_START_TEST (controller_controlsource_refcounts)
|
GST_START_TEST (controller_controlsource_refcounts)
|
||||||
{
|
{
|
||||||
|
@ -466,10 +485,12 @@ GST_START_TEST (controller_controlsource_empty2)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val, G_TYPE_ULONG);
|
g_value_init (&val, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val, 0);
|
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 */
|
/* ... 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 */
|
/* don't fail on empty control point lists */
|
||||||
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
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,
|
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
||||||
GST_INTERPOLATE_NONE));
|
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 */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
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);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
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);
|
g_object_unref (csource);
|
||||||
|
|
||||||
|
@ -534,64 +556,6 @@ GST_START_TEST (controller_interpolate_none)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 */
|
/* test timed value handling with linear interpolation */
|
||||||
GST_START_TEST (controller_interpolate_linear)
|
GST_START_TEST (controller_interpolate_linear)
|
||||||
{
|
{
|
||||||
|
@ -616,14 +580,12 @@ GST_START_TEST (controller_interpolate_linear)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
@ -665,24 +627,20 @@ GST_START_TEST (controller_interpolate_cubic)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||||
g_value_set_double (&val_double, 0.0);
|
g_value_set_double (&val_double, 0.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_double (&val_double, 5.0);
|
g_value_set_double (&val_double, 5.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
csource, 1 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_double (&val_double, 2.0);
|
g_value_set_double (&val_double, 2.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_double (&val_double, 8.0);
|
g_value_set_double (&val_double, 8.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
|
csource, 4 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
@ -731,14 +689,12 @@ GST_START_TEST (controller_interpolate_cubic_too_few_cp)
|
||||||
/* set 2 control values */
|
/* set 2 control values */
|
||||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||||
g_value_set_double (&val_double, 0.0);
|
g_value_set_double (&val_double, 0.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_double (&val_double, 4.0);
|
g_value_set_double (&val_double, 4.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
@ -809,19 +765,16 @@ GST_START_TEST (controller_interpolation_unset)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
csource, 1 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 50);
|
g_value_set_ulong (&val_ulong, 50);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* verify values */
|
/* verify values */
|
||||||
|
@ -833,7 +786,8 @@ GST_START_TEST (controller_interpolation_unset)
|
||||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||||
|
|
||||||
/* unset second */
|
/* 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);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* verify value again */
|
/* 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);
|
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 50);
|
||||||
|
|
||||||
/* unset all values, reset and try to unset again */
|
/* unset all values, reset and try to unset again */
|
||||||
fail_unless (gst_interpolation_control_source_unset (csource,
|
fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
|
||||||
0 * GST_SECOND));
|
*) csource, 0 * GST_SECOND));
|
||||||
fail_unless (gst_interpolation_control_source_unset (csource,
|
fail_unless (gst_timed_value_control_source_unset ((GstTimedValueControlSource
|
||||||
2 * GST_SECOND));
|
*) csource, 2 * GST_SECOND));
|
||||||
gst_interpolation_control_source_unset_all (csource);
|
gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
|
||||||
fail_if (gst_interpolation_control_source_unset (csource, 2 * GST_SECOND));
|
csource);
|
||||||
|
fail_if (gst_timed_value_control_source_unset ((GstTimedValueControlSource *)
|
||||||
|
csource, 2 * GST_SECOND));
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
|
||||||
|
@ -881,14 +837,12 @@ GST_START_TEST (controller_interpolation_unset_all)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
csource, 1 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* verify values */
|
/* 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);
|
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
||||||
|
|
||||||
/* unset all */
|
/* unset all */
|
||||||
gst_interpolation_control_source_unset_all (csource);
|
gst_timed_value_control_source_unset_all ((GstTimedValueControlSource *)
|
||||||
|
csource);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
|
||||||
|
@ -936,14 +891,12 @@ GST_START_TEST (controller_interpolation_linear_value_array)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* now pull in values for some timestamps */
|
/* now pull in values for some timestamps */
|
||||||
|
@ -987,14 +940,12 @@ GST_START_TEST (controller_interpolation_linear_invalid_values)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_float, G_TYPE_FLOAT);
|
g_value_init (&val_float, G_TYPE_FLOAT);
|
||||||
g_value_set_float (&val_float, 200.0);
|
g_value_set_float (&val_float, 200.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_float);
|
||||||
&val_float);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_float (&val_float, -200.0);
|
g_value_set_float (&val_float, -200.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 4 * GST_SECOND,
|
csource, 4 * GST_SECOND, &val_float);
|
||||||
&val_float);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
@ -1056,14 +1007,12 @@ GST_START_TEST (controller_interpolation_linear_default_values)
|
||||||
|
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 1 * GST_SECOND,
|
csource, 1 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 3 * GST_SECOND,
|
csource, 3 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* now pull in values for some timestamps */
|
/* now pull in values for some timestamps */
|
||||||
|
@ -1079,20 +1028,20 @@ GST_START_TEST (controller_interpolation_linear_default_values)
|
||||||
|
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* unset the old ones */
|
/* 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);
|
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);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
/* now pull in values for some timestamps */
|
/* now pull in values for some timestamps */
|
||||||
|
@ -1143,14 +1092,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
g_value_set_ulong (&val_ulong, 0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (csource);
|
g_object_unref (csource);
|
||||||
|
@ -1158,14 +1105,12 @@ GST_START_TEST (controller_interpolate_linear_disabled)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&val_double, G_TYPE_DOUBLE);
|
g_value_init (&val_double, G_TYPE_DOUBLE);
|
||||||
g_value_set_double (&val_double, 2.0);
|
g_value_set_double (&val_double, 2.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource2, 0 * GST_SECOND,
|
csource2, 0 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
g_value_set_double (&val_double, 4.0);
|
g_value_set_double (&val_double, 4.0);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource2, 2 * GST_SECOND,
|
csource2, 2 * GST_SECOND, &val_double);
|
||||||
&val_double);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (csource2));
|
g_object_unref (G_OBJECT (csource2));
|
||||||
|
@ -1289,11 +1234,13 @@ GST_START_TEST (controller_interpolation_set_from_list)
|
||||||
|
|
||||||
list = g_slist_append (list, tval);
|
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 */
|
/* try again with a valid stamp, should work now */
|
||||||
tval->timestamp = 0;
|
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);
|
g_object_unref (csource);
|
||||||
|
|
||||||
|
@ -1306,6 +1253,119 @@ GST_START_TEST (controller_interpolation_set_from_list)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 */
|
/* test lfo control source with sine waveform */
|
||||||
GST_START_TEST (controller_lfo_sine)
|
GST_START_TEST (controller_lfo_sine)
|
||||||
{
|
{
|
||||||
|
@ -1720,28 +1780,10 @@ GST_START_TEST (controller_lfo_none)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
/* tests if we can run helper methods against any GObject */
|
/* test timed value handling in trigger mode */
|
||||||
GST_START_TEST (controller_helper_any_gobject)
|
GST_START_TEST (controller_trigger_exact)
|
||||||
{
|
{
|
||||||
GstElement *elem;
|
GstTriggerControlSource *csource;
|
||||||
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;
|
|
||||||
GstElement *elem;
|
GstElement *elem;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
GValue val_ulong = { 0, };
|
GValue val_ulong = { 0, };
|
||||||
|
@ -1749,54 +1791,50 @@ GST_START_TEST (controller_interpolate_linear_before_ts0)
|
||||||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||||
|
|
||||||
/* Get interpolation control source */
|
/* Get interpolation control source */
|
||||||
csource = gst_interpolation_control_source_new ();
|
csource = gst_trigger_control_source_new ();
|
||||||
|
|
||||||
fail_unless (csource != NULL);
|
fail_unless (csource != NULL);
|
||||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||||
GST_CONTROL_SOURCE (csource)));
|
GST_CONTROL_SOURCE (csource)));
|
||||||
|
|
||||||
/* set interpolation mode */
|
g_value_init (&val_ulong, G_TYPE_ULONG);
|
||||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
fail_if (gst_control_source_get_value (GST_CONTROL_SOURCE (csource),
|
||||||
GST_INTERPOLATE_LINEAR));
|
0 * GST_SECOND, &val_ulong));
|
||||||
|
|
||||||
/* set control values */
|
/* 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);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&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);
|
|
||||||
fail_unless (res, NULL);
|
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);
|
gst_object_sync_values (GST_OBJECT (elem), 2 * GST_SECOND);
|
||||||
fail_unless_equals_int (GST_TEST_MONO_SOURCE (elem)->val_ulong, 100);
|
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_object_unref (elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
/* test control-point handling in interpolation control source */
|
GST_START_TEST (controller_trigger_tolerance)
|
||||||
GST_START_TEST (controller_interpolation_cp_count)
|
|
||||||
{
|
{
|
||||||
GstInterpolationControlSource *csource;
|
GstTriggerControlSource *csource;
|
||||||
GstElement *elem;
|
GstElement *elem;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
GValue val_ulong = { 0, };
|
GValue val_ulong = { 0, };
|
||||||
|
@ -1804,44 +1842,42 @@ GST_START_TEST (controller_interpolation_cp_count)
|
||||||
elem = gst_element_factory_make ("testmonosource", "test_source");
|
elem = gst_element_factory_make ("testmonosource", "test_source");
|
||||||
|
|
||||||
/* Get interpolation control source */
|
/* Get interpolation control source */
|
||||||
csource = gst_interpolation_control_source_new ();
|
csource = gst_trigger_control_source_new ();
|
||||||
|
|
||||||
fail_unless (csource != NULL);
|
fail_unless (csource != NULL);
|
||||||
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
fail_unless (gst_object_set_control_source (GST_OBJECT (elem), "ulong",
|
||||||
GST_CONTROL_SOURCE (csource)));
|
GST_CONTROL_SOURCE (csource)));
|
||||||
|
|
||||||
/* set interpolation mode */
|
g_object_set (csource, "tolerance", G_GINT64_CONSTANT (10), NULL);
|
||||||
fail_unless (gst_interpolation_control_source_set_interpolation_mode (csource,
|
|
||||||
GST_INTERPOLATE_NONE));
|
|
||||||
|
|
||||||
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 */
|
/* set control values */
|
||||||
g_value_init (&val_ulong, G_TYPE_ULONG);
|
g_value_set_ulong (&val_ulong, 50);
|
||||||
g_value_set_ulong (&val_ulong, 0);
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
res =
|
csource, 0 * GST_SECOND, &val_ulong);
|
||||||
gst_interpolation_control_source_set (csource, 0 * GST_SECOND,
|
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
fail_unless (res, NULL);
|
||||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 1);
|
|
||||||
g_value_set_ulong (&val_ulong, 100);
|
g_value_set_ulong (&val_ulong, 100);
|
||||||
res =
|
res = gst_timed_value_control_source_set ((GstTimedValueControlSource *)
|
||||||
gst_interpolation_control_source_set (csource, 2 * GST_SECOND,
|
csource, 2 * GST_SECOND, &val_ulong);
|
||||||
&val_ulong);
|
|
||||||
fail_unless (res, NULL);
|
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);
|
/* now pull in values for some timestamps */
|
||||||
fail_unless (res, NULL);
|
gst_object_sync_values (GST_OBJECT (elem), 0 * GST_SECOND);
|
||||||
fail_unless (gst_interpolation_control_source_get_count (csource) == 0);
|
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);
|
g_object_unref (csource);
|
||||||
|
|
||||||
gst_object_unref (elem);
|
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_okay1);
|
||||||
tcase_add_test (tc, controller_new_okay2);
|
tcase_add_test (tc, controller_new_okay2);
|
||||||
tcase_add_test (tc, controller_param_twice);
|
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_refcounts);
|
||||||
tcase_add_test (tc, controller_controlsource_empty1);
|
tcase_add_test (tc, controller_controlsource_empty1);
|
||||||
tcase_add_test (tc, controller_controlsource_empty2);
|
tcase_add_test (tc, controller_controlsource_empty2);
|
||||||
tcase_add_test (tc, controller_interpolate_none);
|
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_linear);
|
||||||
tcase_add_test (tc, controller_interpolate_cubic);
|
tcase_add_test (tc, controller_interpolate_cubic);
|
||||||
tcase_add_test (tc, controller_interpolate_cubic_too_few_cp);
|
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_interpolation_linear_default_values);
|
||||||
tcase_add_test (tc, controller_interpolate_linear_disabled);
|
tcase_add_test (tc, controller_interpolate_linear_disabled);
|
||||||
tcase_add_test (tc, controller_interpolation_set_from_list);
|
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);
|
||||||
tcase_add_test (tc, controller_lfo_sine_timeshift);
|
tcase_add_test (tc, controller_lfo_sine_timeshift);
|
||||||
tcase_add_test (tc, controller_lfo_square);
|
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_rsaw);
|
||||||
tcase_add_test (tc, controller_lfo_triangle);
|
tcase_add_test (tc, controller_lfo_triangle);
|
||||||
tcase_add_test (tc, controller_lfo_none);
|
tcase_add_test (tc, controller_lfo_none);
|
||||||
tcase_add_test (tc, controller_helper_any_gobject);
|
tcase_add_test (tc, controller_trigger_exact);
|
||||||
tcase_add_test (tc, controller_interpolate_linear_before_ts0);
|
tcase_add_test (tc, controller_trigger_tolerance);
|
||||||
tcase_add_test (tc, controller_interpolation_cp_count);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,18 +66,23 @@ main (gint argc, gchar ** argv)
|
||||||
/* set control values */
|
/* set control values */
|
||||||
g_value_init (&vol, G_TYPE_DOUBLE);
|
g_value_init (&vol, G_TYPE_DOUBLE);
|
||||||
g_value_set_double (&vol, 0.0);
|
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);
|
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_object_unref (csource1);
|
||||||
|
|
||||||
g_value_set_double (&vol, 220.0);
|
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);
|
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);
|
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);
|
g_object_unref (csource2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue