summaryrefslogtreecommitdiffstats
path: root/gst/speexresample/gstspeexresample.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/speexresample/gstspeexresample.c')
-rw-r--r--gst/speexresample/gstspeexresample.c1023
1 files changed, 305 insertions, 718 deletions
diff --git a/gst/speexresample/gstspeexresample.c b/gst/speexresample/gstspeexresample.c
index 4c6dbffe..096c6b93 100644
--- a/gst/speexresample/gstspeexresample.c
+++ b/gst/speexresample/gstspeexresample.c
@@ -1,7 +1,7 @@
/* GStreamer
* Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) 2003,2004 David A. Schleef <ds@schleef.org>
- * Copyright (C) 2007-2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -34,10 +34,6 @@
* </refsect2>
*/
-/* TODO:
- * - Enable SSE/ARM optimizations and select at runtime
- */
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -49,18 +45,13 @@
#include <gst/audio/audio.h>
#include <gst/base/gstbasetransform.h>
-#define OIL_ENABLE_UNSTABLE_API
-#include <liboil/liboilprofile.h>
-#include <liboil/liboil.h>
-
GST_DEBUG_CATEGORY (speex_resample_debug);
#define GST_CAT_DEFAULT speex_resample_debug
enum
{
PROP_0,
- PROP_QUALITY,
- PROP_FILTER_LENGTH
+ PROP_QUALITY
};
#define SUPPORTED_CAPS \
@@ -69,40 +60,16 @@ GST_STATIC_CAPS ( \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \
- "width = (int) { 32, 64 }; " \
- "audio/x-raw-int, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, MAX ], " \
- "endianness = (int) BYTE_ORDER, " \
- "width = (int) 32, " \
- "depth = (int) 32, " \
- "signed = (boolean) true; " \
- "audio/x-raw-int, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, MAX ], " \
- "endianness = (int) BYTE_ORDER, " \
- "width = (int) 24, " \
- "depth = (int) 24, " \
- "signed = (boolean) true; " \
+ "width = (int) 32; " \
"audio/x-raw-int, " \
"rate = (int) [ 1, MAX ], " \
"channels = (int) [ 1, MAX ], " \
"endianness = (int) BYTE_ORDER, " \
"width = (int) 16, " \
"depth = (int) 16, " \
- "signed = (boolean) true; " \
- "audio/x-raw-int, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, MAX ], " \
- "endianness = (int) BYTE_ORDER, " \
- "width = (int) 8, " \
- "depth = (int) 8, " \
"signed = (boolean) true" \
)
-/* If TRUE integer arithmetic resampling is faster and will be used if appropiate */
-static gboolean gst_speex_resample_use_int = FALSE;
-
static GstStaticPadTemplate gst_speex_resample_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS);
@@ -121,8 +88,6 @@ static gboolean gst_speex_resample_get_unit_size (GstBaseTransform * base,
GstCaps * caps, guint * size);
static GstCaps *gst_speex_resample_transform_caps (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps);
-static void gst_speex_resample_fixate_caps (GstBaseTransform * base,
- GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static gboolean gst_speex_resample_transform_size (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * incaps, guint insize,
GstCaps * outcaps, guint * outsize);
@@ -137,8 +102,11 @@ static gboolean gst_speex_resample_stop (GstBaseTransform * base);
static gboolean gst_speex_resample_query (GstPad * pad, GstQuery * query);
static const GstQueryType *gst_speex_resample_query_type (GstPad * pad);
-GST_BOILERPLATE (GstSpeexResample, gst_speex_resample, GstBaseTransform,
- GST_TYPE_BASE_TRANSFORM);
+#define DEBUG_INIT(bla) \
+ GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0, "audio resampling element");
+
+GST_BOILERPLATE_FULL (GstSpeexResample, gst_speex_resample, GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
static void
gst_speex_resample_base_init (gpointer g_class)
@@ -152,7 +120,7 @@ gst_speex_resample_base_init (gpointer g_class)
gst_element_class_set_details_simple (gstelement_class, "Audio resampler",
"Filter/Converter/Audio", "Resamples audio",
- "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+ "Sebastian Dröge <slomo@circular-chaos.org>");
}
static void
@@ -170,14 +138,6 @@ gst_speex_resample_class_init (GstSpeexResampleClass * klass)
SPEEX_RESAMPLER_QUALITY_DEFAULT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- /* FIXME 0.11: Remove this property, it's just for compatibility
- * with old audioresample
- */
- g_object_class_install_property (gobject_class, PROP_FILTER_LENGTH,
- g_param_spec_int ("filter-length", "Filter length",
- "DEPRECATED, DON'T USE THIS! " "Length of the resample filter", 0,
- G_MAXINT, 64, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
GST_BASE_TRANSFORM_CLASS (klass)->start =
GST_DEBUG_FUNCPTR (gst_speex_resample_start);
GST_BASE_TRANSFORM_CLASS (klass)->stop =
@@ -188,8 +148,6 @@ gst_speex_resample_class_init (GstSpeexResampleClass * klass)
GST_DEBUG_FUNCPTR (gst_speex_resample_get_unit_size);
GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
GST_DEBUG_FUNCPTR (gst_speex_resample_transform_caps);
- GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps =
- GST_DEBUG_FUNCPTR (gst_speex_resample_fixate_caps);
GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
GST_DEBUG_FUNCPTR (gst_speex_resample_set_caps);
GST_BASE_TRANSFORM_CLASS (klass)->transform =
@@ -221,9 +179,9 @@ gst_speex_resample_start (GstBaseTransform * base)
{
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
- resample->next_offset = -1;
+ resample->ts_offset = -1;
+ resample->offset = -1;
resample->next_ts = -1;
- resample->next_upstream_ts = -1;
return TRUE;
}
@@ -234,20 +192,10 @@ gst_speex_resample_stop (GstBaseTransform * base)
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
if (resample->state) {
- resample->funcs->destroy (resample->state);
+ resample_resampler_destroy (resample->state);
resample->state = NULL;
}
- resample->funcs = NULL;
-
- g_free (resample->tmp_in);
- resample->tmp_in = NULL;
- resample->tmp_in_size = 0;
-
- g_free (resample->tmp_out);
- resample->tmp_out = NULL;
- resample->tmp_out_size = 0;
-
gst_caps_replace (&resample->sinkcaps, NULL);
gst_caps_replace (&resample->srccaps, NULL);
@@ -268,11 +216,9 @@ gst_speex_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
structure = gst_caps_get_structure (caps, 0);
ret = gst_structure_get_int (structure, "width", &width);
ret &= gst_structure_get_int (structure, "channels", &channels);
+ g_return_val_if_fail (ret, FALSE);
- if (G_UNLIKELY (!ret))
- return FALSE;
-
- *size = (width / 8) * channels;
+ *size = width * channels / 8;
return TRUE;
}
@@ -293,64 +239,38 @@ gst_speex_resample_transform_caps (GstBaseTransform * base,
return res;
}
-/* Fixate rate to the allowed rate that has the smallest difference */
-static void
-gst_speex_resample_fixate_caps (GstBaseTransform * base,
- GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
-{
- GstStructure *s;
- gint rate;
-
- s = gst_caps_get_structure (caps, 0);
- if (G_UNLIKELY (!gst_structure_get_int (s, "rate", &rate)))
- return;
-
- s = gst_caps_get_structure (othercaps, 0);
- gst_structure_fixate_field_nearest_int (s, "rate", rate);
-}
-
-static const SpeexResampleFuncs *
-gst_speex_resample_get_funcs (gint width, gboolean fp)
-{
- const SpeexResampleFuncs *funcs = NULL;
-
- if (gst_speex_resample_use_int && (width == 8 || width == 16) && !fp)
- funcs = &int_funcs;
- else if ((!gst_speex_resample_use_int && (width == 8 || width == 16) && !fp)
- || (width == 32 && fp))
- funcs = &float_funcs;
- else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp))
- funcs = &double_funcs;
- else
- g_assert_not_reached ();
-
- return funcs;
-}
-
static SpeexResamplerState *
-gst_speex_resample_init_state (GstSpeexResample * resample, gint width,
- gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
+gst_speex_resample_init_state (guint channels, guint inrate, guint outrate,
+ guint quality, gboolean fp)
{
SpeexResamplerState *ret = NULL;
gint err = RESAMPLER_ERR_SUCCESS;
- const SpeexResampleFuncs *funcs = gst_speex_resample_get_funcs (width, fp);
- ret = funcs->init (channels, inrate, outrate, quality, &err);
+ if (fp)
+ ret =
+ resample_float_resampler_init (channels, inrate, outrate, quality,
+ &err);
+ else
+ ret =
+ resample_int_resampler_init (channels, inrate, outrate, quality, &err);
- if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
- GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s",
- funcs->strerror (err));
+ if (err != RESAMPLER_ERR_SUCCESS) {
+ GST_ERROR ("Failed to create resampler state: %s",
+ resample_resampler_strerror (err));
return NULL;
}
- funcs->skip_zeros (ret);
+ if (fp)
+ resample_float_resampler_skip_zeros (ret);
+ else
+ resample_int_resampler_skip_zeros (ret);
return ret;
}
static gboolean
-gst_speex_resample_update_state (GstSpeexResample * resample, gint width,
- gint channels, gint inrate, gint outrate, gint quality, gboolean fp)
+gst_speex_resample_update_state (GstSpeexResample * resample, gint channels,
+ gint inrate, gint outrate, gint quality, gboolean fp)
{
gboolean ret = TRUE;
gboolean updated_latency = FALSE;
@@ -360,38 +280,41 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint width,
if (resample->state == NULL) {
ret = TRUE;
- } else if (resample->channels != channels || fp != resample->fp
- || width != resample->width) {
- resample->funcs->destroy (resample->state);
+ } else if (resample->channels != channels || fp != resample->fp) {
+ resample_resampler_destroy (resample->state);
resample->state =
- gst_speex_resample_init_state (resample, width, channels, inrate,
- outrate, quality, fp);
+ gst_speex_resample_init_state (channels, inrate, outrate, quality, fp);
- resample->funcs = gst_speex_resample_get_funcs (width, fp);
ret = (resample->state != NULL);
} else if (resample->inrate != inrate || resample->outrate != outrate) {
gint err = RESAMPLER_ERR_SUCCESS;
- err = resample->funcs->set_rate (resample->state, inrate, outrate);
+ if (fp)
+ err =
+ resample_float_resampler_set_rate (resample->state, inrate, outrate);
+ else
+ err = resample_int_resampler_set_rate (resample->state, inrate, outrate);
- if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
- GST_ERROR_OBJECT (resample, "Failed to update rate: %s",
- resample->funcs->strerror (err));
+ if (err != RESAMPLER_ERR_SUCCESS)
+ GST_ERROR ("Failed to update rate: %s",
+ resample_resampler_strerror (err));
ret = (err == RESAMPLER_ERR_SUCCESS);
} else if (quality != resample->quality) {
gint err = RESAMPLER_ERR_SUCCESS;
- err = resample->funcs->set_quality (resample->state, quality);
+ if (fp)
+ err = resample_float_resampler_set_quality (resample->state, quality);
+ else
+ err = resample_int_resampler_set_quality (resample->state, quality);
- if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS))
- GST_ERROR_OBJECT (resample, "Failed to update quality: %s",
- resample->funcs->strerror (err));
+ if (err != RESAMPLER_ERR_SUCCESS)
+ GST_ERROR ("Failed to update quality: %s",
+ resample_resampler_strerror (err));
ret = (err == RESAMPLER_ERR_SUCCESS);
}
- resample->width = width;
resample->channels = channels;
resample->fp = fp;
resample->quality = quality;
@@ -408,18 +331,20 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint width,
static void
gst_speex_resample_reset_state (GstSpeexResample * resample)
{
- if (resample->state)
- resample->funcs->reset_mem (resample->state);
+ if (resample->state && resample->fp)
+ resample_float_resampler_reset_mem (resample->state);
+ else if (resample->state && !resample->fp)
+ resample_int_resampler_reset_mem (resample->state);
}
static gboolean
gst_speex_resample_parse_caps (GstCaps * incaps,
- GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
- gint * outrate, gboolean * fp)
+ GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate,
+ gboolean * fp)
{
GstStructure *structure;
gboolean ret;
- gint mywidth, myinrate, myoutrate, mychannels;
+ gint myinrate, myoutrate, mychannels;
gboolean myfp;
GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %"
@@ -434,13 +359,12 @@ gst_speex_resample_parse_caps (GstCaps * incaps,
ret = gst_structure_get_int (structure, "rate", &myinrate);
ret &= gst_structure_get_int (structure, "channels", &mychannels);
- ret &= gst_structure_get_int (structure, "width", &mywidth);
- if (G_UNLIKELY (!ret))
+ if (!ret)
goto no_in_rate_channels;
structure = gst_caps_get_structure (outcaps, 0);
ret = gst_structure_get_int (structure, "rate", &myoutrate);
- if (G_UNLIKELY (!ret))
+ if (!ret)
goto no_out_rate;
if (channels)
@@ -449,8 +373,7 @@ gst_speex_resample_parse_caps (GstCaps * incaps,
*inrate = myinrate;
if (outrate)
*outrate = myoutrate;
- if (width)
- *width = mywidth;
+
if (fp)
*fp = myfp;
@@ -469,32 +392,20 @@ no_out_rate:
}
}
-static gint
-_gcd (gint a, gint b)
-{
- while (b != 0) {
- int temp = a;
-
- a = b;
- b = temp % b;
- }
-
- return ABS (a);
-}
-
static gboolean
gst_speex_resample_transform_size (GstBaseTransform * base,
GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
guint * othersize)
{
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
+ SpeexResamplerState *state;
GstCaps *srccaps, *sinkcaps;
+ gboolean use_internal = FALSE; /* whether we use the internal state */
gboolean ret = TRUE;
guint32 ratio_den, ratio_num;
- gint inrate, outrate, gcd;
- gint width;
+ gboolean fp;
- GST_LOG_OBJECT (resample, "asked to transform size %d in direction %s",
+ GST_LOG ("asked to transform size %d in direction %s",
size, direction == GST_PAD_SINK ? "SINK" : "SRC");
if (direction == GST_PAD_SINK) {
sinkcaps = caps;
@@ -504,37 +415,59 @@ gst_speex_resample_transform_size (GstBaseTransform * base,
srccaps = caps;
}
- ret =
- gst_speex_resample_parse_caps (caps, othercaps, &width, NULL, &inrate,
- &outrate, NULL);
- if (G_UNLIKELY (!ret)) {
- GST_ERROR_OBJECT (resample, "Wrong caps");
- return FALSE;
+ /* if the caps are the ones that _set_caps got called with; we can use
+ * our own state; otherwise we'll have to create a state */
+ if (resample->state && gst_caps_is_equal (sinkcaps, resample->sinkcaps) &&
+ gst_caps_is_equal (srccaps, resample->srccaps)) {
+ use_internal = TRUE;
+ state = resample->state;
+ fp = resample->fp;
+ } else {
+ gint inrate, outrate, channels;
+
+ GST_DEBUG ("Can't use internal state, creating state");
+
+ ret =
+ gst_speex_resample_parse_caps (caps, othercaps, &channels, &inrate,
+ &outrate, &fp);
+
+ if (!ret) {
+ GST_ERROR ("Wrong caps");
+ return FALSE;
+ }
+
+ state = gst_speex_resample_init_state (channels, inrate, outrate, 0, TRUE);
+ if (!state)
+ return FALSE;
}
- gcd = _gcd (inrate, outrate);
- ratio_num = inrate / gcd;
- ratio_den = outrate / gcd;
+ if (resample->fp || use_internal)
+ resample_float_resampler_get_ratio (state, &ratio_num, &ratio_den);
+ else
+ resample_int_resampler_get_ratio (state, &ratio_num, &ratio_den);
if (direction == GST_PAD_SINK) {
- gint fac = width / 8;
+ gint fac = (fp) ? 4 : 2;
/* asked to convert size of an incoming buffer */
size /= fac;
- *othersize = (size * ratio_den + ratio_num - 1) / ratio_num;
+ *othersize = (size * ratio_den + (ratio_num >> 1)) / ratio_num;
*othersize *= fac;
size *= fac;
} else {
- gint fac = width / 8;
+ gint fac = (fp) ? 4 : 2;
/* asked to convert size of an outgoing buffer */
size /= fac;
- *othersize = (size * ratio_num + ratio_den - 1) / ratio_den;
+ *othersize = (size * ratio_num + (ratio_den >> 1)) / ratio_den;
*othersize *= fac;
size *= fac;
}
- GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize);
+ GST_LOG ("transformed size %d to %d", size, *othersize);
+
+ if (!use_internal)
+ resample_resampler_destroy (state);
return ret;
}
@@ -544,25 +477,23 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
GstCaps * outcaps)
{
gboolean ret;
- gint width = 0, inrate = 0, outrate = 0, channels = 0;
- gboolean fp;
+ gint inrate = 0, outrate = 0, channels = 0;
+ gboolean fp = FALSE;
GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base);
GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
GST_PTR_FORMAT, incaps, outcaps);
ret = gst_speex_resample_parse_caps (incaps, outcaps,
- &width, &channels, &inrate, &outrate, &fp);
+ &channels, &inrate, &outrate, &fp);
- if (G_UNLIKELY (!ret))
- return FALSE;
+ g_return_val_if_fail (ret, FALSE);
ret =
- gst_speex_resample_update_state (resample, width, channels, inrate,
- outrate, resample->quality, fp);
+ gst_speex_resample_update_state (resample, channels, inrate, outrate,
+ resample->quality, fp);
- if (G_UNLIKELY (!ret))
- return FALSE;
+ g_return_val_if_fail (ret, FALSE);
/* save caps so we can short-circuit in the size_transform if the caps
* are the same */
@@ -572,163 +503,6 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
return TRUE;
}
-#define GST_MAXINT24 (8388607)
-#define GST_MININT24 (-8388608)
-
-#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-#define GST_READ_UINT24 GST_READ_UINT24_LE
-#define GST_WRITE_UINT24 GST_WRITE_UINT24_LE
-#else
-#define GST_READ_UINT24 GST_READ_UINT24_BE
-#define GST_WRITE_UINT24 GST_WRITE_UINT24_BE
-#endif
-
-static void
-gst_speex_resample_convert_buffer (GstSpeexResample * resample,
- const guint8 * in, guint8 * out, guint len, gboolean inverse)
-{
- len *= resample->channels;
-
- if (inverse) {
- if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
- gint8 *o = (gint8 *) out;
- gint16 *i = (gint16 *) in;
- gint32 tmp;
-
- while (len) {
- tmp = *i + (G_MAXINT8 >> 1);
- *o = CLAMP (tmp >> 8, G_MININT8, G_MAXINT8);
- o++;
- i++;
- len--;
- }
- } else if (!gst_speex_resample_use_int && resample->width == 8
- && !resample->fp) {
- gint8 *o = (gint8 *) out;
- gfloat *i = (gfloat *) in;
- gfloat tmp;
-
- while (len) {
- tmp = *i;
- *o = (gint8) CLAMP (tmp * G_MAXINT8 + 0.5, G_MININT8, G_MAXINT8);
- o++;
- i++;
- len--;
- }
- } else if (!gst_speex_resample_use_int && resample->width == 16
- && !resample->fp) {
- gint16 *o = (gint16 *) out;
- gfloat *i = (gfloat *) in;
- gfloat tmp;
-
- while (len) {
- tmp = *i;
- *o = (gint16) CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
- o++;
- i++;
- len--;
- }
- } else if (resample->width == 24 && !resample->fp) {
- guint8 *o = (guint8 *) out;
- gdouble *i = (gdouble *) in;
- gdouble tmp;
-
- while (len) {
- tmp = *i;
- GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5,
- GST_MININT24, GST_MAXINT24));
- o += 3;
- i++;
- len--;
- }
- } else if (resample->width == 32 && !resample->fp) {
- gint32 *o = (gint32 *) out;
- gdouble *i = (gdouble *) in;
- gdouble tmp;
-
- while (len) {
- tmp = *i;
- *o = (gint32) CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32);
- o++;
- i++;
- len--;
- }
- } else {
- g_assert_not_reached ();
- }
- } else {
- if (gst_speex_resample_use_int && resample->width == 8 && !resample->fp) {
- gint8 *i = (gint8 *) in;
- gint16 *o = (gint16 *) out;
- gint32 tmp;
-
- while (len) {
- tmp = *i;
- *o = tmp << 8;
- o++;
- i++;
- len--;
- }
- } else if (!gst_speex_resample_use_int && resample->width == 8
- && !resample->fp) {
- gint8 *i = (gint8 *) in;
- gfloat *o = (gfloat *) out;
- gfloat tmp;
-
- while (len) {
- tmp = *i;
- *o = tmp / G_MAXINT8;
- o++;
- i++;
- len--;
- }
- } else if (!gst_speex_resample_use_int && resample->width == 16
- && !resample->fp) {
- gint16 *i = (gint16 *) in;
- gfloat *o = (gfloat *) out;
- gfloat tmp;
-
- while (len) {
- tmp = *i;
- *o = tmp / G_MAXINT16;
- o++;
- i++;
- len--;
- }
- } else if (resample->width == 24 && !resample->fp) {
- guint8 *i = (guint8 *) in;
- gdouble *o = (gdouble *) out;
- gdouble tmp;
- guint32 tmp2;
-
- while (len) {
- tmp2 = GST_READ_UINT24 (i);
- if (tmp2 & 0x00800000)
- tmp2 |= 0xff000000;
- tmp = (gint32) tmp2;
- *o = tmp / GST_MAXINT24;
- o++;
- i += 3;
- len--;
- }
- } else if (resample->width == 32 && !resample->fp) {
- gint32 *i = (gint32 *) in;
- gdouble *o = (gdouble *) out;
- gdouble tmp;
-
- while (len) {
- tmp = *i;
- *o = tmp / G_MAXINT32;
- o++;
- i++;
- len--;
- }
- } else {
- g_assert_not_reached ();
- }
- }
-}
-
static void
gst_speex_resample_push_drain (GstSpeexResample * resample)
{
@@ -738,97 +512,97 @@ gst_speex_resample_push_drain (GstSpeexResample * resample)
gint outsize;
guint out_len, out_processed;
gint err;
- guint num, den, len;
- guint8 *outtmp = NULL;
- gboolean need_convert = FALSE;
if (!resample->state)
return;
- need_convert = (resample->funcs->width != resample->width);
+ if (resample->fp) {
+ guint num, den;
+
+ resample_float_resampler_get_ratio (resample->state, &num, &den);
- resample->funcs->get_ratio (resample->state, &num, &den);
+ out_len = resample_float_resampler_get_input_latency (resample->state);
+ out_len = out_processed = (out_len * den + (num >> 1)) / num;
+ outsize = 4 * out_len * resample->channels;
+ } else {
+ guint num, den;
- out_len = resample->funcs->get_input_latency (resample->state);
- out_len = out_processed = (out_len * den + num - 1) / num;
- outsize = (resample->width / 8) * out_len * resample->channels;
+ resample_int_resampler_get_ratio (resample->state, &num, &den);
- if (need_convert) {
- guint outsize_tmp =
- (resample->funcs->width / 8) * out_len * resample->channels;
- if (outsize_tmp <= resample->tmp_out_size) {
- outtmp = resample->tmp_out;
- } else {
- resample->tmp_out_size = outsize_tmp;
- resample->tmp_out = outtmp = g_realloc (resample->tmp_out, outsize_tmp);
- }
+ out_len = resample_int_resampler_get_input_latency (resample->state);
+ out_len = out_processed = (out_len * den + (num >> 1)) / num;
+ outsize = 2 * out_len * resample->channels;
}
- res =
- gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE,
- outsize, GST_PAD_CAPS (trans->srcpad), &buf);
+ res = gst_pad_alloc_buffer (trans->srcpad, GST_BUFFER_OFFSET_NONE, outsize,
+ GST_PAD_CAPS (trans->srcpad), &buf);
if (G_UNLIKELY (res != GST_FLOW_OK)) {
- GST_WARNING_OBJECT (resample, "failed allocating buffer of %d bytes",
- outsize);
+ GST_WARNING ("failed allocating buffer of %d bytes", outsize);
return;
}
- len = resample->funcs->get_input_latency (resample->state);
+ if (resample->fp) {
+ guint len = resample_float_resampler_get_input_latency (resample->state);
- err =
- resample->funcs->process (resample->state,
- NULL, &len, (need_convert) ? outtmp : GST_BUFFER_DATA (buf),
- &out_processed);
+ err =
+ resample_float_resampler_process_interleaved_float (resample->state,
+ NULL, &len, (gfloat *) GST_BUFFER_DATA (buf), &out_processed);
+ } else {
+ guint len = resample_int_resampler_get_input_latency (resample->state);
+
+ err =
+ resample_int_resampler_process_interleaved_int (resample->state, NULL,
+ &len, (gint16 *) GST_BUFFER_DATA (buf), &out_processed);
+ }
- if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
- GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
- resample->funcs->strerror (err));
+ if (err != RESAMPLER_ERR_SUCCESS) {
+ GST_WARNING ("Failed to process drain: %s",
+ resample_resampler_strerror (err));
gst_buffer_unref (buf);
return;
}
- if (G_UNLIKELY (out_processed == 0)) {
- GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer");
+ if (out_processed == 0) {
+ GST_WARNING ("Failed to get drain, dropping buffer");
gst_buffer_unref (buf);
return;
}
- /* If we wrote more than allocated something is really wrong now
- * and we should better abort immediately */
- g_assert (out_len >= out_processed);
-
- if (need_convert)
- gst_speex_resample_convert_buffer (resample, outtmp, GST_BUFFER_DATA (buf),
- out_processed, TRUE);
-
- GST_BUFFER_DURATION (buf) =
- GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
+ GST_BUFFER_OFFSET (buf) = resample->offset;
+ GST_BUFFER_TIMESTAMP (buf) = resample->next_ts;
GST_BUFFER_SIZE (buf) =
- out_processed * resample->channels * (resample->width / 8);
-
- if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
- GST_BUFFER_OFFSET (buf) = resample->next_offset;
- GST_BUFFER_OFFSET_END (buf) = resample->next_offset + out_processed;
- GST_BUFFER_TIMESTAMP (buf) = resample->next_ts;
-
- resample->next_ts += GST_BUFFER_DURATION (buf);
- resample->next_offset += out_processed;
+ out_processed * resample->channels * ((resample->fp) ? 4 : 2);
+
+ if (resample->ts_offset != -1) {
+ resample->offset += out_processed;
+ resample->ts_offset += out_processed;
+ resample->next_ts =
+ GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate);
+ GST_BUFFER_OFFSET_END (buf) = resample->offset;
+
+ /* we calculate DURATION as the difference between "next" timestamp
+ * and current timestamp so we ensure a contiguous stream, instead of
+ * having rounding errors. */
+ GST_BUFFER_DURATION (buf) = resample->next_ts - GST_BUFFER_TIMESTAMP (buf);
+ } else {
+ /* no valid offset know, we can still sortof calculate the duration though */
+ GST_BUFFER_DURATION (buf) =
+ GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
}
- GST_LOG_OBJECT (resample,
- "Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT
- " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
- G_GUINT64_FORMAT, GST_BUFFER_SIZE (buf),
+ GST_LOG ("Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT
+ " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT
+ " offset_end %" G_GUINT64_FORMAT,
+ GST_BUFFER_SIZE (buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
- GST_BUFFER_OFFSET_END (buf));
+ GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
+ GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf));
res = gst_pad_push (trans->srcpad, buf);
- if (G_UNLIKELY (res != GST_FLOW_OK))
- GST_WARNING_OBJECT (resample, "Failed to push drain: %s",
- gst_flow_get_name (res));
+ if (res != GST_FLOW_OK)
+ GST_WARNING ("Failed to push drain");
return;
}
@@ -843,15 +617,15 @@ gst_speex_resample_event (GstBaseTransform * base, GstEvent * event)
break;
case GST_EVENT_FLUSH_STOP:
gst_speex_resample_reset_state (resample);
- resample->next_offset = -1;
+ resample->ts_offset = -1;
resample->next_ts = -1;
- resample->next_upstream_ts = -1;
+ resample->offset = -1;
case GST_EVENT_NEWSEGMENT:
gst_speex_resample_push_drain (resample);
gst_speex_resample_reset_state (resample);
- resample->next_offset = -1;
+ resample->ts_offset = -1;
resample->next_ts = -1;
- resample->next_upstream_ts = -1;
+ resample->offset = -1;
break;
case GST_EVENT_EOS:{
gst_speex_resample_push_drain (resample);
@@ -861,8 +635,9 @@ gst_speex_resample_event (GstBaseTransform * base, GstEvent * event)
default:
break;
}
+ parent_class->event (base, event);
- return parent_class->event (base, event);
+ return TRUE;
}
static gboolean
@@ -870,18 +645,19 @@ gst_speex_resample_check_discont (GstSpeexResample * resample,
GstClockTime timestamp)
{
if (timestamp != GST_CLOCK_TIME_NONE &&
- resample->next_upstream_ts != GST_CLOCK_TIME_NONE &&
- timestamp != resample->next_upstream_ts) {
+ resample->prev_ts != GST_CLOCK_TIME_NONE &&
+ resample->prev_duration != GST_CLOCK_TIME_NONE &&
+ timestamp != resample->prev_ts + resample->prev_duration) {
/* Potentially a discontinuous buffer. However, it turns out that many
* elements generate imperfect streams due to rounding errors, so we permit
* a small error (up to one sample) without triggering a filter
* flush/restart (if triggered incorrectly, this will be audible) */
- GstClockTimeDiff diff = timestamp - resample->next_upstream_ts;
+ GstClockTimeDiff diff = timestamp -
+ (resample->prev_ts + resample->prev_duration);
- if (ABS (diff) > (GST_SECOND + resample->inrate - 1) / resample->inrate) {
- GST_WARNING_OBJECT (resample,
- "encountered timestamp discontinuity of %s%" GST_TIME_FORMAT,
- (diff < 0) ? "-" : "", GST_TIME_ARGS ((GstClockTime) ABS (diff)));
+ if (ABS (diff) > GST_SECOND / resample->inrate) {
+ GST_WARNING ("encountered timestamp discontinuity of %" G_GINT64_FORMAT,
+ diff);
return TRUE;
}
}
@@ -889,6 +665,27 @@ gst_speex_resample_check_discont (GstSpeexResample * resample,
return FALSE;
}
+static void
+gst_speex_fix_output_buffer (GstSpeexResample * resample, GstBuffer * outbuf,
+ guint diff)
+{
+ GstClockTime timediff = GST_FRAMES_TO_CLOCK_TIME (diff, resample->outrate);
+
+ GST_LOG ("Adjusting buffer by %d samples", diff);
+
+ GST_BUFFER_DURATION (outbuf) -= timediff;
+ GST_BUFFER_SIZE (outbuf) -=
+ diff * ((resample->fp) ? 4 : 2) * resample->channels;
+
+ if (resample->ts_offset != -1) {
+ GST_BUFFER_OFFSET_END (outbuf) -= diff;
+ resample->offset -= diff;
+ resample->ts_offset -= diff;
+ resample->next_ts =
+ GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate);
+ }
+}
+
static GstFlowReturn
gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf,
GstBuffer * outbuf)
@@ -896,99 +693,70 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf,
guint32 in_len, in_processed;
guint32 out_len, out_processed;
gint err = RESAMPLER_ERR_SUCCESS;
- guint8 *in_tmp = NULL, *out_tmp = NULL;
- gboolean need_convert = (resample->funcs->width != resample->width);
in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
- in_len /= (resample->width / 8);
- out_len /= (resample->width / 8);
+ if (resample->fp) {
+ in_len /= 4;
+ out_len /= 4;
+ } else {
+ in_len /= 2;
+ out_len /= 2;
+ }
in_processed = in_len;
out_processed = out_len;
- if (need_convert) {
- guint in_size_tmp =
- in_len * resample->channels * (resample->funcs->width / 8);
- guint out_size_tmp =
- out_len * resample->channels * (resample->funcs->width / 8);
-
- if (in_size_tmp <= resample->tmp_in_size) {
- in_tmp = resample->tmp_in;
- } else {
- resample->tmp_in = in_tmp = g_realloc (resample->tmp_in, in_size_tmp);
- resample->tmp_in_size = in_size_tmp;
- }
-
- gst_speex_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf),
- in_tmp, in_len, FALSE);
-
- if (out_size_tmp <= resample->tmp_out_size) {
- out_tmp = resample->tmp_out;
- } else {
- resample->tmp_out = out_tmp = g_realloc (resample->tmp_out, out_size_tmp);
- resample->tmp_out_size = out_size_tmp;
- }
- }
-
- if (need_convert) {
- err = resample->funcs->process (resample->state,
- in_tmp, &in_processed, out_tmp, &out_processed);
- } else {
- err = resample->funcs->process (resample->state,
- (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed,
- (guint8 *) GST_BUFFER_DATA (outbuf), &out_processed);
- }
+ if (resample->fp)
+ err = resample_float_resampler_process_interleaved_float (resample->state,
+ (const gfloat *) GST_BUFFER_DATA (inbuf), &in_processed,
+ (gfloat *) GST_BUFFER_DATA (outbuf), &out_processed);
+ else
+ err = resample_int_resampler_process_interleaved_int (resample->state,
+ (const gint16 *) GST_BUFFER_DATA (inbuf), &in_processed,
+ (gint16 *) GST_BUFFER_DATA (outbuf), &out_processed);
- if (G_UNLIKELY (in_len != in_processed))
- GST_WARNING_OBJECT (resample, "Converted %d of %d input samples",
- in_processed, in_len);
+ if (in_len != in_processed)
+ GST_WARNING ("Converted %d of %d input samples", in_processed, in_len);
if (out_len != out_processed) {
+ /* One sample difference is allowed as this will happen
+ * because of rounding errors */
if (out_processed == 0) {
- GST_DEBUG_OBJECT (resample, "Converted to 0 samples, buffer dropped");
+ GST_DEBUG ("Converted to 0 samples, buffer dropped");
+
+ if (resample->ts_offset != -1) {
+ GST_BUFFER_OFFSET_END (outbuf) -= out_len;
+ resample->offset -= out_len;
+ resample->ts_offset -= out_len;
+ resample->next_ts =
+ GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate);
+ }
return GST_BASE_TRANSFORM_FLOW_DROPPED;
+ } else if (out_len - out_processed != 1)
+ GST_WARNING ("Converted to %d instead of %d output samples",
+ out_processed, out_len);
+ if (out_len > out_processed) {
+ gst_speex_fix_output_buffer (resample, outbuf, out_len - out_processed);
+ } else {
+ GST_ERROR ("Wrote more output than allocated!");
+ return GST_FLOW_ERROR;
}
-
- /* If we wrote more than allocated something is really wrong now
- * and we should better abort immediately */
- g_assert (out_len >= out_processed);
}
- if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
- GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
- resample->funcs->strerror (err));
+ if (err != RESAMPLER_ERR_SUCCESS) {
+ GST_ERROR ("Failed to convert data: %s", resample_resampler_strerror (err));
return GST_FLOW_ERROR;
} else {
-
- if (need_convert)
- gst_speex_resample_convert_buffer (resample, out_tmp,
- GST_BUFFER_DATA (outbuf), out_processed, TRUE);
-
- GST_BUFFER_DURATION (outbuf) =
- GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
- GST_BUFFER_SIZE (outbuf) =
- out_processed * resample->channels * (resample->width / 8);
-
- if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
- GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts;
- GST_BUFFER_OFFSET (outbuf) = resample->next_offset;
- GST_BUFFER_OFFSET_END (outbuf) = resample->next_offset + out_processed;
-
- resample->next_ts += GST_BUFFER_DURATION (outbuf);
- resample->next_offset += out_processed;
- }
-
- GST_LOG_OBJECT (resample,
- "Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT
+ GST_LOG ("Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT
", duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
- ", offset_end %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf),
+ ", offset_end %" G_GUINT64_FORMAT,
+ GST_BUFFER_SIZE (outbuf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
-
return GST_FLOW_OK;
}
}
@@ -1001,25 +769,19 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
guint8 *data;
gulong size;
GstClockTime timestamp;
- guint outsamples, insamples;
- GstFlowReturn ret;
+ gint outsamples;
- if (resample->state == NULL) {
- if (G_UNLIKELY (!(resample->state =
- gst_speex_resample_init_state (resample, resample->width,
- resample->channels, resample->inrate, resample->outrate,
- resample->quality, resample->fp))))
+ if (resample->state == NULL)
+ if (!(resample->state = gst_speex_resample_init_state (resample->channels,
+ resample->inrate, resample->outrate, resample->quality,
+ resample->fp)))
return GST_FLOW_ERROR;
- resample->funcs =
- gst_speex_resample_get_funcs (resample->width, resample->fp);
- }
-
data = GST_BUFFER_DATA (inbuf);
size = GST_BUFFER_SIZE (inbuf);
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
- GST_LOG_OBJECT (resample, "transforming buffer of %ld bytes, ts %"
+ GST_LOG ("transforming buffer of %ld bytes, ts %"
GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %"
G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
size, GST_TIME_ARGS (timestamp),
@@ -1033,44 +795,62 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
gst_speex_resample_reset_state (resample);
/* Inform downstream element about discontinuity */
resample->need_discont = TRUE;
- /* We want to recalculate the timestamps */
- resample->next_ts = -1;
- resample->next_upstream_ts = -1;
- resample->next_offset = -1;
+ /* We want to recalculate the offset */
+ resample->ts_offset = -1;
}
- insamples = GST_BUFFER_SIZE (inbuf) / resample->channels;
- insamples /= (resample->width / 8);
-
outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels;
- outsamples /= (resample->width / 8);
+ outsamples /= (resample->fp) ? 4 : 2;
+
+ if (resample->ts_offset == -1) {
+ /* if we don't know the initial offset yet, calculate it based on the
+ * input timestamp. */
+ if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
+ GstClockTime stime;
+
+ /* offset used to calculate the timestamps. We use the sample offset for
+ * this to make it more accurate. We want the first buffer to have the
+ * same timestamp as the incoming timestamp. */
+ resample->next_ts = timestamp;
+ resample->ts_offset =
+ GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate);
+ /* offset used to set as the buffer offset, this offset is always
+ * relative to the stream time, note that timestamp is not... */
+ stime = (timestamp - base->segment.start) + base->segment.time;
+ resample->offset = GST_CLOCK_TIME_TO_FRAMES (stime, resample->outrate);
+ }
+ }
+ resample->prev_ts = timestamp;
+ resample->prev_duration = GST_BUFFER_DURATION (inbuf);
+
+ GST_BUFFER_OFFSET (outbuf) = resample->offset;
+ GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts;
+
+ if (resample->ts_offset != -1) {
+ resample->offset += outsamples;
+ resample->ts_offset += outsamples;
+ resample->next_ts =
+ GST_FRAMES_TO_CLOCK_TIME (resample->ts_offset, resample->outrate);
+ GST_BUFFER_OFFSET_END (outbuf) = resample->offset;
- if (GST_CLOCK_TIME_IS_VALID (timestamp)
- && !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
- resample->next_ts = timestamp;
- resample->next_offset =
- GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate);
+ /* we calculate DURATION as the difference between "next" timestamp
+ * and current timestamp so we ensure a contiguous stream, instead of
+ * having rounding errors. */
+ GST_BUFFER_DURATION (outbuf) = resample->next_ts -
+ GST_BUFFER_TIMESTAMP (outbuf);
+ } else {
+ /* no valid offset know, we can still sortof calculate the duration though */
+ GST_BUFFER_DURATION (outbuf) =
+ GST_FRAMES_TO_CLOCK_TIME (outsamples, resample->outrate);
}
if (G_UNLIKELY (resample->need_discont)) {
- GST_DEBUG_OBJECT (resample, "marking this buffer with the DISCONT flag");
+ GST_DEBUG ("marking this buffer with the DISCONT flag");
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
resample->need_discont = FALSE;
}
- ret = gst_speex_resample_process (resample, inbuf, outbuf);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
- return ret;
-
- if (GST_CLOCK_TIME_IS_VALID (timestamp)
- && !GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
- resample->next_upstream_ts = timestamp;
-
- if (GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
- resample->next_upstream_ts +=
- GST_FRAMES_TO_CLOCK_TIME (insamples, resample->inrate);
-
- return GST_FLOW_OK;
+ return gst_speex_resample_process (resample, inbuf, outbuf);
}
static gboolean
@@ -1090,9 +870,12 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query)
gint rate = resample->inrate;
gint resampler_latency;
- if (resample->state)
+ if (resample->state && resample->fp)
+ resampler_latency =
+ resample_float_resampler_get_input_latency (resample->state);
+ else if (resample->state && !resample->fp)
resampler_latency =
- resample->funcs->get_input_latency (resample->state);
+ resample_int_resampler_get_input_latency (resample->state);
else
resampler_latency = 0;
@@ -1103,7 +886,7 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query)
if ((res = gst_pad_query (peer, query))) {
gst_query_parse_latency (query, &live, &min, &max);
- GST_DEBUG_OBJECT (resample, "Peer latency: min %"
+ GST_DEBUG ("Peer latency: min %"
GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
GST_TIME_ARGS (min), GST_TIME_ARGS (max));
@@ -1114,14 +897,13 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query)
else
latency = 0;
- GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (latency));
+ GST_DEBUG ("Our latency: %" GST_TIME_FORMAT, GST_TIME_ARGS (latency));
min += latency;
if (max != GST_CLOCK_TIME_NONE)
max += latency;
- GST_DEBUG_OBJECT (resample, "Calculated total latency : min %"
+ GST_DEBUG ("Calculated total latency : min %"
GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
GST_TIME_ARGS (min), GST_TIME_ARGS (max));
@@ -1161,45 +943,11 @@ gst_speex_resample_set_property (GObject * object, guint prop_id,
switch (prop_id) {
case PROP_QUALITY:
resample->quality = g_value_get_int (value);
- GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
+ GST_DEBUG ("new quality %d", resample->quality);
- gst_speex_resample_update_state (resample, resample->width,
- resample->channels, resample->inrate, resample->outrate,
- resample->quality, resample->fp);
+ gst_speex_resample_update_state (resample, resample->channels,
+ resample->inrate, resample->outrate, resample->quality, resample->fp);
break;
- case PROP_FILTER_LENGTH:{
- gint filter_length = g_value_get_int (value);
-
- if (filter_length <= 8)
- resample->quality = 0;
- else if (filter_length <= 16)
- resample->quality = 1;
- else if (filter_length <= 32)
- resample->quality = 2;
- else if (filter_length <= 48)
- resample->quality = 3;
- else if (filter_length <= 64)
- resample->quality = 4;
- else if (filter_length <= 80)
- resample->quality = 5;
- else if (filter_length <= 96)
- resample->quality = 6;
- else if (filter_length <= 128)
- resample->quality = 7;
- else if (filter_length <= 160)
- resample->quality = 8;
- else if (filter_length <= 192)
- resample->quality = 9;
- else
- resample->quality = 10;
-
- GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality);
-
- gst_speex_resample_update_state (resample, resample->width,
- resample->channels, resample->inrate, resample->outrate,
- resample->quality, resample->fp);
- break;
- }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1218,177 +966,16 @@ gst_speex_resample_get_property (GObject * object, guint prop_id,
case PROP_QUALITY:
g_value_set_int (value, resample->quality);
break;
- case PROP_FILTER_LENGTH:
- switch (resample->quality) {
- case 0:
- g_value_set_int (value, 8);
- break;
- case 1:
- g_value_set_int (value, 16);
- break;
- case 2:
- g_value_set_int (value, 32);
- break;
- case 3:
- g_value_set_int (value, 48);
- break;
- case 4:
- g_value_set_int (value, 64);
- break;
- case 5:
- g_value_set_int (value, 80);
- break;
- case 6:
- g_value_set_int (value, 96);
- break;
- case 7:
- g_value_set_int (value, 128);
- break;
- case 8:
- g_value_set_int (value, 160);
- break;
- case 9:
- g_value_set_int (value, 192);
- break;
- case 10:
- g_value_set_int (value, 256);
- break;
- }
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
-#define BENCHMARK_SIZE 512
-
-static gboolean
-_benchmark_int_float (SpeexResamplerState * st)
-{
- gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
- gfloat in_tmp[BENCHMARK_SIZE], out_tmp[BENCHMARK_SIZE / 2];
- gint i;
- guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
-
- for (i = 0; i < BENCHMARK_SIZE; i++) {
- gfloat tmp = in[i];
- in_tmp[i] = tmp / G_MAXINT16;
- }
-
- resample_float_resampler_process_interleaved_float (st,
- (const guint8 *) in_tmp, &inlen, (guint8 *) out_tmp, &outlen);
-
- if (outlen == 0) {
- GST_ERROR ("Failed to use float resampler");
- return FALSE;
- }
-
- for (i = 0; i < outlen; i++) {
- gfloat tmp = out_tmp[i];
- out[i] = CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16);
- }
-
- return TRUE;
-}
-
-static gboolean
-_benchmark_int_int (SpeexResamplerState * st)
-{
- gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2];
- guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2;
-
- resample_int_resampler_process_interleaved_int (st, (const guint8 *) in,
- &inlen, (guint8 *) out, &outlen);
-
- if (outlen == 0) {
- GST_ERROR ("Failed to use int resampler");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-_benchmark_integer_resampling (void)
-{
- OilProfile a, b;
- gdouble av, bv;
- SpeexResamplerState *sta, *stb;
-
- oil_profile_init (&a);
- oil_profile_init (&b);
-
- sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL);
- if (sta == NULL) {
- GST_ERROR ("Failed to create float resampler state");
- return FALSE;
- }
-
- stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL);
- if (stb == NULL) {
- resample_float_resampler_destroy (sta);
- GST_ERROR ("Failed to create int resampler state");
- return FALSE;
- }
-
- /* Warm up cache */
- if (!_benchmark_int_float (sta))
- goto error;
- if (!_benchmark_int_float (sta))
- goto error;
-
- /* Benchmark */
- oil_profile_start (&a);
- if (!_benchmark_int_float (sta))
- goto error;
- oil_profile_stop (&a);
-
- /* Warm up cache */
- if (!_benchmark_int_int (stb))
- goto error;
- if (!_benchmark_int_int (stb))
- goto error;
-
- /* Benchmark */
- oil_profile_start (&b);
- if (!_benchmark_int_int (stb))
- goto error;
- oil_profile_stop (&b);
-
- /* Handle results */
- oil_profile_get_ave_std (&a, &av, NULL);
- oil_profile_get_ave_std (&b, &bv, NULL);
-
- gst_speex_resample_use_int = (av > bv);
- resample_float_resampler_destroy (sta);
- resample_float_resampler_destroy (stb);
-
- if (av > bv)
- GST_DEBUG ("Using integer resampler if appropiate: %lf < %lf", bv, av);
- else
- GST_DEBUG ("Using float resampler for everything: %lf <= %lf", av, bv);
-
- return TRUE;
-
-error:
- resample_float_resampler_destroy (sta);
- resample_float_resampler_destroy (stb);
-
- return FALSE;
-}
static gboolean
plugin_init (GstPlugin * plugin)
{
- GST_DEBUG_CATEGORY_INIT (speex_resample_debug, "speex_resample", 0,
- "audio resampling element");
-
- oil_init ();
-
- if (!_benchmark_integer_resampling ())
- return FALSE;
-
if (!gst_element_register (plugin, "speexresample", GST_RANK_NONE,
GST_TYPE_SPEEX_RESAMPLE)) {
return FALSE;