From 9fbe0386d0b5c29c0e8b308dc08ef4d91e58eb0c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 6 Nov 2015 16:03:20 +0100 Subject: [PATCH] channelmix: simplify API a little Remove the format and layout from the mix_samples function and use the format when creating the channel mixer object. Also use a flag to handle the unlikely case of non-interleaved samples like we do elsewhere. --- gst/audioconvert/audioconvert.c | 8 +- gst/audioconvert/gstchannelmix.c | 177 ++++++++++++++++--------------- gst/audioconvert/gstchannelmix.h | 9 +- 3 files changed, 102 insertions(+), 92 deletions(-) diff --git a/gst/audioconvert/audioconvert.c b/gst/audioconvert/audioconvert.c index 7c7f84f92a..0e62e8543f 100644 --- a/gst/audioconvert/audioconvert.c +++ b/gst/audioconvert/audioconvert.c @@ -76,7 +76,6 @@ struct _GstAudioConverter AudioConvertFunc convert_in; - GstAudioFormat mix_format; gboolean mix_passthrough; GstAudioChannelMix *mix; @@ -263,8 +262,8 @@ gst_audio_converter_new (GstAudioInfo * in, GstAudioInfo * out, } /* step 3, channel mix */ - convert->mix_format = format; - convert->mix = gst_audio_channel_mix_new (flags, in->channels, in->position, + convert->mix = + gst_audio_channel_mix_new (flags, format, in->channels, in->position, out->channels, out->position); convert->mix_passthrough = gst_audio_channel_mix_is_passthrough (convert->mix); @@ -427,8 +426,7 @@ gst_audio_converter_samples (GstAudioConverter * convert, else outbuf = tmpbuf; - gst_audio_channel_mix_samples (convert->mix, convert->mix_format, - convert->in.layout, src, outbuf, samples); + gst_audio_channel_mix_samples (convert->mix, src, outbuf, samples); src = outbuf; } /* step 4, optional convert F64 -> S32 for quantize */ diff --git a/gst/audioconvert/gstchannelmix.c b/gst/audioconvert/gstchannelmix.c index 832951e7d4..de3ceea852 100644 --- a/gst/audioconvert/gstchannelmix.c +++ b/gst/audioconvert/gstchannelmix.c @@ -31,9 +31,13 @@ #define INT_MATRIX_FACTOR_EXPONENT 10 +typedef void (*MixFunc) (GstAudioChannelMix * mix, const gpointer src, + gpointer dst, gint samples); + struct _GstAudioChannelMix { GstAudioChannelMixFlags flags; + GstAudioFormat format; gint in_channels; gint out_channels; @@ -49,6 +53,8 @@ struct _GstAudioChannelMix * this is matrix * (2^10) as integers */ gint **matrix_int; + MixFunc func; + gpointer tmp; }; @@ -681,72 +687,6 @@ gst_audio_channel_mix_setup_matrix (GstAudioChannelMix * mix) #endif } -/** - * gst_audio_channel_mix_new: - * @flags: - * @in_channels: - * @in_position: - * @out_channels: - * @out_position: - * - * Create a new channel mixer object. - * - * Returns: a new #GstAudioChannelMix object. Free with gst_audio_channel_mix_free() - * after usage. - */ -GstAudioChannelMix * -gst_audio_channel_mix_new (GstAudioChannelMixFlags flags, - gint in_channels, - GstAudioChannelPosition in_position[64], - gint out_channels, GstAudioChannelPosition out_position[64]) -{ - GstAudioChannelMix *mix; - gint i; - - mix = g_slice_new0 (GstAudioChannelMix); - mix->flags = flags; - mix->in_channels = in_channels; - mix->out_channels = out_channels; - for (i = 0; i < 64; i++) { - mix->in_position[i] = in_position[i]; - mix->out_position[i] = out_position[i]; - } - gst_audio_channel_mix_setup_matrix (mix); - - return mix; -} - -/** - * gst_audio_channel_mix_is_passthrough: - * @mix: a #GstAudioChannelMix - * - * Check if @mix is in passthrough. - * - * Returns: %TRUE is @mix is passthrough. - */ -gboolean -gst_audio_channel_mix_is_passthrough (GstAudioChannelMix * mix) -{ - gint i; - guint64 in_mask, out_mask; - - /* only NxN matrices can be identities */ - if (mix->in_channels != mix->out_channels) - return FALSE; - - /* passthrough for 1->1 channels (MONO and NONE position are the same here) */ - if (mix->in_channels == 1 && mix->out_channels == 1) - return TRUE; - - /* passthrough if both channel masks are the same */ - in_mask = out_mask = 0; - for (i = 0; i < mix->in_channels; i++) { - in_mask |= mix->in_position[i]; - out_mask |= mix->out_position[i]; - } - return in_mask == out_mask; -} - /* IMPORTANT: out_data == in_data is possible, make sure to not overwrite data * you might need later on! */ static void @@ -828,6 +768,91 @@ gst_audio_channel_mix_mix_double (GstAudioChannelMix * mix, } } +/** + * gst_audio_channel_mix_new: + * @flags: + * @in_channels: + * @in_position: + * @out_channels: + * @out_position: + * + * Create a new channel mixer object. + * + * Returns: a new #GstAudioChannelMix object. Free with gst_audio_channel_mix_free() + * after usage. + */ +GstAudioChannelMix * +gst_audio_channel_mix_new (GstAudioChannelMixFlags flags, + GstAudioFormat format, + gint in_channels, + GstAudioChannelPosition in_position[64], + gint out_channels, GstAudioChannelPosition out_position[64]) +{ + GstAudioChannelMix *mix; + gint i; + + g_return_val_if_fail (format == GST_AUDIO_FORMAT_S32 + || format == GST_AUDIO_FORMAT_F64, NULL); + g_return_val_if_fail (in_channels > 0, NULL); + g_return_val_if_fail (out_channels > 0, NULL); + + mix = g_slice_new0 (GstAudioChannelMix); + mix->flags = flags; + mix->format = format; + mix->in_channels = in_channels; + mix->out_channels = out_channels; + + for (i = 0; i < 64; i++) { + mix->in_position[i] = in_position[i]; + mix->out_position[i] = out_position[i]; + } + gst_audio_channel_mix_setup_matrix (mix); + + switch (mix->format) { + case GST_AUDIO_FORMAT_S32: + mix->func = (MixFunc) gst_audio_channel_mix_mix_int; + break; + case GST_AUDIO_FORMAT_F64: + mix->func = (MixFunc) gst_audio_channel_mix_mix_double; + break; + default: + g_assert_not_reached (); + break; + } + return mix; +} + +/** + * gst_audio_channel_mix_is_passthrough: + * @mix: a #GstAudioChannelMix + * + * Check if @mix is in passthrough. + * + * Returns: %TRUE is @mix is passthrough. + */ +gboolean +gst_audio_channel_mix_is_passthrough (GstAudioChannelMix * mix) +{ + gint i; + guint64 in_mask, out_mask; + + /* only NxN matrices can be identities */ + if (mix->in_channels != mix->out_channels) + return FALSE; + + /* passthrough for 1->1 channels (MONO and NONE position are the same here) */ + if (mix->in_channels == 1 && mix->out_channels == 1) + return TRUE; + + /* passthrough if both channel masks are the same */ + in_mask = out_mask = 0; + for (i = 0; i < mix->in_channels; i++) { + in_mask |= mix->in_position[i]; + out_mask |= mix->out_position[i]; + } + return in_mask == out_mask; +} + /** * gst_audio_channel_mix_samples: * @mix: a #GstAudioChannelMix @@ -841,25 +866,11 @@ gst_audio_channel_mix_mix_double (GstAudioChannelMix * mix, * @in_data and @out_data need to be in @format and @layout. */ void -gst_audio_channel_mix_samples (GstAudioChannelMix * mix, GstAudioFormat format, - GstAudioLayout layout, const gpointer in_data, gpointer out_data, - gint samples) +gst_audio_channel_mix_samples (GstAudioChannelMix * mix, + const gpointer in_data, gpointer out_data, gint samples) { g_return_if_fail (mix != NULL); g_return_if_fail (mix->matrix != NULL); - g_return_if_fail (layout == GST_AUDIO_LAYOUT_INTERLEAVED); - switch (format) { - case GST_AUDIO_FORMAT_S32: - gst_audio_channel_mix_mix_int (mix, (const gint32 *) in_data, - (gint32 *) out_data, samples); - break; - case GST_AUDIO_FORMAT_F64: - gst_audio_channel_mix_mix_double (mix, (const gdouble *) in_data, - (gdouble *) out_data, samples); - break; - default: - g_assert_not_reached (); - break; - } + mix->func (mix, in_data, out_data, samples); } diff --git a/gst/audioconvert/gstchannelmix.h b/gst/audioconvert/gstchannelmix.h index d7f6a10309..cbd0ddc6c8 100644 --- a/gst/audioconvert/gstchannelmix.h +++ b/gst/audioconvert/gstchannelmix.h @@ -31,6 +31,7 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix; /** * GstAudioChannelMixFlags: * @GST_AUDIO_CHANNEL_MIX_FLAGS_NONE: no flag + * @GST_AUDIO_CHANNEL_MIX_FLAGS_NON_INTERLEAVED: channels are not interleaved * @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN: input channels are explicitly unpositioned * @GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT: output channels are explicitly unpositioned * @@ -38,11 +39,13 @@ typedef struct _GstAudioChannelMix GstAudioChannelMix; */ typedef enum { GST_AUDIO_CHANNEL_MIX_FLAGS_NONE = 0, - GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 0), - GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 1) + GST_AUDIO_CHANNEL_MIX_FLAGS_NON_INTERLEAVED = (1 << 0), + GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_IN = (1 << 1), + GST_AUDIO_CHANNEL_MIX_FLAGS_UNPOSITIONED_OUT = (1 << 2) } GstAudioChannelMixFlags; GstAudioChannelMix * gst_audio_channel_mix_new (GstAudioChannelMixFlags flags, + GstAudioFormat format, gint in_channels, GstAudioChannelPosition in_position[64], gint out_channels, @@ -58,8 +61,6 @@ gboolean gst_audio_channel_mix_is_passthrough (GstAudioChannelMix *mix); * Do actual mixing. */ void gst_audio_channel_mix_samples (GstAudioChannelMix * mix, - GstAudioFormat format, - GstAudioLayout layout, const gpointer in_data, gpointer out_data, gint samples);