video-format: Add macro checking for validity of GstVideoFormatInfo
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-base / gst-libs / gst / audio / audio-converter.c
1 /* GStreamer
2  * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
3  *           (C) 2015 Wim Taymans <wim.taymans@gmail.com>
4  *
5  * audioconverter.c: Convert audio to different audio formats automatically
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <math.h>
28 #include <string.h>
29
30 #include "audio-converter.h"
31 #include "gstaudiopack.h"
32
33 /**
34  * SECTION:gstaudioconverter
35  * @title: GstAudioConverter
36  * @short_description: Generic audio conversion
37  *
38  * This object is used to convert audio samples from one format to another.
39  * The object can perform conversion of:
40  *
41  *  * audio format with optional dithering and noise shaping
42  *
43  *  * audio samplerate
44  *
45  *  * audio channels and channel layout
46  *
47  */
48
49 #ifndef GST_DISABLE_GST_DEBUG
50 #define GST_CAT_DEFAULT ensure_debug_category()
51 static GstDebugCategory *
52 ensure_debug_category (void)
53 {
54   static gsize cat_gonce = 0;
55
56   if (g_once_init_enter (&cat_gonce)) {
57     gsize cat_done;
58
59     cat_done = (gsize) _gst_debug_category_new ("audio-converter", 0,
60         "audio-converter object");
61
62     g_once_init_leave (&cat_gonce, cat_done);
63   }
64
65   return (GstDebugCategory *) cat_gonce;
66 }
67 #else
68 #define ensure_debug_category() /* NOOP */
69 #endif /* GST_DISABLE_GST_DEBUG */
70
71 typedef struct _AudioChain AudioChain;
72
73 typedef void (*AudioConvertFunc) (gpointer dst, const gpointer src, gint count);
74 typedef gboolean (*AudioConvertSamplesFunc) (GstAudioConverter * convert,
75     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
76     gpointer out[], gsize out_frames);
77 typedef void (*AudioConvertEndianFunc) (gpointer dst, const gpointer src,
78     gint count);
79
80 /*                           int/int    int/float  float/int float/float
81  *
82  *  unpack                     S32          S32         F64       F64
83  *  convert                               S32->F64
84  *  channel mix                S32          F64         F64       F64
85  *  convert                                           F64->S32
86  *  quantize                   S32                      S32
87  *  pack                       S32          F64         S32       F64
88  *
89  *
90  *  interleave
91  *  deinterleave
92  *  resample
93  */
94 struct _GstAudioConverter
95 {
96   GstAudioInfo in;
97   GstAudioInfo out;
98
99   GstStructure *config;
100
101   GstAudioConverterFlags flags;
102   GstAudioFormat current_format;
103   GstAudioLayout current_layout;
104   gint current_channels;
105
106   gboolean in_writable;
107   gpointer *in_data;
108   gsize in_frames;
109   gpointer *out_data;
110   gsize out_frames;
111
112   gboolean in_place;            /* the conversion can be done in place; returned by gst_audio_converter_supports_inplace() */
113
114   gboolean passthrough;
115
116   /* unpack */
117   gboolean in_default;
118   gboolean unpack_ip;
119
120   /* convert in */
121   AudioConvertFunc convert_in;
122
123   /* channel mix */
124   gboolean mix_passthrough;
125   GstAudioChannelMixer *mix;
126
127   /* resample */
128   GstAudioResampler *resampler;
129
130   /* convert out */
131   AudioConvertFunc convert_out;
132
133   /* quant */
134   GstAudioQuantize *quant;
135
136   /* change layout */
137   GstAudioFormat chlayout_format;
138   GstAudioLayout chlayout_target;
139   gint chlayout_channels;
140
141   /* pack */
142   gboolean out_default;
143   AudioChain *chain_end;        /* NULL for empty chain or points to the last element in the chain */
144
145   /* endian swap */
146   AudioConvertEndianFunc swap_endian;
147
148   AudioConvertSamplesFunc convert;
149 };
150
151 static GstAudioConverter *
152 gst_audio_converter_copy (GstAudioConverter * convert)
153 {
154   GstAudioConverter *res =
155       gst_audio_converter_new (convert->flags, &convert->in, &convert->out,
156       convert->config);
157
158   return res;
159 }
160
161 G_DEFINE_BOXED_TYPE (GstAudioConverter, gst_audio_converter,
162     (GBoxedCopyFunc) gst_audio_converter_copy,
163     (GBoxedFreeFunc) gst_audio_converter_free);
164
165 typedef gboolean (*AudioChainFunc) (AudioChain * chain, gpointer user_data);
166 typedef gpointer *(*AudioChainAllocFunc) (AudioChain * chain, gsize num_samples,
167     gpointer user_data);
168
169 struct _AudioChain
170 {
171   AudioChain *prev;
172
173   AudioChainFunc make_func;
174   gpointer make_func_data;
175   GDestroyNotify make_func_notify;
176
177   const GstAudioFormatInfo *finfo;
178   gint stride;
179   gint inc;
180   gint blocks;
181
182   gboolean pass_alloc;
183   gboolean allow_ip;
184
185   AudioChainAllocFunc alloc_func;
186   gpointer alloc_data;
187
188   gpointer *tmp;
189   gsize allocated_samples;
190
191   gpointer *samples;
192   gsize num_samples;
193 };
194
195 static AudioChain *
196 audio_chain_new (AudioChain * prev, GstAudioConverter * convert)
197 {
198   AudioChain *chain;
199
200   chain = g_slice_new0 (AudioChain);
201   chain->prev = prev;
202
203   if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
204     chain->inc = 1;
205     chain->blocks = convert->current_channels;
206   } else {
207     chain->inc = convert->current_channels;
208     chain->blocks = 1;
209   }
210   chain->finfo = gst_audio_format_get_info (convert->current_format);
211   chain->stride = (chain->finfo->width * chain->inc) / 8;
212
213   return chain;
214 }
215
216 static void
217 audio_chain_set_make_func (AudioChain * chain,
218     AudioChainFunc make_func, gpointer user_data, GDestroyNotify notify)
219 {
220   chain->make_func = make_func;
221   chain->make_func_data = user_data;
222   chain->make_func_notify = notify;
223 }
224
225 static void
226 audio_chain_free (AudioChain * chain)
227 {
228   GST_LOG ("free chain %p", chain);
229   if (chain->make_func_notify)
230     chain->make_func_notify (chain->make_func_data);
231   g_free (chain->tmp);
232   g_slice_free (AudioChain, chain);
233 }
234
235 static gpointer *
236 audio_chain_alloc_samples (AudioChain * chain, gsize num_samples)
237 {
238   return chain->alloc_func (chain, num_samples, chain->alloc_data);
239 }
240
241 static void
242 audio_chain_set_samples (AudioChain * chain, gpointer * samples,
243     gsize num_samples)
244 {
245   GST_LOG ("set samples %p %" G_GSIZE_FORMAT, samples, num_samples);
246
247   chain->samples = samples;
248   chain->num_samples = num_samples;
249 }
250
251 static gpointer *
252 audio_chain_get_samples (AudioChain * chain, gsize * avail)
253 {
254   gpointer *res;
255
256   if (!chain->samples)
257     chain->make_func (chain, chain->make_func_data);
258
259   res = chain->samples;
260   *avail = chain->num_samples;
261   chain->samples = NULL;
262
263   return res;
264 }
265
266 static guint
267 get_opt_uint (GstAudioConverter * convert, const gchar * opt, guint def)
268 {
269   guint res;
270   if (!gst_structure_get_uint (convert->config, opt, &res))
271     res = def;
272   return res;
273 }
274
275 static gint
276 get_opt_enum (GstAudioConverter * convert, const gchar * opt, GType type,
277     gint def)
278 {
279   gint res;
280   if (!gst_structure_get_enum (convert->config, opt, type, &res))
281     res = def;
282   return res;
283 }
284
285 static const GValue *
286 get_opt_value (GstAudioConverter * convert, const gchar * opt)
287 {
288   return gst_structure_get_value (convert->config, opt);
289 }
290
291 #define DEFAULT_OPT_RESAMPLER_METHOD GST_AUDIO_RESAMPLER_METHOD_BLACKMAN_NUTTALL
292 #define DEFAULT_OPT_DITHER_METHOD GST_AUDIO_DITHER_NONE
293 #define DEFAULT_OPT_DITHER_THRESHOLD 20
294 #define DEFAULT_OPT_NOISE_SHAPING_METHOD GST_AUDIO_NOISE_SHAPING_NONE
295 #define DEFAULT_OPT_QUANTIZATION 1
296
297 #define GET_OPT_RESAMPLER_METHOD(c) get_opt_enum(c, \
298     GST_AUDIO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_AUDIO_RESAMPLER_METHOD, \
299     DEFAULT_OPT_RESAMPLER_METHOD)
300 #define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \
301     GST_AUDIO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_AUDIO_DITHER_METHOD, \
302     DEFAULT_OPT_DITHER_METHOD)
303 #define GET_OPT_DITHER_THRESHOLD(c) get_opt_uint(c, \
304     GST_AUDIO_CONVERTER_OPT_DITHER_THRESHOLD, DEFAULT_OPT_DITHER_THRESHOLD)
305 #define GET_OPT_NOISE_SHAPING_METHOD(c) get_opt_enum(c, \
306     GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, \
307     DEFAULT_OPT_NOISE_SHAPING_METHOD)
308 #define GET_OPT_QUANTIZATION(c) get_opt_uint(c, \
309     GST_AUDIO_CONVERTER_OPT_QUANTIZATION, DEFAULT_OPT_QUANTIZATION)
310 #define GET_OPT_MIX_MATRIX(c) get_opt_value(c, \
311     GST_AUDIO_CONVERTER_OPT_MIX_MATRIX)
312
313 static gboolean
314 copy_config (GQuark field_id, const GValue * value, gpointer user_data)
315 {
316   GstAudioConverter *convert = user_data;
317
318   gst_structure_id_set_value (convert->config, field_id, value);
319
320   return TRUE;
321 }
322
323 /**
324  * gst_audio_converter_update_config:
325  * @convert: a #GstAudioConverter
326  * @in_rate: input rate
327  * @out_rate: output rate
328  * @config: (transfer full) (allow-none): a #GstStructure or %NULL
329  *
330  * Set @in_rate, @out_rate and @config as extra configuration for @convert.
331  *
332  * @in_rate and @out_rate specify the new sample rates of input and output
333  * formats. A value of 0 leaves the sample rate unchanged.
334  *
335  * @config can be %NULL, in which case, the current configuration is not
336  * changed.
337  *
338  * If the parameters in @config can not be set exactly, this function returns
339  * %FALSE and will try to update as much state as possible. The new state can
340  * then be retrieved and refined with gst_audio_converter_get_config().
341  *
342  * Look at the `GST_AUDIO_CONVERTER_OPT_*` fields to check valid configuration
343  * option and values.
344  *
345  * Returns: %TRUE when the new parameters could be set
346  */
347 gboolean
348 gst_audio_converter_update_config (GstAudioConverter * convert,
349     gint in_rate, gint out_rate, GstStructure * config)
350 {
351   g_return_val_if_fail (convert != NULL, FALSE);
352   g_return_val_if_fail ((in_rate == 0 && out_rate == 0) ||
353       convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE, FALSE);
354
355   GST_LOG ("new rate %d -> %d", in_rate, out_rate);
356
357   if (in_rate <= 0)
358     in_rate = convert->in.rate;
359   if (out_rate <= 0)
360     out_rate = convert->out.rate;
361
362   convert->in.rate = in_rate;
363   convert->out.rate = out_rate;
364
365   if (convert->resampler)
366     gst_audio_resampler_update (convert->resampler, in_rate, out_rate, config);
367
368   if (config) {
369     gst_structure_foreach (config, copy_config, convert);
370     gst_structure_free (config);
371   }
372
373   return TRUE;
374 }
375
376 /**
377  * gst_audio_converter_get_config:
378  * @convert: a #GstAudioConverter
379  * @in_rate: (out) (optional): result input rate
380  * @out_rate: (out) (optional): result output rate
381  *
382  * Get the current configuration of @convert.
383  *
384  * Returns: (transfer none):
385  *   a #GstStructure that remains valid for as long as @convert is valid
386  *   or until gst_audio_converter_update_config() is called.
387  */
388 const GstStructure *
389 gst_audio_converter_get_config (GstAudioConverter * convert,
390     gint * in_rate, gint * out_rate)
391 {
392   g_return_val_if_fail (convert != NULL, NULL);
393
394   if (in_rate)
395     *in_rate = convert->in.rate;
396   if (out_rate)
397     *out_rate = convert->out.rate;
398
399   return convert->config;
400 }
401
402 static gpointer *
403 get_output_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
404 {
405   GstAudioConverter *convert = user_data;
406
407   GST_LOG ("output samples %p %" G_GSIZE_FORMAT, convert->out_data,
408       num_samples);
409
410   return convert->out_data;
411 }
412
413 #define MEM_ALIGN(m,a) ((gint8 *)((guintptr)((gint8 *)(m) + ((a)-1)) & ~((a)-1)))
414 #define ALIGN 16
415
416 static gpointer *
417 get_temp_samples (AudioChain * chain, gsize num_samples, gpointer user_data)
418 {
419   if (num_samples > chain->allocated_samples) {
420     gint i;
421     gint8 *s;
422     gsize stride = GST_ROUND_UP_N (num_samples * chain->stride, ALIGN);
423     /* first part contains the pointers, second part the data, add some extra bytes
424      * for alignment */
425     gsize needed = (stride + sizeof (gpointer)) * chain->blocks + ALIGN - 1;
426
427     GST_DEBUG ("alloc samples %d %" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT,
428         chain->stride, num_samples, needed);
429     chain->tmp = g_realloc (chain->tmp, needed);
430     chain->allocated_samples = num_samples;
431
432     /* pointer to the data, make sure it's 16 bytes aligned */
433     s = MEM_ALIGN (&chain->tmp[chain->blocks], ALIGN);
434
435     /* set up the pointers */
436     for (i = 0; i < chain->blocks; i++)
437       chain->tmp[i] = s + i * stride;
438   }
439   GST_LOG ("temp samples %p %" G_GSIZE_FORMAT, chain->tmp, num_samples);
440
441   return chain->tmp;
442 }
443
444 static gboolean
445 do_unpack (AudioChain * chain, gpointer user_data)
446 {
447   GstAudioConverter *convert = user_data;
448   gsize num_samples;
449   gpointer *tmp;
450   gboolean in_writable;
451
452   in_writable = convert->in_writable;
453   num_samples = convert->in_frames;
454
455   if (!chain->allow_ip || !in_writable || !convert->in_default) {
456     gint i;
457
458     if (in_writable && chain->allow_ip) {
459       tmp = convert->in_data;
460       GST_LOG ("unpack in-place %p, %" G_GSIZE_FORMAT, tmp, num_samples);
461     } else {
462       tmp = audio_chain_alloc_samples (chain, num_samples);
463       GST_LOG ("unpack to tmp %p, %" G_GSIZE_FORMAT, tmp, num_samples);
464     }
465
466     if (convert->in_data) {
467       for (i = 0; i < chain->blocks; i++) {
468         if (convert->in_default) {
469           GST_LOG ("copy %p, %p, %" G_GSIZE_FORMAT, tmp[i], convert->in_data[i],
470               num_samples);
471           memcpy (tmp[i], convert->in_data[i], num_samples * chain->stride);
472         } else {
473           GST_LOG ("unpack %p, %p, %" G_GSIZE_FORMAT, tmp[i],
474               convert->in_data[i], num_samples);
475           convert->in.finfo->unpack_func (convert->in.finfo,
476               GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE, tmp[i], convert->in_data[i],
477               num_samples * chain->inc);
478         }
479       }
480     } else {
481       for (i = 0; i < chain->blocks; i++) {
482         gst_audio_format_info_fill_silence (chain->finfo, tmp[i],
483             num_samples * chain->inc);
484       }
485     }
486   } else {
487     tmp = convert->in_data;
488     GST_LOG ("get in samples %p", tmp);
489   }
490   audio_chain_set_samples (chain, tmp, num_samples);
491
492   return TRUE;
493 }
494
495 static gboolean
496 do_convert_in (AudioChain * chain, gpointer user_data)
497 {
498   gsize num_samples;
499   GstAudioConverter *convert = user_data;
500   gpointer *in, *out;
501   gint i;
502
503   in = audio_chain_get_samples (chain->prev, &num_samples);
504   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
505   GST_LOG ("convert in %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
506
507   for (i = 0; i < chain->blocks; i++)
508     convert->convert_in (out[i], in[i], num_samples * chain->inc);
509
510   audio_chain_set_samples (chain, out, num_samples);
511
512   return TRUE;
513 }
514
515 static gboolean
516 do_mix (AudioChain * chain, gpointer user_data)
517 {
518   gsize num_samples;
519   GstAudioConverter *convert = user_data;
520   gpointer *in, *out;
521
522   in = audio_chain_get_samples (chain->prev, &num_samples);
523   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
524   GST_LOG ("mix %p, %p, %" G_GSIZE_FORMAT, in, out, num_samples);
525
526   gst_audio_channel_mixer_samples (convert->mix, in, out, num_samples);
527
528   audio_chain_set_samples (chain, out, num_samples);
529
530   return TRUE;
531 }
532
533 static gboolean
534 do_resample (AudioChain * chain, gpointer user_data)
535 {
536   GstAudioConverter *convert = user_data;
537   gpointer *in, *out;
538   gsize in_frames, out_frames;
539
540   in = audio_chain_get_samples (chain->prev, &in_frames);
541   out_frames = convert->out_frames;
542   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, out_frames));
543
544   GST_LOG ("resample %p %p,%" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT, in,
545       out, in_frames, out_frames);
546
547   gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
548       out_frames);
549
550   audio_chain_set_samples (chain, out, out_frames);
551
552   return TRUE;
553 }
554
555 static gboolean
556 do_convert_out (AudioChain * chain, gpointer user_data)
557 {
558   GstAudioConverter *convert = user_data;
559   gsize num_samples;
560   gpointer *in, *out;
561   gint i;
562
563   in = audio_chain_get_samples (chain->prev, &num_samples);
564   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
565   GST_LOG ("convert out %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
566
567   for (i = 0; i < chain->blocks; i++)
568     convert->convert_out (out[i], in[i], num_samples * chain->inc);
569
570   audio_chain_set_samples (chain, out, num_samples);
571
572   return TRUE;
573 }
574
575 static gboolean
576 do_quantize (AudioChain * chain, gpointer user_data)
577 {
578   GstAudioConverter *convert = user_data;
579   gsize num_samples;
580   gpointer *in, *out;
581
582   in = audio_chain_get_samples (chain->prev, &num_samples);
583   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
584   GST_LOG ("quantize %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
585
586   if (in && out)
587     gst_audio_quantize_samples (convert->quant, in, out, num_samples);
588
589   audio_chain_set_samples (chain, out, num_samples);
590
591   return TRUE;
592 }
593
594 #define MAKE_INTERLEAVE_FUNC(type) \
595 static inline void \
596 interleave_##type (const type * in[], type * out[], \
597     gsize num_samples, gint channels) \
598 { \
599   gsize s; \
600   gint c; \
601   for (s = 0; s < num_samples; s++) { \
602     for (c = 0; c < channels; c++) { \
603       out[0][s * channels + c] = in[c][s]; \
604     } \
605   } \
606 }
607
608 #define MAKE_DEINTERLEAVE_FUNC(type) \
609 static inline void \
610 deinterleave_##type (const type * in[], type * out[], \
611     gsize num_samples, gint channels) \
612 { \
613   gsize s; \
614   gint c; \
615   for (s = 0; s < num_samples; s++) { \
616     for (c = 0; c < channels; c++) { \
617       out[c][s] = in[0][s * channels + c]; \
618     } \
619   } \
620 }
621
622 MAKE_INTERLEAVE_FUNC (gint16);
623 MAKE_INTERLEAVE_FUNC (gint32);
624 MAKE_INTERLEAVE_FUNC (gfloat);
625 MAKE_INTERLEAVE_FUNC (gdouble);
626 MAKE_DEINTERLEAVE_FUNC (gint16);
627 MAKE_DEINTERLEAVE_FUNC (gint32);
628 MAKE_DEINTERLEAVE_FUNC (gfloat);
629 MAKE_DEINTERLEAVE_FUNC (gdouble);
630
631 static gboolean
632 do_change_layout (AudioChain * chain, gpointer user_data)
633 {
634   GstAudioConverter *convert = user_data;
635   GstAudioFormat format = convert->chlayout_format;
636   GstAudioLayout out_layout = convert->chlayout_target;
637   gint channels = convert->chlayout_channels;
638   gsize num_samples;
639   gpointer *in, *out;
640
641   in = audio_chain_get_samples (chain->prev, &num_samples);
642   out = (chain->allow_ip ? in : audio_chain_alloc_samples (chain, num_samples));
643
644   if (out_layout == GST_AUDIO_LAYOUT_INTERLEAVED) {
645     /* interleave */
646     GST_LOG ("interleaving %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
647     switch (format) {
648       case GST_AUDIO_FORMAT_S16:
649         interleave_gint16 ((const gint16 **) in, (gint16 **) out,
650             num_samples, channels);
651         break;
652       case GST_AUDIO_FORMAT_S32:
653         interleave_gint32 ((const gint32 **) in, (gint32 **) out,
654             num_samples, channels);
655         break;
656       case GST_AUDIO_FORMAT_F32:
657         interleave_gfloat ((const gfloat **) in, (gfloat **) out,
658             num_samples, channels);
659         break;
660       case GST_AUDIO_FORMAT_F64:
661         interleave_gdouble ((const gdouble **) in, (gdouble **) out,
662             num_samples, channels);
663         break;
664       default:
665         g_assert_not_reached ();
666         break;
667     }
668   } else {
669     /* deinterleave */
670     GST_LOG ("deinterleaving %p, %p %" G_GSIZE_FORMAT, in, out, num_samples);
671     switch (format) {
672       case GST_AUDIO_FORMAT_S16:
673         deinterleave_gint16 ((const gint16 **) in, (gint16 **) out,
674             num_samples, channels);
675         break;
676       case GST_AUDIO_FORMAT_S32:
677         deinterleave_gint32 ((const gint32 **) in, (gint32 **) out,
678             num_samples, channels);
679         break;
680       case GST_AUDIO_FORMAT_F32:
681         deinterleave_gfloat ((const gfloat **) in, (gfloat **) out,
682             num_samples, channels);
683         break;
684       case GST_AUDIO_FORMAT_F64:
685         deinterleave_gdouble ((const gdouble **) in, (gdouble **) out,
686             num_samples, channels);
687         break;
688       default:
689         g_assert_not_reached ();
690         break;
691     }
692   }
693
694   audio_chain_set_samples (chain, out, num_samples);
695   return TRUE;
696 }
697
698 static gboolean
699 is_intermediate_format (GstAudioFormat format)
700 {
701   return (format == GST_AUDIO_FORMAT_S16 ||
702       format == GST_AUDIO_FORMAT_S32 ||
703       format == GST_AUDIO_FORMAT_F32 || format == GST_AUDIO_FORMAT_F64);
704 }
705
706 static AudioChain *
707 chain_unpack (GstAudioConverter * convert)
708 {
709   AudioChain *prev;
710   GstAudioInfo *in = &convert->in;
711   GstAudioInfo *out = &convert->out;
712   gboolean same_format;
713
714   same_format = in->finfo->format == out->finfo->format;
715
716   /* do not unpack if we have the same input format as the output format
717    * and it is a possible intermediate format */
718   if (same_format && is_intermediate_format (in->finfo->format)) {
719     convert->current_format = in->finfo->format;
720   } else {
721     convert->current_format = in->finfo->unpack_format;
722   }
723   convert->current_layout = in->layout;
724   convert->current_channels = in->channels;
725
726   convert->in_default = convert->current_format == in->finfo->format;
727
728   GST_INFO ("unpack format %s to %s",
729       gst_audio_format_to_string (in->finfo->format),
730       gst_audio_format_to_string (convert->current_format));
731
732   prev = audio_chain_new (NULL, convert);
733   prev->allow_ip = prev->finfo->width <= in->finfo->width;
734   prev->pass_alloc = FALSE;
735   audio_chain_set_make_func (prev, do_unpack, convert, NULL);
736
737   return prev;
738 }
739
740 static AudioChain *
741 chain_convert_in (GstAudioConverter * convert, AudioChain * prev)
742 {
743   gboolean in_int, out_int;
744   GstAudioInfo *in = &convert->in;
745   GstAudioInfo *out = &convert->out;
746
747   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
748   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
749
750   if (in_int && !out_int) {
751     GST_INFO ("convert S32 to F64");
752     convert->convert_in = (AudioConvertFunc) audio_orc_s32_to_double;
753     convert->current_format = GST_AUDIO_FORMAT_F64;
754
755     prev = audio_chain_new (prev, convert);
756     prev->allow_ip = FALSE;
757     prev->pass_alloc = FALSE;
758     audio_chain_set_make_func (prev, do_convert_in, convert, NULL);
759   }
760   return prev;
761 }
762
763 static gboolean
764 check_mix_matrix (guint in_channels, guint out_channels, const GValue * value)
765 {
766   guint i, j;
767
768   /* audio-channel-mixer will generate an identity matrix */
769   if (gst_value_array_get_size (value) == 0)
770     return TRUE;
771
772   if (gst_value_array_get_size (value) != out_channels) {
773     GST_ERROR ("Invalid mix matrix size, should be %d", out_channels);
774     goto fail;
775   }
776
777   for (j = 0; j < out_channels; j++) {
778     const GValue *row = gst_value_array_get_value (value, j);
779
780     if (gst_value_array_get_size (row) != in_channels) {
781       GST_ERROR ("Invalid mix matrix row size, should be %d", in_channels);
782       goto fail;
783     }
784
785     for (i = 0; i < in_channels; i++) {
786       const GValue *itm;
787
788       itm = gst_value_array_get_value (row, i);
789       if (!G_VALUE_HOLDS_FLOAT (itm)) {
790         GST_ERROR ("Invalid mix matrix element type, should be float");
791         goto fail;
792       }
793     }
794   }
795
796   return TRUE;
797
798 fail:
799   return FALSE;
800 }
801
802 static gfloat **
803 mix_matrix_from_g_value (guint in_channels, guint out_channels,
804     const GValue * value)
805 {
806   guint i, j;
807   gfloat **matrix = g_new (gfloat *, in_channels);
808
809   for (i = 0; i < in_channels; i++)
810     matrix[i] = g_new (gfloat, out_channels);
811
812   for (j = 0; j < out_channels; j++) {
813     const GValue *row = gst_value_array_get_value (value, j);
814
815     for (i = 0; i < in_channels; i++) {
816       const GValue *itm;
817       gfloat coefficient;
818
819       itm = gst_value_array_get_value (row, i);
820       coefficient = g_value_get_float (itm);
821       matrix[i][j] = coefficient;
822     }
823   }
824
825   return matrix;
826 }
827
828 static AudioChain *
829 chain_mix (GstAudioConverter * convert, AudioChain * prev)
830 {
831   GstAudioInfo *in = &convert->in;
832   GstAudioInfo *out = &convert->out;
833   GstAudioFormat format = convert->current_format;
834   const GValue *opt_matrix = GET_OPT_MIX_MATRIX (convert);
835   GstAudioChannelMixerFlags flags = 0;
836
837   convert->current_channels = out->channels;
838
839   /* keep the input layout */
840   if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
841     flags |= GST_AUDIO_CHANNEL_MIXER_FLAGS_NON_INTERLEAVED_IN;
842     flags |= GST_AUDIO_CHANNEL_MIXER_FLAGS_NON_INTERLEAVED_OUT;
843   }
844
845   if (opt_matrix) {
846     gfloat **matrix = NULL;
847
848     if (gst_value_array_get_size (opt_matrix))
849       matrix =
850           mix_matrix_from_g_value (in->channels, out->channels, opt_matrix);
851
852     convert->mix =
853         gst_audio_channel_mixer_new_with_matrix (flags, format, in->channels,
854         out->channels, matrix);
855   } else {
856     flags |=
857         GST_AUDIO_INFO_IS_UNPOSITIONED (in) ?
858         GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_IN : 0;
859     flags |=
860         GST_AUDIO_INFO_IS_UNPOSITIONED (out) ?
861         GST_AUDIO_CHANNEL_MIXER_FLAGS_UNPOSITIONED_OUT : 0;
862
863     convert->mix =
864         gst_audio_channel_mixer_new (flags, format, in->channels, in->position,
865         out->channels, out->position);
866   }
867
868   convert->mix_passthrough =
869       gst_audio_channel_mixer_is_passthrough (convert->mix);
870   GST_INFO ("mix format %s, passthrough %d, in_channels %d, out_channels %d",
871       gst_audio_format_to_string (format), convert->mix_passthrough,
872       in->channels, out->channels);
873
874   if (!convert->mix_passthrough) {
875     prev = audio_chain_new (prev, convert);
876     prev->allow_ip = FALSE;
877     prev->pass_alloc = FALSE;
878     audio_chain_set_make_func (prev, do_mix, convert, NULL);
879   }
880   return prev;
881 }
882
883 static AudioChain *
884 chain_resample (GstAudioConverter * convert, AudioChain * prev)
885 {
886   GstAudioInfo *in = &convert->in;
887   GstAudioInfo *out = &convert->out;
888   GstAudioResamplerMethod method;
889   GstAudioResamplerFlags flags;
890   GstAudioFormat format = convert->current_format;
891   gint channels = convert->current_channels;
892   gboolean variable_rate;
893
894   variable_rate = convert->flags & GST_AUDIO_CONVERTER_FLAG_VARIABLE_RATE;
895
896   if (in->rate != out->rate || variable_rate) {
897     method = GET_OPT_RESAMPLER_METHOD (convert);
898
899     flags = 0;
900     if (convert->current_layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
901       flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED_IN;
902     }
903     /* if the resampler is activated, it is optimal to change layout here */
904     if (out->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
905       flags |= GST_AUDIO_RESAMPLER_FLAG_NON_INTERLEAVED_OUT;
906     }
907     convert->current_layout = out->layout;
908
909     if (variable_rate)
910       flags |= GST_AUDIO_RESAMPLER_FLAG_VARIABLE_RATE;
911
912     convert->resampler =
913         gst_audio_resampler_new (method, flags, format, channels, in->rate,
914         out->rate, convert->config);
915
916     prev = audio_chain_new (prev, convert);
917     prev->allow_ip = FALSE;
918     prev->pass_alloc = FALSE;
919     audio_chain_set_make_func (prev, do_resample, convert, NULL);
920   }
921   return prev;
922 }
923
924 static AudioChain *
925 chain_convert_out (GstAudioConverter * convert, AudioChain * prev)
926 {
927   gboolean in_int, out_int;
928   GstAudioInfo *in = &convert->in;
929   GstAudioInfo *out = &convert->out;
930
931   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (in->finfo);
932   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
933
934   if (!in_int && out_int) {
935     convert->convert_out = (AudioConvertFunc) audio_orc_double_to_s32;
936     convert->current_format = GST_AUDIO_FORMAT_S32;
937
938     GST_INFO ("convert F64 to S32");
939     prev = audio_chain_new (prev, convert);
940     prev->allow_ip = TRUE;
941     prev->pass_alloc = FALSE;
942     audio_chain_set_make_func (prev, do_convert_out, convert, NULL);
943   }
944   return prev;
945 }
946
947 static AudioChain *
948 chain_quantize (GstAudioConverter * convert, AudioChain * prev)
949 {
950   const GstAudioFormatInfo *cur_finfo;
951   GstAudioInfo *out = &convert->out;
952   gint in_depth, out_depth;
953   gboolean in_int, out_int;
954   GstAudioDitherMethod dither;
955   guint dither_threshold;
956   GstAudioNoiseShapingMethod ns;
957
958   dither = GET_OPT_DITHER_METHOD (convert);
959   dither_threshold = GET_OPT_DITHER_THRESHOLD (convert);
960   ns = GET_OPT_NOISE_SHAPING_METHOD (convert);
961
962   cur_finfo = gst_audio_format_get_info (convert->current_format);
963
964   in_depth = GST_AUDIO_FORMAT_INFO_DEPTH (cur_finfo);
965   out_depth = GST_AUDIO_FORMAT_INFO_DEPTH (out->finfo);
966   GST_INFO ("depth in %d, out %d", in_depth, out_depth);
967
968   in_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (cur_finfo);
969   out_int = GST_AUDIO_FORMAT_INFO_IS_INTEGER (out->finfo);
970
971   /* Don't dither or apply noise shaping if target depth is bigger than 20 bits
972    * as DA converters only can do a SNR up to 20 bits in reality.
973    * Also don't dither or apply noise shaping if target depth is larger than
974    * source depth. */
975   if (out_depth > dither_threshold || (in_int && out_depth >= in_depth)) {
976     dither = GST_AUDIO_DITHER_NONE;
977     ns = GST_AUDIO_NOISE_SHAPING_NONE;
978     GST_INFO ("using no dither and noise shaping");
979   } else {
980     GST_INFO ("using dither %d and noise shaping %d", dither, ns);
981     /* Use simple error feedback when output sample rate is smaller than
982      * 32000 as the other methods might move the noise to audible ranges */
983     if (ns > GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK && out->rate < 32000)
984       ns = GST_AUDIO_NOISE_SHAPING_ERROR_FEEDBACK;
985   }
986   /* we still want to run the quantization step when reducing bits to get
987    * the rounding correct */
988   if (out_int && out_depth < 32
989       && convert->current_format == GST_AUDIO_FORMAT_S32) {
990     GST_INFO ("quantize to %d bits, dither %d, ns %d", out_depth, dither, ns);
991     convert->quant =
992         gst_audio_quantize_new (dither, ns, 0, convert->current_format,
993         out->channels, 1U << (32 - out_depth));
994
995     prev = audio_chain_new (prev, convert);
996     prev->allow_ip = TRUE;
997     prev->pass_alloc = TRUE;
998     audio_chain_set_make_func (prev, do_quantize, convert, NULL);
999   }
1000   return prev;
1001 }
1002
1003 static AudioChain *
1004 chain_change_layout (GstAudioConverter * convert, AudioChain * prev)
1005 {
1006   GstAudioInfo *out = &convert->out;
1007
1008   if (convert->current_layout != out->layout) {
1009     convert->current_layout = out->layout;
1010
1011     /* if there is only 1 channel, layouts are identical */
1012     if (convert->current_channels > 1) {
1013       convert->chlayout_target = convert->current_layout;
1014       convert->chlayout_format = convert->current_format;
1015       convert->chlayout_channels = convert->current_channels;
1016
1017       prev = audio_chain_new (prev, convert);
1018       prev->allow_ip = FALSE;
1019       prev->pass_alloc = FALSE;
1020       audio_chain_set_make_func (prev, do_change_layout, convert, NULL);
1021     }
1022   }
1023   return prev;
1024 }
1025
1026 static AudioChain *
1027 chain_pack (GstAudioConverter * convert, AudioChain * prev)
1028 {
1029   GstAudioInfo *out = &convert->out;
1030   GstAudioFormat format = convert->current_format;
1031
1032   convert->current_format = out->finfo->format;
1033
1034   convert->out_default = format == out->finfo->format;
1035   GST_INFO ("pack format %s to %s", gst_audio_format_to_string (format),
1036       gst_audio_format_to_string (out->finfo->format));
1037
1038   return prev;
1039 }
1040
1041 static void
1042 setup_allocators (GstAudioConverter * convert)
1043 {
1044   AudioChain *chain;
1045   AudioChainAllocFunc alloc_func;
1046   gboolean allow_ip;
1047
1048   /* start with using dest if we can directly write into it */
1049   if (convert->out_default) {
1050     alloc_func = get_output_samples;
1051     allow_ip = FALSE;
1052   } else {
1053     alloc_func = get_temp_samples;
1054     allow_ip = TRUE;
1055   }
1056   /* now walk backwards, we try to write into the dest samples directly
1057    * and keep track if the source needs to be writable */
1058   for (chain = convert->chain_end; chain; chain = chain->prev) {
1059     chain->alloc_func = alloc_func;
1060     chain->alloc_data = convert;
1061     chain->allow_ip = allow_ip && chain->allow_ip;
1062     GST_LOG ("chain %p: %d %d", chain, allow_ip, chain->allow_ip);
1063
1064     if (!chain->pass_alloc) {
1065       /* can't pass allocator, make new temp line allocator */
1066       alloc_func = get_temp_samples;
1067       allow_ip = TRUE;
1068     }
1069   }
1070 }
1071
1072 static gboolean
1073 converter_passthrough (GstAudioConverter * convert,
1074     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1075     gpointer out[], gsize out_frames)
1076 {
1077   gint i;
1078   AudioChain *chain;
1079   gsize samples;
1080
1081   /* in-place passthrough -> do nothing */
1082   if (in == out) {
1083     g_assert (convert->in_place);
1084     return TRUE;
1085   }
1086
1087   chain = convert->chain_end;
1088
1089   samples = in_frames * chain->inc;
1090
1091   GST_LOG ("passthrough: %" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " samples",
1092       in_frames, samples);
1093
1094   if (in) {
1095     gsize bytes;
1096
1097     bytes = samples * (convert->in.bpf / convert->in.channels);
1098
1099     for (i = 0; i < chain->blocks; i++) {
1100       if (out[i] == in[i]) {
1101         g_assert (convert->in_place);
1102         continue;
1103       }
1104
1105       memcpy (out[i], in[i], bytes);
1106     }
1107   } else {
1108     for (i = 0; i < chain->blocks; i++)
1109       gst_audio_format_info_fill_silence (convert->in.finfo, out[i], samples);
1110   }
1111   return TRUE;
1112 }
1113
1114 /* perform LE<->BE conversion on a block of @count 16-bit samples
1115  * dst may equal src for in-place conversion
1116  */
1117 static void
1118 converter_swap_endian_16 (gpointer dst, const gpointer src, gint count)
1119 {
1120   guint16 *out = dst;
1121   const guint16 *in = src;
1122   gint i;
1123
1124   for (i = 0; i < count; i++)
1125     out[i] = GUINT16_SWAP_LE_BE (in[i]);
1126 }
1127
1128 /* perform LE<->BE conversion on a block of @count 24-bit samples
1129  * dst may equal src for in-place conversion
1130  *
1131  * naive algorithm, which performs better with -O3 and worse with -O2
1132  * than the commented out optimized algorithm below
1133  */
1134 static void
1135 converter_swap_endian_24 (gpointer dst, const gpointer src, gint count)
1136 {
1137   guint8 *out = dst;
1138   const guint8 *in = src;
1139   gint i;
1140
1141   count *= 3;
1142
1143   for (i = 0; i < count; i += 3) {
1144     guint8 x = in[i + 0];
1145     out[i + 0] = in[i + 2];
1146     out[i + 1] = in[i + 1];
1147     out[i + 2] = x;
1148   }
1149 }
1150
1151 /* the below code performs better with -O2 but worse with -O3 */
1152 #if 0
1153 /* perform LE<->BE conversion on a block of @count 24-bit samples
1154  * dst may equal src for in-place conversion
1155  *
1156  * assumes that dst and src are 32-bit aligned
1157  */
1158 static void
1159 converter_swap_endian_24 (gpointer dst, const gpointer src, gint count)
1160 {
1161   guint32 *out = dst;
1162   const guint32 *in = src;
1163   guint8 *out8;
1164   const guint8 *in8;
1165   gint i;
1166
1167   /* first convert 24-bit samples in multiples of 4 reading 3x 32-bits in one cycle
1168    *
1169    * input:               A1 B1 C1 A2 , B2 C2 A3 B3 , C3 A4 B4 C4
1170    * 32-bit endian swap:  A2 C1 B1 A1 , B3 A3 C2 B2 , C4 B4 A4 C3
1171    *                      <--  x  -->   <--  y  --> , <--  z  -->
1172    *
1173    * desired output:      C1 B1 A1 C2 , B2 A2 C3 B3 , A3 C4 B4 A4
1174    */
1175   for (i = 0; i < count / 4; i++, in += 3, out += 3) {
1176     guint32 x, y, z;
1177
1178     x = GUINT32_SWAP_LE_BE (in[0]);
1179     y = GUINT32_SWAP_LE_BE (in[1]);
1180     z = GUINT32_SWAP_LE_BE (in[2]);
1181
1182 #if G_BYTE_ORDER == G_BIG_ENDIAN
1183     out[0] = (x << 8) + ((y >> 8) & 0xff);
1184     out[1] = (in[1] & 0xff0000ff) + ((x >> 8) & 0xff0000) + ((z << 8) & 0xff00);
1185     out[2] = (z >> 8) + ((y << 8) & 0xff000000);
1186 #else
1187     out[0] = (x >> 8) + ((y << 8) & 0xff000000);
1188     out[1] = (in[1] & 0xff0000ff) + ((x << 8) & 0xff00) + ((z >> 8) & 0xff0000);
1189     out[2] = (z << 8) + ((y >> 8) & 0xff);
1190 #endif
1191   }
1192
1193   /* convert the remainder less efficiently */
1194   for (out8 = (guint8 *) out, in8 = (const guint8 *) in, i = 0; i < (count & 3);
1195       i++) {
1196     guint8 x = in8[i + 0];
1197     out8[i + 0] = in8[i + 2];
1198     out8[i + 1] = in8[i + 1];
1199     out8[i + 2] = x;
1200   }
1201 }
1202 #endif
1203
1204 /* perform LE<->BE conversion on a block of @count 32-bit samples
1205  * dst may equal src for in-place conversion
1206  */
1207 static void
1208 converter_swap_endian_32 (gpointer dst, const gpointer src, gint count)
1209 {
1210   guint32 *out = dst;
1211   const guint32 *in = src;
1212   gint i;
1213
1214   for (i = 0; i < count; i++)
1215     out[i] = GUINT32_SWAP_LE_BE (in[i]);
1216 }
1217
1218 /* perform LE<->BE conversion on a block of @count 64-bit samples
1219  * dst may equal src for in-place conversion
1220  */
1221 static void
1222 converter_swap_endian_64 (gpointer dst, const gpointer src, gint count)
1223 {
1224   guint64 *out = dst;
1225   const guint64 *in = src;
1226   gint i;
1227
1228   for (i = 0; i < count; i++)
1229     out[i] = GUINT64_SWAP_LE_BE (in[i]);
1230 }
1231
1232 /* the worker function to perform endian-conversion only
1233  * assuming finfo and foutinfo have the same depth
1234  */
1235 static gboolean
1236 converter_endian (GstAudioConverter * convert,
1237     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1238     gpointer out[], gsize out_frames)
1239 {
1240   gint i;
1241   AudioChain *chain;
1242   gsize samples;
1243
1244   chain = convert->chain_end;
1245   samples = in_frames * chain->inc;
1246
1247   GST_LOG ("convert endian: %" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT " samples",
1248       in_frames, samples);
1249
1250   if (in) {
1251     for (i = 0; i < chain->blocks; i++)
1252       convert->swap_endian (out[i], in[i], samples);
1253   } else {
1254     for (i = 0; i < chain->blocks; i++)
1255       gst_audio_format_info_fill_silence (convert->in.finfo, out[i], samples);
1256   }
1257   return TRUE;
1258 }
1259
1260 static gboolean
1261 converter_generic (GstAudioConverter * convert,
1262     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1263     gpointer out[], gsize out_frames)
1264 {
1265   AudioChain *chain;
1266   gpointer *tmp;
1267   gint i;
1268   gsize produced;
1269
1270   chain = convert->chain_end;
1271
1272   convert->in_writable = flags & GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE;
1273   convert->in_data = in;
1274   convert->in_frames = in_frames;
1275   convert->out_data = out;
1276   convert->out_frames = out_frames;
1277
1278   /* get frames to pack */
1279   tmp = audio_chain_get_samples (chain, &produced);
1280
1281   if (!convert->out_default && tmp && out) {
1282     GST_LOG ("pack %p, %p %" G_GSIZE_FORMAT, tmp, out, produced);
1283     /* and pack if needed */
1284     for (i = 0; i < chain->blocks; i++)
1285       convert->out.finfo->pack_func (convert->out.finfo, 0, tmp[i], out[i],
1286           produced * chain->inc);
1287   }
1288   return TRUE;
1289 }
1290
1291 static gboolean
1292 converter_resample (GstAudioConverter * convert,
1293     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1294     gpointer out[], gsize out_frames)
1295 {
1296   gst_audio_resampler_resample (convert->resampler, in, in_frames, out,
1297       out_frames);
1298
1299   return TRUE;
1300 }
1301
1302 #define GST_AUDIO_FORMAT_IS_ENDIAN_CONVERSION(info1, info2) \
1303                 ( \
1304                         !(((info1)->flags ^ (info2)->flags) & (~GST_AUDIO_FORMAT_FLAG_UNPACK)) && \
1305                         (info1)->endianness != (info2)->endianness && \
1306                         (info1)->width == (info2)->width && \
1307                         (info1)->depth == (info2)->depth \
1308                 )
1309
1310 /**
1311  * gst_audio_converter_new:
1312  * @flags: extra #GstAudioConverterFlags
1313  * @in_info: a source #GstAudioInfo
1314  * @out_info: a destination #GstAudioInfo
1315  * @config: (transfer full) (nullable): a #GstStructure with configuration options
1316  *
1317  * Create a new #GstAudioConverter that is able to convert between @in and @out
1318  * audio formats.
1319  *
1320  * @config contains extra configuration options, see `GST_AUDIO_CONVERTER_OPT_*`
1321  * parameters for details about the options and values.
1322  *
1323  * Returns: (nullable): a #GstAudioConverter or %NULL if conversion is not possible.
1324  */
1325 GstAudioConverter *
1326 gst_audio_converter_new (GstAudioConverterFlags flags, GstAudioInfo * in_info,
1327     GstAudioInfo * out_info, GstStructure * config)
1328 {
1329   GstAudioConverter *convert;
1330   AudioChain *prev;
1331   const GValue *opt_matrix = NULL;
1332
1333   g_return_val_if_fail (in_info != NULL, FALSE);
1334   g_return_val_if_fail (out_info != NULL, FALSE);
1335
1336   if (config)
1337     opt_matrix =
1338         gst_structure_get_value (config, GST_AUDIO_CONVERTER_OPT_MIX_MATRIX);
1339
1340   if (opt_matrix
1341       && !check_mix_matrix (in_info->channels, out_info->channels, opt_matrix))
1342     goto invalid_mix_matrix;
1343
1344   if ((GST_AUDIO_INFO_CHANNELS (in_info) != GST_AUDIO_INFO_CHANNELS (out_info))
1345       && (GST_AUDIO_INFO_IS_UNPOSITIONED (in_info)
1346           || GST_AUDIO_INFO_IS_UNPOSITIONED (out_info))
1347       && !opt_matrix)
1348     goto unpositioned;
1349
1350   convert = g_slice_new0 (GstAudioConverter);
1351
1352   convert->flags = flags;
1353   convert->in = *in_info;
1354   convert->out = *out_info;
1355
1356   /* default config */
1357   convert->config = gst_structure_new_empty ("GstAudioConverter");
1358   if (config)
1359     gst_audio_converter_update_config (convert, 0, 0, config);
1360
1361   GST_INFO ("unitsizes: %d -> %d", in_info->bpf, out_info->bpf);
1362
1363   /* step 1, unpack */
1364   prev = chain_unpack (convert);
1365   /* step 2, optional convert from S32 to F64 for channel mix */
1366   prev = chain_convert_in (convert, prev);
1367   /* step 3, channel mix */
1368   prev = chain_mix (convert, prev);
1369   /* step 4, resample */
1370   prev = chain_resample (convert, prev);
1371   /* step 5, optional convert for quantize */
1372   prev = chain_convert_out (convert, prev);
1373   /* step 6, optional quantize */
1374   prev = chain_quantize (convert, prev);
1375   /* step 7, change layout */
1376   prev = chain_change_layout (convert, prev);
1377   /* step 8, pack */
1378   convert->chain_end = chain_pack (convert, prev);
1379
1380   convert->convert = converter_generic;
1381   convert->in_place = FALSE;
1382   convert->passthrough = FALSE;
1383
1384   /* optimize */
1385   if (convert->mix_passthrough) {
1386     if (out_info->finfo->format == in_info->finfo->format) {
1387       if (convert->resampler == NULL) {
1388         if (out_info->layout == in_info->layout) {
1389           GST_INFO ("same formats, same layout, no resampler and "
1390               "passthrough mixing -> passthrough");
1391           convert->convert = converter_passthrough;
1392           convert->in_place = TRUE;
1393           convert->passthrough = TRUE;
1394         }
1395       } else {
1396         if (is_intermediate_format (in_info->finfo->format)) {
1397           GST_INFO ("same formats, and passthrough mixing -> only resampling");
1398           convert->convert = converter_resample;
1399         }
1400       }
1401     } else if (GST_AUDIO_FORMAT_IS_ENDIAN_CONVERSION (out_info->finfo,
1402             in_info->finfo)) {
1403       if (convert->resampler == NULL && out_info->layout == in_info->layout) {
1404         GST_INFO ("no resampler, passthrough mixing -> only endian conversion");
1405         convert->convert = converter_endian;
1406         convert->in_place = TRUE;
1407
1408         switch (GST_AUDIO_INFO_WIDTH (in_info)) {
1409           case 16:
1410             GST_DEBUG ("initializing 16-bit endian conversion");
1411             convert->swap_endian = converter_swap_endian_16;
1412             break;
1413           case 24:
1414             GST_DEBUG ("initializing 24-bit endian conversion");
1415             convert->swap_endian = converter_swap_endian_24;
1416             break;
1417           case 32:
1418             GST_DEBUG ("initializing 32-bit endian conversion");
1419             convert->swap_endian = converter_swap_endian_32;
1420             break;
1421           case 64:
1422             GST_DEBUG ("initializing 64-bit endian conversion");
1423             convert->swap_endian = converter_swap_endian_64;
1424             break;
1425           default:
1426             GST_ERROR ("unsupported sample width for endian conversion");
1427             g_assert_not_reached ();
1428         }
1429       }
1430     }
1431   }
1432
1433   setup_allocators (convert);
1434
1435   return convert;
1436
1437   /* ERRORS */
1438 unpositioned:
1439   {
1440     GST_WARNING ("unpositioned channels");
1441     g_clear_pointer (&config, gst_structure_free);
1442     return NULL;
1443   }
1444
1445 invalid_mix_matrix:
1446   {
1447     GST_WARNING ("Invalid mix matrix");
1448     g_clear_pointer (&config, gst_structure_free);
1449     return NULL;
1450   }
1451 }
1452
1453 /**
1454  * gst_audio_converter_free:
1455  * @convert: a #GstAudioConverter
1456  *
1457  * Free a previously allocated @convert instance.
1458  */
1459 void
1460 gst_audio_converter_free (GstAudioConverter * convert)
1461 {
1462   AudioChain *chain;
1463
1464   g_return_if_fail (convert != NULL);
1465
1466   /* walk the chain backwards and free all elements */
1467   for (chain = convert->chain_end; chain;) {
1468     AudioChain *prev = chain->prev;
1469     audio_chain_free (chain);
1470     chain = prev;
1471   }
1472
1473   if (convert->quant)
1474     gst_audio_quantize_free (convert->quant);
1475   if (convert->mix)
1476     gst_audio_channel_mixer_free (convert->mix);
1477   if (convert->resampler)
1478     gst_audio_resampler_free (convert->resampler);
1479   gst_audio_info_init (&convert->in);
1480   gst_audio_info_init (&convert->out);
1481
1482   gst_structure_free (convert->config);
1483
1484   g_slice_free (GstAudioConverter, convert);
1485 }
1486
1487 /**
1488  * gst_audio_converter_get_out_frames:
1489  * @convert: a #GstAudioConverter
1490  * @in_frames: number of input frames
1491  *
1492  * Calculate how many output frames can be produced when @in_frames input
1493  * frames are given to @convert.
1494  *
1495  * Returns: the number of output frames
1496  */
1497 gsize
1498 gst_audio_converter_get_out_frames (GstAudioConverter * convert,
1499     gsize in_frames)
1500 {
1501   if (convert->resampler)
1502     return gst_audio_resampler_get_out_frames (convert->resampler, in_frames);
1503   else
1504     return in_frames;
1505 }
1506
1507 /**
1508  * gst_audio_converter_get_in_frames:
1509  * @convert: a #GstAudioConverter
1510  * @out_frames: number of output frames
1511  *
1512  * Calculate how many input frames are currently needed by @convert to produce
1513  * @out_frames of output frames.
1514  *
1515  * Returns: the number of input frames
1516  */
1517 gsize
1518 gst_audio_converter_get_in_frames (GstAudioConverter * convert,
1519     gsize out_frames)
1520 {
1521   if (convert->resampler)
1522     return gst_audio_resampler_get_in_frames (convert->resampler, out_frames);
1523   else
1524     return out_frames;
1525 }
1526
1527 /**
1528  * gst_audio_converter_get_max_latency:
1529  * @convert: a #GstAudioConverter
1530  *
1531  * Get the maximum number of input frames that the converter would
1532  * need before producing output.
1533  *
1534  * Returns: the latency of @convert as expressed in the number of
1535  * frames.
1536  */
1537 gsize
1538 gst_audio_converter_get_max_latency (GstAudioConverter * convert)
1539 {
1540   if (convert->resampler)
1541     return gst_audio_resampler_get_max_latency (convert->resampler);
1542   else
1543     return 0;
1544 }
1545
1546 /**
1547  * gst_audio_converter_reset:
1548  * @convert: a #GstAudioConverter
1549  *
1550  * Reset @convert to the state it was when it was first created, clearing
1551  * any history it might currently have.
1552  */
1553 void
1554 gst_audio_converter_reset (GstAudioConverter * convert)
1555 {
1556   if (convert->resampler)
1557     gst_audio_resampler_reset (convert->resampler);
1558   if (convert->quant)
1559     gst_audio_quantize_reset (convert->quant);
1560 }
1561
1562 /**
1563  * gst_audio_converter_samples:
1564  * @convert: a #GstAudioConverter
1565  * @flags: extra #GstAudioConverterFlags
1566  * @in: input frames
1567  * @in_frames: number of input frames
1568  * @out: output frames
1569  * @out_frames: number of output frames
1570  *
1571  * Perform the conversion with @in_frames in @in to @out_frames in @out
1572  * using @convert.
1573  *
1574  * In case the samples are interleaved, @in and @out must point to an
1575  * array with a single element pointing to a block of interleaved samples.
1576  *
1577  * If non-interleaved samples are used, @in and @out must point to an
1578  * array with pointers to memory blocks, one for each channel.
1579  *
1580  * @in may be %NULL, in which case @in_frames of silence samples are processed
1581  * by the converter.
1582  *
1583  * This function always produces @out_frames of output and consumes @in_frames of
1584  * input. Use gst_audio_converter_get_out_frames() and
1585  * gst_audio_converter_get_in_frames() to make sure @in_frames and @out_frames
1586  * are matching and @in and @out point to enough memory.
1587  *
1588  * Returns: %TRUE is the conversion could be performed.
1589  */
1590 gboolean
1591 gst_audio_converter_samples (GstAudioConverter * convert,
1592     GstAudioConverterFlags flags, gpointer in[], gsize in_frames,
1593     gpointer out[], gsize out_frames)
1594 {
1595   g_return_val_if_fail (convert != NULL, FALSE);
1596   g_return_val_if_fail (out != NULL, FALSE);
1597
1598   if (in_frames == 0) {
1599     GST_LOG ("skipping empty buffer");
1600     return TRUE;
1601   }
1602   return convert->convert (convert, flags, in, in_frames, out, out_frames);
1603 }
1604
1605 /**
1606  * gst_audio_converter_convert:
1607  * @convert: a #GstAudioConverter
1608  * @flags: extra #GstAudioConverterFlags
1609  * @in: (array length=in_size) (element-type guint8): input data
1610  * @in_size: size of @in
1611  * @out: (out) (array length=out_size) (element-type guint8): a pointer where
1612  *  the output data will be written
1613  * @out_size: (out): a pointer where the size of @out will be written
1614  *
1615  * Convenience wrapper around gst_audio_converter_samples(), which will
1616  * perform allocation of the output buffer based on the result from
1617  * gst_audio_converter_get_out_frames().
1618  *
1619  * Returns: %TRUE is the conversion could be performed.
1620  *
1621  * Since: 1.14
1622  */
1623 gboolean
1624 gst_audio_converter_convert (GstAudioConverter * convert,
1625     GstAudioConverterFlags flags, gpointer in, gsize in_size,
1626     gpointer * out, gsize * out_size)
1627 {
1628   gsize in_frames;
1629   gsize out_frames;
1630
1631   g_return_val_if_fail (convert != NULL, FALSE);
1632   g_return_val_if_fail (flags ^ GST_AUDIO_CONVERTER_FLAG_IN_WRITABLE, FALSE);
1633
1634   in_frames = in_size / convert->in.bpf;
1635   out_frames = gst_audio_converter_get_out_frames (convert, in_frames);
1636
1637   *out_size = out_frames * convert->out.bpf;
1638   *out = g_malloc0 (*out_size);
1639
1640   return gst_audio_converter_samples (convert, flags, &in, in_frames, out,
1641       out_frames);
1642 }
1643
1644 /**
1645  * gst_audio_converter_supports_inplace:
1646  * @convert: a #GstAudioConverter
1647  *
1648  * Returns whether the audio converter can perform the conversion in-place.
1649  * The return value would be typically input to gst_base_transform_set_in_place()
1650  *
1651  * Returns: %TRUE when the conversion can be done in place.
1652  *
1653  * Since: 1.12
1654  */
1655 gboolean
1656 gst_audio_converter_supports_inplace (GstAudioConverter * convert)
1657 {
1658   return convert->in_place;
1659 }
1660
1661 /**
1662  * gst_audio_converter_is_passthrough:
1663  *
1664  * Returns whether the audio converter will operate in passthrough mode.
1665  * The return value would be typically input to gst_base_transform_set_passthrough()
1666  *
1667  * Returns: %TRUE when no conversion will actually occur.
1668  *
1669  * Since: 1.16
1670  */
1671 gboolean
1672 gst_audio_converter_is_passthrough (GstAudioConverter * convert)
1673 {
1674   return convert->passthrough;
1675 }