From d812bea064c3b41d5a6ccc96377fb34aafcea6ae Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Mon, 26 Sep 2005 15:52:06 +0000 Subject: [PATCH] gst/sine/gstsinesrc.*: Refactor, remove the table lookup code, change the 'sync' property to 'is-live' and implement ... Original commit message from CVS: 2005-09-26 Andy Wingo * gst/sine/gstsinesrc.h: * gst/sine/gstsinesrc.c: Refactor, remove the table lookup code, change the 'sync' property to 'is-live' and implement it halfway, update for controller api change. * gst/volume/gstvolume.c (volume_transform_ip): Update for controller api change. --- ChangeLog | 10 ++ gst/sine/gstsinesrc.c | 288 +++++++++++++++---------------------------------- gst/sine/gstsinesrc.h | 19 +--- gst/volume/gstvolume.c | 2 +- 4 files changed, 100 insertions(+), 219 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4754d26..6f3ab58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2005-09-26 Andy Wingo + + * gst/sine/gstsinesrc.h: + * gst/sine/gstsinesrc.c: Refactor, remove the table lookup code, + change the 'sync' property to 'is-live' and implement it halfway, + update for controller api change. + + * gst/volume/gstvolume.c (volume_transform_ip): Update for + controller api change. + 2005-09-24 Wim Taymans * ext/alsa/gstalsasink.c: (gst_alsasink_reset): diff --git a/gst/sine/gstsinesrc.c b/gst/sine/gstsinesrc.c index 5d84a7d..b2fc4a8 100644 --- a/gst/sine/gstsinesrc.c +++ b/gst/sine/gstsinesrc.c @@ -32,7 +32,7 @@ #include "gstsinesrc.h" -/* elementfactory information */ + GstElementDetails gst_sinesrc_details = { "Sine-wave src", "Source/Audio", @@ -41,23 +41,16 @@ GstElementDetails gst_sinesrc_details = { }; -/* SineSrc signals and args */ enum { - /* FILL ME */ - LAST_SIGNAL + PROP_0, + PROP_SAMPLES_PER_BUFFER, + PROP_FREQ, + PROP_VOLUME, + PROP_IS_LIVE, + PROP_TIMESTAMP_OFFSET, }; -enum -{ - ARG_0, - ARG_TABLESIZE, - ARG_SAMPLES_PER_BUFFER, - ARG_FREQ, - ARG_VOLUME, - ARG_SYNC, - ARG_TIMESTAMP_OFFSET, -}; static GstStaticPadTemplate gst_sinesrc_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -70,10 +63,9 @@ GST_STATIC_PAD_TEMPLATE ("src", "depth = (int) 16, " "rate = (int) [ 1, MAX ], " "channels = (int) 1") ); -static void gst_sinesrc_class_init (GstSineSrcClass * klass); -static void gst_sinesrc_base_init (GstSineSrcClass * klass); -static void gst_sinesrc_init (GstSineSrc * src); -static void gst_sinesrc_dispose (GObject * object); + +GST_BOILERPLATE (GstSineSrc, gst_sinesrc, GstBaseSrc, GST_TYPE_BASE_SRC); + static void gst_sinesrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -83,10 +75,6 @@ static void gst_sinesrc_get_property (GObject * object, static gboolean gst_sinesrc_setcaps (GstBaseSrc * basesrc, GstCaps * caps); static void gst_sinesrc_src_fixate (GstPad * pad, GstCaps * caps); -static void gst_sinesrc_update_freq (const GValue * value, gpointer data); -static void gst_sinesrc_populate_sinetable (GstSineSrc * src); -static inline void gst_sinesrc_update_table_inc (GstSineSrc * src); - static const GstQueryType *gst_sinesrc_get_query_types (GstPad * pad); static gboolean gst_sinesrc_src_query (GstPad * pad, GstQuery * query); @@ -94,34 +82,11 @@ static GstFlowReturn gst_sinesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer); static gboolean gst_sinesrc_start (GstBaseSrc * basesrc); -static GstElementClass *parent_class = NULL; - -/*static guint gst_sinesrc_signals[LAST_SIGNAL] = { 0 }; */ - -GType -gst_sinesrc_get_type (void) -{ - static GType sinesrc_type = 0; - - if (!sinesrc_type) { - static const GTypeInfo sinesrc_info = { - sizeof (GstSineSrcClass), - (GBaseInitFunc) gst_sinesrc_base_init, NULL, - (GClassInitFunc) gst_sinesrc_class_init, NULL, NULL, - sizeof (GstSineSrc), 0, - (GInstanceInitFunc) gst_sinesrc_init, - }; - - sinesrc_type = g_type_register_static (GST_TYPE_BASE_SRC, "GstSineSrc", - &sinesrc_info, 0); - } - return sinesrc_type; -} static void -gst_sinesrc_base_init (GstSineSrcClass * klass) +gst_sinesrc_base_init (gpointer g_class) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&gst_sinesrc_src_template)); @@ -132,86 +97,57 @@ static void gst_sinesrc_class_init (GstSineSrcClass * klass) { GObjectClass *gobject_class; - GstElementClass *gstelement_class; GstBaseSrcClass *gstbasesrc_class; gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; gstbasesrc_class = (GstBaseSrcClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_BASE_SRC); - gobject_class->set_property = gst_sinesrc_set_property; gobject_class->get_property = gst_sinesrc_get_property; - gobject_class->dispose = gst_sinesrc_dispose; - g_object_class_install_property (gobject_class, ARG_TABLESIZE, - g_param_spec_int ("tablesize", "tablesize", "tablesize", - 1, G_MAXINT, 1024, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (klass), - ARG_SAMPLES_PER_BUFFER, + PROP_SAMPLES_PER_BUFFER, g_param_spec_int ("samplesperbuffer", "Samples per buffer", "Number of samples in each outgoing buffer", 1, G_MAXINT, 1024, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, ARG_FREQ, + g_object_class_install_property (gobject_class, PROP_FREQ, g_param_spec_double ("freq", "Frequency", "Frequency of sine source", 0.0, 20000.0, 440.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - g_object_class_install_property (gobject_class, ARG_VOLUME, + g_object_class_install_property (gobject_class, PROP_VOLUME, g_param_spec_double ("volume", "Volume", "Volume", 0.0, 1.0, 0.8, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - g_object_class_install_property (gobject_class, ARG_SYNC, - g_param_spec_boolean ("sync", "Sync", "Synchronize to clock", - FALSE, G_PARAM_READWRITE)); - g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TIMESTAMP_OFFSET, + g_object_class_install_property (gobject_class, PROP_IS_LIVE, + g_param_spec_boolean ("is-live", "Is Live", + "Whether to act as a live source", FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", "Timestamp offset", "An offset added to timestamps set on buffers (in ns)", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE)); - - - //gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (); gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_sinesrc_setcaps); gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_sinesrc_start); gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_sinesrc_create); } static void -gst_sinesrc_init (GstSineSrc * src) +gst_sinesrc_init (GstSineSrc * src, GstSineSrcClass * g_class) { - src->srcpad = GST_BASE_SRC (src)->srcpad; + GstPad *pad = GST_BASE_SRC_PAD (src); - gst_pad_set_fixatecaps_function (src->srcpad, gst_sinesrc_src_fixate); - gst_pad_set_query_function (src->srcpad, gst_sinesrc_src_query); - gst_pad_set_query_type_function (src->srcpad, gst_sinesrc_get_query_types); + gst_pad_set_fixatecaps_function (pad, gst_sinesrc_src_fixate); + gst_pad_set_query_function (pad, gst_sinesrc_src_query); + gst_pad_set_query_type_function (pad, gst_sinesrc_get_query_types); src->samplerate = 44100; src->volume = 1.0; src->freq = 440.0; - src->sync = FALSE; + gst_base_src_set_live (GST_BASE_SRC (src), FALSE); - src->table_pos = 0.0; - src->table_size = 1024; src->samples_per_buffer = 1024; src->timestamp = G_GINT64_CONSTANT (0); src->offset = G_GINT64_CONSTANT (0); src->timestamp_offset = G_GINT64_CONSTANT (0); - - src->seq = 0; - - gst_sinesrc_populate_sinetable (src); - gst_sinesrc_update_table_inc (src); - -} - -static void -gst_sinesrc_dispose (GObject * object) -{ - GstSineSrc *sinesrc = GST_SINESRC (object); - - g_free (sinesrc->table_data); - sinesrc->table_data = NULL; - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } static void @@ -294,6 +230,29 @@ gst_sinesrc_src_query (GstPad * pad, GstQuery * query) return res; } +/* with STREAM_LOCK */ +static GstClockReturn +gst_sinesrc_wait (GstSineSrc * src, GstClockTime time) +{ + GstClockReturn ret; + + GST_LOCK (src); + /* clock_id should be NULL outside of this function */ + g_assert (src->clock_id == NULL); + g_assert (GST_CLOCK_TIME_IS_VALID (time)); + src->clock_id = gst_clock_new_single_shot_id (GST_ELEMENT_CLOCK (src), time); + GST_UNLOCK (src); + + ret = gst_clock_id_wait (src->clock_id, NULL); + + GST_LOCK (src); + gst_clock_id_unref (src->clock_id); + src->clock_id = NULL; + GST_UNLOCK (src); + + return ret; +} + static GstFlowReturn gst_sinesrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) @@ -301,7 +260,7 @@ gst_sinesrc_create (GstBaseSrc * basesrc, guint64 offset, GstSineSrc *src; GstBuffer *buf; guint tdiff; - + gdouble step; gint16 *samples; gint i; @@ -321,23 +280,17 @@ gst_sinesrc_create (GstBaseSrc * basesrc, guint64 offset, src->tags_pushed = TRUE; } - /* not negotiated, fixate and set */ - if (GST_PAD_CAPS (basesrc->srcpad) == NULL) { - GstCaps *caps; - - /* see whatever we are allowed to do */ - caps = gst_pad_get_allowed_caps (basesrc->srcpad); - /* fix unfixed values */ - gst_sinesrc_src_fixate (basesrc->srcpad, caps); - /* and use those */ - gst_pad_set_caps (basesrc->srcpad, caps); - gst_caps_unref (caps); - } - tdiff = src->samples_per_buffer * GST_SECOND / src->samplerate; - /* note: the 2 is because of the format we use */ - buf = gst_buffer_new_and_alloc (src->samples_per_buffer * 2); + if (gst_base_src_is_live (basesrc)) { + GstClockReturn ret; + + ret = gst_sinesrc_wait (src, src->timestamp + src->timestamp_offset); + if (ret == GST_CLOCK_UNSCHEDULED) + goto unscheduled; + } + + buf = gst_buffer_new_and_alloc (src->samples_per_buffer * sizeof (gint16)); gst_buffer_set_caps (buf, GST_PAD_CAPS (basesrc->srcpad)); GST_BUFFER_TIMESTAMP (buf) = src->timestamp + src->timestamp_offset; @@ -346,83 +299,58 @@ gst_sinesrc_create (GstBaseSrc * basesrc, guint64 offset, GST_BUFFER_OFFSET_END (buf) = src->offset + src->samples_per_buffer; GST_BUFFER_DURATION (buf) = tdiff; - gst_object_sink_values (G_OBJECT (src), src->timestamp); + gst_object_sync_values (G_OBJECT (src), src->timestamp); samples = (gint16 *) GST_BUFFER_DATA (buf); src->timestamp += tdiff; src->offset += src->samples_per_buffer; - for (i = 0; i < src->samples_per_buffer; i++) { -#if 0 - src->table_lookup = (gint) (src->table_pos); - src->table_lookup_next = src->table_lookup + 1; - src->table_interp = src->table_pos - src->table_lookup; - - /* wrap the array lookups if we're out of bounds */ - if (src->table_lookup_next >= src->table_size) { - src->table_lookup_next -= src->table_size; - if (src->table_lookup >= src->table_size) { - src->table_lookup -= src->table_size; - src->table_pos -= src->table_size; - } - } - - src->table_pos += src->table_inc; - - /*no interpolation */ - /*samples[i] = src->table_data[src->table_lookup] * src->volume * 32767.0; */ + step = 2 * M_PI * src->freq / src->samplerate; - /*linear interpolation */ - samples[i] = ((src->table_interp * (src->table_data[src->table_lookup_next] - - src->table_data[src->table_lookup] - ) - ) + src->table_data[src->table_lookup] - ) * src->volume * 32767.0; -#endif - src->accumulator += 2 * M_PI * src->freq / src->samplerate; - if (src->accumulator >= 2 * M_PI) { + for (i = 0; i < src->samples_per_buffer; i++) { + src->accumulator += step; + if (src->accumulator >= 2 * M_PI) src->accumulator -= 2 * M_PI; - } - *samples++ = sin (src->accumulator) * src->volume * 32767.0; + + samples[i] = sin (src->accumulator) * src->volume * 32767.0; } *buffer = buf; return GST_FLOW_OK; + +unscheduled: + { + GST_DEBUG_OBJECT (src, "Unscheduled while waiting for clock"); + return GST_FLOW_WRONG_STATE; /* is this the right return? */ + } } static void gst_sinesrc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstSineSrc *src; - - g_return_if_fail (GST_IS_SINESRC (object)); - src = GST_SINESRC (object); + GstSineSrc *src = GST_SINESRC (object); switch (prop_id) { - case ARG_TABLESIZE: - src->table_size = g_value_get_int (value); - gst_sinesrc_populate_sinetable (src); - gst_sinesrc_update_table_inc (src); - break; - case ARG_SAMPLES_PER_BUFFER: + case PROP_SAMPLES_PER_BUFFER: src->samples_per_buffer = g_value_get_int (value); break; - case ARG_FREQ: - gst_sinesrc_update_freq (value, src); + case PROP_FREQ: + src->freq = g_value_get_double (value); break; - case ARG_VOLUME: + case PROP_VOLUME: src->volume = g_value_get_double (value); break; - case ARG_SYNC: - src->sync = g_value_get_boolean (value); + case PROP_IS_LIVE: + gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); break; - case ARG_TIMESTAMP_OFFSET: + case PROP_TIMESTAMP_OFFSET: src->timestamp_offset = g_value_get_int64 (value); break; default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } @@ -431,28 +359,22 @@ static void gst_sinesrc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstSineSrc *src; - - g_return_if_fail (GST_IS_SINESRC (object)); - src = GST_SINESRC (object); + GstSineSrc *src = GST_SINESRC (object); switch (prop_id) { - case ARG_TABLESIZE: - g_value_set_int (value, src->table_size); - break; - case ARG_SAMPLES_PER_BUFFER: + case PROP_SAMPLES_PER_BUFFER: g_value_set_int (value, src->samples_per_buffer); break; - case ARG_FREQ: + case PROP_FREQ: g_value_set_double (value, src->freq); break; - case ARG_VOLUME: + case PROP_VOLUME: g_value_set_double (value, src->volume); break; - case ARG_SYNC: - g_value_set_boolean (value, src->sync); + case PROP_IS_LIVE: + g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); break; - case ARG_TIMESTAMP_OFFSET: + case PROP_TIMESTAMP_OFFSET: g_value_set_int64 (value, src->timestamp_offset); break; default: @@ -472,40 +394,6 @@ gst_sinesrc_start (GstBaseSrc * basesrc) return TRUE; } -static void -gst_sinesrc_populate_sinetable (GstSineSrc * src) -{ - gint i; - gdouble pi2scaled = M_PI * 2 / src->table_size; - gdouble *table = g_new (gdouble, src->table_size); - - for (i = 0; i < src->table_size; i++) { - table[i] = (gdouble) sin (i * pi2scaled); - } - - g_free (src->table_data); - src->table_data = table; -} - -static void -gst_sinesrc_update_freq (const GValue * value, gpointer data) -{ - GstSineSrc *src = (GstSineSrc *) data; - - g_return_if_fail (GST_IS_SINESRC (src)); - - src->freq = g_value_get_double (value); - src->table_inc = src->table_size * src->freq / src->samplerate; - - GST_DEBUG ("freq %f", src->freq); -} - -static inline void -gst_sinesrc_update_table_inc (GstSineSrc * src) -{ - src->table_inc = src->table_size * src->freq / src->samplerate; -} - static gboolean plugin_init (GstPlugin * plugin) { diff --git a/gst/sine/gstsinesrc.h b/gst/sine/gstsinesrc.h index 73c457a..095295f 100644 --- a/gst/sine/gstsinesrc.h +++ b/gst/sine/gstsinesrc.h @@ -31,9 +31,6 @@ G_BEGIN_DECLS -GstElementDetails gst_sinesrc_details; - - #define GST_TYPE_SINESRC \ (gst_sinesrc_get_type()) #define GST_SINESRC(obj) \ @@ -51,28 +48,14 @@ typedef struct _GstSineSrcClass GstSineSrcClass; struct _GstSineSrc { GstBaseSrc parent; - /* pads */ - GstPad *srcpad; - /* parameters */ gdouble volume; gdouble freq; - gboolean sync; - /* lookup table data */ - gdouble *table_data; - gdouble table_pos; - gdouble table_inc; - gint table_size; - gdouble table_interp; - gint table_lookup; - gint table_lookup_next; - /* audio parameters */ gint samplerate; gint samples_per_buffer; - gulong seq; guint64 timestamp; guint64 offset; @@ -81,7 +64,7 @@ struct _GstSineSrc { gboolean tags_pushed; - GstClock *clock; + GstClockID clock_id; GstClockTimeDiff timestamp_offset; }; diff --git a/gst/volume/gstvolume.c b/gst/volume/gstvolume.c index 2583006..3bb73eb 100644 --- a/gst/volume/gstvolume.c +++ b/gst/volume/gstvolume.c @@ -411,7 +411,7 @@ volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf) GstVolume *this = GST_VOLUME (base); if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (outbuf))) - gst_object_sink_values (G_OBJECT (this), GST_BUFFER_TIMESTAMP (outbuf)); + gst_object_sync_values (G_OBJECT (this), GST_BUFFER_TIMESTAMP (outbuf)); this->process (this, GST_BUFFER_TIMESTAMP (outbuf), GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); -- 2.7.4