From c36ac3ce45cbf1720de35202c60d8d85bfabed0a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 6 Nov 2015 12:10:48 +0100 Subject: [PATCH] audioconvert: move audio quantize code to libs Move the audio quantize code from audioconvert to the audio library. work on making an audio converter helper function similar to the video converter. Fold fastrandom directly into the quantizer, add some ORC code to optimize this later. --- gst-libs/gst/audio/Makefile.am | 3 + .../gst/audio/audio-quantize.c | 25 +- .../gst/audio/audio-quantize.h | 0 gst-libs/gst/audio/audio.h | 1 + gst-libs/gst/audio/gstaudiopack.orc | 28 ++ gst/audioconvert/Makefile.am | 3 - gst/audioconvert/audioconvert.c | 292 +++++++++++++++------ gst/audioconvert/audioconvert.h | 91 ++++--- gst/audioconvert/gstaudioconvert.c | 93 +++---- gst/audioconvert/gstaudioconvert.h | 7 +- gst/audioconvert/gstfastrandom.h | 70 ----- 11 files changed, 354 insertions(+), 259 deletions(-) rename gst/audioconvert/gstaudioquantize.c => gst-libs/gst/audio/audio-quantize.c (95%) rename gst/audioconvert/gstaudioquantize.h => gst-libs/gst/audio/audio-quantize.h (100%) delete mode 100644 gst/audioconvert/gstfastrandom.h diff --git a/gst-libs/gst/audio/Makefile.am b/gst-libs/gst/audio/Makefile.am index 275d222..dee4e36 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 33e2780..7bedd2c 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 07a997b..277c2e9 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 160c165..5748474 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 1e2672b..d29c6bb 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 5ca86d5..d780703 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 */ +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 -audio_convert_prepare_context (AudioConvertCtx * ctx, GstAudioInfo * in, - GstAudioInfo * out, GstAudioDitherMethod dither, - GstAudioNoiseShapingMethod ns) +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); - - 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; - - g_free (ctx->tmpbuf); - g_free (ctx->tmpbuf2); - ctx->tmpbuf = NULL; - ctx->tmpbuf2 = NULL; - ctx->tmpbufsize = 0; + g_return_if_fail (convert != NULL); - return TRUE; + 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 (convert->tmpbuf); + g_free (convert->tmpbuf2); + gst_structure_free (convert->config); + + 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 c34e2aa..8c3f778 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; - -typedef void (*AudioConvertFunc) (gpointer dst, const gpointer src, gint count); - -struct _AudioConvertCtx -{ - GstAudioInfo in; - GstAudioInfo out; - - gboolean in_default; +/** + * 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" - AudioConvertFunc convert_in; +/** + * 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" - GstAudioFormat mix_format; - gboolean mix_passthrough; - GstChannelMix *mix; +/** + * 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" - AudioConvertFunc convert_out; - GstAudioQuantize *quant; +/** + * @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; - gboolean out_default; +GstAudioConverter * gst_audio_converter_new (GstAudioInfo *in_info, + GstAudioInfo *out_info, + GstStructure *config); - gboolean passthrough; +void gst_audio_converter_free (GstAudioConverter * convert); - gpointer tmpbuf; - gpointer tmpbuf2; - gint tmpbufsize; -}; +gboolean gst_audio_converter_set_config (GstAudioConverter * convert, GstStructure *config); +const GstStructure * gst_audio_converter_get_config (GstAudioConverter * convert); -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 gst_audio_converter_get_sizes (GstAudioConverter * convert, + gint samples, + gint * srcsize, gint * dstsize); -gboolean audio_convert_convert (AudioConvertCtx * ctx, gpointer src, - gpointer dst, gint samples, gboolean src_writable); +gboolean gst_audio_converter_samples (GstAudioConverter * convert, + GstAudioConverterFlags flags, + gpointer src, gpointer dst, + gint samples); -#endif /* __AUDIO_CONVERT_H__ */ +#endif /* __GST_AUDIO_CONVERTER_H__ */ diff --git a/gst/audioconvert/gstaudioconvert.c b/gst/audioconvert/gstaudioconvert.c index f3fbe93..29cab90 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 f52845f..86cec91 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 deaa129..0000000 --- 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__ */ - -- 2.7.4