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>
6 * gstaudioconvert.c: Convert audio to different audio formats automatically
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.
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.
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.
25 * SECTION:element-audioconvert
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>
34 * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw-int,channels=2,width=8,depth=8 ! level ! fakesink silent=TRUE
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.
41 * gst-launch -v -m audiotestsrc ! audioconvert ! vorbisenc ! fakesink silent=TRUE
43 * The vorbis encoder takes float audio data instead of the integer data
44 * generated by audiotestsrc.
48 * Last reviewed on 2006-03-02 (0.10.4)
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.
59 * audioconvert is not supposed to be a one-element-does-anything solution for
69 #include "gstaudioconvert.h"
70 #include "gstchannelmix.h"
73 GST_DEBUG_CATEGORY (audio_convert_debug);
75 /*** DEFINITIONS **************************************************************/
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>");
84 static void gst_audio_convert_dispose (GObject * obj);
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,
100 /* AudioConvert signals and args */
113 #define DEBUG_INIT(bla) \
114 GST_DEBUG_CATEGORY_INIT (audio_convert_debug, "audioconvert", 0, "audio conversion element");
116 GST_BOILERPLATE_FULL (GstAudioConvert, gst_audio_convert, GstBaseTransform,
117 GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
119 /*** GSTREAMER PROTOTYPES *****************************************************/
121 #define 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 } " \
157 static GstAudioChannelPosition *supported_positions;
159 static GstStaticPadTemplate gst_audio_convert_src_template =
160 GST_STATIC_PAD_TEMPLATE ("src",
165 static GstStaticPadTemplate gst_audio_convert_sink_template =
166 GST_STATIC_PAD_TEMPLATE ("sink",
171 /*** TYPE FUNCTIONS ***********************************************************/
174 gst_audio_convert_base_init (gpointer g_class)
176 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
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);
186 gst_audio_convert_class_init (GstAudioConvertClass * klass)
188 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
191 gobject_class->dispose = gst_audio_convert_dispose;
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;
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);
211 GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
215 gst_audio_convert_init (GstAudioConvert * this, GstAudioConvertClass * g_class)
220 gst_audio_convert_dispose (GObject * obj)
222 GstAudioConvert *this = GST_AUDIO_CONVERT (obj);
224 audio_convert_clean_context (&this->ctx);
226 G_OBJECT_CLASS (parent_class)->dispose (obj);
229 /*** GSTREAMER FUNCTIONS ******************************************************/
231 /* convert the given GstCaps to our format */
233 gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt)
235 GstStructure *structure = gst_caps_get_structure (caps, 0);
237 GST_DEBUG ("parse caps %p and %" GST_PTR_FORMAT, caps, caps);
239 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
240 g_return_val_if_fail (fmt != NULL, FALSE);
243 audio_convert_clean_fmt (fmt);
245 fmt->endianness = G_BYTE_ORDER;
247 (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0);
249 /* parse common fields */
250 if (!gst_structure_get_int (structure, "channels", &fmt->channels))
252 if (!(fmt->pos = gst_audio_get_channel_positions (structure)))
254 if (!gst_structure_get_int (structure, "width", &fmt->width))
256 if (!gst_structure_get_int (structure, "rate", &fmt->rate))
260 /* int specific fields */
261 if (!gst_structure_get_boolean (structure, "signed", &fmt->sign))
263 if (!gst_structure_get_int (structure, "depth", &fmt->depth))
266 /* width != 8 can have an endianness field */
267 if (fmt->width != 8) {
268 if (!gst_structure_get_int (structure, "endianness", &fmt->endianness))
271 /* depth cannot be bigger than the width */
272 if (fmt->depth > fmt->width)
276 fmt->unit_size = (fmt->width * fmt->channels) / 8;
283 GST_DEBUG ("could not get some values from structure");
284 audio_convert_clean_fmt (fmt);
289 GST_DEBUG ("width > depth, not allowed - make us advertise correct fmt");
290 audio_convert_clean_fmt (fmt);
295 /* BaseTransform vmethods */
297 gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps,
300 AudioConvertFmt fmt = { 0 };
304 if (!gst_audio_convert_parse_caps (caps, &fmt))
307 *size = fmt.unit_size;
309 audio_convert_clean_fmt (&fmt);
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.
323 static GstStructure *
324 make_lossless_changes (GstStructure * s, gboolean 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);
334 /* int supports either endian, and signed or unsigned. GValues are a pain */
338 gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN };
339 gboolean booleans[] = { TRUE, FALSE };
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);
347 gst_structure_set_value (s, "endianness", &list);
348 g_value_unset (&val);
349 g_value_unset (&list);
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);
357 gst_structure_set_value (s, "signed", &list);
358 g_value_unset (&val);
359 g_value_unset (&list);
365 /* Little utility function to create a related structure for float/int */
367 append_with_other_format (GstCaps * caps, GstStructure * s, gboolean 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);
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);
384 /* Set widths (a list); multiples of 8 between min and max */
386 set_structure_widths (GstStructure * s, int min, int max)
393 gst_structure_set (s, "width", G_TYPE_INT, min, NULL);
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);
404 gst_structure_set_value (s, "width", &list);
405 g_value_unset (&val);
406 g_value_unset (&list);
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.
414 * So, we return, in order (assuming input caps have only one structure;
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!)
421 gst_audio_convert_transform_caps (GstBaseTransform * base,
422 GstPadDirection direction, GstCaps * caps)
425 GstStructure *s, *structure;
427 gint width, depth, channels;
428 gchar *fields_used[] = { "width", "depth", "rate", "channels", "endianness",
433 g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL);
435 structure = gst_caps_get_structure (caps, 0);
437 isfloat = strcmp (gst_structure_get_name (structure),
438 "audio/x-raw-float") == 0;
440 /* We operate on a version of the original structure with any additional
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]));
450 /* Commonly, depth is left out: set it equal to width if we have a fixed
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);
457 ret = gst_caps_new_empty ();
459 /* All lossless conversions */
460 s = make_lossless_changes (s, isfloat);
461 gst_caps_append_structure (ret, s);
463 /* Same, plus a float<->int conversion */
464 append_with_other_format (ret, s, isfloat);
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);
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)) {
474 gst_structure_set (s, "depth", G_TYPE_INT, 32, NULL);
476 gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, depth, 32, NULL);
480 if (gst_structure_get_int (structure, "channels", &channels)) {
482 gst_structure_set (s, "channels", G_TYPE_INT, 8, NULL);
484 gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 8, NULL);
486 gst_caps_append_structure (ret, s);
488 /* Same, plus a float<->int conversion */
489 append_with_other_format (ret, s, isfloat);
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) {
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
501 GstStructure *s2 = gst_structure_copy (s);
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);
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);
515 /* Channel conversions to fewer channels is only done if needed - generally
516 * it's very bad to drop channels entirely.
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);
522 /* Same, plus a float<->int conversion */
523 append_with_other_format (ret, s, isfloat);
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);
533 append_with_other_format (ret, s, TRUE);
534 gst_structure_free (s);
536 gst_caps_append_structure (ret, s);
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
545 gst_audio_convert_fixate_caps (GstBaseTransform * base,
546 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
548 GstStructure *ins, *outs;
549 gint rate, endianness, depth, width, channels;
552 g_return_if_fail (gst_caps_is_fixed (caps));
554 GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
555 " based on caps %" GST_PTR_FORMAT, othercaps, caps);
557 ins = gst_caps_get_structure (caps, 0);
558 outs = gst_caps_get_structure (othercaps, 0);
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);
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);
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);
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);
580 /* this is not allowed */
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);
588 /* set depth as width */
589 if (gst_structure_has_field (outs, "depth")) {
590 gst_structure_fixate_field_nearest_int (outs, "depth", width);
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);
600 GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
604 gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps,
607 AudioConvertFmt in_ac_caps = { 0 };
608 AudioConvertFmt out_ac_caps = { 0 };
609 GstAudioConvert *this = GST_AUDIO_CONVERT (base);
611 GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %"
612 GST_PTR_FORMAT, incaps, outcaps);
614 if (!gst_audio_convert_parse_caps (incaps, &in_ac_caps))
616 if (!gst_audio_convert_parse_caps (outcaps, &out_ac_caps))
619 if (!audio_convert_prepare_context (&this->ctx, &in_ac_caps, &out_ac_caps))
631 gst_audio_convert_transform_ip (GstBaseTransform * base, GstBuffer * buf)
633 /* nothing to do here */
638 gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf,
641 GstAudioConvert *this = GST_AUDIO_CONVERT (base);
643 gint insize, outsize;
647 /* get amount of samples to convert. */
648 samples = GST_BUFFER_SIZE (inbuf) / this->ctx.in.unit_size;
650 /* get in/output sizes, to see if the buffers we got are of correct
652 if (!(res = audio_convert_get_sizes (&this->ctx, samples, &insize, &outsize)))
655 /* check in and outsize */
656 if (GST_BUFFER_SIZE (inbuf) < insize)
658 if (GST_BUFFER_SIZE (outbuf) < outsize)
661 /* get src and dst data */
662 src = GST_BUFFER_DATA (inbuf);
663 dst = GST_BUFFER_DATA (outbuf);
665 /* and convert the samples */
666 if (!(res = audio_convert_convert (&this->ctx, src, dst,
667 samples, gst_buffer_is_writable (inbuf))))
670 GST_BUFFER_SIZE (outbuf) = outsize;
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;
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),
690 return GST_FLOW_ERROR;
694 GST_ELEMENT_ERROR (this, STREAM, NOT_IMPLEMENTED,
695 ("error while converting"), ("error while converting"));
696 return GST_FLOW_ERROR;