libs/gst/controller/: API: Refactor GstController into the core controller which can take a GstControlSource for prov...

Original commit message from CVS:
Reviewed by: Stefan Kost <ensonic@users.sf.net>
* libs/gst/controller/Makefile.am:
* libs/gst/controller/gstcontroller.c:
(gst_controlled_property_add_interpolation_control_source),
(gst_controlled_property_new), (gst_controlled_property_free),
(gst_controller_find_controlled_property),
(gst_controller_new_valist), (gst_controller_new_list),
(gst_controller_new), (gst_controller_remove_properties_valist),
(gst_controller_remove_properties_list),
(gst_controller_remove_properties),
(gst_controller_set_property_disabled),
(gst_controller_set_disabled), (gst_controller_set_control_source),
(gst_controller_get_control_source), (gst_controller_get),
(gst_controller_sync_values), (gst_controller_get_value_array),
(_gst_controller_dispose), (gst_controller_get_type),
(gst_controlled_property_set_interpolation_mode),
(gst_controller_set), (gst_controller_set_from_list),
(gst_controller_unset), (gst_controller_unset_all),
(gst_controller_get_all), (gst_controller_set_interpolation_mode):
* libs/gst/controller/gstcontroller.h:
* libs/gst/controller/gstcontrollerprivate.h:
* libs/gst/controller/gstcontrolsource.c:
(gst_control_source_class_init), (gst_control_source_init),
(gst_control_source_get_value),
(gst_control_source_get_value_array), (gst_control_source_bind):
* libs/gst/controller/gstcontrolsource.h:
* libs/gst/controller/gsthelper.c: (gst_object_set_control_source),
(gst_object_get_control_source):
* libs/gst/controller/gstinterpolation.c:
(gst_interpolation_control_source_find_control_point_node),
(gst_interpolation_control_source_get_first_value),
(_interpolate_none_get), (interpolate_none_get),
(interpolate_none_get_boolean_value_array),
(interpolate_none_get_enum_value_array),
(interpolate_none_get_string_value_array),
(_interpolate_trigger_get), (interpolate_trigger_get),
(interpolate_trigger_get_boolean_value_array),
(interpolate_trigger_get_enum_value_array),
(interpolate_trigger_get_string_value_array):
* libs/gst/controller/gstinterpolationcontrolsource.c:
(gst_control_point_free), (gst_interpolation_control_source_reset),
(gst_interpolation_control_source_new),
(gst_interpolation_control_source_set_interpolation_mode),
(gst_interpolation_control_source_bind),
(gst_control_point_compare), (gst_control_point_find),
(gst_interpolation_control_source_set_internal),
(gst_interpolation_control_source_set),
(gst_interpolation_control_source_set_from_list),
(gst_interpolation_control_source_unset),
(gst_interpolation_control_source_unset_all),
(gst_interpolation_control_source_get_all),
(gst_interpolation_control_source_get_count),
(gst_interpolation_control_source_init),
(gst_interpolation_control_source_finalize),
(gst_interpolation_control_source_dispose),
(gst_interpolation_control_source_class_init):
* libs/gst/controller/gstinterpolationcontrolsource.h:
* libs/gst/controller/gstinterpolationcontrolsourceprivate.h:
API: Refactor GstController into the core controller which can take
a GstControlSource for providing actual values for timestamps.
Implement a interpolation control source and use this for backward
compatibility, deprecate a bunch of functions that are now handled
by GstControlSource or GstInterpolationControlSource.
Make it possible to disable the controller completely or only for
specific properties. Fixes #450711.
* docs/libs/gstreamer-libs-docs.sgml:
* docs/libs/gstreamer-libs-sections.txt:
* docs/libs/gstreamer-libs.types:
Add new functions and classes to the docs.
* tests/check/libs/controller.c: (GST_START_TEST),
(gst_controller_suite):
* tests/examples/controller/audio-example.c: (main):
Port unit test and example to the new API and add some new
unit tests.
This commit is contained in:
Sebastian Dröge 2007-07-06 21:50:02 +00:00
parent fc70188d3e
commit 286cd75855
17 changed files with 2968 additions and 1248 deletions

View file

@ -1,3 +1,81 @@
2007-07-06 Sebastian Dröge <slomo@circular-chaos.org>
Reviewed by: Stefan Kost <ensonic@users.sf.net>
* libs/gst/controller/Makefile.am:
* libs/gst/controller/gstcontroller.c:
(gst_controlled_property_add_interpolation_control_source),
(gst_controlled_property_new), (gst_controlled_property_free),
(gst_controller_find_controlled_property),
(gst_controller_new_valist), (gst_controller_new_list),
(gst_controller_new), (gst_controller_remove_properties_valist),
(gst_controller_remove_properties_list),
(gst_controller_remove_properties),
(gst_controller_set_property_disabled),
(gst_controller_set_disabled), (gst_controller_set_control_source),
(gst_controller_get_control_source), (gst_controller_get),
(gst_controller_sync_values), (gst_controller_get_value_array),
(_gst_controller_dispose), (gst_controller_get_type),
(gst_controlled_property_set_interpolation_mode),
(gst_controller_set), (gst_controller_set_from_list),
(gst_controller_unset), (gst_controller_unset_all),
(gst_controller_get_all), (gst_controller_set_interpolation_mode):
* libs/gst/controller/gstcontroller.h:
* libs/gst/controller/gstcontrollerprivate.h:
* libs/gst/controller/gstcontrolsource.c:
(gst_control_source_class_init), (gst_control_source_init),
(gst_control_source_get_value),
(gst_control_source_get_value_array), (gst_control_source_bind):
* libs/gst/controller/gstcontrolsource.h:
* libs/gst/controller/gsthelper.c: (gst_object_set_control_source),
(gst_object_get_control_source):
* libs/gst/controller/gstinterpolation.c:
(gst_interpolation_control_source_find_control_point_node),
(gst_interpolation_control_source_get_first_value),
(_interpolate_none_get), (interpolate_none_get),
(interpolate_none_get_boolean_value_array),
(interpolate_none_get_enum_value_array),
(interpolate_none_get_string_value_array),
(_interpolate_trigger_get), (interpolate_trigger_get),
(interpolate_trigger_get_boolean_value_array),
(interpolate_trigger_get_enum_value_array),
(interpolate_trigger_get_string_value_array):
* libs/gst/controller/gstinterpolationcontrolsource.c:
(gst_control_point_free), (gst_interpolation_control_source_reset),
(gst_interpolation_control_source_new),
(gst_interpolation_control_source_set_interpolation_mode),
(gst_interpolation_control_source_bind),
(gst_control_point_compare), (gst_control_point_find),
(gst_interpolation_control_source_set_internal),
(gst_interpolation_control_source_set),
(gst_interpolation_control_source_set_from_list),
(gst_interpolation_control_source_unset),
(gst_interpolation_control_source_unset_all),
(gst_interpolation_control_source_get_all),
(gst_interpolation_control_source_get_count),
(gst_interpolation_control_source_init),
(gst_interpolation_control_source_finalize),
(gst_interpolation_control_source_dispose),
(gst_interpolation_control_source_class_init):
* libs/gst/controller/gstinterpolationcontrolsource.h:
* libs/gst/controller/gstinterpolationcontrolsourceprivate.h:
API: Refactor GstController into the core controller which can take
a GstControlSource for providing actual values for timestamps.
Implement a interpolation control source and use this for backward
compatibility, deprecate a bunch of functions that are now handled
by GstControlSource or GstInterpolationControlSource.
Make it possible to disable the controller completely or only for
specific properties. Fixes #450711.
* docs/libs/gstreamer-libs-docs.sgml:
* docs/libs/gstreamer-libs-sections.txt:
* docs/libs/gstreamer-libs.types:
Add new functions and classes to the docs.
* tests/check/libs/controller.c: (GST_START_TEST),
(gst_controller_suite):
* tests/examples/controller/audio-example.c: (main):
Port unit test and example to the new API and add some new
unit tests.
2007-07-05 Wim Taymans <wim.taymans@gmail.com> 2007-07-05 Wim Taymans <wim.taymans@gmail.com>
Patch by: Mark Nauwelaerts <manauw at skynet be> Patch by: Mark Nauwelaerts <manauw at skynet be>

View file

@ -17,6 +17,8 @@
<!ENTITY GstCheckBufferStraw SYSTEM "xml/gstcheckbufferstraw.xml"> <!ENTITY GstCheckBufferStraw SYSTEM "xml/gstcheckbufferstraw.xml">
<!ENTITY GstController SYSTEM "xml/gstcontroller.xml"> <!ENTITY GstController SYSTEM "xml/gstcontroller.xml">
<!ENTITY GstControlSource SYSTEM "xml/gstcontrolsource.xml">
<!ENTITY GstInterpolationControlSource SYSTEM "xml/gstinterpolationcontrolsource.xml">
<!ENTITY GstControllerGObject SYSTEM "xml/gstcontrollergobject.xml"> <!ENTITY GstControllerGObject SYSTEM "xml/gstcontrollergobject.xml">
<!ENTITY GstDataProtocol SYSTEM "xml/gstdataprotocol.xml"> <!ENTITY GstDataProtocol SYSTEM "xml/gstdataprotocol.xml">
@ -66,6 +68,8 @@
<chapter id="gstreamer-control"> <chapter id="gstreamer-control">
<title>GStreamer Dynamic Parameter Control</title> <title>GStreamer Dynamic Parameter Control</title>
&GstController; &GstController;
&GstControlSource;
&GstInterpolationControlSource;
&GstControllerGObject; &GstControllerGObject;
</chapter> </chapter>

View file

