From ca675bc9dc690b4aab48fd0254136d3c113db438 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 1 Jun 2006 20:39:30 +0000 Subject: [PATCH] gst/volume/gstvolume.*: rewrite the passthrough check, split _int16 and _int16_clamp, fix another property desc., rem... Original commit message from CVS: * gst/volume/gstvolume.c: (volume_choose_func), (volume_update_real_volume), (gst_volume_class_init), (gst_volume_init), (volume_process_float), (volume_process_int16), (volume_process_int16_clamp), (volume_set_caps), (volume_transform_ip), (plugin_init): * gst/volume/gstvolume.h: rewrite the passthrough check, split _int16 and _int16_clamp, fix another property desc., remove unused param from process function * tests/check/elements/volume.c: (volume_suite): reactivate the passthrough test --- ChangeLog | 14 +++++ gst/volume/gstvolume.c | 116 ++++++++++++++++++++++++++++-------------- gst/volume/gstvolume.h | 9 +++- tests/check/elements/volume.c | 7 +-- 4 files changed, 102 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index f71a2b7..ed74e99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2006-06-01 Stefan Kost + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_update_real_volume), (gst_volume_class_init), + (gst_volume_init), (volume_process_float), (volume_process_int16), + (volume_process_int16_clamp), (volume_set_caps), + (volume_transform_ip), (plugin_init): + * gst/volume/gstvolume.h: + rewrite the passthrough check, split _int16 and _int16_clamp, fix + another property desc., remove unused param from process function + + * tests/check/elements/volume.c: (volume_suite): + reactivate the passthrough test + +2006-06-01 Stefan Kost + * ext/alsa/gstalsamixerelement.h: * ext/alsa/gstalsamixeroptions.h: * ext/alsa/gstalsamixertrack.h: diff --git a/gst/volume/gstvolume.c b/gst/volume/gstvolume.c index 2ffdf90..9b1b794 100644 --- a/gst/volume/gstvolume.c +++ b/gst/volume/gstvolume.c @@ -50,6 +50,7 @@ #include #include #include +#include #include "gstvolume.h" @@ -157,23 +158,51 @@ static GstFlowReturn volume_transform_ip (GstBaseTransform * base, static gboolean volume_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps); -static void volume_process_float (GstVolume * this, GstClockTime tstamp, - gpointer bytes, gint n_bytes); -static void volume_process_int16 (GstVolume * this, GstClockTime tstamp, - gpointer bytes, gint n_bytes); +static void volume_process_float (GstVolume * this, gpointer bytes, + gint n_bytes); +static void volume_process_int16 (GstVolume * this, gpointer bytes, + gint n_bytes); +static void volume_process_int16_clamp (GstVolume * this, gpointer bytes, + gint n_bytes); /* helper functions */ static void +volume_choose_func (GstVolume * this) +{ + switch (this->format) { + case GST_VOLUME_FORMAT_INT: + /* only clamp if the gain is greater than 1.0 + * FIXME: real_vol_i can change while processing the buffer! + */ + if (this->real_vol_i > VOLUME_UNITY_INT) + this->process = volume_process_int16_clamp; + else + this->process = volume_process_int16; + break; + case GST_VOLUME_FORMAT_FLOAT: + this->process = volume_process_float; + break; + default: + this->process = NULL; + } +} + +static void volume_update_real_volume (GstVolume * this) { + gboolean passthrough = FALSE; + if (this->mute) { this->real_vol_f = 0.0; this->real_vol_i = 0; } else { this->real_vol_f = this->volume_f; this->real_vol_i = this->volume_i; + passthrough = (this->volume_i == VOLUME_UNITY_INT); } + volume_choose_func (this); + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (this), passthrough); } /* Mixer interface */ @@ -295,7 +324,7 @@ gst_volume_class_init (GstVolumeClass * klass) gobject_class->dispose = gst_volume_dispose; g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MUTE, - g_param_spec_boolean ("mute", "mute", "mute", + g_param_spec_boolean ("mute", "Mute", "mute channel", FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VOLUME, @@ -320,6 +349,7 @@ gst_volume_init (GstVolume * this, GstVolumeClass * g_class) this->real_vol_i = VOLUME_UNITY_INT; this->real_vol_f = 1.0; this->tracklist = NULL; + this->format = GST_VOLUME_FORMAT_NONE; track = g_object_new (GST_TYPE_MIXER_TRACK, NULL); @@ -339,8 +369,7 @@ gst_volume_init (GstVolume * this, GstVolumeClass * g_class) */ static void -volume_process_float (GstVolume * this, GstClockTime tstamp, - gpointer bytes, gint n_bytes) +volume_process_float (GstVolume * this, gpointer bytes, gint n_bytes) { gfloat *data; gint i, num_samples; @@ -351,14 +380,13 @@ volume_process_float (GstVolume * this, GstClockTime tstamp, for (i = 0; i < num_samples; i++) { *data++ *= this->real_vol_f; } - /* FIXME: need... liboil... + /* FIXME: seems to be slower than above! oil_scalarmultiply_f32_ns (data, data, &this->real_vol_f, num_samples); */ } static void -volume_process_int16 (GstVolume * this, GstClockTime tstamp, - gpointer bytes, gint n_bytes) +volume_process_int16 (GstVolume * this, gpointer bytes, gint n_bytes) { gint16 *data; gint i, val, num_samples; @@ -368,25 +396,34 @@ volume_process_int16 (GstVolume * this, GstClockTime tstamp, /* FIXME: need... liboil... * oil_scalarmultiply_s16_ns ? + * https://bugs.freedesktop.org/show_bug.cgi?id=7060 */ + for (i = 0; i < num_samples; i++) { + /* we use bitshifting instead of dividing by UNITY_INT for speed */ + val = (gint) * data; + *data++ = (gint16) ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT); + } +} - /* only clamp if the gain is greater than 1.0 - * FIXME: real_vol_i can change while processing the buffer! +static void +volume_process_int16_clamp (GstVolume * this, gpointer bytes, gint n_bytes) +{ + gint16 *data; + gint i, val, num_samples; + + data = (gint16 *) bytes; + num_samples = n_bytes / sizeof (gint16); + + /* FIXME: need... liboil... + * oil_scalarmultiply_s16_ns ? + * https://bugs.freedesktop.org/show_bug.cgi?id=7060 */ - if (this->real_vol_i > VOLUME_UNITY_INT) { - for (i = 0; i < num_samples; i++) { - /* we use bitshifting instead of dividing by UNITY_INT for speed */ - val = (gint) * data; - *data++ = - (gint16) CLAMP ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT, - VOLUME_MIN_INT16, VOLUME_MAX_INT16); - } - } else { - for (i = 0; i < num_samples; i++) { - /* we use bitshifting instead of dividing by UNITY_INT for speed */ - val = (gint) * data; - *data++ = (gint16) ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT); - } + for (i = 0; i < num_samples; i++) { + /* we use bitshifting instead of dividing by UNITY_INT for speed */ + val = (gint) * data; + *data++ = + (gint16) CLAMP ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT, + VOLUME_MIN_INT16, VOLUME_MAX_INT16); } } @@ -404,15 +441,18 @@ volume_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) mimetype = gst_structure_get_name (gst_caps_get_structure (incaps, 0)); - /* based on mimetype, install the correct volume_process method */ - if (strcmp (mimetype, "audio/x-raw-int") == 0) - this->process = volume_process_int16; - else if (strcmp (mimetype, "audio/x-raw-float") == 0) - this->process = volume_process_float; - else { + /* based on mimetype, choose the correct volume_process format */ + if (strcmp (mimetype, "audio/x-raw-int") == 0) { + this->format = GST_VOLUME_FORMAT_INT; + GST_INFO_OBJECT (this, "use int16"); + } else if (strcmp (mimetype, "audio/x-raw-float") == 0) { + this->format = GST_VOLUME_FORMAT_FLOAT; + GST_INFO_OBJECT (this, "use float"); + } else { this->process = NULL; goto invalid_format; } + volume_choose_func (this); return TRUE; @@ -435,17 +475,17 @@ volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf) GstVolume *this = GST_VOLUME (base); GstClockTime timestamp; - /* don't process data in passthrough-mode (requires #343196) - if (!gst_buffer_is_writable (outbuf)) return GST_FLOW_OK; - */ + /* don't process data in passthrough-mode */ + if (gst_base_transform_is_passthrough (base)) + return GST_FLOW_OK; + /* FIXME: subdivide GST_BUFFER_SIZE into small chunks for smooth fades */ timestamp = GST_BUFFER_TIMESTAMP (outbuf); if (GST_CLOCK_TIME_IS_VALID (timestamp)) gst_object_sync_values (G_OBJECT (this), timestamp); - this->process (this, timestamp, - GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); + this->process (this, GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); return GST_FLOW_OK; } @@ -520,6 +560,8 @@ volume_get_property (GObject * object, guint prop_id, GValue * value, static gboolean plugin_init (GstPlugin * plugin) { + /*oil_init (); */ + /* initialize gst controller library */ gst_controller_init (NULL, NULL); diff --git a/gst/volume/gstvolume.h b/gst/volume/gstvolume.h index b05df8d..ade193b 100644 --- a/gst/volume/gstvolume.h +++ b/gst/volume/gstvolume.h @@ -42,6 +42,12 @@ G_BEGIN_DECLS typedef struct _GstVolume GstVolume; typedef struct _GstVolumeClass GstVolumeClass; +typedef enum { + GST_VOLUME_FORMAT_NONE, + GST_VOLUME_FORMAT_INT, + GST_VOLUME_FORMAT_FLOAT +} GstVolumeFormat; + /** * GstVolume: * @@ -50,13 +56,14 @@ typedef struct _GstVolumeClass GstVolumeClass; struct _GstVolume { GstBaseTransform element; - void (*process)(GstVolume*, GstClockTime, gpointer, gint); + void (*process)(GstVolume*, gpointer, gint); gboolean mute; gint volume_i, real_vol_i; /* the _i(nt) values get synchronized with the */ gfloat volume_f, real_vol_f; /* _f(loat) values on each update */ GList *tracklist; + GstVolumeFormat format; }; struct _GstVolumeClass { diff --git a/tests/check/elements/volume.c b/tests/check/elements/volume.c index 9c1c1de..a594bcd 100644 --- a/tests/check/elements/volume.c +++ b/tests/check/elements/volume.c @@ -330,8 +330,6 @@ GST_START_TEST (test_wrong_caps) GST_END_TEST; -/* requires #343196 */ -#if 0 GST_START_TEST (test_passthrough) { GstElement *volume; @@ -371,7 +369,6 @@ GST_START_TEST (test_passthrough) } GST_END_TEST; -#endif Suite * volume_suite (void) @@ -385,9 +382,7 @@ volume_suite (void) tcase_add_test (tc_chain, test_double); tcase_add_test (tc_chain, test_mute); tcase_add_test (tc_chain, test_wrong_caps); - /* requires #343196 - tcase_add_test (tc_chain, test_passthrough); - */ + tcase_add_test (tc_chain, test_passthrough); return s; } -- 2.7.4