2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2006,2011> Tim-Philipp Müller <tim centricular net>
4 * Copyright (C) <2006> Jan Schmidt <thaytan at mad scientist com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * SECTION:element-flacdec
24 * @see_also: #GstFlacEnc
26 * flacdec decodes FLAC streams.
27 * <ulink url="http://flac.sourceforge.net/">FLAC</ulink>
28 * is a Free Lossless Audio Codec.
31 * <title>Example launch line</title>
33 * gst-launch-0.11 filesrc location=media/small/dark.441-16-s.flac ! flacparse ! flacdec ! audioconvert ! audioresample ! autoaudiosink
36 * gst-launch-0.11 souphttpsrc location=http://gstreamer.freedesktop.org/media/small/dark.441-16-s.flac ! flacparse ! flacdec ! audioconvert ! audioresample ! queue min-threshold-buffers=10 ! autoaudiosink
47 #include "gstflacdec.h"
48 #include <gst/gst-i18n-plugin.h>
49 #include <gst/tag/tag.h>
51 /* Taken from http://flac.sourceforge.net/format.html#frame_header */
52 static const GstAudioChannelPosition channel_positions[8][8] = {
53 {GST_AUDIO_CHANNEL_POSITION_MONO},
54 {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
55 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
56 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
57 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
58 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
59 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
60 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
61 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
62 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
63 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
64 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
65 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
66 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
67 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
68 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
69 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
70 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
71 GST_AUDIO_CHANNEL_POSITION_LFE1,
72 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
73 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
74 /* FIXME: 7/8 channel layouts are not defined in the FLAC specs */
76 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
77 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
78 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
79 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
80 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
81 GST_AUDIO_CHANNEL_POSITION_LFE1,
82 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
83 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
84 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
85 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
86 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
87 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
88 GST_AUDIO_CHANNEL_POSITION_LFE1,
89 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
90 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
93 GST_DEBUG_CATEGORY_STATIC (flacdec_debug);
94 #define GST_CAT_DEFAULT flacdec_debug
96 static FLAC__StreamDecoderReadStatus
97 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
98 FLAC__byte buffer[], size_t * bytes, void *client_data);
99 static FLAC__StreamDecoderWriteStatus
100 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
101 const FLAC__Frame * frame,
102 const FLAC__int32 * const buffer[], void *client_data);
103 static void gst_flac_dec_metadata_cb (const FLAC__StreamDecoder *
104 decoder, const FLAC__StreamMetadata * metadata, void *client_data);
105 static void gst_flac_dec_error_cb (const FLAC__StreamDecoder *
106 decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
108 static void gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard);
109 static gboolean gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps);
110 static gboolean gst_flac_dec_start (GstAudioDecoder * dec);
111 static gboolean gst_flac_dec_stop (GstAudioDecoder * dec);
112 static GstFlowReturn gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec,
115 G_DEFINE_TYPE (GstFlacDec, gst_flac_dec, GST_TYPE_AUDIO_DECODER);
117 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
118 #define FORMATS "{ S8LE, S16LE, S32LE } "
120 #define FORMATS "{ S8BE, S16BE, S32BE } "
123 #define GST_FLAC_DEC_SRC_CAPS \
125 "format = (string) " FORMATS ", " \
126 "layout = (string) interleaved, " \
127 "rate = (int) [ 1, 655350 ], " \
128 "channels = (int) [ 1, 8 ]"
130 #define GST_FLAC_DEC_SINK_CAPS \
132 "framed = (boolean) true, " \
133 "rate = (int) [ 1, 655350 ], " \
134 "channels = (int) [ 1, 8 ]"
136 static GstStaticPadTemplate flac_dec_src_factory =
137 GST_STATIC_PAD_TEMPLATE ("src",
140 GST_STATIC_CAPS (GST_FLAC_DEC_SRC_CAPS));
141 static GstStaticPadTemplate flac_dec_sink_factory =
142 GST_STATIC_PAD_TEMPLATE ("sink",
145 GST_STATIC_CAPS (GST_FLAC_DEC_SINK_CAPS));
148 gst_flac_dec_class_init (GstFlacDecClass * klass)
150 GstAudioDecoderClass *audiodecoder_class;
151 GstElementClass *gstelement_class;
153 audiodecoder_class = (GstAudioDecoderClass *) klass;
154 gstelement_class = (GstElementClass *) klass;
156 GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
158 audiodecoder_class->stop = GST_DEBUG_FUNCPTR (gst_flac_dec_stop);
159 audiodecoder_class->start = GST_DEBUG_FUNCPTR (gst_flac_dec_start);
160 audiodecoder_class->flush = GST_DEBUG_FUNCPTR (gst_flac_dec_flush);
161 audiodecoder_class->set_format = GST_DEBUG_FUNCPTR (gst_flac_dec_set_format);
162 audiodecoder_class->handle_frame =
163 GST_DEBUG_FUNCPTR (gst_flac_dec_handle_frame);
165 gst_element_class_add_pad_template (gstelement_class,
166 gst_static_pad_template_get (&flac_dec_src_factory));
167 gst_element_class_add_pad_template (gstelement_class,
168 gst_static_pad_template_get (&flac_dec_sink_factory));
170 gst_element_class_set_details_simple (gstelement_class, "FLAC audio decoder",
171 "Codec/Decoder/Audio", "Decodes FLAC lossless audio streams",
172 "Tim-Philipp Müller <tim@centricular.net>, "
173 "Wim Taymans <wim.taymans@gmail.com>");
177 gst_flac_dec_init (GstFlacDec * flacdec)
179 /* nothing to do here */
183 gst_flac_dec_start (GstAudioDecoder * audio_dec)
185 FLAC__StreamDecoderInitStatus s;
188 dec = GST_FLAC_DEC (audio_dec);
190 dec->adapter = gst_adapter_new ();
192 dec->decoder = FLAC__stream_decoder_new ();
194 gst_audio_info_init (&dec->info);
197 /* no point calculating MD5 since it's never checked here */
198 FLAC__stream_decoder_set_md5_checking (dec->decoder, false);
200 GST_DEBUG_OBJECT (dec, "initializing decoder");
201 s = FLAC__stream_decoder_init_stream (dec->decoder,
202 gst_flac_dec_read_stream, NULL, NULL, NULL, NULL,
203 gst_flac_dec_write_stream, gst_flac_dec_metadata_cb,
204 gst_flac_dec_error_cb, dec);
206 if (s != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
207 GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL));
211 dec->got_headers = FALSE;
217 gst_flac_dec_stop (GstAudioDecoder * dec)
219 GstFlacDec *flacdec = GST_FLAC_DEC (dec);
221 if (flacdec->decoder) {
222 FLAC__stream_decoder_delete (flacdec->decoder);
223 flacdec->decoder = NULL;
226 if (flacdec->adapter) {
227 gst_adapter_clear (flacdec->adapter);
228 g_object_unref (flacdec->adapter);
229 flacdec->adapter = NULL;
236 gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps)
238 const GValue *headers;
243 flacdec = GST_FLAC_DEC (dec);
245 GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps);
247 s = gst_caps_get_structure (caps, 0);
248 headers = gst_structure_get_value (s, "streamheader");
249 if (headers == NULL || !GST_VALUE_HOLDS_ARRAY (headers)) {
250 GST_WARNING_OBJECT (dec, "no 'streamheader' field in input caps, try "
251 "adding a flacparse element upstream");
255 if (gst_adapter_available (flacdec->adapter) > 0) {
256 GST_WARNING_OBJECT (dec, "unexpected data left in adapter");
257 gst_adapter_clear (flacdec->adapter);
260 num = gst_value_array_get_size (headers);
261 for (i = 0; i < num; ++i) {
262 const GValue *header_val;
263 GstBuffer *header_buf;
265 header_val = gst_value_array_get_value (headers, i);
266 if (header_val == NULL || !GST_VALUE_HOLDS_BUFFER (header_val))
269 header_buf = g_value_dup_boxed (header_val);
270 GST_INFO_OBJECT (dec, "pushing header buffer of %" G_GSIZE_FORMAT " bytes "
271 "into adapter", gst_buffer_get_size (header_buf));
272 gst_adapter_push (flacdec->adapter, header_buf);
275 GST_DEBUG_OBJECT (dec, "Processing headers and metadata");
276 if (!FLAC__stream_decoder_process_until_end_of_metadata (flacdec->decoder)) {
277 GST_WARNING_OBJECT (dec, "process_until_end_of_metadata failed");
279 GST_INFO_OBJECT (dec, "headers and metadata are now processed");
283 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
284 static const guint8 crc8_table[256] = {
285 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
286 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
287 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
288 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
289 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
290 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
291 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
292 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
293 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
294 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
295 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
296 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
297 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
298 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
299 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
300 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
301 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
302 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
303 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
304 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
305 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
306 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
307 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
308 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
309 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
310 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
311 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
312 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
313 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
314 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
315 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
316 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
320 gst_flac_calculate_crc8 (guint8 * data, guint length)
325 crc = crc8_table[crc ^ *data];
332 /* FIXME: for our purposes it's probably enough to just check for the sync
333 * marker - we just want to know if it's a header frame or not */
335 gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,
336 gint64 * last_sample_num)
339 guint sr_from_end = 0; /* can be 0, 8 or 16 */
340 guint bs_from_end = 0; /* can be 0, 8 or 16 */
342 guint8 bs, sr, ca, ss, pb;
348 if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
351 GST_WARNING_OBJECT (flacdec, "Variable block size FLAC unsupported");
355 bs = (data[2] & 0xF0) >> 4; /* blocksize marker */
356 sr = (data[2] & 0x0F); /* samplerate marker */
357 ca = (data[3] & 0xF0) >> 4; /* channel assignment */
358 ss = (data[3] & 0x0F) >> 1; /* sample size marker */
359 pb = (data[3] & 0x01); /* padding bit */
361 GST_LOG_OBJECT (flacdec,
362 "got sync, bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", bs, sr, ca, ss, pb);
364 if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
368 /* read block size from end of header? */
374 /* read sample rate from end of header? */
377 else if (sr == 0x0D || sr == 0x0E)
380 /* FIXME: This is can be 36 bit if variable block size is used,
381 * fortunately not encoder supports this yet and we check for that
384 val = (guint32) g_utf8_get_char_validated ((gchar *) data + 4, -1);
386 if (val == (guint32) - 1 || val == (guint32) - 2) {
387 GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
391 headerlen = 4 + g_unichar_to_utf8 ((gunichar) val, NULL) +
392 (bs_from_end / 8) + (sr_from_end / 8);
394 if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
395 GST_LOG_OBJECT (flacdec, "invalid checksum");
399 if (flacdec->min_blocksize == flacdec->max_blocksize) {
400 *last_sample_num = (val + 1) * flacdec->min_blocksize;
402 *last_sample_num = 0; /* FIXME: + length of last block in samples */
405 /* FIXME: only valid for fixed block size streams */
406 GST_DEBUG_OBJECT (flacdec, "frame number: %" G_GINT64_FORMAT,
409 if (flacdec->info.rate > 0 && *last_sample_num != 0) {
410 GST_DEBUG_OBJECT (flacdec, "last sample %" G_GINT64_FORMAT " = %"
411 GST_TIME_FORMAT, *last_sample_num,
412 GST_TIME_ARGS (*last_sample_num * GST_SECOND / flacdec->info.rate));
419 gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg)
424 if (dec->error_count > 10) {
426 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL));
427 dec->last_flow = GST_FLOW_ERROR;
430 GST_DEBUG_OBJECT (dec, "ignoring error for now at count %d",
439 gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder,
440 const FLAC__StreamMetadata * metadata, void *client_data)
442 GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
444 GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type);
446 switch (metadata->type) {
447 case FLAC__METADATA_TYPE_STREAMINFO:{
451 samples = metadata->data.stream_info.total_samples;
453 flacdec->min_blocksize = metadata->data.stream_info.min_blocksize;
454 flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
455 flacdec->depth = depth = metadata->data.stream_info.bits_per_sample;
464 gst_audio_info_set_format (&flacdec->info,
465 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, width),
466 metadata->data.stream_info.sample_rate,
467 metadata->data.stream_info.channels, NULL);
469 memcpy (flacdec->info.position,
470 channel_positions[flacdec->info.channels - 1],
471 sizeof (GstAudioChannelPosition) * flacdec->info.channels);
472 gst_audio_channel_positions_to_valid_order (flacdec->info.position,
473 flacdec->info.channels);
474 /* Note: we create the inverse reordering map here */
475 gst_audio_get_channel_reorder_map (flacdec->info.channels,
476 flacdec->info.position, channel_positions[flacdec->info.channels - 1],
477 flacdec->channel_reorder_map);
479 GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
480 flacdec->min_blocksize, flacdec->max_blocksize);
481 GST_DEBUG_OBJECT (flacdec, "sample rate: %u, channels: %u",
482 flacdec->info.rate, flacdec->info.channels);
483 GST_DEBUG_OBJECT (flacdec, "depth: %u, width: %u", flacdec->depth,
484 flacdec->info.finfo->width);
486 GST_DEBUG_OBJECT (flacdec, "total samples = %" G_GINT64_FORMAT, samples);
495 gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
496 FLAC__StreamDecoderErrorStatus status, void *client_data)
501 dec = GST_FLAC_DEC (client_data);
504 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
505 /* Ignore this error and keep processing */
507 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
508 error = "bad header";
510 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
511 error = "CRC mismatch";
514 error = "unknown error";
518 if (gst_flac_dec_handle_decoder_error (dec, FALSE))
519 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
522 static FLAC__StreamDecoderReadStatus
523 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
524 FLAC__byte buffer[], size_t * bytes, void *client_data)
526 GstFlacDec *dec = GST_FLAC_DEC (client_data);
529 len = MIN (gst_adapter_available (dec->adapter), *bytes);
532 GST_LOG_OBJECT (dec, "0 bytes available at the moment");
533 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
536 GST_LOG_OBJECT (dec, "feeding %u bytes to decoder "
537 "(available=%" G_GSIZE_FORMAT ", bytes=%u)",
538 len, gst_adapter_available (dec->adapter), (guint) * bytes);
539 gst_adapter_copy (dec->adapter, buffer, 0, len);
542 gst_adapter_flush (dec->adapter, len);
544 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
547 static FLAC__StreamDecoderWriteStatus
548 gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
549 const FLAC__int32 * const buffer[])
551 GstFlowReturn ret = GST_FLOW_OK;
553 guint depth = frame->header.bits_per_sample;
555 guint sample_rate = frame->header.sample_rate;
556 guint channels = frame->header.channels;
557 guint samples = frame->header.blocksize;
560 gboolean caps_changed;
562 GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);
565 if (flacdec->depth < 4 || flacdec->depth > 32) {
566 GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
568 ret = GST_FLOW_ERROR;
572 depth = flacdec->depth;
589 GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
590 ret = GST_FLOW_ERROR;
594 if (sample_rate == 0) {
595 if (flacdec->info.rate != 0) {
596 sample_rate = flacdec->info.rate;
598 GST_ERROR_OBJECT (flacdec, "unknown sample rate");
599 ret = GST_FLOW_ERROR;
604 caps_changed = (sample_rate != flacdec->info.rate)
605 || (width != flacdec->info.finfo->width)
606 || (channels != flacdec->info.channels);
609 || !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) {
610 GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate,
613 gst_audio_info_set_format (&flacdec->info,
614 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, width),
615 sample_rate, channels, NULL);
617 memcpy (flacdec->info.position,
618 channel_positions[flacdec->info.channels - 1],
619 sizeof (GstAudioChannelPosition) * flacdec->info.channels);
620 gst_audio_channel_positions_to_valid_order (flacdec->info.position,
621 flacdec->info.channels);
622 /* Note: we create the inverse reordering map here */
623 gst_audio_get_channel_reorder_map (flacdec->info.channels,
624 flacdec->info.position, channel_positions[flacdec->info.channels - 1],
625 flacdec->channel_reorder_map);
627 flacdec->depth = depth;
629 gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec),
634 gst_buffer_new_allocate (NULL, samples * channels * (width / 8), NULL);
636 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
638 gint8 *outbuffer = (gint8 *) map.data;
639 gint *reorder_map = flacdec->channel_reorder_map;
641 if (width != depth) {
642 for (i = 0; i < samples; i++) {
643 for (j = 0; j < channels; j++) {
644 *outbuffer++ = (gint8) (buffer[reorder_map[j]][i] << (width - depth));
648 for (i = 0; i < samples; i++) {
649 for (j = 0; j < channels; j++) {
650 *outbuffer++ = (gint8) buffer[reorder_map[j]][i];
654 } else if (width == 16) {
655 gint16 *outbuffer = (gint16 *) map.data;
656 gint *reorder_map = flacdec->channel_reorder_map;
658 if (width != depth) {
659 for (i = 0; i < samples; i++) {
660 for (j = 0; j < channels; j++) {
662 (gint16) (buffer[reorder_map[j]][i] << (width - depth));
666 for (i = 0; i < samples; i++) {
667 for (j = 0; j < channels; j++) {
668 *outbuffer++ = (gint16) buffer[reorder_map[j]][i];
672 } else if (width == 32) {
673 gint32 *outbuffer = (gint32 *) map.data;
674 gint *reorder_map = flacdec->channel_reorder_map;
676 if (width != depth) {
677 for (i = 0; i < samples; i++) {
678 for (j = 0; j < channels; j++) {
680 (gint32) (buffer[reorder_map[j]][i] << (width - depth));
684 for (i = 0; i < samples; i++) {
685 for (j = 0; j < channels; j++) {
686 *outbuffer++ = (gint32) buffer[reorder_map[j]][i];
691 g_assert_not_reached ();
693 gst_buffer_unmap (outbuf, &map);
695 GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
696 if (flacdec->error_count)
697 flacdec->error_count--;
699 ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
701 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
702 GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret));
707 /* we act on the flow return value later in the handle_frame function, as we
708 * don't want to mess up the internal decoder state by returning ABORT when
709 * the error is in fact non-fatal (like a pad in flushing mode) and we want
710 * to continue later. So just pretend everything's dandy and act later. */
711 flacdec->last_flow = ret;
713 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
716 static FLAC__StreamDecoderWriteStatus
717 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
718 const FLAC__Frame * frame,
719 const FLAC__int32 * const buffer[], void *client_data)
721 return gst_flac_dec_write (GST_FLAC_DEC (client_data), frame, buffer);
725 gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard)
727 GstFlacDec *dec = GST_FLAC_DEC (audio_dec);
730 guint available = gst_adapter_available (dec->adapter);
733 GST_INFO_OBJECT (dec, "draining, %u bytes left in adapter", available);
734 FLAC__stream_decoder_process_until_end_of_stream (dec->decoder);
738 FLAC__stream_decoder_flush (dec->decoder);
739 gst_adapter_clear (dec->adapter);
743 gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
747 dec = GST_FLAC_DEC (audio_dec);
749 /* drain remaining data? */
750 if (G_UNLIKELY (buf == NULL)) {
751 gst_flac_dec_flush (audio_dec, FALSE);
755 GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, "
756 "%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
757 GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf));
759 /* drop any in-stream headers, we've processed those in set_format already */
760 if (G_UNLIKELY (!dec->got_headers)) {
761 gboolean got_audio_frame;
765 /* check if this is a flac audio frame (rather than a header or junk) */
766 gst_buffer_map (buf, &map, GST_MAP_READ);
768 gst_flac_dec_scan_got_frame (dec, map.data, map.size, &unused);
769 gst_buffer_unmap (buf, &map);
771 if (!got_audio_frame) {
772 GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " "
774 gst_audio_decoder_finish_frame (audio_dec, NULL, 1);
778 GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
779 dec->got_headers = TRUE;
782 gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
785 dec->last_flow = GST_FLOW_OK;
787 /* framed - there should always be enough data to decode something */
788 GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available",
789 gst_adapter_available (dec->adapter));
791 if (!FLAC__stream_decoder_process_single (dec->decoder)) {
792 GST_INFO_OBJECT (dec, "process_single failed");
795 return dec->last_flow;