gst/audioconvert/gstaudioconvert.c: Lower debug, use g_assert in _get_unit_size
[platform/upstream/gstreamer.git] / gst / audioconvert / gstaudioconvert.c
1 /* GStreamer
2  * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
3  * Copyright (C) 2005 Thomas Vander Stichele <thomas at apestaart dot org>
4  * Copyright (C) 2005 Wim Taymans <wim at fluendo dot com>
5  *
6  * gstaudioconvert.c: Convert audio to different audio formats automatically
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:element-audioconvert
26  *
27  * <refsect2>
28  * Audioconvert converts raw audio buffers between various possible formats.
29  * It supports integer to float conversion, width/depth conversion,
30  * signedness and endianness conversion.
31  * <title>Example launch line</title>
32  * <para>
33  * <programlisting>
34  * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw-int,channels=2,width=8,depth=8 ! level ! fakesink silent=TRUE
35  * </programlisting>
36  * This pipeline converts audio to 8-bit.  The level element shows that
37  * the output levels still match the one for a sine wave.
38  * </para>
39  * <para>
40  * <programlisting>
41  * gst-launch -v -m audiotestsrc ! audioconvert ! vorbisenc ! fakesink silent=TRUE
42  * </programlisting>
43  * The vorbis encoder takes float audio data instead of the integer data
44  * generated by audiotestsrc.
45  * </para>
46  * </refsect2>
47  *
48  * Last reviewed on 2006-03-02 (0.10.4)
49  */
50
51 /*
52  * design decisions:
53  * - audioconvert converts buffers in a set of supported caps. If it supports
54  *   a caps, it supports conversion from these caps to any other caps it
55  *   supports. (example: if it does A=>B and A=>C, it also does B=>C)
56  * - audioconvert does not save state between buffers. Every incoming buffer is
57  *   converted and the converted buffer is pushed out.
58  * conclusion:
59  * audioconvert is not supposed to be a one-element-does-anything solution for
60  * audio conversions.
61  */
62
63 #ifdef HAVE_CONFIG_H
64 #include "config.h"
65 #endif
66
67 #include <string.h>
68
69 #include "gstaudioconvert.h"
70 #include "gstchannelmix.h"
71 #include "plugin.h"
72
73 GST_DEBUG_CATEGORY (audio_convert_debug);
74
75 /*** DEFINITIONS **************************************************************/
76
77 static const GstElementDetails audio_convert_details =
78 GST_ELEMENT_DETAILS ("Audio converter",
79     "Filter/Converter/Audio",
80     "Convert audio to different formats",
81     "Benjamin Otte <in7y118@public.uni-hamburg.de>");
82
83 /* type functions */
84 static void gst_audio_convert_dispose (GObject * obj);
85
86 /* gstreamer functions */
87 static gboolean gst_audio_convert_get_unit_size (GstBaseTransform * base,
88     GstCaps * caps, guint * size);
89 static GstCaps *gst_audio_convert_transform_caps (GstBaseTransform * base,
90     GstPadDirection direction, GstCaps * caps);
91 static void gst_audio_convert_fixate_caps (GstBaseTransform * base,
92     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
93 static gboolean gst_audio_convert_set_caps (GstBaseTransform * base,
94     GstCaps * incaps, GstCaps * outcaps);
95 static GstFlowReturn gst_audio_convert_transform (GstBaseTransform * base,
96     GstBuffer * inbuf, GstBuffer * outbuf);
97 static GstFlowReturn gst_audio_convert_transform_ip (GstBaseTransform * base,
98     GstBuffer * buf);
99
100 /* AudioConvert signals and args */
101 enum
102 {
103   /* FILL ME */
104   LAST_SIGNAL
105 };
106
107 enum
108 {
109   ARG_0,
110   ARG_AGGRESSIVE
111 };
112
113 #define DEBUG_INIT(bla) \
114   GST_DEBUG_CATEGORY_INIT (audio_convert_debug, "audioconvert", 0, "audio conversion element");
115
116 GST_BOILERPLATE_FULL (GstAudioConvert, gst_audio_convert, GstBaseTransform,
117     GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
118
119 /*** GSTREAMER PROTOTYPES *****************************************************/
120
121 #define STATIC_CAPS \
122 GST_STATIC_CAPS ( \
123   "audio/x-raw-float, " \
124     "rate = (int) [ 1, MAX ], " \
125     "channels = (int) [ 1, 8 ], " \
126     "endianness = (int) BYTE_ORDER, " \
127     "width = (int) 32;" \
128   "audio/x-raw-int, " \
129     "rate = (int) [ 1, MAX ], " \
130     "channels = (int) [ 1, 8 ], " \
131     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
132     "width = (int) 32, " \
133     "depth = (int) [ 1, 32 ], " \
134     "signed = (boolean) { true, false }; " \
135   "audio/x-raw-int, "   \
136     "rate = (int) [ 1, MAX ], " \
137     "channels = (int) [ 1, 8 ], "       \
138     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "        \
139     "width = (int) 24, "        \
140     "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; "  \
141   "audio/x-raw-int, " \
142     "rate = (int) [ 1, MAX ], " \
143     "channels = (int) [ 1, 8 ], " \
144     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
145     "width = (int) 16, " \
146     "depth = (int) [ 1, 16 ], " \
147     "signed = (boolean) { true, false }; " \
148   "audio/x-raw-int, " \
149     "rate = (int) [ 1, MAX ], " \
150     "channels = (int) [ 1, 8 ], " \
151     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
152     "width = (int) 8, " \
153     "depth = (int) [ 1, 8 ], " \
154     "signed = (boolean) { true, false } " \
155 )
156
157 static GstAudioChannelPosition *supported_positions;
158
159 static GstStaticPadTemplate gst_audio_convert_src_template =
160 GST_STATIC_PAD_TEMPLATE ("src",
161     GST_PAD_SRC,
162     GST_PAD_ALWAYS,
163     STATIC_CAPS);
164
165 static GstStaticPadTemplate gst_audio_convert_sink_template =
166 GST_STATIC_PAD_TEMPLATE ("sink",
167     GST_PAD_SINK,
168     GST_PAD_ALWAYS,
169     STATIC_CAPS);
170
171 /*** TYPE FUNCTIONS ***********************************************************/
172
173 static void
174 gst_audio_convert_base_init (gpointer g_class)
175 {
176   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
177
178   gst_element_class_add_pad_template (element_class,
179       gst_static_pad_template_get (&gst_audio_convert_src_template));
180   gst_element_class_add_pad_template (element_class,
181       gst_static_pad_template_get (&gst_audio_convert_sink_template));
182   gst_element_class_set_details (element_class, &audio_convert_details);
183 }
184
185 static void
186 gst_audio_convert_class_init (GstAudioConvertClass * klass)
187 {
188   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
189   gint i;
190
191   gobject_class->dispose = gst_audio_convert_dispose;
192
193   supported_positions = g_new0 (GstAudioChannelPosition,
194       GST_AUDIO_CHANNEL_POSITION_NUM);
195   for (i = 0; i < GST_AUDIO_CHANNEL_POSITION_NUM; i++)
196     supported_positions[i] = i;
197
198   GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size =
199       GST_DEBUG_FUNCPTR (gst_audio_convert_get_unit_size);
200   GST_BASE_TRANSFORM_CLASS (klass)->transform_caps =
201       GST_DEBUG_FUNCPTR (gst_audio_convert_transform_caps);
202   GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps =
203       GST_DEBUG_FUNCPTR (gst_audio_convert_fixate_caps);
204   GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
205       GST_DEBUG_FUNCPTR (gst_audio_convert_set_caps);
206   GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
207       GST_DEBUG_FUNCPTR (gst_audio_convert_transform_ip);
208   GST_BASE_TRANSFORM_CLASS (klass)->transform =
209       GST_DEBUG_FUNCPTR (gst_audio_convert_transform);
210
211   GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
212 }
213
214 static void
215 gst_audio_convert_init (GstAudioConvert * this, GstAudioConvertClass * g_class)
216 {
217 }
218
219 static void
220 gst_audio_convert_dispose (GObject * obj)
221 {
222   GstAudioConvert *this = GST_AUDIO_CONVERT (obj);
223
224   audio_convert_clean_context (&this->ctx);
225
226   G_OBJECT_CLASS (parent_class)->dispose (obj);
227 }
228
229 /*** GSTREAMER FUNCTIONS ******************************************************/
230
231 /* convert the given GstCaps to our format */
232 static gboolean
233 gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt)
234 {
235   GstStructure *structure = gst_caps_get_structure (caps, 0);
236
237   GST_DEBUG ("parse caps %p and %" GST_PTR_FORMAT, caps, caps);
238
239   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
240   g_return_val_if_fail (fmt != NULL, FALSE);
241
242   /* cleanup old */
243   audio_convert_clean_fmt (fmt);
244
245   fmt->endianness = G_BYTE_ORDER;
246   fmt->is_int =
247       (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0);
248
249   /* parse common fields */
250   if (!gst_structure_get_int (structure, "channels", &fmt->channels))
251     goto no_values;
252   if (!(fmt->pos = gst_audio_get_channel_positions (structure)))
253     goto no_values;
254   if (!gst_structure_get_int (structure, "width", &fmt->width))
255     goto no_values;
256   if (!gst_structure_get_int (structure, "rate", &fmt->rate))
257     goto no_values;
258
259   if (fmt->is_int) {
260     /* int specific fields */
261     if (!gst_structure_get_boolean (structure, "signed", &fmt->sign))
262       goto no_values;
263     if (!gst_structure_get_int (structure, "depth", &fmt->depth))
264       goto no_values;
265
266     /* width != 8 can have an endianness field */
267     if (fmt->width != 8) {
268       if (!gst_structure_get_int (structure, "endianness", &fmt->endianness))
269         goto no_values;
270     }
271     /* depth cannot be bigger than the width */
272     if (fmt->depth > fmt->width)
273       goto not_allowed;
274   }
275
276   fmt->unit_size = (fmt->width * fmt->channels) / 8;
277
278   return TRUE;
279
280   /* ERRORS */
281 no_values:
282   {
283     GST_DEBUG ("could not get some values from structure");
284     audio_convert_clean_fmt (fmt);
285     return FALSE;
286   }
287 not_allowed:
288   {
289     GST_DEBUG ("width > depth, not allowed - make us advertise correct fmt");
290     audio_convert_clean_fmt (fmt);
291     return FALSE;
292   }
293 }
294
295 /* BaseTransform vmethods */
296 static gboolean
297 gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps,
298     guint * size)
299 {
300   AudioConvertFmt fmt = { 0 };
301
302   g_assert (size);
303
304   if (!gst_audio_convert_parse_caps (caps, &fmt))
305     goto parse_error;
306
307   *size = fmt.unit_size;
308
309   audio_convert_clean_fmt (&fmt);
310
311   return TRUE;
312
313 parse_error:
314   {
315     return FALSE;
316   }
317 }
318
319 /* Modify the structure so that things that must always have a single
320  * value (for float), or can always be losslessly converted (for int), have
321  * appropriate values.
322  */
323 static GstStructure *
324 make_lossless_changes (GstStructure * s, gboolean isfloat)
325 {
326   if (isfloat) {
327     /* float doesn't have a depth or signedness field and only supports a
328      * width of 32 and native endianness */
329     gst_structure_remove_field (s, "depth");
330     gst_structure_remove_field (s, "signed");
331     gst_structure_set (s, "width", G_TYPE_INT, 32, NULL);
332     gst_structure_set (s, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
333   } else {
334     /* int supports either endian, and signed or unsigned. GValues are a pain */
335     GValue list = { 0 };
336     GValue val = { 0 };
337     int i;
338     gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN };
339     gboolean booleans[] = { TRUE, FALSE };
340
341     g_value_init (&list, GST_TYPE_LIST);
342     g_value_init (&val, G_TYPE_INT);
343     for (i = 0; i < 2; i++) {
344       g_value_set_int (&val, endian[i]);
345       gst_value_list_append_value (&list, &val);
346     }
347     gst_structure_set_value (s, "endianness", &list);
348     g_value_unset (&val);
349     g_value_unset (&list);
350
351     g_value_init (&list, GST_TYPE_LIST);
352     g_value_init (&val, G_TYPE_BOOLEAN);
353     for (i = 0; i < 2; i++) {
354       g_value_set_boolean (&val, booleans[i]);
355       gst_value_list_append_value (&list, &val);
356     }
357     gst_structure_set_value (s, "signed", &list);
358     g_value_unset (&val);
359     g_value_unset (&list);
360   }
361
362   return s;
363 }
364
365 /* Little utility function to create a related structure for float/int */
366 static void
367 append_with_other_format (GstCaps * caps, GstStructure * s, gboolean isfloat)
368 {
369   GstStructure *s2;
370
371   if (isfloat) {
372     s2 = gst_structure_copy (s);
373     gst_structure_set_name (s2, "audio/x-raw-int");
374     s = make_lossless_changes (s2, FALSE);
375     gst_caps_append_structure (caps, s2);
376   } else {
377     s2 = gst_structure_copy (s);
378     gst_structure_set_name (s2, "audio/x-raw-float");
379     s = make_lossless_changes (s2, TRUE);
380     gst_caps_append_structure (caps, s2);
381   }
382 }
383
384 /* Set widths (a list); multiples of 8 between min and max */
385 static void
386 set_structure_widths (GstStructure * s, int min, int max)
387 {
388   GValue list = { 0 };
389   GValue val = { 0 };
390   int width;
391
392   if (min == max) {
393     gst_structure_set (s, "width", G_TYPE_INT, min, NULL);
394     return;
395   }
396
397   g_value_init (&list, GST_TYPE_LIST);
398   g_value_init (&val, G_TYPE_INT);
399   for (width = min; width <= max; width += 8) {
400     g_value_set_int (&val, width);
401     gst_value_list_append_value (&list, &val);
402     GST_LOG ("Appended width %d to widths available", width);
403   }
404   gst_structure_set_value (s, "width", &list);
405   g_value_unset (&val);
406   g_value_unset (&list);
407 }
408
409 /* Audioconvert can perform all conversions on audio except for resampling. 
410  * However, there are some conversions we _prefer_ not to do. For example, it's
411  * better to convert format (float<->int, endianness, etc) than the number of
412  * channels, as the latter conversion is not lossless.
413  *
414  * So, we return, in order (assuming input caps have only one structure; 
415  * is this right?):
416 *  - input caps with a different format (lossless conversions).
417  *  - input caps with a different format (slightly lossy conversions).
418  *  - input caps with a different number of channels (very lossy!)
419  */
420 static GstCaps *
421 gst_audio_convert_transform_caps (GstBaseTransform * base,
422     GstPadDirection direction, GstCaps * caps)
423 {
424   GstCaps *ret;
425   GstStructure *s, *structure;
426   gboolean isfloat;
427   gint width, depth, channels;
428   gchar *fields_used[] = { "width", "depth", "rate", "channels", "endianness",
429     "signed"
430   };
431   int i;
432
433   g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL);
434
435   structure = gst_caps_get_structure (caps, 0);
436
437   isfloat = strcmp (gst_structure_get_name (structure),
438       "audio/x-raw-float") == 0;
439
440   /* We operate on a version of the original structure with any additional
441    * fields absent */
442   s = gst_structure_empty_new (gst_structure_get_name (structure));
443   for (i = 0; i < sizeof (fields_used) / sizeof (*fields_used); i++) {
444     if (gst_structure_has_field (structure, fields_used[i]))
445       gst_structure_set_value (s, fields_used[i],
446           gst_structure_get_value (structure, fields_used[i]));
447   }
448
449   if (!isfloat) {
450     /* Commonly, depth is left out: set it equal to width if we have a fixed
451      * width, if so */
452     if (!gst_structure_has_field (s, "depth") &&
453         gst_structure_get_int (s, "width", &width))
454       gst_structure_set (s, "depth", G_TYPE_INT, width, NULL);
455   }
456
457   ret = gst_caps_new_empty ();
458
459   /* All lossless conversions */
460   s = make_lossless_changes (s, isfloat);
461   gst_caps_append_structure (ret, s);
462
463   /* Same, plus a float<->int conversion */
464   append_with_other_format (ret, s, isfloat);
465
466   /* We don't mind increasing width/depth/channels, but reducing them is 
467    * Very Bad. Only available if width, depth, channels are already fixed. */
468   s = gst_structure_copy (s);
469   if (!isfloat) {
470     if (gst_structure_get_int (structure, "width", &width))
471       set_structure_widths (s, width, 32);
472     if (gst_structure_get_int (structure, "depth", &depth)) {
473       if (depth == 32)
474         gst_structure_set (s, "depth", G_TYPE_INT, 32, NULL);
475       else
476         gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, depth, 32, NULL);
477     }
478   }
479
480   if (gst_structure_get_int (structure, "channels", &channels)) {
481     if (channels == 8)
482       gst_structure_set (s, "channels", G_TYPE_INT, 8, NULL);
483     else
484       gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 8, NULL);
485   }
486   gst_caps_append_structure (ret, s);
487
488   /* Same, plus a float<->int conversion */
489   append_with_other_format (ret, s, isfloat);
490
491   /* We'll reduce depth if we must... only for integer, since we can't do this
492    * for float. We reduce as low as 16 bits; reducing to less than this is
493    * even worse than dropping channels. We only do this if we haven't already
494    * done the equivalent above. */
495   if (!gst_structure_get_int (structure, "width", &width) || width > 16) {
496     if (isfloat) {
497       /* These are invalid widths/depths for float, but we don't actually use
498        * them - we just pass it to append_with_other_format, which makes them
499        * valid
500        */
501       GstStructure *s2 = gst_structure_copy (s);
502
503       set_structure_widths (s2, 16, 32);
504       gst_structure_set (s2, "depth", GST_TYPE_INT_RANGE, 16, 32, NULL);
505       append_with_other_format (ret, s2, TRUE);
506       gst_structure_free (s2);
507     } else {
508       s = gst_structure_copy (s);
509       set_structure_widths (s, 16, 32);
510       gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, 16, 32, NULL);
511       gst_caps_append_structure (ret, s);
512     }
513   }
514
515   /* Channel conversions to fewer channels is only done if needed - generally
516    * it's very bad to drop channels entirely.
517    */
518   s = gst_structure_copy (s);
519   gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 8, NULL);
520   gst_caps_append_structure (ret, s);
521
522   /* Same, plus a float<->int conversion */
523   append_with_other_format (ret, s, isfloat);
524
525   /* And, finally, for integer only, we allow conversion to any width/depth we
526    * support: this should be equivalent to our (non-float) template caps. (the
527    * floating point case should be being handled just above) */
528   s = gst_structure_copy (s);
529   set_structure_widths (s, 8, 32);
530   gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL);
531
532   if (isfloat) {
533     append_with_other_format (ret, s, TRUE);
534     gst_structure_free (s);
535   } else
536     gst_caps_append_structure (ret, s);
537
538   return ret;
539 }
540
541 /* try to keep as many of the structure members the same by fixating the
542  * possible ranges; this way we convert the least amount of things as possible
543  */
544 static void
545 gst_audio_convert_fixate_caps (GstBaseTransform * base,
546     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
547 {
548   GstStructure *ins, *outs;
549   gint rate, endianness, depth, width, channels;
550   gboolean signedness;
551
552   g_return_if_fail (gst_caps_is_fixed (caps));
553
554   GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
555       " based on caps %" GST_PTR_FORMAT, othercaps, caps);
556
557   ins = gst_caps_get_structure (caps, 0);
558   outs = gst_caps_get_structure (othercaps, 0);
559
560   if (gst_structure_get_int (ins, "channels", &channels)) {
561     if (gst_structure_has_field (outs, "channels")) {
562       gst_structure_fixate_field_nearest_int (outs, "channels", channels);
563     }
564   }
565   if (gst_structure_get_int (ins, "rate", &rate)) {
566     if (gst_structure_has_field (outs, "rate")) {
567       gst_structure_fixate_field_nearest_int (outs, "rate", rate);
568     }
569   }
570   if (gst_structure_get_int (ins, "endianness", &endianness)) {
571     if (gst_structure_has_field (outs, "endianness")) {
572       gst_structure_fixate_field_nearest_int (outs, "endianness", endianness);
573     }
574   }
575   if (gst_structure_get_int (ins, "width", &width)) {
576     if (gst_structure_has_field (outs, "width")) {
577       gst_structure_fixate_field_nearest_int (outs, "width", width);
578     }
579   } else {
580     /* this is not allowed */
581   }
582
583   if (gst_structure_get_int (ins, "depth", &depth)) {
584     if (gst_structure_has_field (outs, "depth")) {
585       gst_structure_fixate_field_nearest_int (outs, "depth", depth);
586     }
587   } else {
588     /* set depth as width */
589     if (gst_structure_has_field (outs, "depth")) {
590       gst_structure_fixate_field_nearest_int (outs, "depth", width);
591     }
592   }
593
594   if (gst_structure_get_boolean (ins, "signed", &signedness)) {
595     if (gst_structure_has_field (outs, "signed")) {
596       gst_structure_fixate_field_boolean (outs, "signed", signedness);
597     }
598   }
599
600   GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
601 }
602
603 static gboolean
604 gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps,
605     GstCaps * outcaps)
606 {
607   AudioConvertFmt in_ac_caps = { 0 };
608   AudioConvertFmt out_ac_caps = { 0 };
609   GstAudioConvert *this = GST_AUDIO_CONVERT (base);
610
611   GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %"
612       GST_PTR_FORMAT, incaps, outcaps);
613
614   if (!gst_audio_convert_parse_caps (incaps, &in_ac_caps))
615     return FALSE;
616   if (!gst_audio_convert_parse_caps (outcaps, &out_ac_caps))
617     return FALSE;
618
619   if (!audio_convert_prepare_context (&this->ctx, &in_ac_caps, &out_ac_caps))
620     goto no_converter;
621
622   return TRUE;
623
624 no_converter:
625   {
626     return FALSE;
627   }
628 }
629
630 static GstFlowReturn
631 gst_audio_convert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
632 {
633   /* nothing to do here */
634   return GST_FLOW_OK;
635 }
636
637 static GstFlowReturn
638 gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
639     GstBuffer * outbuf)
640 {
641   GstAudioConvert *this = GST_AUDIO_CONVERT (base);
642   gboolean res;
643   gint insize, outsize;
644   gint samples;
645   gpointer src, dst;
646
647   /* get amount of samples to convert. */
648   samples = GST_BUFFER_SIZE (inbuf) / this->ctx.in.unit_size;
649
650   /* get in/output sizes, to see if the buffers we got are of correct
651    * sizes */
652   if (!(res = audio_convert_get_sizes (&this->ctx, samples, &insize, &outsize)))
653     goto error;
654
655   /* check in and outsize */
656   if (GST_BUFFER_SIZE (inbuf) < insize)
657     goto wrong_size;
658   if (GST_BUFFER_SIZE (outbuf) < outsize)
659     goto wrong_size;
660
661   /* get src and dst data */
662   src = GST_BUFFER_DATA (inbuf);
663   dst = GST_BUFFER_DATA (outbuf);
664
665   /* and convert the samples */
666   if (!(res = audio_convert_convert (&this->ctx, src, dst,
667               samples, gst_buffer_is_writable (inbuf))))
668     goto convert_error;
669
670   GST_BUFFER_SIZE (outbuf) = outsize;
671
672   return GST_FLOW_OK;
673
674   /* ERRORS */
675 error:
676   {
677     GST_ELEMENT_ERROR (this, STREAM, NOT_IMPLEMENTED,
678         ("cannot get input/output sizes for %d samples", samples),
679         ("cannot get input/output sizes for %d samples", samples));
680     return GST_FLOW_ERROR;
681   }
682 wrong_size:
683   {
684     GST_ELEMENT_ERROR (this, STREAM, NOT_IMPLEMENTED,
685         ("input/output buffers are of wrong size in: %d < %d or out: %d < %d",
686             GST_BUFFER_SIZE (inbuf), insize, GST_BUFFER_SIZE (outbuf), outsize),
687         ("input/output buffers are of wrong size in: %d < %d or out: %d < %d",
688             GST_BUFFER_SIZE (inbuf), insize, GST_BUFFER_SIZE (outbuf),
689             outsize));
690     return GST_FLOW_ERROR;
691   }
692 convert_error:
693   {
694     GST_ELEMENT_ERROR (this, STREAM, NOT_IMPLEMENTED,
695         ("error while converting"), ("error while converting"));
696     return GST_FLOW_ERROR;
697   }
698 }