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:
parent
131fb86b4b
commit
ca675bc9dc
14
ChangeLog
14
ChangeLog
@ -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:
|
||||||
|
@ -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,12 +396,28 @@ 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;
|
||||||
@ -381,13 +425,6 @@ volume_process_int16 (GstVolume * this, GstClockTime tstamp,
|
|||||||
(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GstBaseTransform vmethod implementations */
|
/* GstBaseTransform vmethod implementations */
|
||||||
@ -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);
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user