diff --git a/gst-libs/gst/audio/Makefile.am b/gst-libs/gst/audio/Makefile.am index 275d22227c..dee4e364a7 100644 --- a/gst-libs/gst/audio/Makefile.am +++ b/gst-libs/gst/audio/Makefile.am @@ -7,6 +7,7 @@ glib_enum_headers= \ audio-format.h \ audio-channels.h \ audio-info.h \ + audio-quantize.h \ gstaudioringbuffer.h glib_enum_define = GST_AUDIO @@ -27,6 +28,7 @@ libgstaudio_@GST_API_VERSION@_la_SOURCES = \ audio-format.c \ audio-channels.c \ audio-info.c \ + audio-quantize.c \ gstaudioringbuffer.c \ gstaudioclock.c \ gstaudiocdsrc.c \ @@ -50,6 +52,7 @@ libgstaudio_@GST_API_VERSION@include_HEADERS = \ audio-format.h \ audio-channels.h \ audio-info.h \ + audio-quantize.h \ gstaudioringbuffer.h \ gstaudioclock.h \ gstaudiofilter.h \ diff --git a/gst/audioconvert/gstaudioquantize.c b/gst-libs/gst/audio/audio-quantize.c similarity index 95% rename from gst/audioconvert/gstaudioquantize.c rename to gst-libs/gst/audio/audio-quantize.c index 33e27803ef..7bedd2c0e6 100644 --- a/gst/audioconvert/gstaudioquantize.c +++ b/gst-libs/gst/audio/audio-quantize.c @@ -29,10 +29,9 @@ #include #include #include -#include "gstaudioconvertorc.h" -#include "gstaudioquantize.h" -#include "gstfastrandom.h" +#include "gstaudiopack.h" +#include "audio-quantize.h" typedef void (*QuantizeFunc) (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint count); @@ -85,10 +84,26 @@ static void gst_audio_quantize_quantize_int_none_none (GstAudioQuantize * quant, const gpointer src, gpointer dst, gint samples) { - audio_convert_orc_int_bias (dst, src, quant->bias, ~quant->mask, + audio_orc_int_bias (dst, src, quant->bias, ~quant->mask, samples * quant->channels); } +/* This is the base function, implementing a linear congruential generator + * and returning a pseudo random number between 0 and 2^32 - 1. + */ +static inline guint32 +gst_fast_random_uint32 (void) +{ + static guint32 state = 0xdeadbeef; + return (state = state * 1103515245 + 12345); +} + +static inline gint32 +gst_fast_random_int32 (void) +{ + return (gint32) gst_fast_random_uint32 (); +} + /* Assuming dither == 2^n, * returns one of 2^(n+1) possible random values: * -dither <= retval < dither */ @@ -155,7 +170,7 @@ gst_audio_quantize_quantize_int_dither_none (GstAudioQuantize * quant, { setup_dither_buf (quant, samples); - audio_convert_orc_int_dither (dst, src, quant->dither_buf, ~quant->mask, + audio_orc_int_dither (dst, src, quant->dither_buf, ~quant->mask, samples * quant->channels); } diff --git a/gst/audioconvert/gstaudioquantize.h b/gst-libs/gst/audio/audio-quantize.h similarity index 100% rename from gst/audioconvert/gstaudioquantize.h rename to gst-libs/gst/audio/audio-quantize.h diff --git a/gst-libs/gst/audio/audio.h b/gst-libs/gst/audio/audio.h index 07a997bc5a..277c2e9eb7 100644 --- a/gst-libs/gst/audio/audio.h +++ b/gst-libs/gst/audio/audio.h @@ -27,6 +27,7 @@ #include #include #include +#include G_BEGIN_DECLS diff --git a/gst-libs/gst/audio/gstaudiopack.orc b/gst-libs/gst/audio/gstaudiopack.orc index 160c165494..57484744d9 100644 --- a/gst-libs/gst/audio/gstaudiopack.orc +++ b/gst-libs/gst/audio/gstaudiopack.orc @@ -380,3 +380,31 @@ copyl d1, p1 copyq d1, p1 +.function audio_orc_int_bias +.dest 4 d1 gint32 +.source 4 s1 gint32 +.param 4 bias gint32 +.param 4 mask gint32 +.temp 4 t1 + +addssl t1, s1, bias +andl d1, t1, mask + +.function audio_orc_int_dither +.dest 4 d1 gint32 +.source 4 s1 gint32 +.source 4 dither gint32 +.param 4 mask gint32 +.temp 4 t1 + +addssl t1, s1, dither +andl d1, t1, mask + +.function audio_orc_update_rand +.dest 4 r guint32 +.temp 4 t + +mulll t, r, 1103515245 +addl r, t, 12345 + + diff --git a/gst/audioconvert/Makefile.am b/gst/audioconvert/Makefile.am index 1e2672b61d..d29c6bbef2 100644 --- a/gst/audioconvert/Makefile.am +++ b/gst/audioconvert/Makefile.am @@ -7,7 +7,6 @@ libgstaudioconvert_la_SOURCES = \ gstaudioconvert.c \ audioconvert.c \ gstchannelmix.c \ - gstaudioquantize.c \ plugin.c nodist_libgstaudioconvert_la_SOURCES = $(ORC_NODIST_SOURCES) @@ -22,6 +21,4 @@ noinst_HEADERS = \ gstaudioconvert.h \ audioconvert.h \ gstchannelmix.h \ - gstaudioquantize.h \ - gstfastrandom.h \ plugin.h diff --git a/gst/audioconvert/audioconvert.c b/gst/audioconvert/audioconvert.c index 5ca86d5f23..d7807036fe 100644 --- a/gst/audioconvert/audioconvert.c +++ b/gst/audioconvert/audioconvert.c @@ -27,10 +27,11 @@ #include #include "gstchannelmix.h" -#include "gstaudioquantize.h" #include "audioconvert.h" #include "gstaudioconvertorc.h" +typedef void (*AudioConvertFunc) (gpointer dst, const gpointer src, gint count); + /** * int/int int/float float/int float/float * @@ -41,29 +42,160 @@ * quantize S32 S32 * pack S32 F64 S32 F64 */ -gboolean -audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in, - GstAudioInfo * out, GstAudioDitherMethod dither, - GstAudioNoiseShapingMethod ns) +struct _GstAudioConverter { + GstAudioInfo in; + GstAudioInfo out; + + GstStructure *config; + + gboolean in_default; + + AudioConvertFunc convert_in; + + GstAudioFormat mix_format; + gboolean mix_passthrough; + GstChannelMix *mix; + + AudioConvertFunc convert_out; + + GstAudioQuantize *quant; + + gboolean out_default; + + gboolean passthrough; + + gpointer tmpbuf; + gpointer tmpbuf2; + gint tmpbufsize; +}; + +/* +static guint +get_opt_uint (GstAudioConverter * convert, const gchar * opt, guint def) +{ + guint res; + if (!gst_structure_get_uint (convert->config, opt, &res)) + res = def; + return res; +} +*/ + +static gint +get_opt_enum (GstAudioConverter * convert, const gchar * opt, GType type, + gint def) +{ + gint res; + if (!gst_structure_get_enum (convert->config, opt, type, &res)) + res = def; + return res; +} + +#define DEFAULT_OPT_DITHER_METHOD GST_AUDIO_DITHER_NONE +#define DEFAULT_OPT_NOISE_SHAPING_METHOD GST_AUDIO_NOISE_SHAPING_NONE +#define DEFAULT_OPT_QUANTIZATION 1 + +#define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \ + GST_AUDIO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_AUDIO_DITHER_METHOD, \ + DEFAULT_OPT_DITHER_METHOD) +#define GET_OPT_NOISE_SHAPING_METHOD(c) get_opt_enum(c, \ + GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, \ + DEFAULT_OPT_NOISE_SHAPING_METHOD) +#define GET_OPT_QUANTIZATION(c) get_opt_uint(c, \ + GST_AUDIO_CONVERTER_OPT_QUANTIZATION, DEFAULT_OPT_QUANTIZATION) + +static gboolean +copy_config (GQuark field_id, const GValue * value, gpointer user_data) +{ + GstAudioConverter *convert = user_data; + + gst_structure_id_set_value (convert->config, field_id, value); + + return TRUE; +} + +/** + * gst_audio_converter_set_config: + * @convert: a #GstAudioConverter + * @config: (transfer full): a #GstStructure + * + * Set @config as extra configuraion for @convert. + * + * If the parameters in @config can not be set exactly, this function returns + * %FALSE and will try to update as much state as possible. The new state can + * then be retrieved and refined with gst_audio_converter_get_config(). + * + * Look at the #GST_AUDIO_CONVERTER_OPT_* fields to check valid configuration + * option and values. + * + * Returns: %TRUE when @config could be set. + */ +gboolean +gst_audio_converter_set_config (GstAudioConverter * convert, + GstStructure * config) +{ + g_return_val_if_fail (convert != NULL, FALSE); + g_return_val_if_fail (config != NULL, FALSE); + + gst_structure_foreach (config, copy_config, convert); + gst_structure_free (config); + + return TRUE; +} + +/** + * gst_audio_converter_get_config: + * @convert: a #GstAudioConverter + * + * Get the current configuration of @convert. + * + * Returns: a #GstStructure that remains valid for as long as @convert is valid + * or until gst_audio_converter_set_config() is called. + */ +const GstStructure * +gst_audio_converter_get_config (GstAudioConverter * convert) +{ + g_return_val_if_fail (convert != NULL, NULL); + + return convert->config; +} + + +/** + * + */ +GstAudioConverter * +gst_audio_converter_new (GstAudioInfo * in, GstAudioInfo * out, + GstStructure * config) +{ + GstAudioConverter *convert; gint in_depth, out_depth; GstChannelMixFlags flags; gboolean in_int, out_int; GstAudioFormat format; + GstAudioDitherMethod dither; + GstAudioNoiseShapingMethod ns; - g_return_val_if_fail (ctx != NULL, FALSE); g_return_val_if_fail (in != NULL, FALSE); g_return_val_if_fail (out != NULL, FALSE); - /* first clean the existing context */ - audio_convert_clean_context (ctx); if ((GST_AUDIO_INFO_CHANNELS (in) != GST_AUDIO_INFO_CHANNELS (out)) && (GST_AUDIO_INFO_IS_UNPOSITIONED (in) || GST_AUDIO_INFO_IS_UNPOSITIONED (out))) goto unpositioned; - ctx->in = *in; - ctx->out = *out; + convert = g_slice_new0 (GstAudioConverter); + + convert->in = *in; + convert->out = *out; + + /* default config */ + convert->config = gst_structure_new_empty ("GstAudioConverter"); + if (config) + gst_audio_converter_set_config (convert, config); + + dither = GET_OPT_DITHER_METHOD (convert); + ns = GET_OPT_NOISE_SHAPING_METHOD (convert); GST_INFO ("unitsizes: %d -> %d", in->bpf, out->bpf); @@ -85,7 +217,7 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in, /* step 1, unpack */ format = in->finfo->unpack_format; - ctx->in_default = in->finfo->unpack_format == in->finfo->format; + convert->in_default = in->finfo->unpack_format == in->finfo->format; GST_INFO ("unpack format %s to %s", gst_audio_format_to_string (in->finfo->format), gst_audio_format_to_string (format)); @@ -93,23 +225,23 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in, /* step 2, optional convert from S32 to F64 for channel mix */ if (in_int && !out_int) { GST_INFO ("convert S32 to F64"); - ctx->convert_in = (AudioConvertFunc) audio_convert_orc_s32_to_double; + convert->convert_in = (AudioConvertFunc) audio_convert_orc_s32_to_double; format = GST_AUDIO_FORMAT_F64; } /* step 3, channel mix */ - ctx->mix_format = format; - ctx->mix = gst_channel_mix_new (flags, in->channels, in->position, + convert->mix_format = format; + convert->mix = gst_channel_mix_new (flags, in->channels, in->position, out->channels, out->position); - ctx->mix_passthrough = gst_channel_mix_is_passthrough (ctx->mix); + convert->mix_passthrough = gst_channel_mix_is_passthrough (convert->mix); GST_INFO ("mix format %s, passthrough %d, in_channels %d, out_channels %d", - gst_audio_format_to_string (format), ctx->mix_passthrough, + gst_audio_format_to_string (format), convert->mix_passthrough, in->channels, out->channels); /* step 4, optional convert for quantize */ if (!in_int && out_int) { GST_INFO ("convert F64 to S32"); - ctx->convert_out = (AudioConvertFunc) audio_convert_orc_double_to_s32; + convert->convert_out = (AudioConvertFunc) audio_convert_orc_double_to_s32; format = GST_AUDIO_FORMAT_S32; } /* step 5, optional quantize */ @@ -132,78 +264,72 @@ audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in, * the rounding correct */ if (out_int && out_depth < 32) { GST_INFO ("quantize to %d bits, dither %d, ns %d", out_depth, dither, ns); - ctx->quant = gst_audio_quantize_new (dither, ns, 0, format, + convert->quant = gst_audio_quantize_new (dither, ns, 0, format, out->channels, 1U << (32 - out_depth)); } /* step 6, pack */ g_assert (out->finfo->unpack_format == format); - ctx->out_default = format == out->finfo->format; + convert->out_default = format == out->finfo->format; GST_INFO ("pack format %s to %s", gst_audio_format_to_string (format), gst_audio_format_to_string (out->finfo->format)); /* optimize */ - if (out->finfo->format == in->finfo->format && ctx->mix_passthrough) { + if (out->finfo->format == in->finfo->format && convert->mix_passthrough) { GST_INFO ("same formats and passthrough mixing -> passthrough"); - ctx->passthrough = TRUE; + convert->passthrough = TRUE; } - return TRUE; + return convert; /* ERRORS */ unpositioned: { GST_WARNING ("unpositioned channels"); - return FALSE; + return NULL; } } -gboolean -audio_convert_clean_context (AudioConvertCtx * ctx) +void +gst_audio_converter_free (GstAudioConverter * convert) { - g_return_val_if_fail (ctx != NULL, FALSE); + g_return_if_fail (convert != NULL); - if (ctx->quant) - gst_audio_quantize_free (ctx->quant); - ctx->quant = NULL; - if (ctx->mix) - gst_channel_mix_free (ctx->mix); - ctx->mix = NULL; - gst_audio_info_init (&ctx->in); - gst_audio_info_init (&ctx->out); - ctx->convert_in = NULL; - ctx->convert_out = NULL; + if (convert->quant) + gst_audio_quantize_free (convert->quant); + if (convert->mix) + gst_channel_mix_free (convert->mix); + gst_audio_info_init (&convert->in); + gst_audio_info_init (&convert->out); - g_free (ctx->tmpbuf); - g_free (ctx->tmpbuf2); - ctx->tmpbuf = NULL; - ctx->tmpbuf2 = NULL; - ctx->tmpbufsize = 0; + g_free (convert->tmpbuf); + g_free (convert->tmpbuf2); + gst_structure_free (convert->config); - return TRUE; + g_slice_free (GstAudioConverter, convert); } gboolean -audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, gint * srcsize, - gint * dstsize) +gst_audio_converter_get_sizes (GstAudioConverter * convert, gint samples, + gint * srcsize, gint * dstsize) { - g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (convert != NULL, FALSE); if (srcsize) - *srcsize = samples * ctx->in.bpf; + *srcsize = samples * convert->in.bpf; if (dstsize) - *dstsize = samples * ctx->out.bpf; + *dstsize = samples * convert->out.bpf; return TRUE; } gboolean -audio_convert_convert (AudioConvertCtx * ctx, gpointer src, - gpointer dst, gint samples, gboolean src_writable) +gst_audio_converter_samples (GstAudioConverter * convert, + GstAudioConverterFlags flags, gpointer src, gpointer dst, gint samples) { guint size; gpointer outbuf, tmpbuf, tmpbuf2; - g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (convert != NULL, FALSE); g_return_val_if_fail (src != NULL, FALSE); g_return_val_if_fail (dst != NULL, FALSE); g_return_val_if_fail (samples >= 0, FALSE); @@ -211,86 +337,88 @@ audio_convert_convert (AudioConvertCtx * ctx, gpointer src, if (samples == 0) return TRUE; - if (ctx->passthrough) { - memcpy (dst, src, samples * ctx->in.bpf); + if (convert->passthrough) { + memcpy (dst, src, samples * convert->in.bpf); return TRUE; } - size = sizeof (gdouble) * samples * MAX (ctx->in.channels, ctx->out.channels); + size = + sizeof (gdouble) * samples * MAX (convert->in.channels, + convert->out.channels); - if (size > ctx->tmpbufsize) { - ctx->tmpbuf = g_realloc (ctx->tmpbuf, size); - ctx->tmpbuf2 = g_realloc (ctx->tmpbuf2, size); - ctx->tmpbufsize = size; + if (size > convert->tmpbufsize) { + convert->tmpbuf = g_realloc (convert->tmpbuf, size); + convert->tmpbuf2 = g_realloc (convert->tmpbuf2, size); + convert->tmpbufsize = size; } - tmpbuf = ctx->tmpbuf; - tmpbuf2 = ctx->tmpbuf2; + tmpbuf = convert->tmpbuf; + tmpbuf2 = convert->tmpbuf2; /* 1. unpack */ - if (!ctx->in_default) { - if (!ctx->convert_in && ctx->mix_passthrough && !ctx->convert_out - && !ctx->quant && ctx->out_default) + if (!convert->in_default) { + if (!convert->convert_in && convert->mix_passthrough + && !convert->convert_out && !convert->quant && convert->out_default) outbuf = dst; else outbuf = tmpbuf; - ctx->in.finfo->unpack_func (ctx->in.finfo, + convert->in.finfo->unpack_func (convert->in.finfo, GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE, outbuf, src, - samples * ctx->in.channels); + samples * convert->in.channels); src = outbuf; } /* 2. optionally convert for mixing */ - if (ctx->convert_in) { - if (ctx->mix_passthrough && !ctx->convert_out && !ctx->quant - && ctx->out_default) + if (convert->convert_in) { + if (convert->mix_passthrough && !convert->convert_out && !convert->quant + && convert->out_default) outbuf = dst; else if (src == tmpbuf) outbuf = tmpbuf2; else outbuf = tmpbuf; - ctx->convert_in (outbuf, src, samples * ctx->in.channels); + convert->convert_in (outbuf, src, samples * convert->in.channels); src = outbuf; } /* step 3, channel mix if not passthrough */ - if (!ctx->mix_passthrough) { - if (!ctx->convert_out && !ctx->quant && ctx->out_default) + if (!convert->mix_passthrough) { + if (!convert->convert_out && !convert->quant && convert->out_default) outbuf = dst; else outbuf = tmpbuf; - gst_channel_mix_mix (ctx->mix, ctx->mix_format, ctx->in.layout, src, outbuf, - samples); + gst_channel_mix_mix (convert->mix, convert->mix_format, convert->in.layout, + src, outbuf, samples); src = outbuf; } /* step 4, optional convert F64 -> S32 for quantize */ - if (ctx->convert_out) { - if (!ctx->quant && ctx->out_default) + if (convert->convert_out) { + if (!convert->quant && convert->out_default) outbuf = dst; else outbuf = tmpbuf; - ctx->convert_out (outbuf, src, samples * ctx->out.channels); + convert->convert_out (outbuf, src, samples * convert->out.channels); src = outbuf; } /* step 5, optional quantize */ - if (ctx->quant) { - if (ctx->out_default) + if (convert->quant) { + if (convert->out_default) outbuf = dst; else outbuf = tmpbuf; - gst_audio_quantize_samples (ctx->quant, outbuf, src, samples); + gst_audio_quantize_samples (convert->quant, outbuf, src, samples); src = outbuf; } /* step 6, pack */ - if (!ctx->out_default) { - ctx->out.finfo->pack_func (ctx->out.finfo, 0, src, dst, - samples * ctx->out.channels); + if (!convert->out_default) { + convert->out.finfo->pack_func (convert->out.finfo, 0, src, dst, + samples * convert->out.channels); } return TRUE; diff --git a/gst/audioconvert/audioconvert.h b/gst/audioconvert/audioconvert.h index c34e2aa8e0..8c3f778c28 100644 --- a/gst/audioconvert/audioconvert.h +++ b/gst/audioconvert/audioconvert.h @@ -1,7 +1,8 @@ /* GStreamer * Copyright (C) 2004 Ronald Bultje + * (C) 2015 Wim Taymans * - * audioconvert.h: audio format conversion library + * audioconverter.h: audio format conversion library * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -19,57 +20,73 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __AUDIO_CONVERT_H__ -#define __AUDIO_CONVERT_H__ +#ifndef __GST_AUDIO_CONVERTER_H__ +#define __GST_AUDIO_CONVERTER_H__ #include #include #include "gstchannelmix.h" -#include "gstaudioquantize.h" -GST_DEBUG_CATEGORY_EXTERN (audio_convert_debug); -#define GST_CAT_DEFAULT (audio_convert_debug) +typedef struct _GstAudioConverter GstAudioConverter; -typedef struct _AudioConvertCtx AudioConvertCtx; +/** + * GST_AUDIO_CONVERTER_OPT_DITHER_METHOD: + * + * #GST_TYPE_AUDIO_DITHER_METHOD, The dither method to use when + * changing bit depth. + * Default is #GST_AUDIO_DITHER_NONE. + */ +#define GST_AUDIO_CONVERTER_OPT_DITHER_METHOD "GstAudioConverter.dither-method" -typedef void (*AudioConvertFunc) (gpointer dst, const gpointer src, gint count); +/** + * GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD: + * + * #GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, The noise shaping method to use + * to mask noise from quantization errors. + * Default is #GST_AUDIO_NOISE_SHAPING_NONE. + */ +#define GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD "GstAudioConverter.noise-shaping-method" -struct _AudioConvertCtx -{ - GstAudioInfo in; - GstAudioInfo out; +/** + * GST_AUDIO_CONVERTER_OPT_QUANTIZATION: + * + * #G_TYPE_UINT, The quantization amount. Components will be + * quantized to multiples of this value. + * Default is 1 + */ +#define GST_AUDIO_CONVERTER_OPT_QUANTIZATION "GstAudioConverter.quantization" - gboolean in_default; - AudioConvertFunc convert_in; +/** + * @GST_AUDIO_CONVERTER_FLAG_NONE: no flag + * @GST_AUDIO_CONVERTER_FLAG_SOURCE_WRITABLE: the source is writable and can be + * used as temporary storage during conversion. + * + * Extra flags passed to gst_audio_converter_samples(). + */ +typedef enum { + GST_AUDIO_CONVERTER_FLAG_NONE = 0, + GST_AUDIO_CONVERTER_FLAG_SOURCE_WRITABLE = (1 << 0) +} GstAudioConverterFlags; - GstAudioFormat mix_format; - gboolean mix_passthrough; - GstChannelMix *mix; +GstAudioConverter * gst_audio_converter_new (GstAudioInfo *in_info, + GstAudioInfo *out_info, + GstStructure *config); - AudioConvertFunc convert_out; +void gst_audio_converter_free (GstAudioConverter * convert); - GstAudioQuantize *quant; +gboolean gst_audio_converter_set_config (GstAudioConverter * convert, GstStructure *config); +const GstStructure * gst_audio_converter_get_config (GstAudioConverter * convert); - gboolean out_default; - gboolean passthrough; +gboolean gst_audio_converter_get_sizes (GstAudioConverter * convert, + gint samples, + gint * srcsize, gint * dstsize); - gpointer tmpbuf; - gpointer tmpbuf2; - gint tmpbufsize; -}; +gboolean gst_audio_converter_samples (GstAudioConverter * convert, + GstAudioConverterFlags flags, + gpointer src, gpointer dst, + gint samples); -gboolean audio_convert_prepare_context (AudioConvertCtx * ctx, - GstAudioInfo * in, GstAudioInfo * out, - GstAudioDitherMethod dither, GstAudioNoiseShapingMethod ns); -gboolean audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, - gint * srcsize, gint * dstsize); - -gboolean audio_convert_clean_context (AudioConvertCtx * ctx); - -gboolean audio_convert_convert (AudioConvertCtx * ctx, gpointer src, - gpointer dst, gint samples, gboolean src_writable); - -#endif /* __AUDIO_CONVERT_H__ */ +#endif /* __GST_AUDIO_CONVERTER_H__ */ diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index f3fbe93ee1..29cab90e6d 100644 --- a/gst/audioconvert/gstaudioconvert.c +++ b/gst/audioconvert/gstaudioconvert.c @@ -64,7 +64,6 @@ #include "gstaudioconvert.h" #include "gstchannelmix.h" -#include "gstaudioquantize.h" #include "plugin.h" GST_DEBUG_CATEGORY (audio_convert_debug); @@ -134,51 +133,6 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_ALWAYS, STATIC_CAPS); -#define GST_TYPE_AUDIO_CONVERT_DITHERING (gst_audio_convert_dithering_get_type ()) -static GType -gst_audio_convert_dithering_get_type (void) -{ - static GType gtype = 0; - - if (gtype == 0) { - static const GEnumValue values[] = { - {GST_AUDIO_DITHER_NONE, "No dithering", - "none"}, - {GST_AUDIO_DITHER_RPDF, "Rectangular dithering", "rpdf"}, - {GST_AUDIO_DITHER_TPDF, "Triangular dithering (default)", "tpdf"}, - {GST_AUDIO_DITHER_TPDF_HF, "High frequency triangular dithering", - "tpdf-hf"}, - {0, NULL, NULL} - }; - - gtype = g_enum_register_static ("GstAudioConvertDithering", values); - } - return gtype; -} - -#define GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING (gst_audio_convert_ns_get_type ()) -static GType -gst_audio_convert_ns_get_type (void) -{ - static GType gtype = 0; - - if (gtype == 0) { - static const GEnumValue values[] = { - {GST_AUDIO_NOISE_SHAPING_NONE, "No noise shaping (default)", - "none"}, - {GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK, "Error feedback", - "error-feedback"}, - {GST_AUDIO_NOISE_SHAPING_SIMPLE, "Simple 2-pole noise shaping", "simple"}, - {GST_AUDIO_NOISE_SHAPING_MEDIUM, "Medium 5-pole noise shaping", "medium"}, - {GST_AUDIO_NOISE_SHAPING_HIGH, "High 8-pole noise shaping", "high"}, - {0, NULL, NULL} - }; - - gtype = g_enum_register_static ("GstAudioConvertNoiseShaping", values); - } - return gtype; -} - /*** TYPE FUNCTIONS ***********************************************************/ static void @@ -195,13 +149,13 @@ gst_audio_convert_class_init (GstAudioConvertClass * klass) g_object_class_install_property (gobject_class, PROP_DITHERING, g_param_spec_enum ("dithering", "Dithering", "Selects between different dithering methods.", - GST_TYPE_AUDIO_CONVERT_DITHERING, GST_AUDIO_DITHER_TPDF, + GST_TYPE_AUDIO_DITHER_METHOD, GST_AUDIO_DITHER_TPDF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_NOISE_SHAPING, g_param_spec_enum ("noise-shaping", "Noise shaping", "Selects between different noise shaping methods.", - GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING, GST_AUDIO_NOISE_SHAPING_NONE, + GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, GST_AUDIO_NOISE_SHAPING_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gst_element_class_add_pad_template (element_class, @@ -235,7 +189,6 @@ gst_audio_convert_init (GstAudioConvert * this) { this->dither = GST_AUDIO_DITHER_TPDF; this->ns = GST_AUDIO_NOISE_SHAPING_NONE; - memset (&this->ctx, 0, sizeof (AudioConvertCtx)); gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (this), TRUE); } @@ -245,7 +198,7 @@ gst_audio_convert_dispose (GObject * obj) { GstAudioConvert *this = GST_AUDIO_CONVERT (obj); - audio_convert_clean_context (&this->ctx); + gst_audio_converter_free (this->convert); G_OBJECT_CLASS (parent_class)->dispose (obj); } @@ -694,15 +647,29 @@ gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps, GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %" GST_PTR_FORMAT, incaps, outcaps); + if (this->convert) { + gst_audio_converter_free (this->convert); + this->convert = NULL; + } + if (!gst_audio_info_from_caps (&in_info, incaps)) goto invalid_in; if (!gst_audio_info_from_caps (&out_info, outcaps)) goto invalid_out; - if (!audio_convert_prepare_context (&this->ctx, &in_info, &out_info, - this->dither, this->ns)) + this->convert = gst_audio_converter_new (&in_info, &out_info, + gst_structure_new ("GstAudioConverterConfig", + GST_AUDIO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_AUDIO_DITHER_METHOD, + this->dither, + GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, + GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, this->ns, NULL)); + + if (this->convert == NULL) goto no_converter; + this->in_info = in_info; + this->out_info = out_info; + return TRUE; /* ERRORS */ @@ -718,7 +685,7 @@ invalid_out: } no_converter: { - GST_ERROR_OBJECT (base, "could not find converter"); + GST_ERROR_OBJECT (base, "could not make converter"); return FALSE; } } @@ -732,15 +699,17 @@ gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf, GstMapInfo srcmap, dstmap; gint insize, outsize; gboolean inbuf_writable; + GstAudioConverterFlags flags; gint samples; /* get amount of samples to convert. */ - samples = gst_buffer_get_size (inbuf) / this->ctx.in.bpf; + samples = gst_buffer_get_size (inbuf) / this->in_info.bpf; /* get in/output sizes, to see if the buffers we got are of correct * sizes */ - if (!audio_convert_get_sizes (&this->ctx, samples, &insize, &outsize)) + if (!gst_audio_converter_get_sizes (this->convert, samples, &insize, + &outsize)) goto error; if (insize == 0 || outsize == 0) @@ -762,13 +731,17 @@ gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf, goto wrong_size; /* and convert the samples */ + flags = 0; + if (inbuf_writable) + flags |= GST_AUDIO_CONVERTER_FLAG_SOURCE_WRITABLE; + if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { - if (!audio_convert_convert (&this->ctx, srcmap.data, dstmap.data, - samples, inbuf_writable)) + if (!gst_audio_converter_samples (this->convert, flags, srcmap.data, + dstmap.data, samples)) goto convert_error; } else { /* Create silence buffer */ - gst_audio_format_fill_silence (this->ctx.out.finfo, dstmap.data, outsize); + gst_audio_format_fill_silence (this->out_info.finfo, dstmap.data, outsize); } ret = GST_FLOW_OK; @@ -829,8 +802,8 @@ gst_audio_convert_submit_input_buffer (GstBaseTransform * base, if (base->segment.format == GST_FORMAT_TIME) { input = - gst_audio_buffer_clip (input, &base->segment, this->ctx.in.rate, - this->ctx.in.bpf); + gst_audio_buffer_clip (input, &base->segment, this->in_info.rate, + this->in_info.bpf); if (!input) return GST_FLOW_OK; diff --git a/gst/audioconvert/gstaudioconvert.h b/gst/audioconvert/gstaudioconvert.h index f52845fbf9..86cec91d6c 100644 --- a/gst/audioconvert/gstaudioconvert.h +++ b/gst/audioconvert/gstaudioconvert.h @@ -46,10 +46,13 @@ struct _GstAudioConvert { GstBaseTransform element; - AudioConvertCtx ctx; - + /* properties */ GstAudioDitherMethod dither; GstAudioNoiseShapingMethod ns; + + GstAudioInfo in_info; + GstAudioInfo out_info; + GstAudioConverter *convert; }; struct _GstAudioConvertClass diff --git a/gst/audioconvert/gstfastrandom.h b/gst/audioconvert/gstfastrandom.h deleted file mode 100644 index deaa1291fd..0000000000 --- a/gst/audioconvert/gstfastrandom.h +++ /dev/null @@ -1,70 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Sebastian Dröge - * - * gstfastrandom.h: Fast, bad PNRG - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -#ifndef __GST_FAST_RANDOM__ -#define __GST_FAST_RANDOM__ - -/* transform [0..2^32] -> [0..1] */ -#define GST_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10 - -/* This is the base function, implementing a linear congruential generator - * and returning a pseudo random number between 0 and 2^32 - 1. - */ -static inline guint32 -gst_fast_random_uint32 (void) -{ - static guint32 state = 0xdeadbeef; - - return (state = state * 1103515245 + 12345); -} - -static inline gint32 -gst_fast_random_int32 (void) -{ - return (gint32) gst_fast_random_uint32 (); -} - -static inline gdouble -gst_fast_random_double (void) -{ - gdouble ret; - - ret = gst_fast_random_uint32 () * GST_RAND_DOUBLE_TRANSFORM; - ret = (ret + gst_fast_random_uint32 ()) * GST_RAND_DOUBLE_TRANSFORM; - - if (ret >= 1.0) - return gst_fast_random_double (); - - return ret; -} - -static inline gdouble -gst_fast_random_double_range (gdouble start, gdouble end) -{ - return gst_fast_random_double () * (end - start) + start; -} - -#undef GST_RAND_DOUBLE_TRANSFORM - -#endif /* __GST_FAST_RANDOM__ */ -