copy/paste caused some issues here
[swfdec.git] / libswfdec / swfdec_codec_audio.c
bloba42dba899ffa7b3611e4b6b55d4289d9024b3dd1
1 /* Swfdec
2 * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_codec_audio.h"
25 #include "swfdec_debug.h"
26 #include "swfdec_internal.h"
28 /*** UNCOMPRESSED SOUND ***/
30 typedef struct {
31 SwfdecAudioDecoder decoder;
32 SwfdecBufferQueue * queue; /* queue collecting output buffers */
33 } SwfdecAudioDecoderUncompressed;
35 static void
36 swfdec_audio_decoder_uncompressed_decode_8bit (SwfdecAudioDecoder *decoder,
37 SwfdecBuffer *buffer)
39 SwfdecBuffer *ret;
40 gint16 *out;
41 guint8 *in;
42 guint i;
44 if (buffer == NULL)
45 return;
47 ret = swfdec_buffer_new_and_alloc (buffer->length * 2);
48 out = (gint16 *) ret->data;
49 in = buffer->data;
50 for (i = 0; i < buffer->length; i++) {
51 *out = ((gint16) *in << 8) ^ (-1);
52 out++;
53 in++;
55 swfdec_buffer_queue_push (((SwfdecAudioDecoderUncompressed *) decoder)->queue, ret);
58 static void
59 swfdec_audio_decoder_uncompressed_decode_16bit (SwfdecAudioDecoder *decoder,
60 SwfdecBuffer *buffer)
62 if (buffer == NULL)
63 return;
65 swfdec_buffer_ref (buffer);
66 swfdec_buffer_queue_push (((SwfdecAudioDecoderUncompressed *) decoder)->queue, buffer);
69 static SwfdecBuffer *
70 swfdec_audio_decoder_uncompressed_pull (SwfdecAudioDecoder *decoder)
72 SwfdecAudioDecoderUncompressed *dec = (SwfdecAudioDecoderUncompressed *) decoder;
74 return swfdec_buffer_queue_pull_buffer (dec->queue);
77 static void
78 swfdec_audio_decoder_uncompressed_free (SwfdecAudioDecoder *decoder)
80 SwfdecAudioDecoderUncompressed *dec = (SwfdecAudioDecoderUncompressed *) decoder;
82 swfdec_buffer_queue_unref (dec->queue);
83 g_free (dec);
86 static SwfdecAudioDecoder *
87 swfdec_audio_decoder_uncompressed_new (SwfdecAudioCodec type, SwfdecAudioFormat format)
89 SwfdecAudioDecoderUncompressed *dec;
91 if (type != SWFDEC_AUDIO_CODEC_UNDEFINED &&
92 type != SWFDEC_AUDIO_CODEC_UNCOMPRESSED)
93 return NULL;
94 if (type == SWFDEC_AUDIO_CODEC_UNDEFINED) {
95 SWFDEC_WARNING ("endianness of audio unknown, assuming little endian");
97 dec = g_new (SwfdecAudioDecoderUncompressed, 1);
98 dec->decoder.format = format;
99 if (swfdec_audio_format_is_16bit (format))
100 dec->decoder.push = swfdec_audio_decoder_uncompressed_decode_16bit;
101 else
102 dec->decoder.push = swfdec_audio_decoder_uncompressed_decode_8bit;
103 dec->decoder.pull = swfdec_audio_decoder_uncompressed_pull;
104 dec->decoder.free = swfdec_audio_decoder_uncompressed_free;
105 dec->queue = swfdec_buffer_queue_new ();
107 return &dec->decoder;
110 /*** PUBLIC API ***/
113 * swfdec_audio_decoder_new:
114 * @format: #SwfdecAudioCodec to decode
116 * Creates a decoder suitable for decoding @format. If no decoder is available
117 * for the given for mat, %NULL is returned.
119 * Returns: a new decoder or %NULL
121 SwfdecAudioDecoder *
122 swfdec_audio_decoder_new (SwfdecAudioCodec codec, SwfdecAudioFormat format)
124 SwfdecAudioDecoder *ret;
126 g_return_val_if_fail (SWFDEC_IS_AUDIO_FORMAT (format), NULL);
128 ret = swfdec_audio_decoder_uncompressed_new (codec, format);
129 if (ret == NULL)
130 ret = swfdec_audio_decoder_adpcm_new (codec, format);
131 #ifdef HAVE_MAD
132 if (ret == NULL)
133 ret = swfdec_audio_decoder_mad_new (codec, format);
134 #endif
135 #ifdef HAVE_FFMPEG
136 if (ret == NULL)
137 ret = swfdec_audio_decoder_ffmpeg_new (codec, format);
138 #endif
139 #ifdef HAVE_GST
140 if (ret == NULL)
141 ret = swfdec_audio_decoder_gst_new (codec, format);
142 #endif
143 if (ret) {
144 ret->codec = codec;
145 g_return_val_if_fail (SWFDEC_IS_AUDIO_FORMAT (ret->format), NULL);
146 g_return_val_if_fail (ret->push, NULL);
147 g_return_val_if_fail (ret->pull, NULL);
148 g_return_val_if_fail (ret->free, NULL);
149 } else {
150 SWFDEC_ERROR ("no suitable decoder for audio codec %u", codec);
151 return NULL;
153 return ret;
157 * swfdec_audio_decoder_free:
158 * @decoder: a #SwfdecAudioDecoder
160 * Frees the given decoder. When finishing decoding, be sure to pass a %NULL
161 * buffer to swfdec_audio_decoder_push() first to flush the decoder. See that
162 * function for details.
164 void
165 swfdec_audio_decoder_free (SwfdecAudioDecoder *decoder)
167 g_return_if_fail (decoder != NULL);
169 decoder->free (decoder);
173 * swfdec_audio_decoder_get_format:
174 * @decoder: a #SwfdecAudioDecoder
176 * Queries the format that is used by the decoder for its produced output.
178 * Returns: the format of the decoded data
180 SwfdecAudioFormat
181 swfdec_audio_decoder_get_format (SwfdecAudioDecoder *decoder)
183 g_return_val_if_fail (decoder != NULL, 0);
185 return decoder->format;
189 * swfdec_audio_decoder_push:
190 * @decoder: a #SwfdecAudioDecoder
191 * @buffer: a #SwfdecBuffer to process or %NULL to flush
193 * Pushes a new buffer into the decoding pipeline. After this the results can
194 * be queried using swfdec_audio_decoder_pull(). Some decoders may not decode
195 * all available data immediately. So when you are done decoding, you may want
196 * to flush the decoder. Flushing can be achieved by passing %NULL as the
197 * @buffer argument. Do this when you are finished decoding.
199 void
200 swfdec_audio_decoder_push (SwfdecAudioDecoder *decoder, SwfdecBuffer *buffer)
202 g_return_if_fail (decoder != NULL);
204 decoder->push (decoder, buffer);
208 * swfdec_audio_decoder_pull:
209 * @decoder: a #SwfdecAudioDecoder
211 * Gets the next buffer of decoded audio data. Since some decoders do not
212 * produce one output buffer per input buffer, any number of buffers may be
213 * available after calling swfdec_audio_decoder_push(), even none. When no more
214 * buffers are available, this function returns %NULL. You need to provide more
215 * input in then. A simple decoding pipeline would look like this:
216 * <informalexample><programlisting>do {
217 * input = next_input_buffer ();
218 * swfdec_audio_decoder_push (decoder, input);
219 * while ((output = swfdec_audio_decoder_pull (decoder))) {
220 * ... process output ...
222 * } while (input != NULL); </programlisting></informalexample>
224 * Returns: the next buffer or %NULL if no more buffers are available.
226 SwfdecBuffer *
227 swfdec_audio_decoder_pull (SwfdecAudioDecoder *decoder)
229 g_return_val_if_fail (decoder != NULL, NULL);
231 return decoder->pull (decoder);