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
This commit is contained in:
Stefan Kost 2006-06-01 20:39:30 +00:00
parent 131fb86b4b
commit ca675bc9dc
4 changed files with 102 additions and 44 deletions

View File

@ -1,3 +1,17 @@
2006-06-01 Stefan Kost <ensonic@users.sf.net>
* 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 <ensonic@users.sf.net> 2006-06-01 Stefan Kost <ensonic@users.sf.net>
* ext/alsa/gstalsamixerelement.h: * ext/alsa/gstalsamixerelement.h:

View File

@ -50,6 +50,7 @@
#include <gst/audio/audio.h> #include <gst/audio/audio.h>
#include <gst/interfaces/mixer.h> #include <gst/interfaces/mixer.h>
#include <gst/controller/gstcontroller.h> #include <gst/controller/gstcontroller.h>
#include <liboil/liboil.h>
#include "gstvolume.h" #include "gstvolume.h"
@ -157,23 +158,51 @@ static GstFlowReturn volume_transform_ip (GstBaseTransform * base,
static gboolean volume_set_caps (GstBaseTransform * base, GstCaps * incaps, static gboolean volume_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps); GstCaps * outcaps);
static void volume_process_float (GstVolume * this, GstClockTime tstamp, static void volume_process_float (GstVolume * this, gpointer bytes,
gpointer bytes, gint n_bytes); gint n_bytes);
static void volume_process_int16 (GstVolume * this, GstClockTime tstamp, static void volume_process_int16 (GstVolume * this, gpointer bytes,
gpointer bytes, gint n_bytes); gint n_bytes);
static void volume_process_int16_clamp (GstVolume * this, gpointer bytes,
gint n_bytes);
/* helper functions */ /* 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 static void
volume_update_real_volume (GstVolume * this) volume_update_real_volume (GstVolume * this)
{ {
gboolean passthrough = FALSE;
if (this->mute) { if (this->mute) {
this->real_vol_f = 0.0; this->real_vol_f = 0.0;
this->real_vol_i = 0; this->real_vol_i = 0;
} else { } else {
this->real_vol_f = this->volume_f; this->real_vol_f = this->volume_f;
this->real_vol_i = this->volume_i; 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 */ /* Mixer interface */
@ -295,7 +324,7 @@ gst_volume_class_init (GstVolumeClass * klass)
gobject_class->dispose = gst_volume_dispose; gobject_class->dispose = gst_volume_dispose;
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MUTE, 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)); FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VOLUME, 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_i = VOLUME_UNITY_INT;
this->real_vol_f = 1.0; this->real_vol_f = 1.0;
this->tracklist = NULL; this->tracklist = NULL;
this->format = GST_VOLUME_FORMAT_NONE;
track = g_object_new (GST_TYPE_MIXER_TRACK, NULL); track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
@ -339,8 +369,7 @@ gst_volume_init (GstVolume * this, GstVolumeClass * g_class)
*/ */
static void static void
volume_process_float (GstVolume * this, GstClockTime tstamp, volume_process_float (GstVolume * this, gpointer bytes, gint n_bytes)
gpointer bytes, gint n_bytes)
{ {
gfloat *data; gfloat *data;
gint i, num_samples; gint i, num_samples;
@ -351,14 +380,13 @@ volume_process_float (GstVolume * this, GstClockTime tstamp,
for (i = 0; i < num_samples; i++) { for (i = 0; i < num_samples; i++) {
*data++ *= this->real_vol_f; *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); oil_scalarmultiply_f32_ns (data, data, &this->real_vol_f, num_samples);
*/ */
} }
static void static void
volume_process_int16 (GstVolume * this, GstClockTime tstamp, volume_process_int16 (GstVolume * this, gpointer bytes, gint n_bytes)
gpointer bytes, gint n_bytes)
{ {
gint16 *data; gint16 *data;
gint i, val, num_samples; gint i, val, num_samples;
@ -368,25 +396,34 @@ volume_process_int16 (GstVolume * this, GstClockTime tstamp,
/* FIXME: need... liboil... /* FIXME: need... liboil...
* oil_scalarmultiply_s16_ns ? * 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 static void
* FIXME: real_vol_i can change while processing the buffer! 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++) {
for (i = 0; i < num_samples; i++) { /* we use bitshifting instead of dividing by UNITY_INT for speed */
/* we use bitshifting instead of dividing by UNITY_INT for speed */ val = (gint) * data;
val = (gint) * data; *data++ =
*data++ = (gint16) CLAMP ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT,
(gint16) CLAMP ((this->real_vol_i * val) >> VOLUME_UNITY_BIT_SHIFT, VOLUME_MIN_INT16, VOLUME_MAX_INT16);
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);
}
} }
} }
@ -404,15 +441,18 @@ volume_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps)
mimetype = gst_structure_get_name (gst_caps_get_structure (incaps, 0)); mimetype = gst_structure_get_name (gst_caps_get_structure (incaps, 0));
/* based on mimetype, install the correct volume_process method */ /* based on mimetype, choose the correct volume_process format */
if (strcmp (mimetype, "audio/x-raw-int") == 0) if (strcmp (mimetype, "audio/x-raw-int") == 0) {
this->process = volume_process_int16; this->format = GST_VOLUME_FORMAT_INT;
else if (strcmp (mimetype, "audio/x-raw-float") == 0) GST_INFO_OBJECT (this, "use int16");
this->process = volume_process_float; } else if (strcmp (mimetype, "audio/x-raw-float") == 0) {
else { this->format = GST_VOLUME_FORMAT_FLOAT;
GST_INFO_OBJECT (this, "use float");
} else {
this->process = NULL; this->process = NULL;
goto invalid_format; goto invalid_format;
} }
volume_choose_func (this);
return TRUE; return TRUE;
@ -435,17 +475,17 @@ volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf)
GstVolume *this = GST_VOLUME (base); GstVolume *this = GST_VOLUME (base);
GstClockTime timestamp; GstClockTime timestamp;
/* don't process data in passthrough-mode (requires #343196) /* don't process data in passthrough-mode */
if (!gst_buffer_is_writable (outbuf)) return GST_FLOW_OK; 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); timestamp = GST_BUFFER_TIMESTAMP (outbuf);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) if (GST_CLOCK_TIME_IS_VALID (timestamp))
gst_object_sync_values (G_OBJECT (this), timestamp); gst_object_sync_values (G_OBJECT (this), timestamp);
this->process (this, timestamp, this->process (this, GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -520,6 +560,8 @@ volume_get_property (GObject * object, guint prop_id, GValue * value,
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
/*oil_init (); */
/* initialize gst controller library */ /* initialize gst controller library */
gst_controller_init (NULL, NULL); gst_controller_init (NULL, NULL);

View File

@ -42,6 +42,12 @@ G_BEGIN_DECLS
typedef struct _GstVolume GstVolume; typedef struct _GstVolume GstVolume;
typedef struct _GstVolumeClass GstVolumeClass; typedef struct _GstVolumeClass GstVolumeClass;
typedef enum {
GST_VOLUME_FORMAT_NONE,
GST_VOLUME_FORMAT_INT,
GST_VOLUME_FORMAT_FLOAT
} GstVolumeFormat;
/** /**
* GstVolume: * GstVolume:
* *
@ -50,13 +56,14 @@ typedef struct _GstVolumeClass GstVolumeClass;
struct _GstVolume { struct _GstVolume {
GstBaseTransform element; GstBaseTransform element;
void (*process)(GstVolume*, GstClockTime, gpointer, gint); void (*process)(GstVolume*, gpointer, gint);
gboolean mute; gboolean mute;
gint volume_i, real_vol_i; /* the _i(nt) values get synchronized with the */ 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 */ gfloat volume_f, real_vol_f; /* _f(loat) values on each update */
GList *tracklist; GList *tracklist;
GstVolumeFormat format;
}; };
struct _GstVolumeClass { struct _GstVolumeClass {

View File

@ -330,8 +330,6 @@ GST_START_TEST (test_wrong_caps)
GST_END_TEST; GST_END_TEST;
/* requires #343196 */
#if 0
GST_START_TEST (test_passthrough) GST_START_TEST (test_passthrough)
{ {
GstElement *volume; GstElement *volume;
@ -371,7 +369,6 @@ GST_START_TEST (test_passthrough)
} }
GST_END_TEST; GST_END_TEST;
#endif
Suite * Suite *
volume_suite (void) volume_suite (void)
@ -385,9 +382,7 @@ volume_suite (void)
tcase_add_test (tc_chain, test_double); tcase_add_test (tc_chain, test_double);
tcase_add_test (tc_chain, test_mute); tcase_add_test (tc_chain, test_mute);
tcase_add_test (tc_chain, test_wrong_caps); 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; return s;
} }