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_metadata_cb (const FLAC__StreamDecoder * decoder,
420 const FLAC__StreamMetadata * metadata, void *client_data)
422 GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
424 GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type);
426 switch (metadata->type) {
427 case FLAC__METADATA_TYPE_STREAMINFO:{
431 samples = metadata->data.stream_info.total_samples;
433 flacdec->min_blocksize = metadata->data.stream_info.min_blocksize;
434 flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
435 flacdec->depth = depth = metadata->data.stream_info.bits_per_sample;
444 gst_audio_info_set_format (&flacdec->info,
445 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, width),
446 metadata->data.stream_info.sample_rate,
447 metadata->data.stream_info.channels, NULL);
449 memcpy (flacdec->info.position,
450 channel_positions[flacdec->info.channels - 1],
451 sizeof (GstAudioChannelPosition) * flacdec->info.channels);
452 gst_audio_channel_positions_to_valid_order (flacdec->info.position,
453 flacdec->info.channels);
454 /* Note: we create the inverse reordering map here */
455 gst_audio_get_channel_reorder_map (flacdec->info.channels,
456 flacdec->info.position, channel_positions[flacdec->info.channels - 1],
457 flacdec->channel_reorder_map);
459 GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
460 flacdec->min_blocksize, flacdec->max_blocksize);
461 GST_DEBUG_OBJECT (flacdec, "sample rate: %u, channels: %u",
462 flacdec->info.rate, flacdec->info.channels);
463 GST_DEBUG_OBJECT (flacdec, "depth: %u, width: %u", flacdec->depth,
464 flacdec->info.finfo->width);
466 GST_DEBUG_OBJECT (flacdec, "total samples = %" G_GINT64_FORMAT, samples);
475 gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
476 FLAC__StreamDecoderErrorStatus status, void *client_data)
481 dec = GST_FLAC_DEC (client_data);
484 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
485 /* Ignore this error and keep processing */
487 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
488 error = "bad header";
490 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
491 error = "CRC mismatch";
494 error = "unknown error";
498 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
499 dec->last_flow = GST_FLOW_ERROR;
502 static FLAC__StreamDecoderReadStatus
503 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
504 FLAC__byte buffer[], size_t * bytes, void *client_data)
506 GstFlacDec *dec = GST_FLAC_DEC (client_data);
509 len = MIN (gst_adapter_available (dec->adapter), *bytes);
512 GST_LOG_OBJECT (dec, "0 bytes available at the moment");
513 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
516 GST_LOG_OBJECT (dec, "feeding %u bytes to decoder "
517 "(available=%" G_GSIZE_FORMAT ", bytes=%u)",
518 len, gst_adapter_available (dec->adapter), (guint) * bytes);
519 gst_adapter_copy (dec->adapter, buffer, 0, len);
522 gst_adapter_flush (dec->adapter, len);
524 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
527 static FLAC__StreamDecoderWriteStatus
528 gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
529 const FLAC__int32 * const buffer[])
531 GstFlowReturn ret = GST_FLOW_OK;
533 guint depth = frame->header.bits_per_sample;
535 guint sample_rate = frame->header.sample_rate;
536 guint channels = frame->header.channels;
537 guint samples = frame->header.blocksize;
540 gboolean caps_changed;
542 GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);
545 if (flacdec->depth < 4 || flacdec->depth > 32) {
546 GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
548 ret = GST_FLOW_ERROR;
552 depth = flacdec->depth;
569 GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
570 ret = GST_FLOW_ERROR;
574 if (sample_rate == 0) {
575 if (flacdec->info.rate != 0) {
576 sample_rate = flacdec->info.rate;
578 GST_ERROR_OBJECT (flacdec, "unknown sample rate");
579 ret = GST_FLOW_ERROR;
584 caps_changed = (sample_rate != flacdec->info.rate)
585 || (width != flacdec->info.finfo->width)
586 || (channels != flacdec->info.channels);
589 || !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) {
590 GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate,
593 gst_audio_info_set_format (&flacdec->info,
594 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, width),
595 sample_rate, channels, NULL);
597 memcpy (flacdec->info.position,
598 channel_positions[flacdec->info.channels - 1],
599 sizeof (GstAudioChannelPosition) * flacdec->info.channels);
600 gst_audio_channel_positions_to_valid_order (flacdec->info.position,
601 flacdec->info.channels);
602 /* Note: we create the inverse reordering map here */
603 gst_audio_get_channel_reorder_map (flacdec->info.channels,
604 flacdec->info.position, channel_positions[flacdec->info.channels - 1],
605 flacdec->channel_reorder_map);
607 flacdec->depth = depth;
609 gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec),
613 GST_LOG_OBJECT (flacdec, "alloc_buffer_and_set_caps");
614 outbuf = gst_buffer_new_allocate (NULL, samples * channels * (width / 8), 0);
616 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
618 gint8 *outbuffer = (gint8 *) map.data;
619 gint *reorder_map = flacdec->channel_reorder_map;
621 if (width != depth) {
622 for (i = 0; i < samples; i++) {
623 for (j = 0; j < channels; j++) {
624 *outbuffer++ = (gint8) (buffer[reorder_map[j]][i] << (width - depth));
628 for (i = 0; i < samples; i++) {
629 for (j = 0; j < channels; j++) {
630 *outbuffer++ = (gint8) buffer[reorder_map[j]][i];
634 } else if (width == 16) {
635 gint16 *outbuffer = (gint16 *) map.data;
636 gint *reorder_map = flacdec->channel_reorder_map;
638 if (width != depth) {
639 for (i = 0; i < samples; i++) {
640 for (j = 0; j < channels; j++) {
642 (gint16) (buffer[reorder_map[j]][i] << (width - depth));
646 for (i = 0; i < samples; i++) {
647 for (j = 0; j < channels; j++) {
648 *outbuffer++ = (gint16) buffer[reorder_map[j]][i];
652 } else if (width == 32) {
653 gint32 *outbuffer = (gint32 *) map.data;
654 gint *reorder_map = flacdec->channel_reorder_map;
656 if (width != depth) {
657 for (i = 0; i < samples; i++) {
658 for (j = 0; j < channels; j++) {
660 (gint32) (buffer[reorder_map[j]][i] << (width - depth));
664 for (i = 0; i < samples; i++) {
665 for (j = 0; j < channels; j++) {
666 *outbuffer++ = (gint32) buffer[reorder_map[j]][i];
671 g_assert_not_reached ();
673 gst_buffer_unmap (outbuf, &map);
675 GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
677 ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
679 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
680 GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret));
685 /* we act on the flow return value later in the handle_frame function, as we
686 * don't want to mess up the internal decoder state by returning ABORT when
687 * the error is in fact non-fatal (like a pad in flushing mode) and we want
688 * to continue later. So just pretend everything's dandy and act later. */
689 flacdec->last_flow = ret;
691 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
694 static FLAC__StreamDecoderWriteStatus
695 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
696 const FLAC__Frame * frame,
697 const FLAC__int32 * const buffer[], void *client_data)
699 return gst_flac_dec_write (GST_FLAC_DEC (client_data), frame, buffer);
703 gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard)
705 GstFlacDec *dec = GST_FLAC_DEC (audio_dec);
708 guint available = gst_adapter_available (dec->adapter);
711 GST_INFO_OBJECT (dec, "draining, %u bytes left in adapter", available);
712 FLAC__stream_decoder_process_until_end_of_stream (dec->decoder);
716 FLAC__stream_decoder_flush (dec->decoder);
717 gst_adapter_clear (dec->adapter);
721 gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
725 dec = GST_FLAC_DEC (audio_dec);
727 /* drain remaining data? */
728 if (G_UNLIKELY (buf == NULL)) {
729 gst_flac_dec_flush (audio_dec, FALSE);
733 GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, "
734 "%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
735 GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf));
737 /* drop any in-stream headers, we've processed those in set_format already */
738 if (G_UNLIKELY (!dec->got_headers)) {
739 gboolean got_audio_frame;
743 /* check if this is a flac audio frame (rather than a header or junk) */
744 gst_buffer_map (buf, &map, GST_MAP_READ);
746 gst_flac_dec_scan_got_frame (dec, map.data, map.size, &unused);
747 gst_buffer_unmap (buf, &map);
749 if (!got_audio_frame) {
750 GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " "
752 gst_audio_decoder_finish_frame (audio_dec, NULL, 1);
756 GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
757 dec->got_headers = TRUE;
760 gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
763 dec->last_flow = GST_FLOW_OK;
765 /* framed - there should always be enough data to decode something */
766 GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available",
767 gst_adapter_available (dec->adapter));
769 if (!FLAC__stream_decoder_process_single (dec->decoder)) {
770 GST_INFO_OBJECT (dec, "process_single failed");
773 return dec->last_flow;