diff options
author | Sebastian Dröge <slomo@circular-chaos.org> | 2008-10-30 12:43:44 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@circular-chaos.org> | 2008-10-30 12:43:44 +0000 |
commit | 12766882b5d6ffcb8c48f2fa0a1f19ab17c05077 (patch) | |
tree | 83a8473ea4c6dea91928397eb5bb871100d1e2e6 /gst/speexresample/gstspeexresample.c | |
parent | 51262eeb4c2741369bcdd5440d8be4f618e99af2 (diff) | |
download | gst-plugins-bad-12766882b5d6ffcb8c48f2fa0a1f19ab17c05077.tar.gz gst-plugins-bad-12766882b5d6ffcb8c48f2fa0a1f19ab17c05077.tar.bz2 gst-plugins-bad-12766882b5d6ffcb8c48f2fa0a1f19ab17c05077.zip |
Add support for double samples as input and refactor the usage of the different compilation flavors of the speex resa...
Original commit message from CVS:
* gst/speexresample/Makefile.am:
* gst/speexresample/arch.h:
* gst/speexresample/gstspeexresample.c: (gst_speex_resample_stop),
(gst_speex_resample_get_unit_size), (gst_speex_resample_get_funcs),
(gst_speex_resample_init_state), (gst_speex_resample_update_state),
(gst_speex_resample_reset_state), (gst_speex_resample_parse_caps),
(_gcd), (gst_speex_resample_transform_size),
(gst_speex_resample_set_caps), (gst_speex_resample_push_drain),
(gst_speex_resample_process), (gst_speex_resample_transform),
(gst_speex_resample_query), (gst_speex_resample_set_property):
* gst/speexresample/gstspeexresample.h:
* gst/speexresample/resample.c:
* gst/speexresample/speex_resampler.h:
* gst/speexresample/speex_resampler_double.c:
* gst/speexresample/speex_resampler_wrapper.h:
* tests/check/elements/speexresample.c: (setup_speexresample),
(test_perfect_stream_instance), (GST_START_TEST),
(test_discont_stream_instance):
Add support for double samples as input and refactor the usage
of the different compilation flavors of the speex resampler.
Diffstat (limited to 'gst/speexresample/gstspeexresample.c')
-rw-r--r-- | gst/speexresample/gstspeexresample.c | 263 |
1 files changed, 118 insertions, 145 deletions
diff --git a/gst/speexresample/gstspeexresample.c b/gst/speexresample/gstspeexresample.c index f9b5b0e3..e0dee7db 100644 --- a/gst/speexresample/gstspeexresample.c +++ b/gst/speexresample/gstspeexresample.c @@ -60,7 +60,7 @@ GST_STATIC_CAPS ( \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \ "endianness = (int) BYTE_ORDER, " \ - "width = (int) 32; " \ + "width = (int) { 32, 64 }; " \ "audio/x-raw-int, " \ "rate = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \ @@ -196,10 +196,12 @@ gst_speex_resample_stop (GstBaseTransform * base) GstSpeexResample *resample = GST_SPEEX_RESAMPLE (base); if (resample->state) { - resample_resampler_destroy (resample->state); + resample->funcs->destroy (resample->state); resample->state = NULL; } + resample->funcs = NULL; + gst_caps_replace (&resample->sinkcaps, NULL); gst_caps_replace (&resample->srccaps, NULL); @@ -224,7 +226,7 @@ gst_speex_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps, if (G_UNLIKELY (!ret)) return FALSE; - *size = gst_util_uint64_scale (width, channels, 8); + *size = (width / 8) * channels; return TRUE; } @@ -261,38 +263,47 @@ gst_speex_resample_fixate_caps (GstBaseTransform * base, 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 (width == 16 && !fp) + funcs = &int_funcs; + else if (width == 32 && fp) + funcs = &float_funcs; + else if (width == 64 && fp) + funcs = &double_funcs; + else + g_assert_not_reached (); + + return funcs; +} + static SpeexResamplerState * -gst_speex_resample_init_state (gint channels, gint inrate, gint outrate, - gint quality, gboolean fp) +gst_speex_resample_init_state (GstSpeexResample * resample, gint width, + gint channels, gint inrate, gint outrate, gint quality, gboolean fp) { SpeexResamplerState *ret = NULL; gint err = RESAMPLER_ERR_SUCCESS; + const SpeexResampleFuncs *funcs = gst_speex_resample_get_funcs (width, fp); - if (fp) - ret = - resample_float_resampler_init (channels, inrate, outrate, quality, - &err); - else - ret = - resample_int_resampler_init (channels, inrate, outrate, quality, &err); + ret = funcs->init (channels, inrate, outrate, quality, &err); if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { - GST_ERROR ("Failed to create resampler state: %s", - resample_resampler_strerror (err)); + GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s", + funcs->strerror (err)); return NULL; } - if (fp) - resample_float_resampler_skip_zeros (ret); - else - resample_int_resampler_skip_zeros (ret); + funcs->skip_zeros (ret); return ret; } static gboolean -gst_speex_resample_update_state (GstSpeexResample * resample, gint channels, - gint inrate, gint outrate, gint quality, gboolean fp) +gst_speex_resample_update_state (GstSpeexResample * resample, gint width, + gint channels, gint inrate, gint outrate, gint quality, gboolean fp) { gboolean ret = TRUE; gboolean updated_latency = FALSE; @@ -302,41 +313,38 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels, if (resample->state == NULL) { ret = TRUE; - } else if (resample->channels != channels || fp != resample->fp) { - resample_resampler_destroy (resample->state); + } else if (resample->channels != channels || fp != resample->fp + || width != resample->width) { + resample->funcs->destroy (resample->state); resample->state = - gst_speex_resample_init_state (channels, inrate, outrate, quality, fp); + gst_speex_resample_init_state (resample, width, 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; - if (fp) - err = - resample_float_resampler_set_rate (resample->state, inrate, outrate); - else - err = resample_int_resampler_set_rate (resample->state, inrate, outrate); + err = resample->funcs->set_rate (resample->state, inrate, outrate); if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) GST_ERROR_OBJECT (resample, "Failed to update rate: %s", - resample_resampler_strerror (err)); + resample->funcs->strerror (err)); ret = (err == RESAMPLER_ERR_SUCCESS); } else if (quality != resample->quality) { gint err = RESAMPLER_ERR_SUCCESS; - if (fp) - err = resample_float_resampler_set_quality (resample->state, quality); - else - err = resample_int_resampler_set_quality (resample->state, quality); + err = resample->funcs->set_quality (resample->state, quality); if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) GST_ERROR_OBJECT (resample, "Failed to update quality: %s", - resample_resampler_strerror (err)); + resample->funcs->strerror (err)); ret = (err == RESAMPLER_ERR_SUCCESS); } + resample->width = width; resample->channels = channels; resample->fp = fp; resample->quality = quality; @@ -353,20 +361,18 @@ gst_speex_resample_update_state (GstSpeexResample * resample, gint channels, static void gst_speex_resample_reset_state (GstSpeexResample * resample) { - 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); + if (resample->state) + resample->funcs->reset_mem (resample->state); } static gboolean gst_speex_resample_parse_caps (GstCaps * incaps, - GstCaps * outcaps, gint * channels, gint * inrate, gint * outrate, - gboolean * fp) + GstCaps * outcaps, gint * width, gint * channels, gint * inrate, + gint * outrate, gboolean * fp) { GstStructure *structure; gboolean ret; - gint myinrate, myoutrate, mychannels; + gint mywidth, myinrate, myoutrate, mychannels; gboolean myfp; GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %" @@ -381,6 +387,7 @@ 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)) goto no_in_rate_channels; @@ -395,7 +402,8 @@ gst_speex_resample_parse_caps (GstCaps * incaps, *inrate = myinrate; if (outrate) *outrate = myoutrate; - + if (width) + *width = mywidth; if (fp) *fp = myfp; @@ -414,18 +422,30 @@ 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; - gboolean fp; + gint inrate, outrate, gcd; + gint width; GST_LOG_OBJECT (resample, "asked to transform size %d in direction %s", size, direction == GST_PAD_SINK ? "SINK" : "SRC"); @@ -437,60 +457,40 @@ gst_speex_resample_transform_size (GstBaseTransform * base, srccaps = caps; } - /* 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_OBJECT (resample, "Can't use internal state, creating state"); - - ret = - gst_speex_resample_parse_caps (caps, othercaps, &channels, &inrate, - &outrate, &fp); - - if (G_UNLIKELY (!ret)) { - GST_ERROR_OBJECT (resample, "Wrong caps"); - return FALSE; - } - - state = gst_speex_resample_init_state (channels, inrate, outrate, 0, TRUE); - if (G_UNLIKELY (!state)) - return FALSE; + 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 (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); + gcd = _gcd (inrate, outrate); + ratio_num = inrate / gcd; + ratio_den = outrate / gcd; if (direction == GST_PAD_SINK) { - gint fac = (fp) ? 4 : 2; + gint fac = width / 8; /* 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 = (size * ratio_den + ratio_num - 1) / ratio_num; *othersize *= fac; size *= fac; } else { - gint fac = (fp) ? 4 : 2; + gint fac = width / 8; /* 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 = (size * ratio_num + ratio_den - 1) / ratio_den; *othersize *= fac; size *= fac; } GST_LOG_OBJECT (resample, "transformed size %d to %d", size, *othersize); - if (!use_internal) - resample_resampler_destroy (state); - return ret; } @@ -499,22 +499,22 @@ gst_speex_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, GstCaps * outcaps) { gboolean ret; - gint inrate = 0, outrate = 0, channels = 0; - gboolean fp = FALSE; + gint width = 0, inrate = 0, outrate = 0, channels = 0; + gboolean fp; 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, - &channels, &inrate, &outrate, &fp); + &width, &channels, &inrate, &outrate, &fp); if (G_UNLIKELY (!ret)) return FALSE; ret = - gst_speex_resample_update_state (resample, channels, inrate, outrate, - resample->quality, fp); + gst_speex_resample_update_state (resample, width, channels, inrate, + outrate, resample->quality, fp); if (G_UNLIKELY (!ret)) return FALSE; @@ -536,27 +536,16 @@ gst_speex_resample_push_drain (GstSpeexResample * resample) gint outsize; guint out_len, out_processed; gint err; + guint num, den, len; if (!resample->state) return; - if (resample->fp) { - guint num, den; - - resample_float_resampler_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; - - resample_int_resampler_get_ratio (resample->state, &num, &den); + resample->funcs->get_ratio (resample->state, &num, &den); - 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; - } + 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; res = gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE, @@ -568,23 +557,15 @@ gst_speex_resample_push_drain (GstSpeexResample * resample) return; } - if (resample->fp) { - guint len = resample_float_resampler_get_input_latency (resample->state); - - 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); + len = resample->funcs->get_input_latency (resample->state); - err = - resample_int_resampler_process_interleaved_int (resample->state, NULL, - &len, (gint16 *) GST_BUFFER_DATA (buf), &out_processed); - } + err = + resample->funcs->process (resample->state, + NULL, &len, (guint8 *) GST_BUFFER_DATA (buf), &out_processed); if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { GST_WARNING_OBJECT (resample, "Failed to process drain: %s", - resample_resampler_strerror (err)); + resample->funcs->strerror (err)); gst_buffer_unref (buf); return; } @@ -598,7 +579,7 @@ gst_speex_resample_push_drain (GstSpeexResample * resample) GST_BUFFER_DURATION (buf) = GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); GST_BUFFER_SIZE (buf) = - out_processed * resample->channels * ((resample->fp) ? 4 : 2); + out_processed * resample->channels * (resample->width / 8); if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { GST_BUFFER_OFFSET (buf) = resample->next_offset; @@ -693,25 +674,15 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf, in_len = GST_BUFFER_SIZE (inbuf) / resample->channels; out_len = GST_BUFFER_SIZE (outbuf) / resample->channels; - if (resample->fp) { - in_len /= 4; - out_len /= 4; - } else { - in_len /= 2; - out_len /= 2; - } + in_len /= (resample->width / 8); + out_len /= (resample->width / 8); in_processed = in_len; out_processed = out_len; - 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); + err = resample->funcs->process (resample->state, + (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed, + (guint8 *) GST_BUFFER_DATA (outbuf), &out_processed); if (G_UNLIKELY (in_len != in_processed)) GST_WARNING_OBJECT (resample, "Converted %d of %d input samples", @@ -738,13 +709,13 @@ gst_speex_resample_process (GstSpeexResample * resample, GstBuffer * inbuf, if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { GST_ERROR_OBJECT (resample, "Failed to convert data: %s", - resample_resampler_strerror (err)); + resample->funcs->strerror (err)); return GST_FLOW_ERROR; } else { GST_BUFFER_DURATION (outbuf) = GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate); GST_BUFFER_SIZE (outbuf) = - out_processed * resample->channels * ((resample->fp) ? 4 : 2); + out_processed * resample->channels * (resample->width / 8); if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts; @@ -778,13 +749,17 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, guint outsamples, insamples; GstFlowReturn ret; - if (resample->state == NULL) + if (resample->state == NULL) { if (G_UNLIKELY (!(resample->state = - gst_speex_resample_init_state (resample->channels, - resample->inrate, resample->outrate, resample->quality, - resample->fp)))) + gst_speex_resample_init_state (resample, resample->width, + 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); @@ -810,10 +785,10 @@ gst_speex_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, } insamples = GST_BUFFER_SIZE (inbuf) / resample->channels; - insamples /= (resample->fp) ? 4 : 2; + insamples /= (resample->width / 8); outsamples = GST_BUFFER_SIZE (outbuf) / resample->channels; - outsamples /= (resample->fp) ? 4 : 2; + outsamples /= (resample->width / 8); if (GST_CLOCK_TIME_IS_VALID (timestamp) && !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) { @@ -860,12 +835,9 @@ gst_speex_resample_query (GstPad * pad, GstQuery * query) gint rate = resample->inrate; gint resampler_latency; - if (resample->state && resample->fp) - resampler_latency = - resample_float_resampler_get_input_latency (resample->state); - else if (resample->state && !resample->fp) + if (resample->state) resampler_latency = - resample_int_resampler_get_input_latency (resample->state); + resample->funcs->get_input_latency (resample->state); else resampler_latency = 0; @@ -936,8 +908,9 @@ gst_speex_resample_set_property (GObject * object, guint prop_id, resample->quality = g_value_get_int (value); GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); - gst_speex_resample_update_state (resample, resample->channels, - resample->inrate, resample->outrate, resample->quality, resample->fp); + 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); |