@ -59,7 +59,6 @@ gst_dp_version_get_type
<TITLE>GstController</TITLE> <TITLE>GstController</TITLE>
<INCLUDE>gst/controller/gstcontroller.h</INCLUDE> <INCLUDE>gst/controller/gstcontroller.h</INCLUDE>
GstController GstController
GstInterpolateMode
gst_controller_init gst_controller_init
gst_controller_new gst_controller_new
gst_controller_new_list gst_controller_new_list
@ -67,16 +66,20 @@ gst_controller_new_valist
gst_controller_remove_properties gst_controller_remove_properties
gst_controller_remove_properties_list gst_controller_remove_properties_list
gst_controller_remove_properties_valist gst_controller_remove_properties_valist
gst_controller_set_disabled
gst_controller_set_property_disabled
gst_controller_suggest_next_sync
gst_controller_sync_values
gst_controller_get_control_source
gst_controller_set_control_source
gst_controller_get
gst_controller_get_value_arrays
gst_controller_get_value_array
gst_controller_set gst_controller_set
gst_controller_set_from_list gst_controller_set_from_list
gst_controller_unset gst_controller_unset
gst_controller_unset_all gst_controller_unset_all
gst_controller_get
gst_controller_get_all gst_controller_get_all
gst_controller_suggest_next_sync
gst_controller_sync_values
gst_controller_get_value_arrays
gst_controller_get_value_array
gst_controller_set_interpolation_mode gst_controller_set_interpolation_mode
GST_PARAM_CONTROLLABLE GST_PARAM_CONTROLLABLE
<SUBSECTION Standard> <SUBSECTION Standard>
@ -89,12 +92,62 @@ GST_IS_CONTROLLER_CLASS
GST_CONTROLLER_GET_CLASS GST_CONTROLLER_GET_CLASS
GST_TYPE_CONTROLLER GST_TYPE_CONTROLLER
<SUBSECTION Private> <SUBSECTION Private>
InterpolateGet
InterpolateGetValueArray
GST_CONTROLLED_PROPERTY GST_CONTROLLED_PROPERTY
gst_controller_get_type gst_controller_get_type
</SECTION> </SECTION>
<SECTION>
<FILE>gstcontrolsource</FILE>
<TITLE>GstControlSource</TITLE>
<INCLUDE>libs/controller/gstcontrolsource.h</INCLUDE>
GstControlSource
GstControlSourceClass
GstControlSourceBind
GstControlSourceGetValue
GstControlSourceGetValueArray
GstTimedValue
GstValueArray
gst_control_source_bind
gst_control_source_get_value
gst_control_source_get_value_array
<SUBSECTION Standard>
GST_CONTROL_SOURCE
GST_IS_CONTROL_SOURCE
GST_CONTROL_SOURCE_CLASS
GST_IS_CONTROL_SOURCE_CLASS
GST_CONTROL_SOURCE_GET_CLASS
GST_TYPE_CONTROL_SOURCE
<SUBSECTION Private>
gst_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
gst_interpolation_control_source_set_from_list
gst_interpolation_control_source_set_interpolation_mode
gst_interpolation_control_source_get_all
gst_interpolation_control_source_unset
gst_interpolation_control_source_unset_all
gst_interpolation_control_source_get_count
<SUBSECTION Standard>
GstInterpolationControlSourceClass
GstInterpolationControlSourcePrivate
GST_INTERPOLATION_CONTROL_SOURCE
GST_IS_INTERPOLATION_CONTROL_SOURCE
GST_INTERPOLATION_CONTROL_SOURCE_CLASS
GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS
GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS
GST_TYPE_INTERPOLATION_CONTROL_SOURCE
<SUBSECTION Private>
gst_interpolation_control_source_get_type
</SECTION>
<SECTION> <SECTION>
<FILE>gstcontrollergobject</FILE> <FILE>gstcontrollergobject</FILE>
<TITLE>GstControllerGObject</TITLE> <TITLE>GstControllerGObject</TITLE>
@ -105,6 +158,8 @@ gst_object_get_controller
gst_object_set_controller gst_object_set_controller
gst_object_suggest_next_sync gst_object_suggest_next_sync
gst_object_sync_values gst_object_sync_values
gst_object_get_control_source
gst_object_set_control_source
gst_object_get_value_arrays gst_object_get_value_arrays
gst_object_get_value_array gst_object_get_value_array
gst_object_get_control_rate gst_object_get_control_rate
@ -113,7 +168,6 @@ gst_object_set_control_rate
<SUBSECTION Private> <SUBSECTION Private>
</SECTION> </SECTION>
# base classes # base classes
<SECTION> <SECTION>

View file

@ -2,6 +2,10 @@
#include <gst/controller/gstcontroller.h> #include <gst/controller/gstcontroller.h>
gst_controller_get_type gst_controller_get_type
#include <gst/controller/gstcontrolsource.h>
gst_control_source_get_type
#include <gst/controller/gstinterpolationcontrolsource.h>
gst_interpolation_control_source_get_type
#include <gst/base/gstadapter.h> #include <gst/base/gstadapter.h>
gst_adapter_get_type gst_adapter_get_type

View file

