mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-08 13:18:52 +00:00
450 lines
13 KiB
C
450 lines
13 KiB
C
/*
|
|
* control-sources.c
|
|
*
|
|
* Generates a datafile for various control sources.
|
|
*
|
|
* Needs gnuplot for plotting.
|
|
* plot "ctrl_i1.dat" using 1:2 with points title 'none', "" using 1:3 with points title 'linear', "" using 1:4 with points title 'cubic', "ctrl_i2.dat" using 1:2 with lines title 'none', "" using 1:3 with lines title 'linear', "" using 1:4 with lines title 'cubic'
|
|
* plot "ctrl_l1.dat" using 1:2 with points title 'sine', "" using 1:3 with points title 'square', "" using 1:4 with points title 'saw', "" using 1:5 with points title 'revsaw', "" using 1:6 with points title 'triangle', "ctrl_l2.dat" using 1:2 with lines title 'sine', "" using 1:3 with lines title 'square', "" using 1:4 with lines title 'saw', "" using 1:5 with lines title 'revsaw', "" using 1:6 with lines title 'triangle'
|
|
* plot "ctrl_cl1.dat" using 1:2 with points title 'sine', "ctrl_cl2.dat" using 1:2 with lines title 'sine'
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <gst/gst.h>
|
|
#include <gst/controller/gstinterpolationcontrolsource.h>
|
|
#include <gst/controller/gstlfocontrolsource.h>
|
|
#include <gst/controller/gstdirectcontrolbinding.h>
|
|
|
|
/* local test element */
|
|
|
|
enum
|
|
{
|
|
PROP_INT = 1,
|
|
PROP_FLOAT,
|
|
PROP_DOUBLE,
|
|
PROP_BOOLEAN,
|
|
PROP_COUNT
|
|
};
|
|
|
|
#define GST_TYPE_TEST_OBJ (gst_test_obj_get_type ())
|
|
#define GST_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TEST_OBJ, GstTestObj))
|
|
#define GST_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TEST_OBJ, GstTestObjClass))
|
|
#define GST_IS_TEST_OBJ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TEST_OBJ))
|
|
#define GST_IS_TEST_OBJ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TEST_OBJ))
|
|
#define GST_TEST_OBJ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TEST_OBJ, GstTestObjClass))
|
|
|
|
typedef struct _GstTestObj GstTestObj;
|
|
typedef struct _GstTestObjClass GstTestObjClass;
|
|
|
|
struct _GstTestObj
|
|
{
|
|
GstElement parent;
|
|
gint val_int;
|
|
gfloat val_float;
|
|
gdouble val_double;
|
|
gboolean val_boolean;
|
|
};
|
|
struct _GstTestObjClass
|
|
{
|
|
GstElementClass parent_class;
|
|
};
|
|
|
|
static GType gst_test_obj_get_type (void);
|
|
|
|
static void
|
|
gst_test_obj_get_property (GObject * object,
|
|
guint property_id, GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstTestObj *self = GST_TEST_OBJ (object);
|
|
|
|
switch (property_id) {
|
|
case PROP_INT:
|
|
g_value_set_int (value, self->val_int);
|
|
break;
|
|
case PROP_FLOAT:
|
|
g_value_set_float (value, self->val_float);
|
|
break;
|
|
case PROP_DOUBLE:
|
|
g_value_set_double (value, self->val_double);
|
|
break;
|
|
case PROP_BOOLEAN:
|
|
g_value_set_boolean (value, self->val_boolean);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_test_obj_set_property (GObject * object,
|
|
guint property_id, const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstTestObj *self = GST_TEST_OBJ (object);
|
|
|
|
switch (property_id) {
|
|
case PROP_INT:
|
|
self->val_int = g_value_get_int (value);
|
|
GST_DEBUG ("test value int=%d", self->val_int);
|
|
break;
|
|
case PROP_FLOAT:
|
|
self->val_float = g_value_get_float (value);
|
|
GST_DEBUG ("test value float=%f", self->val_float);
|
|
break;
|
|
case PROP_DOUBLE:
|
|
self->val_double = g_value_get_double (value);
|
|
GST_DEBUG ("test value double=%f", self->val_double);
|
|
break;
|
|
case PROP_BOOLEAN:
|
|
self->val_boolean = g_value_get_boolean (value);
|
|
GST_DEBUG ("test value boolean=%d", self->val_boolean);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_test_obj_class_init (GstTestObjClass * klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
gobject_class->set_property = gst_test_obj_set_property;
|
|
gobject_class->get_property = gst_test_obj_get_property;
|
|
|
|
g_object_class_install_property (gobject_class, PROP_INT,
|
|
g_param_spec_int ("int",
|
|
"int prop",
|
|
"int number parameter",
|
|
0, 100, 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_FLOAT,
|
|
g_param_spec_float ("float",
|
|
"float prop",
|
|
"float number parameter",
|
|
0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_DOUBLE,
|
|
g_param_spec_double ("double",
|
|
"double prop",
|
|
"double number parameter",
|
|
0.0, 100.0, 0.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
|
|
g_object_class_install_property (gobject_class, PROP_BOOLEAN,
|
|
g_param_spec_boolean ("boolean",
|
|
"boolean prop",
|
|
"boolean parameter",
|
|
FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
|
|
}
|
|
|
|
static void
|
|
gst_test_obj_base_init (GstTestObjClass * klass)
|
|
{
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
|
|
|
gst_element_class_set_metadata (element_class,
|
|
"test object for unit tests",
|
|
"Test", "Use in unit tests", "Stefan Sauer <ensonic@users.sf.net>");
|
|
}
|
|
|
|
static GType
|
|
gst_test_obj_get_type (void)
|
|
{
|
|
static volatile gsize TEST_OBJ_type = 0;
|
|
|
|
if (g_once_init_enter (&TEST_OBJ_type)) {
|
|
GType type;
|
|
static const GTypeInfo info = {
|
|
(guint16) sizeof (GstTestObjClass),
|
|
(GBaseInitFunc) gst_test_obj_base_init, // base_init
|
|
NULL, // base_finalize
|
|
(GClassInitFunc) gst_test_obj_class_init, // class_init
|
|
NULL, // class_finalize
|
|
NULL, // class_data
|
|
(guint16) sizeof (GstTestObj),
|
|
0, // n_preallocs
|
|
NULL, // instance_init
|
|
NULL // value_table
|
|
};
|
|
type = g_type_register_static (GST_TYPE_ELEMENT, "GstTestObj", &info, 0);
|
|
g_once_init_leave (&TEST_OBJ_type, type);
|
|
}
|
|
return TEST_OBJ_type;
|
|
}
|
|
|
|
static void
|
|
test_interpolation (void)
|
|
{
|
|
GstObject *e;
|
|
GstTimedValueControlSource *tvcs;
|
|
GstControlSource *cs;
|
|
gint t, i1, i2, i3;
|
|
GValue *v1, *v2, *v3;
|
|
gint n_values;
|
|
FILE *f;
|
|
|
|
e = (GstObject *) gst_element_factory_make ("testobj", NULL);
|
|
|
|
cs = gst_interpolation_control_source_new ();
|
|
tvcs = (GstTimedValueControlSource *) cs;
|
|
|
|
gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int",
|
|
cs));
|
|
|
|
gst_timed_value_control_source_set (tvcs, 0 * GST_SECOND, 0.0);
|
|
gst_timed_value_control_source_set (tvcs, 10 * GST_SECOND, 1.0);
|
|
gst_timed_value_control_source_set (tvcs, 20 * GST_SECOND, 0.5);
|
|
gst_timed_value_control_source_set (tvcs, 30 * GST_SECOND, 0.2);
|
|
|
|
/* test single values */
|
|
if (!(f = fopen ("ctrl_i1.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time None Linear Cubic\n");
|
|
|
|
for (t = 0; t < 40; t++) {
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i1 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i2 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i3 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
fprintf (f, "%4.1f %d %d %d\n", (gfloat) t, i1, i2, i3);
|
|
}
|
|
|
|
fclose (f);
|
|
|
|
/* test value arrays */
|
|
if (!(f = fopen ("ctrl_i2.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time None Linear Cubic\n");
|
|
n_values = 40 * 10;
|
|
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_NONE, NULL);
|
|
v1 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
|
|
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
|
|
v2 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
|
|
|
|
g_object_set (cs, "mode", GST_INTERPOLATION_MODE_CUBIC, NULL);
|
|
v3 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
|
|
|
|
for (t = 0; t < n_values; t++) {
|
|
i1 = g_value_get_int (&v1[t]);
|
|
i2 = g_value_get_int (&v2[t]);
|
|
i3 = g_value_get_int (&v3[t]);
|
|
fprintf (f, "%4.1f %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3);
|
|
g_value_unset (&v1[t]);
|
|
g_value_unset (&v2[t]);
|
|
g_value_unset (&v3[t]);
|
|
}
|
|
g_free (v1);
|
|
g_free (v2);
|
|
g_free (v3);
|
|
|
|
fclose (f);
|
|
|
|
gst_object_unref (cs);
|
|
gst_object_unref (e);
|
|
}
|
|
|
|
static void
|
|
test_lfo (void)
|
|
{
|
|
GstObject *e;
|
|
GstControlSource *cs;
|
|
gint t, i1, i2, i3, i4, i5;
|
|
GValue *v1, *v2, *v3, *v4, *v5;
|
|
gint n_values;
|
|
FILE *f;
|
|
|
|
e = (GstObject *) gst_element_factory_make ("testobj", NULL);
|
|
|
|
cs = gst_lfo_control_source_new ();
|
|
|
|
gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int",
|
|
cs));
|
|
|
|
g_object_set (cs,
|
|
"frequency", (gdouble) 0.05,
|
|
"timeshift", (GstClockTime) 0,
|
|
"amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
|
|
|
|
/* test single values */
|
|
if (!(f = fopen ("ctrl_l1.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n");
|
|
|
|
for (t = 0; t < 40; t++) {
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i1 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i2 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i3 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i4 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL);
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i5 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t, i1, i2, i3, i4, i5);
|
|
}
|
|
|
|
fclose (f);
|
|
|
|
/* test value arrays */
|
|
if (!(f = fopen ("ctrl_l2.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time Sine Square Saw RevSaw Triangle\n");
|
|
n_values = 40 * 10;
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SINE, NULL);
|
|
v1 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SQUARE, NULL);
|
|
v2 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v2);
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_SAW, NULL);
|
|
v3 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v3);
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_REVERSE_SAW, NULL);
|
|
v4 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v4);
|
|
|
|
g_object_set (cs, "waveform", GST_LFO_WAVEFORM_TRIANGLE, NULL);
|
|
v5 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v5);
|
|
|
|
for (t = 0; t < n_values; t++) {
|
|
i1 = g_value_get_int (&v1[t]);
|
|
i2 = g_value_get_int (&v2[t]);
|
|
i3 = g_value_get_int (&v3[t]);
|
|
i4 = g_value_get_int (&v4[t]);
|
|
i5 = g_value_get_int (&v5[t]);
|
|
fprintf (f, "%4.1f %d %d %d %d %d\n", (gfloat) t / 10.0, i1, i2, i3, i4,
|
|
i5);
|
|
g_value_unset (&v1[t]);
|
|
g_value_unset (&v2[t]);
|
|
g_value_unset (&v3[t]);
|
|
g_value_unset (&v4[t]);
|
|
g_value_unset (&v5[t]);
|
|
}
|
|
g_free (v1);
|
|
g_free (v2);
|
|
g_free (v3);
|
|
g_free (v4);
|
|
g_free (v5);
|
|
|
|
fclose (f);
|
|
|
|
gst_object_unref (cs);
|
|
gst_object_unref (e);
|
|
}
|
|
|
|
static void
|
|
test_chained_lfo (void)
|
|
{
|
|
GstObject *e;
|
|
GstControlSource *cs1, *cs2;
|
|
gint t, i1;
|
|
GValue *v1;
|
|
gint n_values;
|
|
FILE *f;
|
|
|
|
e = (GstObject *) gst_element_factory_make ("testobj", NULL);
|
|
|
|
cs1 = gst_lfo_control_source_new ();
|
|
|
|
gst_object_add_control_binding (e, gst_direct_control_binding_new (e, "int",
|
|
cs1));
|
|
|
|
g_object_set (cs1,
|
|
"waveform", GST_LFO_WAVEFORM_SINE,
|
|
"frequency", (gdouble) 0.05,
|
|
"timeshift", (GstClockTime) 0, "offset", (gdouble) 0.5, NULL);
|
|
|
|
cs2 = gst_lfo_control_source_new ();
|
|
|
|
gst_object_add_control_binding ((GstObject *) cs1,
|
|
gst_direct_control_binding_new ((GstObject *) cs1, "amplitude", cs2));
|
|
|
|
g_object_set (cs2,
|
|
"waveform", GST_LFO_WAVEFORM_SINE,
|
|
"frequency", (gdouble) 0.05,
|
|
"timeshift", (GstClockTime) 0,
|
|
"amplitude", (gdouble) 0.5, "offset", (gdouble) 0.5, NULL);
|
|
|
|
/* test single values */
|
|
if (!(f = fopen ("ctrl_cl1.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time Sine\n");
|
|
|
|
for (t = 0; t < 40; t++) {
|
|
gst_object_sync_values (e, t * GST_SECOND);
|
|
i1 = GST_TEST_OBJ (e)->val_int;
|
|
|
|
fprintf (f, "%4.1f %d\n", (gfloat) t, i1);
|
|
}
|
|
|
|
fclose (f);
|
|
|
|
/* test value arrays */
|
|
if (!(f = fopen ("ctrl_cl2.dat", "w")))
|
|
exit (-1);
|
|
fprintf (f, "# Time Sine\n");
|
|
n_values = 40 * 10;
|
|
|
|
v1 = g_new0 (GValue, n_values);
|
|
gst_object_get_g_value_array (e, "int", 0, GST_SECOND / 10, n_values, v1);
|
|
|
|
for (t = 0; t < n_values; t++) {
|
|
i1 = g_value_get_int (&v1[t]);
|
|
fprintf (f, "%4.1f %d\n", (gfloat) t / 10.0, i1);
|
|
g_value_unset (&v1[t]);
|
|
}
|
|
g_free (v1);
|
|
|
|
fclose (f);
|
|
|
|
gst_object_unref (cs1);
|
|
gst_object_unref (cs2);
|
|
gst_object_unref (e);
|
|
}
|
|
|
|
gint
|
|
main (gint argc, gchar ** argv)
|
|
{
|
|
gst_init (&argc, &argv);
|
|
|
|
gst_element_register (NULL, "testobj", GST_RANK_NONE, GST_TYPE_TEST_OBJ);
|
|
|
|
test_interpolation ();
|
|
test_lfo ();
|
|
|
|
test_chained_lfo ();
|
|
|
|
return 0;
|
|
}
|