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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, 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-1.0 filesrc location=media/small/dark.441-16-s.flac ! flacparse ! flacdec ! audioconvert ! audioresample ! autoaudiosink
36 * gst-launch-1.0 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);
104 gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg);
105 static void gst_flac_dec_metadata_cb (const FLAC__StreamDecoder *
106 decoder, const FLAC__StreamMetadata * metadata, void *client_data);
107 static void gst_flac_dec_error_cb (const FLAC__StreamDecoder *
108 decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
110 static void gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard);
111 static gboolean gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps);
112 static gboolean gst_flac_dec_start (GstAudioDecoder * dec);
113 static gboolean gst_flac_dec_stop (GstAudioDecoder * dec);
114 static GstFlowReturn gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec,
117 G_DEFINE_TYPE (GstFlacDec, gst_flac_dec, GST_TYPE_AUDIO_DECODER);
119 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
120 #define FORMATS "{ S8, S16LE, S24_32LE, S32LE } "
122 #define FORMATS "{ S8, S16BE, S24_32BE, S32BE } "
125 #define GST_FLAC_DEC_SRC_CAPS \
127 "format = (string) " FORMATS ", " \
128 "layout = (string) interleaved, " \
129 "rate = (int) [ 1, 655350 ], " \
130 "channels = (int) [ 1, 8 ]"
132 #define GST_FLAC_DEC_SINK_CAPS \
134 "framed = (boolean) true, " \
135 "rate = (int) [ 1, 655350 ], " \
136 "channels = (int) [ 1, 8 ]"
138 static GstStaticPadTemplate flac_dec_src_factory =
139 GST_STATIC_PAD_TEMPLATE ("src",
142 GST_STATIC_CAPS (GST_FLAC_DEC_SRC_CAPS));
143 static GstStaticPadTemplate flac_dec_sink_factory =
144 GST_STATIC_PAD_TEMPLATE ("sink",
147 GST_STATIC_CAPS (GST_FLAC_DEC_SINK_CAPS));
150 gst_flac_dec_class_init (GstFlacDecClass * klass)
152 GstAudioDecoderClass *audiodecoder_class;
153 GstElementClass *gstelement_class;
155 audiodecoder_class = (GstAudioDecoderClass *) klass;
156 gstelement_class = (GstElementClass *) klass;
158 GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
160 audiodecoder_class->stop = GST_DEBUG_FUNCPTR (gst_flac_dec_stop);
161 audiodecoder_class->start = GST_DEBUG_FUNCPTR (gst_flac_dec_start);
162 audiodecoder_class->flush = GST_DEBUG_FUNCPTR (gst_flac_dec_flush);
163 audiodecoder_class->set_format = GST_DEBUG_FUNCPTR (gst_flac_dec_set_format);
164 audiodecoder_class->handle_frame =
165 GST_DEBUG_FUNCPTR (gst_flac_dec_handle_frame);
167 gst_element_class_add_static_pad_template (gstelement_class,
168 &flac_dec_src_factory);
169 gst_element_class_add_static_pad_template (gstelement_class,
170 &flac_dec_sink_factory);
172 gst_element_class_set_static_metadata (gstelement_class, "FLAC audio decoder",
173 "Codec/Decoder/Audio", "Decodes FLAC lossless audio streams",
174 "Tim-Philipp Müller <tim@centricular.net>, "
175 "Wim Taymans <wim.taymans@gmail.com>");
179 gst_flac_dec_init (GstFlacDec * flacdec)
181 flacdec->do_resync = FALSE;
182 gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (flacdec), TRUE);
183 gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
185 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (flacdec));
189 gst_flac_dec_start (GstAudioDecoder * audio_dec)
191 FLAC__StreamDecoderInitStatus s;
194 dec = GST_FLAC_DEC (audio_dec);
196 dec->adapter = gst_adapter_new ();
198 dec->decoder = FLAC__stream_decoder_new ();
200 gst_audio_info_init (&dec->info);
203 /* no point calculating MD5 since it's never checked here */
204 FLAC__stream_decoder_set_md5_checking (dec->decoder, false);
206 GST_DEBUG_OBJECT (dec, "initializing decoder");
207 s = FLAC__stream_decoder_init_stream (dec->decoder,
208 gst_flac_dec_read_stream, NULL, NULL, NULL, NULL,
209 gst_flac_dec_write_stream, gst_flac_dec_metadata_cb,
210 gst_flac_dec_error_cb, dec);
212 if (s != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
213 GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL));
217 dec->got_headers = FALSE;
223 gst_flac_dec_stop (GstAudioDecoder * dec)
225 GstFlacDec *flacdec = GST_FLAC_DEC (dec);
227 if (flacdec->decoder) {
228 FLAC__stream_decoder_delete (flacdec->decoder);
229 flacdec->decoder = NULL;
232 if (flacdec->adapter) {
233 gst_adapter_clear (flacdec->adapter);
234 g_object_unref (flacdec->adapter);
235 flacdec->adapter = NULL;
242 gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps)
244 const GValue *headers;
249 flacdec = GST_FLAC_DEC (dec);
251 GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps);
253 s = gst_caps_get_structure (caps, 0);
254 headers = gst_structure_get_value (s, "streamheader");
255 if (headers == NULL || !GST_VALUE_HOLDS_ARRAY (headers)) {
256 GST_WARNING_OBJECT (dec, "no 'streamheader' field in input caps, try "
257 "adding a flacparse element upstream");
261 if (gst_adapter_available (flacdec->adapter) > 0) {
262 GST_WARNING_OBJECT (dec, "unexpected data left in adapter");
263 gst_adapter_clear (flacdec->adapter);
266 num = gst_value_array_get_size (headers);
267 for (i = 0; i < num; ++i) {
268 const GValue *header_val;
269 GstBuffer *header_buf;
271 header_val = gst_value_array_get_value (headers, i);
272 if (header_val == NULL || !GST_VALUE_HOLDS_BUFFER (header_val))
275 header_buf = g_value_dup_boxed (header_val);
276 GST_INFO_OBJECT (dec, "pushing header buffer of %" G_GSIZE_FORMAT " bytes "
277 "into adapter", gst_buffer_get_size (header_buf));
278 gst_adapter_push (flacdec->adapter, header_buf);
281 GST_DEBUG_OBJECT (dec, "Processing headers and metadata");
282 if (!FLAC__stream_decoder_process_until_end_of_metadata (flacdec->decoder)) {
283 GST_WARNING_OBJECT (dec, "process_until_end_of_metadata failed");
284 if (FLAC__stream_decoder_get_state (flacdec->decoder) ==
285 FLAC__STREAM_DECODER_ABORTED) {
286 GST_WARNING_OBJECT (flacdec, "Read callback caused internal abort");
288 gst_adapter_clear (flacdec->adapter);
289 FLAC__stream_decoder_flush (flacdec->decoder);
290 gst_flac_dec_handle_decoder_error (flacdec, TRUE);
293 GST_INFO_OBJECT (dec, "headers and metadata are now processed");
297 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
298 static const guint8 crc8_table[256] = {
299 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
300 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
301 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
302 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
303 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
304 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
305 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
306 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
307 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
308 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
309 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
310 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
311 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
312 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
313 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
314 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
315 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
316 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
317 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
318 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
319 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
320 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
321 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
322 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
323 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
324 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
325 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
326 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
327 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
328 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
329 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
330 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
334 gst_flac_calculate_crc8 (const guint8 * data, guint length)
339 crc = crc8_table[crc ^ *data];
346 /* FIXME: for our purposes it's probably enough to just check for the sync
347 * marker - we just want to know if it's a header frame or not */
349 gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, const guint8 * data,
353 guint sr_from_end = 0; /* can be 0, 8 or 16 */
354 guint bs_from_end = 0; /* can be 0, 8 or 16 */
356 guint8 bs, sr, ca, ss, pb;
363 if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
366 vbs = ! !(data[1] & 1); /* variable blocksize */
367 bs = (data[2] & 0xF0) >> 4; /* blocksize marker */
368 sr = (data[2] & 0x0F); /* samplerate marker */
369 ca = (data[3] & 0xF0) >> 4; /* channel assignment */
370 ss = (data[3] & 0x0F) >> 1; /* sample size marker */
371 pb = (data[3] & 0x01); /* padding bit */
373 GST_LOG_OBJECT (flacdec,
374 "got sync, vbs=%d,bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", vbs, bs, sr, ca, ss,
377 if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
381 /* read block size from end of header? */
387 /* read sample rate from end of header? */
390 else if (sr == 0x0D || sr == 0x0E)
394 /* This is slightly faster than a loop */
397 } else if ((val & 0xc0) && !(val & 0x20)) {
399 } else if ((val & 0xe0) && !(val & 0x10)) {
401 } else if ((val & 0xf0) && !(val & 0x08)) {
403 } else if ((val & 0xf8) && !(val & 0x04)) {
405 } else if ((val & 0xfc) && !(val & 0x02)) {
407 } else if ((val & 0xfe) && !(val & 0x01)) {
410 GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
415 headerlen = 4 + val + (bs_from_end / 8) + (sr_from_end / 8);
417 if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
418 GST_LOG_OBJECT (flacdec, "invalid checksum");
426 gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg)
431 if (dec->error_count > 10) {
433 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL));
434 dec->last_flow = GST_FLOW_ERROR;
437 GST_DEBUG_OBJECT (dec, "ignoring error for now at count %d",
446 gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder,
447 const FLAC__StreamMetadata * metadata, void *client_data)
449 GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
450 GstAudioChannelPosition position[8];
452 GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type);
454 switch (metadata->type) {
455 case FLAC__METADATA_TYPE_STREAMINFO:{
457 guint depth, width, gdepth, channels;
459 samples = metadata->data.stream_info.total_samples;
461 flacdec->min_blocksize = metadata->data.stream_info.min_blocksize;
462 flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
463 flacdec->depth = depth = metadata->data.stream_info.bits_per_sample;
467 } else if (depth < 17) {
469 } else if (depth < 25) {
476 channels = metadata->data.stream_info.channels;
477 memcpy (position, channel_positions[channels - 1], sizeof (position));
478 gst_audio_channel_positions_to_valid_order (position, channels);
479 /* Note: we create the inverse reordering map here */
480 gst_audio_get_channel_reorder_map (channels,
481 position, channel_positions[channels - 1],
482 flacdec->channel_reorder_map);
484 gst_audio_info_set_format (&flacdec->info,
485 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth),
486 metadata->data.stream_info.sample_rate,
487 metadata->data.stream_info.channels, position);
489 GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
490 flacdec->min_blocksize, flacdec->max_blocksize);
491 GST_DEBUG_OBJECT (flacdec, "sample rate: %u, channels: %u",
492 flacdec->info.rate, flacdec->info.channels);
493 GST_DEBUG_OBJECT (flacdec, "depth: %u, width: %u", flacdec->depth,
494 flacdec->info.finfo->width);
496 GST_DEBUG_OBJECT (flacdec, "total samples = %" G_GINT64_FORMAT, samples);
505 gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
506 FLAC__StreamDecoderErrorStatus status, void *client_data)
511 dec = GST_FLAC_DEC (client_data);
514 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
515 dec->do_resync = TRUE;
517 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
518 error = "bad header";
520 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
521 error = "CRC mismatch";
524 error = "unknown error";
528 if (gst_flac_dec_handle_decoder_error (dec, FALSE))
529 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
532 static FLAC__StreamDecoderReadStatus
533 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
534 FLAC__byte buffer[], size_t * bytes, void *client_data)
536 GstFlacDec *dec = GST_FLAC_DEC (client_data);
539 len = MIN (gst_adapter_available (dec->adapter), *bytes);
542 GST_LOG_OBJECT (dec, "0 bytes available at the moment");
543 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
546 GST_LOG_OBJECT (dec, "feeding %u bytes to decoder "
547 "(available=%" G_GSIZE_FORMAT ", bytes=%u)",
548 len, gst_adapter_available (dec->adapter), (guint) * bytes);
549 gst_adapter_copy (dec->adapter, buffer, 0, len);
552 gst_adapter_flush (dec->adapter, len);
554 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
557 static FLAC__StreamDecoderWriteStatus
558 gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
559 const FLAC__int32 * const buffer[])
561 GstFlowReturn ret = GST_FLOW_OK;
563 guint depth = frame->header.bits_per_sample;
565 guint sample_rate = frame->header.sample_rate;
566 guint channels = frame->header.channels;
567 guint samples = frame->header.blocksize;
570 gboolean caps_changed;
571 GstAudioChannelPosition chanpos[8];
573 GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);
576 if (flacdec->depth < 4 || flacdec->depth > 32) {
577 GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
579 ret = GST_FLOW_ERROR;
583 depth = flacdec->depth;
603 GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
604 ret = GST_FLOW_ERROR;
608 if (sample_rate == 0) {
609 if (flacdec->info.rate != 0) {
610 sample_rate = flacdec->info.rate;
612 GST_ERROR_OBJECT (flacdec, "unknown sample rate");
613 ret = GST_FLOW_ERROR;
618 caps_changed = (sample_rate != GST_AUDIO_INFO_RATE (&flacdec->info))
619 || (width != GST_AUDIO_INFO_WIDTH (&flacdec->info))
620 || (gdepth != GST_AUDIO_INFO_DEPTH (&flacdec->info))
621 || (channels != GST_AUDIO_INFO_CHANNELS (&flacdec->info));
624 || !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) {
625 GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate,
628 memcpy (chanpos, channel_positions[flacdec->info.channels - 1],
630 gst_audio_channel_positions_to_valid_order (chanpos,
631 flacdec->info.channels);
632 gst_audio_info_set_format (&flacdec->info,
633 gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth),
634 sample_rate, channels, chanpos);
636 /* Note: we create the inverse reordering map here */
637 gst_audio_get_channel_reorder_map (flacdec->info.channels,
638 flacdec->info.position, channel_positions[flacdec->info.channels - 1],
639 flacdec->channel_reorder_map);
641 flacdec->depth = depth;
643 gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec),
648 gst_buffer_new_allocate (NULL, samples * channels * (width / 8), NULL);
650 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
652 gint8 *outbuffer = (gint8 *) map.data;
653 gint *reorder_map = flacdec->channel_reorder_map;
655 g_assert (gdepth == 8 && depth == 8);
656 for (i = 0; i < samples; i++) {
657 for (j = 0; j < channels; j++) {
658 *outbuffer++ = (gint8) buffer[reorder_map[j]][i];
661 } else if (width == 16) {
662 gint16 *outbuffer = (gint16 *) map.data;
663 gint *reorder_map = flacdec->channel_reorder_map;
665 if (gdepth != depth) {
666 for (i = 0; i < samples; i++) {
667 for (j = 0; j < channels; j++) {
669 (gint16) (buffer[reorder_map[j]][i] << (gdepth - depth));
673 for (i = 0; i < samples; i++) {
674 for (j = 0; j < channels; j++) {
675 *outbuffer++ = (gint16) buffer[reorder_map[j]][i];
679 } else if (width == 32) {
680 gint32 *outbuffer = (gint32 *) map.data;
681 gint *reorder_map = flacdec->channel_reorder_map;
683 if (gdepth != depth) {
684 for (i = 0; i < samples; i++) {
685 for (j = 0; j < channels; j++) {
687 (gint32) (buffer[reorder_map[j]][i] << (gdepth - depth));
691 for (i = 0; i < samples; i++) {
692 for (j = 0; j < channels; j++) {
693 *outbuffer++ = (gint32) buffer[reorder_map[j]][i];
698 g_assert_not_reached ();
700 gst_buffer_unmap (outbuf, &map);
702 GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
703 if (flacdec->error_count)
704 flacdec->error_count--;
706 ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
708 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
709 GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret));
714 /* we act on the flow return value later in the handle_frame function, as we
715 * don't want to mess up the internal decoder state by returning ABORT when
716 * the error is in fact non-fatal (like a pad in flushing mode) and we want
717 * to continue later. So just pretend everything's dandy and act later. */
718 flacdec->last_flow = ret;
720 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
723 static FLAC__StreamDecoderWriteStatus
724 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
725 const FLAC__Frame * frame,
726 const FLAC__int32 * const buffer[], void *client_data)
728 return gst_flac_dec_write (GST_FLAC_DEC (client_data), frame, buffer);
732 gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard)
734 GstFlacDec *dec = GST_FLAC_DEC (audio_dec);
737 guint available = gst_adapter_available (dec->adapter);
740 GST_INFO_OBJECT (dec, "draining, %u bytes left in adapter", available);
741 FLAC__stream_decoder_process_until_end_of_stream (dec->decoder);
745 dec->do_resync = FALSE;
746 FLAC__stream_decoder_flush (dec->decoder);
747 gst_adapter_clear (dec->adapter);
751 gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
755 dec = GST_FLAC_DEC (audio_dec);
757 /* drain remaining data? */
758 if (G_UNLIKELY (buf == NULL)) {
759 gst_flac_dec_flush (audio_dec, FALSE);
763 if (dec->do_resync) {
764 GST_WARNING_OBJECT (dec, "Lost sync, flushing decoder");
765 FLAC__stream_decoder_flush (dec->decoder);
766 dec->do_resync = FALSE;
769 GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, "
770 "%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
771 GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf));
773 /* drop any in-stream headers, we've processed those in set_format already */
774 if (G_UNLIKELY (!dec->got_headers)) {
775 gboolean got_audio_frame;
778 /* check if this is a flac audio frame (rather than a header or junk) */
779 gst_buffer_map (buf, &map, GST_MAP_READ);
780 got_audio_frame = gst_flac_dec_scan_got_frame (dec, map.data, map.size);
781 gst_buffer_unmap (buf, &map);
783 if (!got_audio_frame) {
784 GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " "
786 gst_audio_decoder_finish_frame (audio_dec, NULL, 1);
790 GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
791 dec->got_headers = TRUE;
794 gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
797 dec->last_flow = GST_FLOW_OK;
799 /* framed - there should always be enough data to decode something */
800 GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available",
801 gst_adapter_available (dec->adapter));
803 if (!FLAC__stream_decoder_process_single (dec->decoder)) {
804 GST_INFO_OBJECT (dec, "process_single failed");
805 if (FLAC__stream_decoder_get_state (dec->decoder) ==
806 FLAC__STREAM_DECODER_ABORTED) {
807 GST_WARNING_OBJECT (dec, "Read callback caused internal abort");
809 gst_adapter_clear (dec->adapter);
810 FLAC__stream_decoder_flush (dec->decoder);
811 gst_flac_dec_handle_decoder_error (dec, TRUE);
815 return dec->last_flow;