@ -2,14 +2,21 @@ 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 = \
gstcontroller.h gstcontroller.h \
noinst_HEADERS = gstcontrollerprivate.h gstcontrolsource.h \
gstinterpolationcontrolsource.h
noinst_HEADERS = \
gstcontrollerprivate.h \
gstinterpolationcontrolsourceprivate.h
libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \ libgstcontroller_@GST_MAJORMINOR@_la_SOURCES = \
lib.c \ lib.c \
gstcontroller.c \ gstcontroller.c \
gstinterpolation.c \ gstinterpolation.c \
gsthelper.c gsthelper.c \
gstcontrolsource.c \
gstinterpolationcontrolsource.c
libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS) libgstcontroller_@GST_MAJORMINOR@_la_CFLAGS = $(GST_OBJ_CFLAGS)
libgstcontroller_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS) libgstcontroller_@GST_MAJORMINOR@_la_LIBADD = $(GST_OBJ_LIBS)

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,9 @@
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include <gst/gst.h> #include <gst/gst.h>
#include "gstcontrolsource.h"
#include "gstinterpolationcontrolsource.h"
G_BEGIN_DECLS G_BEGIN_DECLS
/** /**
@ -41,59 +44,6 @@ G_BEGIN_DECLS
*/ */
#define GST_PARAM_CONTROLLABLE (1 << (G_PARAM_USER_SHIFT + 1)) #define GST_PARAM_CONTROLLABLE (1 << (G_PARAM_USER_SHIFT + 1))
/**
* GstTimedValue:
*
* a structure for value+time
*/
typedef struct _GstTimedValue
{
GstClockTime timestamp; /* timestamp of the value change */
GValue value; /* the new value */
} GstTimedValue;
/**
* GstValueArray:
* @property_name: the name of the property this array belongs to
* @nbsamples: number of samples requested
* @sample_interval: interval between each sample
* @values: pointer to the array
*
* Structure to receive multiple values at once.
*/
typedef struct _GstValueArray
{
gchar *property_name;
gint nbsamples;
GstClockTime sample_interval;
gpointer *values;
} GstValueArray;
/**
* GstInterpolateMode:
* @GST_INTERPOLATE_NONE: steps-like interpolation, default
* @GST_INTERPOLATE_TRIGGER: returns the default value of the property,
* except for times with specific values
* @GST_INTERPOLATE_LINEAR: linear interpolation
* @GST_INTERPOLATE_QUADRATIC: square interpolation (not yet available)
* @GST_INTERPOLATE_CUBIC: cubic interpolation (not yet available)
* @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
*
* The various interpolation modes available.
*/
typedef enum
{
GST_INTERPOLATE_NONE,
GST_INTERPOLATE_TRIGGER,
GST_INTERPOLATE_LINEAR,
GST_INTERPOLATE_QUADRATIC,
GST_INTERPOLATE_CUBIC,
GST_INTERPOLATE_USER
} GstInterpolateMode;
/* type macros */ /* type macros */
#define GST_TYPE_CONTROLLER (gst_controller_get_type ()) #define GST_TYPE_CONTROLLER (gst_controller_get_type ())
@ -107,7 +57,6 @@ typedef struct _GstController GstController;
typedef struct _GstControllerClass GstControllerClass; typedef struct _GstControllerClass GstControllerClass;
typedef struct _GstControllerPrivate GstControllerPrivate; typedef struct _GstControllerPrivate GstControllerPrivate;
/** /**
* GstController: * GstController:
* *
@ -135,7 +84,7 @@ struct _GstControllerClass
gpointer _gst_reserved[GST_PADDING]; gpointer _gst_reserved[GST_PADDING];
}; };
GType gst_controller_get_type (void); GType gst_controller_get_type ();
/* GstController functions */ /* GstController functions */
@ -149,33 +98,22 @@ gboolean gst_controller_remove_properties_list (GstController * self,
GList *list); GList *list);
gboolean gst_controller_remove_properties (GstController * self, ...) G_GNUC_NULL_TERMINATED; gboolean gst_controller_remove_properties (GstController * self, ...) G_GNUC_NULL_TERMINATED;
gboolean gst_controller_set (GstController * self, gchar * property_name, void gst_controller_set_disabled (GstController *self, gboolean disabled);
GstClockTime timestamp, GValue * value); void gst_controller_set_property_disabled (GstController *self, gchar * property_name, gboolean disabled);
gboolean gst_controller_set_from_list (GstController * self, gboolean gst_controller_set_control_source (GstController *self, gchar * property_name, GstControlSource *csource);
gchar * property_name, GSList * timedvalues); GstControlSource * gst_controller_get_control_source (GstController *self, gchar * property_name);
gboolean gst_controller_unset (GstController * self, gchar * property_name,
GstClockTime timestamp);
gboolean gst_controller_unset_all (GstController * self, gchar * property_name);
GValue *gst_controller_get (GstController * self, gchar * property_name,
GstClockTime timestamp);
const GList *gst_controller_get_all (GstController * self,
gchar * property_name);
GstClockTime gst_controller_suggest_next_sync (GstController *self); GstClockTime gst_controller_suggest_next_sync (GstController *self);
gboolean gst_controller_sync_values (GstController * self, gboolean gst_controller_sync_values (GstController * self,
GstClockTime timestamp); GstClockTime timestamp);
GValue *gst_controller_get (GstController * self, gchar * property_name,
GstClockTime timestamp);
gboolean gst_controller_get_value_arrays (GstController * self, gboolean gst_controller_get_value_arrays (GstController * self,
GstClockTime timestamp, GSList * value_arrays); GstClockTime timestamp, GSList * value_arrays);
gboolean gst_controller_get_value_array (GstController * self, gboolean gst_controller_get_value_array (GstController * self,
GstClockTime timestamp, GstValueArray * value_array); GstClockTime timestamp, GstValueArray * value_array);
gboolean gst_controller_set_interpolation_mode (GstController * self,
gchar * property_name, GstInterpolateMode mode);
/* GObject convenience functions */ /* GObject convenience functions */
GstController *gst_object_control_properties (GObject * object, ...) G_GNUC_NULL_TERMINATED; GstController *gst_object_control_properties (GObject * object, ...) G_GNUC_NULL_TERMINATED;
@ -187,6 +125,9 @@ gboolean gst_object_set_controller (GObject * object, GstController * controller
GstClockTime gst_object_suggest_next_sync (GObject * object); GstClockTime gst_object_suggest_next_sync (GObject * object);
gboolean gst_object_sync_values (GObject * object, GstClockTime timestamp); gboolean gst_object_sync_values (GObject * object, GstClockTime timestamp);
gboolean gst_object_set_control_source (GObject *object, gchar * property_name, GstControlSource *csource);
GstControlSource * gst_object_get_control_source (GObject *object, gchar * property_name);
gboolean gst_object_get_value_arrays (GObject * object, gboolean gst_object_get_value_arrays (GObject * object,
GstClockTime timestamp, GSList * value_arrays); GstClockTime timestamp, GSList * value_arrays);
gboolean gst_object_get_value_array (GObject * object, gboolean gst_object_get_value_array (GObject * object,
@ -199,5 +140,25 @@ void gst_object_set_control_rate (GObject * object, GstClockTime control_rate);
gboolean gst_controller_init (int * argc, char ***argv); gboolean gst_controller_init (int * argc, char ***argv);
/* FIXME: deprecated functions */
#ifndef GST_DISABLE_DEPRECATED
gboolean gst_controller_set (GstController * self, gchar * property_name,
GstClockTime timestamp, GValue * value);
gboolean gst_controller_set_from_list (GstController * self,
gchar * property_name, GSList * timedvalues);
gboolean gst_controller_unset (GstController * self, gchar * property_name,
GstClockTime timestamp);
gboolean gst_controller_unset_all (GstController * self, gchar * property_name);
const GList *gst_controller_get_all (GstController * self,
gchar * property_name);
gboolean gst_controller_set_interpolation_mode (GstController * self,
gchar * property_name, GstInterpolateMode mode);
#endif /* GST_DISABLE_DEPRECATED */
G_END_DECLS G_END_DECLS
#endif /* __GST_CONTROLLER_H__ */ #endif /* __GST_CONTROLLER_H__ */

View file

@ -28,97 +28,19 @@
#include <gst/gst.h> #include <gst/gst.h>
#include "gstcontroller.h" #include "gstcontroller.h"
#include "gstcontrolsource.h"
G_BEGIN_DECLS G_BEGIN_DECLS
struct _GstControlledProperty;
typedef GValue *(*InterpolateGet) (struct _GstControlledProperty * prop,
GstClockTime timestamp);
typedef gboolean (*InterpolateGetValueArray) (struct _GstControlledProperty * prop,
GstClockTime timestamp, GstValueArray * value_array);
/**
* GstInterpolateMethod:
*
* Function pointer structure to do user-defined interpolation methods
*/
typedef struct _GstInterpolateMethod
{
InterpolateGet get_int;
InterpolateGetValueArray get_int_value_array;
InterpolateGet get_uint;
InterpolateGetValueArray get_uint_value_array;
InterpolateGet get_long;
InterpolateGetValueArray get_long_value_array;
InterpolateGet get_ulong;
InterpolateGetValueArray get_ulong_value_array;
InterpolateGet get_float;
InterpolateGetValueArray get_float_value_array;
InterpolateGet get_double;
InterpolateGetValueArray get_double_value_array;
InterpolateGet get_boolean;
InterpolateGetValueArray get_boolean_value_array;
InterpolateGet get_enum;
InterpolateGetValueArray get_enum_value_array;
InterpolateGet get_string;
InterpolateGetValueArray get_string_value_array;
} GstInterpolateMethod;
/**
* GstControlPoint:
*
* a internal structure for value+time and various temporary
* values used for interpolation. This "inherits" from
* GstTimedValue.
*/
/* FIXME 0.11: This should be merged with GstTimedValue for 0.11 */
typedef struct _GstControlPoint
{
/* fields from GstTimedValue. DO NOT CHANGE! */
GstClockTime timestamp; /* timestamp of the value change */
GValue value; /* the new value */
/* internal fields */
/* Caches for the interpolators */
union {
struct {
gdouble h;
gdouble z;
} cubic;
} cache;
} GstControlPoint;
/** /**
* GstControlledProperty: * GstControlledProperty:
*/ */
typedef struct _GstControlledProperty typedef struct _GstControlledProperty
{ {
GParamSpec *pspec; /* GParamSpec for this property */
gchar *name; /* name of the property */ gchar *name; /* name of the property */
GType type; /* type of the handled property */ GstControlSource *csource; /* GstControlSource for this property */
GType base; /* base-type of the handled property */ gboolean disabled;
GValue default_value; /* default value for the handled property */
GValue min_value; /* min value for the handled property */
GValue max_value; /* max value for the handled property */
GValue result_value; /* result value location for the interpolation method */
GstControlPoint last_value; /* the last value a _sink call wrote */
GstControlPoint live_value; /* temporary value override for live input */
gulong notify_handler_id; /* id of the notify::<name> signal handler */
GstInterpolateMode interpolation; /* Interpolation mode */
/* TODO instead of *method, have pointers to get() and get_value_array() here
gst_controller_set_interpolation_mode() will pick the right ones for the
properties value type
GstInterpolateMethod *method; // User-implemented handler (if interpolation == GST_INTERPOLATE_USER)
*/
InterpolateGet get;
InterpolateGetValueArray get_value_array;
GList *values; /* List of GstControlPoint */
gint nvalues; /* Number of control points */
GList *last_requested_value; /* last search result, can be used for incremental searches */
gboolean valid_cache;
} GstControlledProperty; } GstControlledProperty;
#define GST_CONTROLLED_PROPERTY(obj) ((GstControlledProperty *)(obj)) #define GST_CONTROLLED_PROPERTY(obj) ((GstControlledProperty *)(obj))

View file

@ -0,0 +1,158 @@
/* GStreamer
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* gstcontrolsource.c: Interface declaration for 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:gstcontrolsource
* @short_description: base class for control source sources
*
* The #GstControlSource is a base class for control value sources that could
* be used by #GstController to get timestamp-value pairs.
*
* A #GstControlSource is used by first getting an instance, binding it to a
* #GParamSpec (for example by using gst_controller_set_control_source()) and
* then by having it used by the #GstController or calling
* gst_control_source_get_value() or gst_control_source_get_value_array().
*
* For implementing a new #GstControlSource one has to implement a
* #GstControlSourceBind method, which will depending on the #GParamSpec set up
* the control source for use and sets the #GstControlSourceGetValue and
* #GstControlSourceGetValueArray functions. These are then used by
* gst_control_source_get_value() or gst_control_source_get_value_array()
* to get values for specific timestamps.
*
*/
#include <glib-object.h>
#include <gst/gst.h>
#include "gstcontrolsource.h"
#define GST_CAT_DEFAULT gst_controller_debug
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
static void gst_control_source_class_init (GstControlSourceClass * klass);
static void gst_control_source_init (GstControlSource * self);
G_DEFINE_ABSTRACT_TYPE (GstControlSource, gst_control_source, G_TYPE_OBJECT);
static GObjectClass *parent_class = NULL;
static void
gst_control_source_class_init (GstControlSourceClass * klass)
{
//GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
/* Has to be implemented by children */
klass->bind = NULL;
}
static void
gst_control_source_init (GstControlSource * self)
{
/* Set default handlers that print a warning */
self->get_value = NULL;
self->get_value_array = NULL;
self->bound = FALSE;
}
/**
* gst_control_source_get_value:
* @self: the #GstControlSource object
* @timestamp: the time for which the value should be returned
* @value: the value
*
* Gets the value for this #GstControlSource at a given timestamp.
*
* Returns: FALSE if the value couldn't be returned, TRUE otherwise.
*/
gboolean
gst_control_source_get_value (GstControlSource * self, GstClockTime timestamp,
GValue * value)
{
g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
if (self->get_value) {
return self->get_value (self, timestamp, value);
} else {
GST_ERROR ("Not bound to a specific property yet!");
return FALSE;
}
}
/**
* gst_control_source_get_value_array:
* @self: the #GstControlSource object
* @timestamp: the time that should be processed
* @value_array: array to put control-values in
*
* Gets an array of values for one element property.
*
* All fields of @value_array must be filled correctly. Especially the
* @value_array->values array must be big enough to keep the requested amount
* of values.
*
* The type of the values in the array is the same as the property's type.
*
* Returns: %TRUE if the given array could be filled, %FALSE otherwise
*/
gboolean
gst_control_source_get_value_array (GstControlSource * self,
GstClockTime timestamp, GstValueArray * value_array)
{
g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
if (self->get_value_array) {
return self->get_value_array (self, timestamp, value_array);
} else {
GST_ERROR ("Not bound to a specific property yet!");
return FALSE;
}
}
/**
* gst_control_source_bind:
* @self: the #GstControlSource object
* @pspec: #GParamSpec for the property for which this #GstControlSource should generate values.
*
* Binds a #GstControlSource to a specific property. This must be called only once for a
* #GstControlSource.
*
* Returns: %TRUE if the #GstControlSource was bound correctly, %FALSE otherwise.
*/
gboolean
gst_control_source_bind (GstControlSource * self, GParamSpec * pspec)
{
gboolean ret = FALSE;
g_return_val_if_fail (GST_IS_CONTROL_SOURCE (self), FALSE);
g_return_val_if_fail (GST_CONTROL_SOURCE_GET_CLASS (self)->bind, FALSE);
g_return_val_if_fail (!self->bound, FALSE);
ret = GST_CONTROL_SOURCE_GET_CLASS (self)->bind (self, pspec);
if (ret)
self->bound = TRUE;
return ret;
}

View file

@ -0,0 +1,161 @@
/* GStreamer
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* gstcontrolsource.h: Interface declaration for 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_CONTROL_SOURCE_H__
#define __GST_CONTROL_SOURCE_H__
#include <glib-object.h>
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_CONTROL_SOURCE \
(gst_control_source_get_type())
#define GST_CONTROL_SOURCE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CONTROL_SOURCE,GstControlSource))
#define GST_CONTROL_SOURCE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CONTROL_SOURCE,GstControlSourceClass))
#define GST_IS_CONTROL_SOURCE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CONTROL_SOURCE))
#define GST_IS_CONTROL_SOURCE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CONTROL_SOURCE))
#define GST_CONTROL_SOURCE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CONTOL_SOURCE, GstControlSourceClass))
typedef struct _GstControlSource GstControlSource;
typedef struct _GstControlSourceClass GstControlSourceClass;
typedef struct _GstTimedValue GstTimedValue;
typedef struct _GstValueArray GstValueArray;
/**
* GstTimedValue:
*
* Structure for saving a timestamp and a value.
*/
struct _GstTimedValue
{
GstClockTime timestamp; /* timestamp of the value change */
GValue value; /* the corresponding value */
};
/**
* GstValueArray:
* @property_name: the name of the property this array belongs to
* @nbsamples: number of samples requested
* @sample_interval: interval between each sample
* @values: pointer to the array
*
* Structure to receive multiple values at once.
*/
struct _GstValueArray
{
gchar *property_name;
gint nbsamples;
GstClockTime sample_interval;
gpointer *values;
};
/**
* GstControlSourceGetValue
* @self: the #GstControlSource instance
* @timestamp: timestamp for which a value should be calculated
* @value: a #GValue which will be set to the result. It must be initialized to the correct type.
*
* Function for returning a value for a given timestamp.
*
* Returns: %TRUE if the value was successfully calculated.
*
*/
typedef gboolean (* GstControlSourceGetValue) (GstControlSource *self, GstClockTime timestamp, GValue *value);
/**
* GstControlSourceGetValueArray
* @self: the #GstControlSource instance
* @timestamp: timestamp for which a value should be calculated
* @value_array: array to put control-values in
*
* Function for returning a #GstValueArray for a given timestamp.
*
* Returns: %TRUE if the values were successfully calculated.
*
*/
typedef gboolean (* GstControlSourceGetValueArray) (GstControlSource *self, GstClockTime timestamp, GstValueArray *value_array);
/**
* GstControlSourceBind
* @self: the #GstControlSource instance
* @pspec: #GParamSpec that should be bound to
*
* Function for binding a #GstControlSource to a #GParamSpec.
*
* Returns: %TRUE if the property could be bound to the #GstControlSource, %FALSE otherwise.
*/
typedef gboolean (* GstControlSourceBind) (GstControlSource *self, GParamSpec *pspec);
/**
* GstControlSource:
* @get_value: Function for returning a value for a given timestamp
* @get_value_array: Function for returning a #GstValueArray for a given timestamp
*
* The instance structure of #GstControlSource.
*/
struct _GstControlSource {
GObject parent;
/*< public >*/
GstControlSourceGetValue get_value; /* Returns the value for a property at a given timestamp */
GstControlSourceGetValueArray get_value_array; /* Returns values for a property in a given timespan */
/*< private >*/
gboolean bound;
gpointer _gst_reserved[GST_PADDING];
};
/**
* GstControlSourceClass:
* @parent_class: Parent class
* @bind: Class method for binding the #GstControlSource to a specific GParamSpec
*
* The class structure of #GstControlSource.
*/
struct _GstControlSourceClass
{
GObjectClass parent_class;
GstControlSourceBind bind; /* Binds the GstControlSource to a specific GParamSpec */
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_control_source_get_type ();
/* Functions */
gboolean gst_control_source_get_value (GstControlSource *self, GstClockTime timestamp, GValue *value);
gboolean gst_control_source_get_value_array (GstControlSource *self, GstClockTime timestamp, GstValueArray *value_array);
gboolean gst_control_source_bind (GstControlSource *self, GParamSpec *pspec);
G_END_DECLS
#endif /* __GST_CONTROL_SOURCE_H__ */

View file

@ -148,7 +148,6 @@ gst_object_set_controller (GObject * object, GstController * controller)
/** /**
* gst_object_suggest_next_sync: * gst_object_suggest_next_sync:
* @object: the object that has controlled properties * @object: the object that has controlled properties
* @timestamp: the time that should be processed
* *
* Convenience function for GObject * Convenience function for GObject
* *
@ -192,6 +191,61 @@ gst_object_sync_values (GObject * object, GstClockTime timestamp)
return (FALSE); return (FALSE);
} }
/**
* gst_object_set_control_source:
* @object: the controller object
* @property_name: name of the property for which the #GstControlSource should be set
* @csource: the #GstControlSource that should be used for the property
*
* Sets the #GstControlSource for @property_name. If there already was a #GstControlSource
* for this property it will be unreferenced.
*
* Returns: %FALSE if the given property isn't handled by the controller or the new #GstControlSource
* couldn't be bound to the property, %TRUE if everything worked as expected.
*
* Since: 0.10.14
*/
gboolean
gst_object_set_control_source (GObject * object, gchar * property_name,
GstControlSource * csource)
{
GstController *ctrl = NULL;
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
g_return_val_if_fail (GST_IS_CONTROL_SOURCE (csource), FALSE);
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
return gst_controller_set_control_source (ctrl, property_name, csource);
}
return FALSE;
}
/**
* gst_object_get_control_source:
* @object: the object
* @property_name: name of the property for which the #GstControlSource should be get
*
* Gets the corresponding #GstControlSource for the property. This should be unreferenced
* again after use.
*
* Returns: the #GstControlSource for @property_name or NULL if the property is not
* controlled by this controller or no #GstControlSource was assigned yet.
*
* Since: 0.10.14
*/
GstControlSource *
gst_object_get_control_source (GObject * object, gchar * property_name)
{
GstController *ctrl = NULL;
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
return gst_controller_get_control_source (ctrl, property_name);
}
return FALSE;
}
/** /**
* gst_object_get_value_arrays: * gst_object_get_value_arrays:
* @object: the object that has controlled properties * @object: the object that has controlled properties

View file

@ -24,8 +24,9 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
#include "gstcontrollerprivate.h"
#include "gstcontroller.h" #include "gstinterpolationcontrolsource.h"
#include "gstinterpolationcontrolsourceprivate.h"
#define GST_CAT_DEFAULT gst_controller_debug #define GST_CAT_DEFAULT gst_controller_debug
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT); GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
@ -33,28 +34,29 @@ GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
/* common helper */ /* common helper */
/* /*
* gst_controlled_property_find_control_point_node: * gst_interpolation_control_source_find_control_point_node:
* @prop: the controlled property to search in * @self: the interpolation control source to search in
* @timestamp: the search key * @timestamp: the search key
* *
* Find last value before given timestamp in control point list. * Find last value before given timestamp in control point list.
* *
* Returns: the found #GList node or %NULL * Returns: the found #GList node or %NULL
*/ */
GList * static GList *gst_interpolation_control_source_find_control_point_node
gst_controlled_property_find_control_point_node (GstControlledProperty * prop, (GstInterpolationControlSource * self, GstClockTime timestamp)
GstClockTime timestamp)
{ {
GList *prev_node = g_list_last (prop->values); GList *prev_node = g_list_last (self->priv->values);
GList *node; GList *node;
GstControlPoint *cp; GstControlPoint *cp;
node = prop->values; /* Check if we can start from the last requested value
if (prop->last_requested_value) { * to save some time */
GstControlPoint *last_cp = prop->last_requested_value->data; node = self->priv->values;
if (self->priv->last_requested_value) {
GstControlPoint *last_cp = self->priv->last_requested_value->data;
if (timestamp > last_cp->timestamp) if (timestamp > last_cp->timestamp)
node = prop->last_requested_value; node = self->priv->last_requested_value;
} }
/* iterate over timed value list */ /* iterate over timed value list */
@ -68,286 +70,476 @@ gst_controlled_property_find_control_point_node (GstControlledProperty * prop,
} }
} }
/* If we have something to return save it as a
* potential start position for the next search */
if (prev_node) if (prev_node)
prop->last_requested_value = prev_node; self->priv->last_requested_value = prev_node;
return prev_node; return prev_node;
} }
/*
* gst_interpolation_control_source_get_first_value:
* @self: the interpolation control source to search in
*
* Find the first value and return it.
*
* Returns: the found #GValue or %NULL if there are none.
*/
static inline GValue *
gst_interpolation_control_source_get_first_value (GstInterpolationControlSource
* self)
{
if (self->priv->values && self->priv->nvalues > 0) {
GstControlPoint *cp = self->priv->values->data;
return &cp->value;
} else {
return NULL;
}
}
/* 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 GValue *
interpolate_none_get (GstControlledProperty * prop, GstClockTime timestamp)
{
GList *node;
if ((node =
gst_controlled_property_find_control_point_node (prop, timestamp))) {
GstControlPoint *cp = node->data;
return &cp->value;
}
return &prop->default_value;
}
#define interpolate_none_get_boolean interpolate_none_get
#define DEFINE_NONE_GET(type) \ #define DEFINE_NONE_GET(type) \
static GValue * \ static inline GValue * \
interpolate_none_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ _interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
{ \ { \
GValue *ret; \
GList *node; \ GList *node; \
\ \
if ((node = \ if ((node = \
gst_controlled_property_find_control_point_node (prop, timestamp))) { \ gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
GstControlPoint *cp = node->data; \ GstControlPoint *cp = node->data; \
g##type ret = g_value_get_##type (&cp->value); \ g##type ret_val = g_value_get_##type (&cp->value); \
if (g_value_get_##type (&prop->min_value) > ret) \ \
return &prop->min_value; \ if (g_value_get_##type (&self->priv->minimum_value) > ret_val) \
else if (g_value_get_##type (&prop->max_value) < ret) \ ret = &self->priv->minimum_value; \
return &prop->max_value; \ else if (g_value_get_##type (&self->priv->maximum_value) < ret_val) \
return &cp->value; \ ret = &self->priv->maximum_value; \
else \
ret = &cp->value; \
} else { \
ret = gst_interpolation_control_source_get_first_value (self); \
} \ } \
return &prop->default_value; \ return ret; \
} \
\
static gboolean \
interpolate_none_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
GValue *ret; \
g_mutex_lock (self->lock); \
\
ret = _interpolate_none_get_##type (self, 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_none_get_##type##_value_array (GstInterpolationControlSource *self, \
GstClockTime timestamp, GstValueArray * value_array) \
{ \
gint i; \
GstClockTime ts = timestamp; \
g##type *values = (g##type *) value_array->values; \
GValue *ret; \
\
g_mutex_lock (self->lock); \
for(i = 0; i < value_array->nbsamples; i++) { \
ret = _interpolate_none_get_##type (self, timestamp); \
if (!ret) { \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
*values = g_value_get_##type (ret); \
ts += value_array->sample_interval; \
values++; \
} \
g_mutex_unlock (self->lock); \
return TRUE; \
} }
DEFINE_NONE_GET (int); DEFINE_NONE_GET (int);
DEFINE_NONE_GET (uint); DEFINE_NONE_GET (uint);
DEFINE_NONE_GET (long); DEFINE_NONE_GET (long);
DEFINE_NONE_GET (ulong); DEFINE_NONE_GET (ulong);
DEFINE_NONE_GET (int64);
DEFINE_NONE_GET (uint64);
DEFINE_NONE_GET (float); DEFINE_NONE_GET (float);
DEFINE_NONE_GET (double); DEFINE_NONE_GET (double);
#define DEFINE_NONE_GET_VALUE_ARRAY(type) \ static inline GValue *
static gboolean \ _interpolate_none_get (GstInterpolationControlSource * self,
interpolate_none_get_##type##_value_array (GstControlledProperty * prop, \ GstClockTime timestamp)
GstClockTime timestamp, GstValueArray * value_array) \ {
{ \ GList *node;
gint i; \ GValue *ret;
GstClockTime ts = timestamp; \
g##type *values = (g##type *) value_array->values; \ if ((node =
\ gst_interpolation_control_source_find_control_point_node (self,
for(i = 0; i < value_array->nbsamples; i++) { \ timestamp))) {
*values = g_value_get_##type (interpolate_none_get_##type (prop,ts)); \ GstControlPoint *cp = node->data;
ts += value_array->sample_interval; \
values++; \ ret = &cp->value;
} \ } else {
return TRUE; \ ret = gst_interpolation_control_source_get_first_value (self);
}
return ret;
} }
DEFINE_NONE_GET_VALUE_ARRAY (int); static gboolean
interpolate_none_get (GstInterpolationControlSource * self,
GstClockTime timestamp, GValue * value)
{
GValue *ret;
DEFINE_NONE_GET_VALUE_ARRAY (uint); g_mutex_lock (self->lock);
DEFINE_NONE_GET_VALUE_ARRAY (long); ret = _interpolate_none_get (self, timestamp);
DEFINE_NONE_GET_VALUE_ARRAY (ulong); if (!ret) {
DEFINE_NONE_GET_VALUE_ARRAY (float); g_mutex_unlock (self->lock);
DEFINE_NONE_GET_VALUE_ARRAY (double); return FALSE;
}
DEFINE_NONE_GET_VALUE_ARRAY (boolean); g_value_copy (ret, value);
g_mutex_unlock (self->lock);
return TRUE;
}
static gboolean static gboolean
interpolate_none_get_enum_value_array (GstControlledProperty * prop, interpolate_none_get_boolean_value_array (GstInterpolationControlSource * self,
GstClockTime timestamp, GstValueArray * value_array)
{
gint i;
GstClockTime ts = timestamp;
gboolean *values = (gboolean *) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) {
ret = _interpolate_none_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = g_value_get_boolean (ret);
ts += value_array->sample_interval;
values++;
}
g_mutex_unlock (self->lock);
return TRUE;
}
static gboolean
interpolate_none_get_enum_value_array (GstInterpolationControlSource * self,
GstClockTime timestamp, GstValueArray * value_array) GstClockTime timestamp, GstValueArray * value_array)
{ {
gint i; gint i;
GstClockTime ts = timestamp; GstClockTime ts = timestamp;
gint *values = (gint *) value_array->values; gint *values = (gint *) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) { for (i = 0; i < value_array->nbsamples; i++) {
*values = g_value_get_enum (interpolate_none_get (prop, ts)); ret = _interpolate_none_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = g_value_get_enum (ret);
ts += value_array->sample_interval; ts += value_array->sample_interval;
values++; values++;
} }
g_mutex_unlock (self->lock);
return TRUE; return TRUE;
} }
static gboolean static gboolean
interpolate_none_get_string_value_array (GstControlledProperty * prop, interpolate_none_get_string_value_array (GstInterpolationControlSource * self,
GstClockTime timestamp, GstValueArray * value_array) GstClockTime timestamp, GstValueArray * value_array)
{ {
gint i; gint i;
GstClockTime ts = timestamp; GstClockTime ts = timestamp;
gchar **values = (gchar **) value_array->values; gchar **values = (gchar **) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) { for (i = 0; i < value_array->nbsamples; i++) {
*values = (gchar *) g_value_get_string (interpolate_none_get (prop, ts)); ret = _interpolate_none_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = (gchar *) g_value_get_string (ret);
ts += value_array->sample_interval; ts += value_array->sample_interval;
values++; values++;
} }
g_mutex_unlock (self->lock);
return TRUE; return TRUE;
} }
static GstInterpolateMethod interpolate_none = { static GstInterpolateMethod interpolate_none = {
interpolate_none_get_int, (GstControlSourceGetValue) interpolate_none_get_int,
interpolate_none_get_int_value_array, (GstControlSourceGetValueArray) interpolate_none_get_int_value_array,
interpolate_none_get_uint, (GstControlSourceGetValue) interpolate_none_get_uint,
interpolate_none_get_uint_value_array, (GstControlSourceGetValueArray) interpolate_none_get_uint_value_array,
interpolate_none_get_long, (GstControlSourceGetValue) interpolate_none_get_long,
interpolate_none_get_long_value_array, (GstControlSourceGetValueArray) interpolate_none_get_long_value_array,
interpolate_none_get_ulong, (GstControlSourceGetValue) interpolate_none_get_ulong,
interpolate_none_get_ulong_value_array, (GstControlSourceGetValueArray) interpolate_none_get_ulong_value_array,
interpolate_none_get_float, (GstControlSourceGetValue) interpolate_none_get_int64,
interpolate_none_get_float_value_array, (GstControlSourceGetValueArray) interpolate_none_get_int64_value_array,
interpolate_none_get_double, (GstControlSourceGetValue) interpolate_none_get_uint64,
interpolate_none_get_double_value_array, (GstControlSourceGetValueArray) interpolate_none_get_uint64_value_array,
interpolate_none_get, (GstControlSourceGetValue) interpolate_none_get_float,
interpolate_none_get_boolean_value_array, (GstControlSourceGetValueArray) interpolate_none_get_float_value_array,
interpolate_none_get, (GstControlSourceGetValue) interpolate_none_get_double,
interpolate_none_get_enum_value_array, (GstControlSourceGetValueArray) interpolate_none_get_double_value_array,
interpolate_none_get, (GstControlSourceGetValue) interpolate_none_get,
interpolate_none_get_string_value_array (GstControlSourceGetValueArray) interpolate_none_get_boolean_value_array,
(GstControlSourceGetValue) interpolate_none_get,
(GstControlSourceGetValueArray) interpolate_none_get_enum_value_array,
(GstControlSourceGetValue) interpolate_none_get,
(GstControlSourceGetValueArray) interpolate_none_get_string_value_array
}; };
/* returns the default value of the property, except for times with specific values */ /* returns the default value of the property, except for times with specific values */
/* needed for one-shot events, such as notes and triggers */ /* needed for one-shot events, such as notes and triggers */
static GValue *
interpolate_trigger_get (GstControlledProperty * prop, GstClockTime timestamp)
{
GList *node;
GstControlPoint *cp;
/* check if there is a value at the registered timestamp */
if ((node =
gst_controlled_property_find_control_point_node (prop, timestamp))) {
cp = node->data;
if (timestamp == cp->timestamp) {
return &cp->value;
}
}
return &prop->default_value;
}
#define interpolate_trigger_get_boolean interpolate_trigger_get
#define DEFINE_TRIGGER_GET(type) \ #define DEFINE_TRIGGER_GET(type) \
static GValue * \ static inline GValue * \
interpolate_trigger_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ _interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp) \
{ \ { \
GList *node; \ GList *node; \
GstControlPoint *cp; \ GstControlPoint *cp; \
\ \
/* check if there is a value at the registered timestamp */ \ /* check if there is a value at the registered timestamp */ \
if ((node = \ if ((node = \
gst_controlled_property_find_control_point_node (prop, timestamp))) { \ gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
cp = node->data; \ cp = node->data; \
if (timestamp == cp->timestamp) { \ if (timestamp == cp->timestamp) { \
g##type ret = g_value_get_##type (&cp->value); \ g##type ret = g_value_get_##type (&cp->value); \
if (g_value_get_##type (&prop->min_value) > ret) \ if (g_value_get_##type (&self->priv->minimum_value) > ret) \
return &prop->min_value; \ return &self->priv->minimum_value; \
else if (g_value_get_##type (&prop->max_value) < ret) \ else if (g_value_get_##type (&self->priv->maximum_value) < ret) \
return &prop->max_value; \ return &self->priv->maximum_value; \
return &cp->value; \ else \
return &cp->value; \
} \ } \
} \ } \
\ \
return &prop->default_value; \ if (self->priv->nvalues > 0) \
} return &self->priv->default_value; \
else \
DEFINE_TRIGGER_GET (int); return NULL; \
DEFINE_TRIGGER_GET (uint); } \
DEFINE_TRIGGER_GET (long); \
DEFINE_TRIGGER_GET (ulong);
DEFINE_TRIGGER_GET (float);
DEFINE_TRIGGER_GET (double);
#define DEFINE_TRIGGER_GET_VALUE_ARRAY(type) \
static gboolean \ static gboolean \
interpolate_trigger_get_##type##_value_array (GstControlledProperty * prop, \ interpolate_trigger_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
GValue *ret; \
g_mutex_lock (self->lock); \
ret = _interpolate_trigger_get_##type (self, 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, GstValueArray * value_array) \ GstClockTime timestamp, GstValueArray * value_array) \
{ \ { \
gint i; \ gint i; \
GstClockTime ts = timestamp; \ GstClockTime ts = timestamp; \
g##type *values = (g##type *) value_array->values; \ g##type *values = (g##type *) value_array->values; \
GValue *ret; \
\ \
g_mutex_lock (self->lock); \
for(i = 0; i < value_array->nbsamples; i++) { \ for(i = 0; i < value_array->nbsamples; i++) { \
*values = g_value_get_##type (interpolate_trigger_get_##type (prop,ts)); \ ret = _interpolate_trigger_get_##type (self, timestamp); \
if (!ret) { \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
*values = g_value_get_##type (ret); \
ts += value_array->sample_interval; \ ts += value_array->sample_interval; \
values++; \ values++; \
} \ } \
g_mutex_unlock (self->lock); \
return TRUE; \ return TRUE; \
} }
DEFINE_TRIGGER_GET_VALUE_ARRAY (int);
DEFINE_TRIGGER_GET_VALUE_ARRAY (uint); DEFINE_TRIGGER_GET (int);
DEFINE_TRIGGER_GET_VALUE_ARRAY (long);
DEFINE_TRIGGER_GET_VALUE_ARRAY (ulong); DEFINE_TRIGGER_GET (uint);
DEFINE_TRIGGER_GET_VALUE_ARRAY (float); DEFINE_TRIGGER_GET (long);
DEFINE_TRIGGER_GET_VALUE_ARRAY (double);
DEFINE_TRIGGER_GET_VALUE_ARRAY (boolean); DEFINE_TRIGGER_GET (ulong);
DEFINE_TRIGGER_GET (int64);
DEFINE_TRIGGER_GET (uint64);
DEFINE_TRIGGER_GET (float);
DEFINE_TRIGGER_GET (double);
static inline GValue *
_interpolate_trigger_get (GstInterpolationControlSource * self,
GstClockTime timestamp)
{
GList *node;
GstControlPoint *cp;
/* check if there is a value at the registered timestamp */
if ((node =
gst_interpolation_control_source_find_control_point_node (self,
timestamp))) {
cp = node->data;
if (timestamp == cp->timestamp) {
return &cp->value;
}
}
if (self->priv->nvalues > 0)
return &self->priv->default_value;
else
return NULL;
}
static gboolean static gboolean
interpolate_trigger_get_enum_value_array (GstControlledProperty * prop, interpolate_trigger_get (GstInterpolationControlSource * self,
GstClockTime timestamp, GValue * value)
{
GValue *ret;
g_mutex_lock (self->lock);
ret = _interpolate_trigger_get (self, 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_boolean_value_array (GstInterpolationControlSource *
self, GstClockTime timestamp, GstValueArray * value_array)
{
gint i;
GstClockTime ts = timestamp;
gint *values = (gint *) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) {
ret = _interpolate_trigger_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = g_value_get_boolean (ret);
ts += value_array->sample_interval;
values++;
}
g_mutex_unlock (self->lock);
return TRUE;
}
static gboolean
interpolate_trigger_get_enum_value_array (GstInterpolationControlSource * self,
GstClockTime timestamp, GstValueArray * value_array) GstClockTime timestamp, GstValueArray * value_array)
{ {
gint i; gint i;
GstClockTime ts = timestamp; GstClockTime ts = timestamp;
gint *values = (gint *) value_array->values; gint *values = (gint *) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) { for (i = 0; i < value_array->nbsamples; i++) {
*values = g_value_get_enum (interpolate_trigger_get (prop, ts)); ret = _interpolate_trigger_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = g_value_get_enum (ret);
ts += value_array->sample_interval; ts += value_array->sample_interval;
values++; values++;
} }
g_mutex_unlock (self->lock);
return TRUE; return TRUE;
} }
static gboolean static gboolean
interpolate_trigger_get_string_value_array (GstControlledProperty * prop, interpolate_trigger_get_string_value_array (GstInterpolationControlSource *
GstClockTime timestamp, GstValueArray * value_array) self, GstClockTime timestamp, GstValueArray * value_array)
{ {
gint i; gint i;
GstClockTime ts = timestamp; GstClockTime ts = timestamp;
gchar **values = (gchar **) value_array->values; gchar **values = (gchar **) value_array->values;
GValue *ret;
g_mutex_lock (self->lock);
for (i = 0; i < value_array->nbsamples; i++) { for (i = 0; i < value_array->nbsamples; i++) {
*values = (gchar *) g_value_get_string (interpolate_trigger_get (prop, ts)); ret = _interpolate_trigger_get (self, timestamp);
if (!ret) {
g_mutex_unlock (self->lock);
return FALSE;
}
*values = (gchar *) g_value_get_string (ret);
ts += value_array->sample_interval; ts += value_array->sample_interval;
values++; values++;
} }
g_mutex_unlock (self->lock);
return TRUE; return TRUE;
} }
static GstInterpolateMethod interpolate_trigger = { static GstInterpolateMethod interpolate_trigger = {
interpolate_trigger_get_int, (GstControlSourceGetValue) interpolate_trigger_get_int,
interpolate_trigger_get_int_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_int_value_array,
interpolate_trigger_get_uint, (GstControlSourceGetValue) interpolate_trigger_get_uint,
interpolate_trigger_get_uint_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_uint_value_array,
interpolate_trigger_get_long, (GstControlSourceGetValue) interpolate_trigger_get_long,
interpolate_trigger_get_long_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_long_value_array,
interpolate_trigger_get_ulong, (GstControlSourceGetValue) interpolate_trigger_get_ulong,
interpolate_trigger_get_ulong_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_ulong_value_array,
interpolate_trigger_get_float, (GstControlSourceGetValue) interpolate_trigger_get_int64,
interpolate_trigger_get_float_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_int64_value_array,
interpolate_trigger_get_double, (GstControlSourceGetValue) interpolate_trigger_get_uint64,
interpolate_trigger_get_double_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_uint64_value_array,
interpolate_trigger_get, (GstControlSourceGetValue) interpolate_trigger_get_float,
interpolate_trigger_get_boolean_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_float_value_array,
interpolate_trigger_get, (GstControlSourceGetValue) interpolate_trigger_get_double,
interpolate_trigger_get_enum_value_array, (GstControlSourceGetValueArray) interpolate_trigger_get_double_value_array,
interpolate_trigger_get, (GstControlSourceGetValue) interpolate_trigger_get,
interpolate_trigger_get_string_value_array (GstControlSourceGetValueArray) interpolate_trigger_get_boolean_value_array,
(GstControlSourceGetValue) interpolate_trigger_get,
(GstControlSourceGetValueArray) interpolate_trigger_get_enum_value_array,
(GstControlSourceGetValue) interpolate_trigger_get,
(GstControlSourceGetValueArray) interpolate_trigger_get_string_value_array
}; };
/* linear interpolation */ /* linear interpolation */
/* smoothes inbetween values */ /* smoothes inbetween values */
#define DEFINE_LINEAR_GET(type) \ #define DEFINE_LINEAR_GET(type) \
static g##type \ static inline gboolean \
_interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ _interpolate_linear_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, g##type *ret) \
{ \ { \
GList *node; \ GList *node; \
g##type ret; \
\ \
if ((node = gst_controlled_property_find_control_point_node (prop, timestamp))) { \ if ((node = gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
GstControlPoint *cp1, *cp2; \ GstControlPoint *cp1, *cp2; \
\ \
cp1 = node->data; \ cp1 = node->data; \
@ -361,38 +553,53 @@ _interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime times
value2 = g_value_get_##type (&cp2->value); \ value2 = g_value_get_##type (&cp2->value); \
slope = (gdouble) (value2 - value1) / gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \ slope = (gdouble) (value2 - value1) / gst_guint64_to_gdouble (cp2->timestamp - cp1->timestamp); \
\ \
ret = (g##type) (value1 + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope); \ *ret = (g##type) (value1 + gst_guint64_to_gdouble (timestamp - cp1->timestamp) * slope); \
} \ } \
else { \ else { \
ret = g_value_get_##type (&cp1->value); \ *ret = g_value_get_##type (&cp1->value); \
} \ } \
} else { \ } else { \
ret = g_value_get_##type (&prop->default_value); \ GValue *first = gst_interpolation_control_source_get_first_value (self); \
if (!first) \
return FALSE; \
*ret = g_value_get_##type (first); \
} \ } \
ret = CLAMP (ret, g_value_get_##type (&prop->min_value), g_value_get_##type (&prop->max_value)); \ *ret = CLAMP (*ret, g_value_get_##type (&self->priv->minimum_value), g_value_get_##type (&self->priv->maximum_value)); \
return ret; \ return TRUE; \
} \
\
static GValue * \
interpolate_linear_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \
{ \
g_value_set_##type (&prop->result_value,_interpolate_linear_get_##type (prop,timestamp)); \
return &prop->result_value; \
} \ } \
\ \
static gboolean \ static gboolean \
interpolate_linear_get_##type##_value_array (GstControlledProperty * prop, \ interpolate_linear_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
g##type ret; \
g_mutex_lock (self->lock); \
if (_interpolate_linear_get_##type (self, timestamp, &ret)) { \
g_value_set_##type (value, ret); \
g_mutex_unlock (self->lock); \
return TRUE; \
} \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
\
static gboolean \
interpolate_linear_get_##type##_value_array (GstInterpolationControlSource *self, \
GstClockTime timestamp, GstValueArray * value_array) \ GstClockTime timestamp, GstValueArray * value_array) \
{ \ { \
gint i; \ gint i; \
GstClockTime ts = timestamp; \ GstClockTime ts = timestamp; \
g##type *values = (g##type *) value_array->values; \ g##type *values = (g##type *) value_array->values; \
\ \
g_mutex_lock (self->lock); \
for(i = 0; i < value_array->nbsamples; i++) { \ for(i = 0; i < value_array->nbsamples; i++) { \
*values = _interpolate_linear_get_##type (prop, ts); \ if (! _interpolate_linear_get_##type (self, ts, values)) { \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
ts += value_array->sample_interval; \ ts += value_array->sample_interval; \
values++; \ values++; \
} \ } \
g_mutex_unlock (self->lock); \
return TRUE; \ return TRUE; \
} }
@ -402,28 +609,34 @@ DEFINE_LINEAR_GET (uint);
DEFINE_LINEAR_GET (long); DEFINE_LINEAR_GET (long);
DEFINE_LINEAR_GET (ulong); DEFINE_LINEAR_GET (ulong);
DEFINE_LINEAR_GET (int64);
DEFINE_LINEAR_GET (uint64);
DEFINE_LINEAR_GET (float); DEFINE_LINEAR_GET (float);
DEFINE_LINEAR_GET (double); DEFINE_LINEAR_GET (double);
static GstInterpolateMethod interpolate_linear = { static GstInterpolateMethod interpolate_linear = {
interpolate_linear_get_int, (GstControlSourceGetValue) interpolate_linear_get_int,
interpolate_linear_get_int_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_int_value_array,
interpolate_linear_get_uint, (GstControlSourceGetValue) interpolate_linear_get_uint,
interpolate_linear_get_uint_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_uint_value_array,
interpolate_linear_get_long, (GstControlSourceGetValue) interpolate_linear_get_long,
interpolate_linear_get_long_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_long_value_array,
interpolate_linear_get_ulong, (GstControlSourceGetValue) interpolate_linear_get_ulong,
interpolate_linear_get_ulong_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_ulong_value_array,
interpolate_linear_get_float, (GstControlSourceGetValue) interpolate_linear_get_int64,
interpolate_linear_get_float_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_int64_value_array,
interpolate_linear_get_double, (GstControlSourceGetValue) interpolate_linear_get_uint64,
interpolate_linear_get_double_value_array, (GstControlSourceGetValueArray) interpolate_linear_get_uint64_value_array,
NULL, (GstControlSourceGetValue) interpolate_linear_get_float,
NULL, (GstControlSourceGetValueArray) interpolate_linear_get_float_value_array,
NULL, (GstControlSourceGetValue) interpolate_linear_get_double,
NULL, (GstControlSourceGetValueArray) interpolate_linear_get_double_value_array,
NULL, (GstControlSourceGetValue) NULL,
NULL (GstControlSourceGetValueArray) NULL,
(GstControlSourceGetValue) NULL,
(GstControlSourceGetValueArray) NULL,
(GstControlSourceGetValue) NULL,
(GstControlSourceGetValueArray) NULL
}; };
/* square interpolation */ /* square interpolation */
@ -445,9 +658,9 @@ static GstInterpolateMethod interpolate_linear = {
#define DEFINE_CUBIC_GET(type) \ #define DEFINE_CUBIC_GET(type) \
static void \ static void \
_interpolate_cubic_update_cache_##type (GstControlledProperty *prop) \ _interpolate_cubic_update_cache_##type (GstInterpolationControlSource *self) \
{ \ { \
gint i, n = prop->nvalues; \ gint i, n = self->priv->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); \
@ -462,7 +675,7 @@ _interpolate_cubic_update_cache_##type (GstControlledProperty *prop) \
g##type y_prev, y, y_next; \ g##type y_prev, y, y_next; \
\ \
/* Fill linear system of equations */ \ /* Fill linear system of equations */ \
node = prop->values; \ node = self->priv->values; \
cp = node->data; \ cp = node->data; \
x = cp->timestamp; \ x = cp->timestamp; \
y = g_value_get_##type (&cp->value); \ y = g_value_get_##type (&cp->value); \
@ -508,7 +721,7 @@ _interpolate_cubic_update_cache_##type (GstControlledProperty *prop) \
\ \
/* Save cache next in the GstControlPoint */ \ /* Save cache next in the GstControlPoint */ \
\ \
node = prop->values; \ node = self->priv->values; \
for (i = 0; i < n; i++) { \ for (i = 0; i < n; i++) { \
cp = node->data; \ cp = node->data; \
cp->cache.cubic.h = h[i]; \ cp->cache.cubic.h = h[i]; \
@ -525,21 +738,20 @@ _interpolate_cubic_update_cache_##type (GstControlledProperty *prop) \
g_free (z); \ g_free (z); \
} \ } \
\ \
static g##type \ static inline gboolean \
_interpolate_cubic_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \ _interpolate_cubic_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, g##type *ret) \
{ \ { \
GList *node; \ GList *node; \
g##type ret; \
\ \
if (prop->nvalues <= 2) \ if (self->priv->nvalues <= 2) \
return _interpolate_linear_get_##type (prop, timestamp); \ return _interpolate_linear_get_##type (self, timestamp, ret); \
\ \
if (!prop->valid_cache) { \ if (!self->priv->valid_cache) { \
_interpolate_cubic_update_cache_##type (prop); \ _interpolate_cubic_update_cache_##type (self); \
prop->valid_cache = TRUE; \ self->priv->valid_cache = TRUE; \
} \ } \
\ \
if ((node = gst_controlled_property_find_control_point_node (prop, timestamp))) { \ if ((node = gst_interpolation_control_source_find_control_point_node (self, timestamp))) { \
GstControlPoint *cp1, *cp2; \ GstControlPoint *cp1, *cp2; \
\ \
cp1 = node->data; \ cp1 = node->data; \
@ -560,38 +772,53 @@ _interpolate_cubic_get_##type (GstControlledProperty * prop, GstClockTime timest
out += (value2 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \ out += (value2 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp2->cache.cubic.z) * diff1; \
out += (value1 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \ out += (value1 / cp1->cache.cubic.h - cp1->cache.cubic.h * cp1->cache.cubic.z) * diff2; \
\ \
ret = (g##type) out; \ *ret = (g##type) out; \
} \ } \
else { \ else { \
ret = g_value_get_##type (&cp1->value); \ *ret = g_value_get_##type (&cp1->value); \
} \ } \
} else {\ } else { \
ret = g_value_get_##type (&prop->default_value); \ GValue *first = gst_interpolation_control_source_get_first_value (self); \
if (!first) \
return FALSE; \
*ret = g_value_get_##type (first); \
} \ } \
ret = CLAMP (ret, g_value_get_##type (&prop->min_value), g_value_get_##type (&prop->max_value)); \ *ret = CLAMP (*ret, g_value_get_##type (&self->priv->minimum_value), g_value_get_##type (&self->priv->maximum_value)); \
return ret; \ return TRUE; \
} \
\
static GValue * \
interpolate_cubic_get_##type (GstControlledProperty * prop, GstClockTime timestamp) \
{ \
g_value_set_##type (&prop->result_value,_interpolate_cubic_get_##type (prop,timestamp)); \
return &prop->result_value; \
} \ } \
\ \
static gboolean \ static gboolean \
interpolate_cubic_get_##type##_value_array (GstControlledProperty * prop, \ interpolate_cubic_get_##type (GstInterpolationControlSource *self, GstClockTime timestamp, GValue *value) \
{ \
g##type ret; \
g_mutex_lock (self->lock); \
if (_interpolate_cubic_get_##type (self, timestamp, &ret)) { \
g_value_set_##type (value, ret); \
g_mutex_unlock (self->lock); \
return TRUE; \
} \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
\
static gboolean \
interpolate_cubic_get_##type##_value_array (GstInterpolationControlSource *self, \
GstClockTime timestamp, GstValueArray * value_array) \ GstClockTime timestamp, GstValueArray * value_array) \
{ \ { \
gint i; \ gint i; \
GstClockTime ts = timestamp; \ GstClockTime ts = timestamp; \
g##type *values = (g##type *) value_array->values; \ g##type *values = (g##type *) value_array->values; \
\ \
g_mutex_lock (self->lock); \
for(i = 0; i < value_array->nbsamples; i++) { \ for(i = 0; i < value_array->nbsamples; i++) { \
*values = _interpolate_cubic_get_##type (prop, ts); \ if (! _interpolate_cubic_get_##type (self, ts, values)) { \
g_mutex_unlock (self->lock); \
return FALSE; \
} \
ts += value_array->sample_interval; \ ts += value_array->sample_interval; \
values++; \ values++; \
} \ } \
g_mutex_unlock (self->lock); \
return TRUE; \ return TRUE; \
} }
@ -601,28 +828,34 @@ DEFINE_CUBIC_GET (uint);
DEFINE_CUBIC_GET (long); DEFINE_CUBIC_GET (long);
DEFINE_CUBIC_GET (ulong); DEFINE_CUBIC_GET (ulong);
DEFINE_CUBIC_GET (int64);
DEFINE_CUBIC_GET (uint64);
DEFINE_CUBIC_GET (float); DEFINE_CUBIC_GET (float);
DEFINE_CUBIC_GET (double); DEFINE_CUBIC_GET (double);
static GstInterpolateMethod interpolate_cubic = { static GstInterpolateMethod interpolate_cubic = {
interpolate_cubic_get_int, (GstControlSourceGetValue) interpolate_cubic_get_int,
interpolate_cubic_get_int_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_int_value_array,
interpolate_cubic_get_uint, (GstControlSourceGetValue) interpolate_cubic_get_uint,
interpolate_cubic_get_uint_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_uint_value_array,
interpolate_cubic_get_long, (GstControlSourceGetValue) interpolate_cubic_get_long,
interpolate_cubic_get_long_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_long_value_array,
interpolate_cubic_get_ulong, (GstControlSourceGetValue) interpolate_cubic_get_ulong,
interpolate_cubic_get_ulong_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_ulong_value_array,
interpolate_cubic_get_float, (GstControlSourceGetValue) interpolate_cubic_get_int64,
interpolate_cubic_get_float_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_int64_value_array,
interpolate_cubic_get_double, (GstControlSourceGetValue) interpolate_cubic_get_uint64,
interpolate_cubic_get_double_value_array, (GstControlSourceGetValueArray) interpolate_cubic_get_uint64_value_array,
NULL, (GstControlSourceGetValue) interpolate_cubic_get_float,
NULL, (GstControlSourceGetValueArray) interpolate_cubic_get_float_value_array,
NULL, (GstControlSourceGetValue) interpolate_cubic_get_double,
NULL, (GstControlSourceGetValueArray) interpolate_cubic_get_double_value_array,
NULL, (GstControlSourceGetValue) NULL,
NULL (GstControlSourceGetValueArray) NULL,
(GstControlSourceGetValue) NULL,
(GstControlSourceGetValueArray) NULL,
(GstControlSourceGetValue) NULL,
(GstControlSourceGetValueArray) NULL
}; };

View file

@ -0,0 +1,667 @@
/* GStreamer
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* gstinterpolationcontrolsource.c: Control source that provides several
* interpolation methods
*
* 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:gstinterpolationcontrolsource
* @short_description: interpolation control source
*
* #GstInterpolationControlSource is a #GstControlSource, that interpolates values between user-given
* control points. It supports several interpolation modes and property types.
*
* To use #GstInterpolationControlSource get a new instance by calling
* gst_interpolation_control_source_new(), bind it to a #GParamSpec, select a interpolation mode with
* gst_interpolation_control_source_set_interpolation_mode() and set some control points by calling
* gst_interpolation_control_source_set().
*
* All functions are MT-safe.
*
*/
#include <glib-object.h>
#include <gst/gst.h>
#include "gstcontrolsource.h"
#include "gstinterpolationcontrolsource.h"
#include "gstinterpolationcontrolsourceprivate.h"
extern GstInterpolateMethod *interpolation_methods[];
extern guint num_interpolation_methods;
static void gst_interpolation_control_source_init (GstInterpolationControlSource
* self);
static void
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
* klass);
G_DEFINE_TYPE (GstInterpolationControlSource, gst_interpolation_control_source,
GST_TYPE_CONTROL_SOURCE);
static GObjectClass *parent_class = NULL;
/*
* gst_control_point_free:
* @prop: the object to free
*
* Private method which frees all data allocated by a #GstControlPoint
* instance.
*/
static void
gst_control_point_free (GstControlPoint * cp)
{
g_return_if_fail (cp);
g_value_unset (&cp->value);
g_free (cp);
}
static void
gst_interpolation_control_source_reset (GstInterpolationControlSource * self)
{
GstControlSource *csource = GST_CONTROL_SOURCE (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_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
g_list_free (self->priv->values);
self->priv->values = NULL;
}
self->priv->nvalues = 0;
self->priv->last_requested_value = NULL;
self->priv->valid_cache = FALSE;
}
/**
* gst_interpolation_control_source_new:
*
* This returns a new, unbound #GstInterpolationControlSource.
*
* Returns: a new, unbound #GstInterpolationControlSource.
*/
GstInterpolationControlSource *
gst_interpolation_control_source_new ()
{
return g_object_new (GST_TYPE_INTERPOLATION_CONTROL_SOURCE, NULL);
}
/**
* gst_interpolation_control_source_set_interpolation_mode:
* @self: the #GstInterpolationControlSource object
* @mode: interpolation mode
*
* Sets the given interpolation mode.
*
* <note><para>User interpolation is not yet available and quadratic interpolation
* is deprecated and maps to cubic interpolation.</para></note>
*
* Returns: %TRUE if the interpolation mode could be set, %FALSE otherwise
*/
gboolean
gst_interpolation_control_source_set_interpolation_mode
(GstInterpolationControlSource * self, GstInterpolateMode mode) {
gboolean ret = TRUE;
GstControlSource *csource = GST_CONTROL_SOURCE (self);
if (mode >= num_interpolation_methods || interpolation_methods[mode] == NULL) {
GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
return FALSE;
}
if (mode == GST_INTERPOLATE_QUADRATIC) {
GST_WARNING ("Quadratic interpolation mode is deprecated, using cubic"
"interpolation mode");
}
if (mode == GST_INTERPOLATE_USER) {
GST_WARNING ("User interpolation mode is not implemented yet");
return FALSE;
}
g_mutex_lock (self->lock);
switch (self->priv->base) {
case G_TYPE_INT:
csource->get_value = interpolation_methods[mode]->get_int;
csource->get_value_array =
interpolation_methods[mode]->get_int_value_array;
break;
case G_TYPE_UINT:{
csource->get_value = interpolation_methods[mode]->get_uint;
csource->get_value_array =
interpolation_methods[mode]->get_uint_value_array;
break;
}
case G_TYPE_LONG:{
csource->get_value = interpolation_methods[mode]->get_long;
csource->get_value_array =
interpolation_methods[mode]->get_long_value_array;
break;
}
case G_TYPE_ULONG:{
csource->get_value = interpolation_methods[mode]->get_ulong;
csource->get_value_array =
interpolation_methods[mode]->get_ulong_value_array;
break;
}
case G_TYPE_INT64:{
csource->get_value = interpolation_methods[mode]->get_int64;
csource->get_value_array =
interpolation_methods[mode]->get_int64_value_array;
break;
}
case G_TYPE_UINT64:{
csource->get_value = interpolation_methods[mode]->get_uint64;
csource->get_value_array =
interpolation_methods[mode]->get_uint64_value_array;
break;
}
case G_TYPE_FLOAT:{
csource->get_value = interpolation_methods[mode]->get_float;
csource->get_value_array =
interpolation_methods[mode]->get_float_value_array;
break;
}
case G_TYPE_DOUBLE:{
csource->get_value = interpolation_methods[mode]->get_double;
csource->get_value_array =
interpolation_methods[mode]->get_double_value_array;
break;
}
case G_TYPE_BOOLEAN:{
csource->get_value = interpolation_methods[mode]->get_boolean;
csource->get_value_array =
interpolation_methods[mode]->get_boolean_value_array;
break;
}
case G_TYPE_ENUM:{
csource->get_value = interpolation_methods[mode]->get_enum;
csource->get_value_array =
interpolation_methods[mode]->get_enum_value_array;
break;
}
case G_TYPE_STRING:{
csource->get_value = interpolation_methods[mode]->get_string;
csource->get_value_array =
interpolation_methods[mode]->get_string_value_array;
break;
}
default:
ret = FALSE;
break;
}
/* Incomplete implementation */
if (!ret || !csource->get_value || !csource->get_value_array) {
gst_interpolation_control_source_reset (self);
ret = FALSE;
}
self->priv->valid_cache = FALSE;
self->priv->interpolation_mode = mode;
g_mutex_unlock (self->lock);
return ret;
}
static gboolean
gst_interpolation_control_source_bind (GstControlSource * source,
GParamSpec * pspec)
{
GType type, base;
GstInterpolationControlSource *self =
GST_INTERPOLATION_CONTROL_SOURCE (source);
gboolean ret = TRUE;
/* get the fundamental base type */
self->priv->type = base = type = G_PARAM_SPEC_VALUE_TYPE (pspec);
while ((type = g_type_parent (type)))
base = type;
self->priv->base = base;
/* restore type */
type = self->priv->type;
if (!gst_interpolation_control_source_set_interpolation_mode (self,
self->priv->interpolation_mode))
return FALSE;
switch (base) {
case G_TYPE_INT:{
GParamSpecInt *tpspec = G_PARAM_SPEC_INT (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_int (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_int (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_int (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_UINT:{
GParamSpecUInt *tpspec = G_PARAM_SPEC_UINT (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_uint (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_uint (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_uint (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_LONG:{
GParamSpecLong *tpspec = G_PARAM_SPEC_LONG (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_long (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_long (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_long (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_ULONG:{
GParamSpecULong *tpspec = G_PARAM_SPEC_ULONG (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_ulong (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_ulong (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_ulong (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_INT64:{
GParamSpecInt64 *tpspec = G_PARAM_SPEC_INT64 (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_int64 (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_int64 (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_int64 (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_UINT64:{
GParamSpecUInt64 *tpspec = G_PARAM_SPEC_UINT64 (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_uint64 (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_uint64 (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_uint64 (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_FLOAT:{
GParamSpecFloat *tpspec = G_PARAM_SPEC_FLOAT (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_float (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_float (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_float (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_DOUBLE:{
GParamSpecDouble *tpspec = G_PARAM_SPEC_DOUBLE (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_double (&self->priv->default_value, tpspec->default_value);
g_value_init (&self->priv->minimum_value, type);
g_value_set_double (&self->priv->minimum_value, tpspec->minimum);
g_value_init (&self->priv->maximum_value, type);
g_value_set_double (&self->priv->maximum_value, tpspec->maximum);
break;
}
case G_TYPE_BOOLEAN:{
GParamSpecBoolean *tpspec = G_PARAM_SPEC_BOOLEAN (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_boolean (&self->priv->default_value, tpspec->default_value);
break;
}
case G_TYPE_ENUM:{
GParamSpecEnum *tpspec = G_PARAM_SPEC_ENUM (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_enum (&self->priv->default_value, tpspec->default_value);
break;
}
case G_TYPE_STRING:{
GParamSpecString *tpspec = G_PARAM_SPEC_STRING (pspec);
g_value_init (&self->priv->default_value, type);
g_value_set_string (&self->priv->default_value, tpspec->default_value);
break;
}
default:
GST_WARNING ("incomplete implementation for paramspec type '%s'",
G_PARAM_SPEC_TYPE_NAME (pspec));
ret = FALSE;
break;
}
if (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 void
gst_interpolation_control_source_set_internal (GstInterpolationControlSource *
self, GstClockTime timestamp, GValue * value)
{
GstControlPoint *cp;
GList *node;
/* check if a control point for the timestamp already exists */
if ((node = g_list_find_custom (self->priv->values, &timestamp,
gst_control_point_find))) {
cp = node->data;
g_value_reset (&cp->value);
g_value_copy (value, &cp->value);
} else {
/* create a new GstControlPoint */
cp = g_new0 (GstControlPoint, 1);
cp->timestamp = timestamp;
g_value_init (&cp->value, self->priv->type);
g_value_copy (value, &cp->value);
/* and sort it into the prop->values list */
self->priv->values =
g_list_insert_sorted (self->priv->values, cp,
gst_control_point_compare);
self->priv->nvalues++;
}
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, 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: 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, GSList * timedvalues)
{
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)
{
GList *node;
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 ((node = g_list_find_custom (self->priv->values, &timestamp,
gst_control_point_find))) {
GstControlPoint *cp = node->data;
if (cp->timestamp == 0) {
/* Restore the default node */
g_value_reset (&cp->value);
g_value_copy (&self->priv->default_value, &cp->value);
} else {
if (node == self->priv->last_requested_value)
self->priv->last_requested_value = NULL;
gst_control_point_free (node->data); /* free GstControlPoint */
self->priv->values = g_list_delete_link (self->priv->values, node);
self->priv->nvalues--;
}
self->priv->valid_cache = FALSE;
res = TRUE;
}
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 */
g_list_foreach (self->priv->values, (GFunc) gst_control_point_free, NULL);
g_list_free (self->priv->values);
self->priv->last_requested_value = NULL;
self->priv->values = NULL;
self->priv->nvalues = 0;
self->priv->valid_cache = FALSE;
g_mutex_unlock (self->lock);
}
/**
* 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: 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)
{
GList *res = NULL;
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), NULL);
g_mutex_lock (self->lock);
if (self->priv->values)
res = g_list_copy (self->priv->values);
g_mutex_unlock (self->lock);
return res;
}
/**
* gst_interpolation_control_source_get_count:
* @self: the #GstInterpolationControlSource to get the number of values from
*
* Returns the number of control points that are set.
*
* Returns: the number of control points that are set.
*
*/
gint
gst_interpolation_control_source_get_count (GstInterpolationControlSource *
self)
{
g_return_val_if_fail (GST_IS_INTERPOLATION_CONTROL_SOURCE (self), 0);
return self->priv->nvalues;
}
static void
gst_interpolation_control_source_init (GstInterpolationControlSource * self)
{
self->lock = g_mutex_new ();
self->priv =
G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_INTERPOLATION_CONTROL_SOURCE,
GstInterpolationControlSourcePrivate);
self->priv->interpolation_mode = GST_INTERPOLATE_NONE;
}
static void
gst_interpolation_control_source_finalize (GObject * obj)
{
GstInterpolationControlSource *self = GST_INTERPOLATION_CONTROL_SOURCE (obj);
g_mutex_lock (self->lock);
gst_interpolation_control_source_reset (self);
g_mutex_unlock (self->lock);
g_mutex_free (self->lock);
G_OBJECT_CLASS (parent_class)->finalize (obj);
}
static void
gst_interpolation_control_source_dispose (GObject * obj)
{
G_OBJECT_CLASS (parent_class)->dispose (obj);
}
static void
gst_interpolation_control_source_class_init (GstInterpolationControlSourceClass
* klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstControlSourceClass *csource_class = GST_CONTROL_SOURCE_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass,
sizeof (GstInterpolationControlSourcePrivate));
gobject_class->finalize = gst_interpolation_control_source_finalize;
gobject_class->dispose = gst_interpolation_control_source_dispose;
csource_class->bind = gst_interpolation_control_source_bind;
}

View file

@ -0,0 +1,109 @@
/* GStreamer
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* gstinterpolationcontrolsource.h: Control source that provides several
* interpolation methods
*
* 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_INTERPOLATION_CONTROL_SOURCE_H__
#define __GST_INTERPOLATION_CONTROL_SOURCE_H__
#include <glib-object.h>
#include <gst/gst.h>
#include "gstcontrolsource.h"
G_BEGIN_DECLS
#define GST_TYPE_INTERPOLATION_CONTROL_SOURCE \
(gst_interpolation_control_source_get_type ())
#define GST_INTERPOLATION_CONTROL_SOURCE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSource))
#define GST_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \
(G_TYPE_CHECK_CLASS_CAST ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass))
#define GST_IS_INTERPOLATION_CONTROL_SOURCE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INTERPOLATION_CONTROL_SOURCE))
#define GST_IS_INTERPOLATION_CONTROL_SOURCE_CLASS(vtable) \
(G_TYPE_CHECK_CLASS_TYPE ((vtable), GST_TYPE_INTERPOLATION_CONTROL_SOURCE))
#define GST_INTERPOLATION_CONTROL_SOURCE_GET_CLASS(inst) \
(G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_INTERPOLATION_CONTROL_SOURCE, GstInterpolationControlSourceClass))
typedef struct _GstInterpolationControlSource GstInterpolationControlSource;
typedef struct _GstInterpolationControlSourceClass GstInterpolationControlSourceClass;
typedef struct _GstInterpolationControlSourcePrivate GstInterpolationControlSourcePrivate;
/**
* GstInterpolateMode:
* @GST_INTERPOLATE_NONE: steps-like interpolation, default
* @GST_INTERPOLATE_TRIGGER: returns the default value of the property,
* except for times with specific values
* @GST_INTERPOLATE_LINEAR: linear interpolation
* @GST_INTERPOLATE_QUADRATIC: square interpolation (deprecated, maps to cubic)
* @GST_INTERPOLATE_CUBIC: cubic interpolation
* @GST_INTERPOLATE_USER: user-provided interpolation (not yet available)
*
* The various interpolation modes available.
*/
typedef enum
{
GST_INTERPOLATE_NONE,
GST_INTERPOLATE_TRIGGER,
GST_INTERPOLATE_LINEAR,
GST_INTERPOLATE_QUADRATIC,
GST_INTERPOLATE_CUBIC,
GST_INTERPOLATE_USER
} GstInterpolateMode;
/**
* GstInterpolationControlSource:
*
* The instance structure of #GstControlSource.
*/
struct _GstInterpolationControlSource {
GstControlSource parent;
/* <private> */
GMutex *lock;
GstInterpolationControlSourcePrivate *priv;
gpointer _gst_reserved[GST_PADDING];
};
struct _GstInterpolationControlSourceClass {
GstControlSourceClass parent_class;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
GType gst_interpolation_control_source_get_type ();
/* Functions */
GstInterpolationControlSource *gst_interpolation_control_source_new ();
gboolean gst_interpolation_control_source_set_interpolation_mode (GstInterpolationControlSource *self, GstInterpolateMode mode);
gboolean gst_interpolation_control_source_set (GstInterpolationControlSource * self, GstClockTime timestamp, GValue * value);
gboolean gst_interpolation_control_source_set_from_list (GstInterpolationControlSource * self, 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
#endif /* __GST_INTERPOLATION_CONTROL_SOURCE_H__ */

View file

@ -0,0 +1,100 @@
/* GStreamer
*
* Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* gstinterpolationcontrolsourceprivate.h: Private declarations for the
* GstInterpolationControlSource
*
* 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_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__
#define __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__
/**
* GstInterpolateMethod:
*
* Function pointer structure to do user-defined interpolation methods
*/
typedef struct _GstInterpolateMethod
{
GstControlSourceGetValue get_int;
GstControlSourceGetValueArray get_int_value_array;
GstControlSourceGetValue get_uint;
GstControlSourceGetValueArray get_uint_value_array;
GstControlSourceGetValue get_long;
GstControlSourceGetValueArray get_long_value_array;
GstControlSourceGetValue get_ulong;
GstControlSourceGetValueArray get_ulong_value_array;
GstControlSourceGetValue get_int64;
GstControlSourceGetValueArray get_int64_value_array;
GstControlSourceGetValue get_uint64;
GstControlSourceGetValueArray get_uint64_value_array;
GstControlSourceGetValue get_float;
GstControlSourceGetValueArray get_float_value_array;
GstControlSourceGetValue get_double;
GstControlSourceGetValueArray get_double_value_array;
GstControlSourceGetValue get_boolean;
GstControlSourceGetValueArray get_boolean_value_array;
GstControlSourceGetValue get_enum;
GstControlSourceGetValueArray get_enum_value_array;
GstControlSourceGetValue get_string;
GstControlSourceGetValueArray get_string_value_array;
} GstInterpolateMethod;
/**
* GstControlPoint:
*
* a internal structure for value+time and various temporary
* values used for interpolation. This "inherits" from
* GstTimedValue.
*/
typedef struct _GstControlPoint
{
/* fields from GstTimedValue. DO NOT CHANGE! */
GstClockTime timestamp; /* timestamp of the value change */
GValue value; /* the new value */
/* internal fields */
/* Caches for the interpolators */
union {
struct {
gdouble h;
gdouble z;
} cubic;
} cache;
} 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;
GList *values; /* List of GstControlPoint */
gint nvalues; /* Number of control points */
GList *last_requested_value; /* last search result, can be used for incremental searches */
gboolean valid_cache;
};
#endif /* __GST_INTERPOLATION_CONTROL_SOURCE_PRIVATE_H__ */

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/controller/gstcontroller.h> #include <gst/controller/gstcontroller.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
gint gint
main (gint argc, gchar ** argv) main (gint argc, gchar ** argv)
@ -17,6 +18,7 @@ main (gint argc, gchar ** argv)
GstElement *src, *sink; GstElement *src, *sink;
GstElement *bin; GstElement *bin;
GstController *ctrl; GstController *ctrl;
GstInterpolationControlSource *csource1, *csource2;
GstClock *clock; GstClock *clock;
GstClockID clock_id; GstClockID clock_id;
GstClockReturn wait_ret; GstClockReturn wait_ret;
@ -46,23 +48,38 @@ main (gint argc, gchar ** argv)
goto Error; goto Error;
} }
/* set interpolation */ csource1 = gst_interpolation_control_source_new ();
gst_controller_set_interpolation_mode (ctrl, "volume", csource2 = gst_interpolation_control_source_new ();
gst_controller_set_control_source (ctrl, "volume",
GST_CONTROL_SOURCE (csource1));
gst_controller_set_control_source (ctrl, "freq",
GST_CONTROL_SOURCE (csource2));
/* Set interpolation mode */
gst_interpolation_control_source_set_interpolation_mode (csource1,
GST_INTERPOLATE_LINEAR);
gst_interpolation_control_source_set_interpolation_mode (csource2,
GST_INTERPOLATE_LINEAR); GST_INTERPOLATE_LINEAR);
gst_controller_set_interpolation_mode (ctrl, "freq", GST_INTERPOLATE_LINEAR);
/* 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_controller_set (ctrl, "volume", 0 * GST_SECOND, &vol); gst_interpolation_control_source_set (csource1, 0 * GST_SECOND, &vol);
g_value_set_double (&vol, 1.0); g_value_set_double (&vol, 1.0);
gst_controller_set (ctrl, "volume", 5 * GST_SECOND, &vol); gst_interpolation_control_source_set (csource1, 5 * GST_SECOND, &vol);
g_object_unref (csource1);
g_value_set_double (&vol, 220.0); g_value_set_double (&vol, 220.0);
gst_controller_set (ctrl, "freq", 0 * GST_SECOND, &vol); gst_interpolation_control_source_set (csource2, 0 * GST_SECOND, &vol);
g_value_set_double (&vol, 3520.0); g_value_set_double (&vol, 3520.0);
gst_controller_set (ctrl, "freq", 3 * GST_SECOND, &vol); gst_interpolation_control_source_set (csource2, 3 * GST_SECOND, &vol);
g_value_set_double (&vol, 440.0); g_value_set_double (&vol, 440.0);
gst_controller_set (ctrl, "freq", 6 * GST_SECOND, &vol); gst_interpolation_control_source_set (csource2, 6 * GST_SECOND, &vol);
g_object_unref (csource2);
clock_id = clock_id =
gst_clock_new_single_shot_id (clock, gst_clock_new_single_shot_id (clock,