2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include <sys/soundcard.h>
23 /*#define DEBUG_ENABLED */
24 #include "gstflacdec.h"
26 #include "flac_compat.h"
28 extern GstPadTemplate *gst_flacdec_src_template, *gst_flacdec_sink_template;
30 /* elementfactory information */
31 GstElementDetails flacdec_details = {
33 "Codec/Audio/Decoder",
35 "Decodes FLAC lossless audio streams",
37 "Wim Taymans <wim.taymans@chello.be>",
41 /* FlacDec signals and args */
51 static void gst_flacdec_class_init (FlacDecClass *klass);
52 static void gst_flacdec_init (FlacDec *flacdec);
54 static void gst_flacdec_loop (GstElement *element);
55 static GstElementStateReturn
56 gst_flacdec_change_state (GstElement *element);
57 static const GstFormat* gst_flacdec_get_src_formats (GstPad *pad);
58 static gboolean gst_flacdec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
59 GstFormat *dest_format, gint64 *dest_value);
60 static const GstPadQueryType*
61 gst_flacdec_get_src_query_types (GstPad *pad);
62 static gboolean gst_flacdec_src_query (GstPad *pad, GstPadQueryType type,
63 GstFormat *format, gint64 *value);
64 static const GstEventMask*
65 gst_flacdec_get_src_event_masks (GstPad *pad);
66 static gboolean gst_flacdec_src_event (GstPad *pad, GstEvent *event);
68 static FLAC__SeekableStreamDecoderReadStatus
69 gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder,
70 FLAC__byte buffer[], unsigned *bytes,
72 static FLAC__SeekableStreamDecoderSeekStatus
73 gst_flacdec_seek (const FLAC__SeekableStreamDecoder *decoder,
74 FLAC__uint64 position, void *client_data);
75 static FLAC__SeekableStreamDecoderTellStatus
76 gst_flacdec_tell (const FLAC__SeekableStreamDecoder *decoder,
77 FLAC__uint64 *position, void *client_data);
78 static FLAC__SeekableStreamDecoderLengthStatus
79 gst_flacdec_length (const FLAC__SeekableStreamDecoder *decoder,
80 FLAC__uint64 *length, void *client_data);
81 static FLAC__bool gst_flacdec_eof (const FLAC__SeekableStreamDecoder *decoder,
83 static FLAC__StreamDecoderWriteStatus
84 gst_flacdec_write (const FLAC__SeekableStreamDecoder *decoder,
85 const FLAC__Frame *frame,
86 const FLAC__int32 * const buffer[],
88 static void gst_flacdec_metadata_callback (const FLAC__SeekableStreamDecoder *decoder,
89 const FLAC__StreamMetadata *metadata,
91 static void gst_flacdec_error_callback (const FLAC__SeekableStreamDecoder *decoder,
92 FLAC__StreamDecoderErrorStatus status,
95 static GstElementClass *parent_class = NULL;
96 /*static guint gst_flacdec_signals[LAST_SIGNAL] = { 0 }; */
99 flacdec_get_type(void) {
100 static GType flacdec_type = 0;
103 static const GTypeInfo flacdec_info = {
104 sizeof(FlacDecClass),
107 (GClassInitFunc)gst_flacdec_class_init,
112 (GInstanceInitFunc)gst_flacdec_init,
114 flacdec_type = g_type_register_static (GST_TYPE_ELEMENT, "FlacDec", &flacdec_info, 0);
120 gst_flacdec_class_init (FlacDecClass *klass)
122 GstElementClass *gstelement_class;
124 gstelement_class = (GstElementClass*)klass;
126 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
128 gstelement_class->change_state = gst_flacdec_change_state;
132 gst_flacdec_init (FlacDec *flacdec)
134 flacdec->sinkpad = gst_pad_new_from_template (gst_flacdec_sink_template, "sink");
135 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
136 gst_pad_set_convert_function (flacdec->sinkpad, NULL);
138 gst_element_set_loop_function (GST_ELEMENT (flacdec), gst_flacdec_loop);
139 flacdec->srcpad = gst_pad_new_from_template (gst_flacdec_src_template, "src");
140 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
141 gst_pad_set_formats_function (flacdec->srcpad, gst_flacdec_get_src_formats);
142 gst_pad_set_convert_function (flacdec->srcpad, gst_flacdec_convert_src);
143 gst_pad_set_query_type_function (flacdec->srcpad, gst_flacdec_get_src_query_types);
144 gst_pad_set_query_function (flacdec->srcpad, gst_flacdec_src_query);
145 gst_pad_set_event_mask_function (flacdec->srcpad, gst_flacdec_get_src_event_masks);
146 gst_pad_set_event_function (flacdec->srcpad, gst_flacdec_src_event);
148 flacdec->decoder = FLAC__seekable_stream_decoder_new ();
149 flacdec->total_samples = 0;
150 flacdec->init = TRUE;
151 flacdec->eos = FALSE;
152 flacdec->seek_pending = FALSE;
154 FLAC__seekable_stream_decoder_set_read_callback (flacdec->decoder, gst_flacdec_read);
155 FLAC__seekable_stream_decoder_set_seek_callback (flacdec->decoder, gst_flacdec_seek);
156 FLAC__seekable_stream_decoder_set_tell_callback (flacdec->decoder, gst_flacdec_tell);
157 FLAC__seekable_stream_decoder_set_length_callback (flacdec->decoder, gst_flacdec_length);
158 FLAC__seekable_stream_decoder_set_eof_callback (flacdec->decoder, gst_flacdec_eof);
159 #if FLAC_VERSION >= 0x010003
160 FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder, gst_flacdec_write);
162 FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder,
163 (FLAC__StreamDecoderWriteStatus (*)
164 (const FLAC__SeekableStreamDecoder *decoder,
165 const FLAC__Frame *frame,
166 const FLAC__int32 *buffer[],
168 (gst_flacdec_write));
170 FLAC__seekable_stream_decoder_set_metadata_callback (flacdec->decoder, gst_flacdec_metadata_callback);
171 FLAC__seekable_stream_decoder_set_error_callback (flacdec->decoder, gst_flacdec_error_callback);
172 FLAC__seekable_stream_decoder_set_client_data (flacdec->decoder, flacdec);
176 gst_flacdec_metadata_callback (const FLAC__SeekableStreamDecoder *decoder,
177 const FLAC__StreamMetadata *metadata, void *client_data)
181 flacdec = GST_FLACDEC (client_data);
183 flacdec->stream_samples = metadata->data.stream_info.total_samples;
187 gst_flacdec_error_callback (const FLAC__SeekableStreamDecoder *decoder,
188 FLAC__StreamDecoderErrorStatus status, void *client_data)
193 flacdec = GST_FLACDEC (client_data);
196 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
199 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
200 error = "bad header";
202 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
203 error = "CRC mismatch";
206 error = "unkown error";
210 GST_DEBUG (0, error);
212 gst_element_error (GST_ELEMENT (flacdec), error);
215 static FLAC__SeekableStreamDecoderSeekStatus
216 gst_flacdec_seek (const FLAC__SeekableStreamDecoder *decoder,
217 FLAC__uint64 position, void *client_data)
221 flacdec = GST_FLACDEC (client_data);
223 GST_DEBUG (0, "seek %lld\n", position);
224 if (!gst_bytestream_seek (flacdec->bs, position, GST_SEEK_METHOD_SET)) {
225 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
227 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
230 static FLAC__SeekableStreamDecoderTellStatus
231 gst_flacdec_tell (const FLAC__SeekableStreamDecoder *decoder,
232 FLAC__uint64 *position, void *client_data)
236 flacdec = GST_FLACDEC (client_data);
238 *position = gst_bytestream_tell (flacdec->bs);
240 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
242 GST_DEBUG (0, "tell %lld\n", *position);
244 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
247 static FLAC__SeekableStreamDecoderLengthStatus
248 gst_flacdec_length (const FLAC__SeekableStreamDecoder *decoder,
249 FLAC__uint64 *length, void *client_data)
253 flacdec = GST_FLACDEC (client_data);
255 *length = gst_bytestream_length (flacdec->bs);
257 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
259 GST_DEBUG (0, "length %lld\n", *length);
261 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
265 gst_flacdec_eof (const FLAC__SeekableStreamDecoder *decoder,
270 flacdec = GST_FLACDEC (client_data);
271 GST_DEBUG (0, "eof %d\n", flacdec->eos);
276 static FLAC__SeekableStreamDecoderReadStatus
277 gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder,
278 FLAC__byte buffer[], unsigned *bytes,
285 flacdec = GST_FLACDEC (client_data);
287 //g_print ("read %u\n", *bytes);
289 while (insize == 0) {
290 insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, *bytes);
291 if (insize < *bytes) {
295 gst_bytestream_get_status (flacdec->bs, &avail, &event);
297 switch (GST_EVENT_TYPE (event)) {
299 GST_DEBUG (0, "eos");
301 gst_event_unref (event);
306 case GST_EVENT_DISCONTINUOUS:
307 GST_DEBUG (0, "discont");
309 /* we are not yet sending the discont, we'll do that in the next write operation */
310 flacdec->need_discont = TRUE;
311 gst_event_unref (event);
314 gst_pad_event_default (flacdec->sinkpad, event);
318 insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, avail);
324 memcpy (buffer, indata, insize);
326 gst_bytestream_flush_fast (flacdec->bs, insize);
328 return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
331 static FLAC__StreamDecoderWriteStatus
332 gst_flacdec_write (const FLAC__SeekableStreamDecoder *decoder,
333 const FLAC__Frame *frame,
334 const FLAC__int32 * const buffer[],
339 guint depth = frame->header.bits_per_sample;
340 guint channels = frame->header.channels;
341 guint samples = frame->header.blocksize;
344 flacdec = GST_FLACDEC (client_data);
346 if (flacdec->need_discont) {
347 gint64 time = 0, bytes = 0;
351 flacdec->need_discont = FALSE;
353 if (flacdec->seek_pending) {
354 flacdec->total_samples = flacdec->seek_value;
357 GST_DEBUG (0, "send discont");
359 format = GST_FORMAT_TIME;
360 gst_pad_convert (flacdec->srcpad, GST_FORMAT_UNITS, flacdec->total_samples,
362 format = GST_FORMAT_BYTES;
363 gst_pad_convert (flacdec->srcpad, GST_FORMAT_UNITS, flacdec->total_samples,
365 discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
366 GST_FORMAT_BYTES, bytes,
367 GST_FORMAT_UNITS, flacdec->total_samples,
370 gst_pad_push (flacdec->srcpad, GST_BUFFER (discont));
373 if (!GST_PAD_CAPS (flacdec->srcpad)) {
374 gst_pad_try_set_caps (flacdec->srcpad,
378 "format", GST_PROPS_STRING ("int"),
379 "law", GST_PROPS_INT (0),
380 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
381 "signed", GST_PROPS_BOOLEAN (TRUE),
382 "width", GST_PROPS_INT (depth),
383 "depth", GST_PROPS_INT (depth),
384 "rate", GST_PROPS_INT (frame->header.sample_rate),
385 "channels", GST_PROPS_INT (channels)
388 flacdec->depth = depth;
389 flacdec->channels = channels;
390 flacdec->frequency = frame->header.sample_rate;
393 outbuf = gst_buffer_new ();
394 GST_BUFFER_SIZE (outbuf) = samples * channels * ((depth+7)>>3);
395 GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
396 GST_BUFFER_TIMESTAMP (outbuf) = flacdec->total_samples * GST_SECOND / frame->header.sample_rate;
399 guint8 *outbuffer = (guint8 *)GST_BUFFER_DATA (outbuf);
401 for (i=0; i<samples; i++) {
402 for (j=0; j < channels; j++) {
403 *outbuffer++ = (guint8) buffer[j][i];
407 else if (depth == 16) {
408 guint16 *outbuffer = (guint16 *)GST_BUFFER_DATA (outbuf);
410 for (i=0; i<samples; i++) {
411 for (j=0; j < channels; j++) {
412 *outbuffer++ = (guint16) buffer[j][i];
417 g_warning ("flacdec: invalid depth %d found\n", depth);
418 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
421 flacdec->total_samples += samples;
423 gst_pad_push (flacdec->srcpad, outbuf);
425 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
429 gst_flacdec_loop (GstElement *element)
434 flacdec = GST_FLACDEC (element);
437 FLAC__seekable_stream_decoder_init (flacdec->decoder);
438 FLAC__seekable_stream_decoder_process_metadata (flacdec->decoder);
439 flacdec->init = FALSE;
442 if (flacdec->seek_pending) {
443 GST_DEBUG (GST_CAT_EVENT, "perform seek to sample %lld\n",
444 flacdec->seek_value);
446 if (FLAC__seekable_stream_decoder_seek_absolute (flacdec->decoder,
447 flacdec->seek_value))
449 flacdec->total_samples = flacdec->seek_value;
450 GST_DEBUG (GST_CAT_EVENT, "seek done\n");
453 GST_DEBUG (GST_CAT_EVENT, "seek failed\n");
455 flacdec->seek_pending = FALSE;
458 res = FLAC__seekable_stream_decoder_process_one_frame (flacdec->decoder);
459 if (FLAC__seekable_stream_decoder_get_state (flacdec->decoder) ==
460 FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
464 FLAC__seekable_stream_decoder_finish(flacdec->decoder);
465 flacdec->init = TRUE;
467 event = gst_event_new(GST_EVENT_EOS);
468 gst_pad_push (flacdec->srcpad, GST_BUFFER (event));
469 gst_element_set_eos (element);
473 GST_FORMATS_FUNCTION (gst_flacdec_get_src_formats,
480 gst_flacdec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
481 GstFormat *dest_format, gint64 *dest_value)
484 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
486 gint bytes_per_sample;
488 bytes_per_sample = flacdec->channels * ((flacdec->depth+7)>>3);
490 switch (src_format) {
491 case GST_FORMAT_BYTES:
492 switch (*dest_format) {
493 case GST_FORMAT_UNITS:
494 if (bytes_per_sample == 0)
496 *dest_value = src_value / bytes_per_sample;
498 case GST_FORMAT_DEFAULT:
499 *dest_format = GST_FORMAT_TIME;
500 case GST_FORMAT_TIME:
502 gint byterate = bytes_per_sample * flacdec->frequency;
506 *dest_value = src_value * GST_SECOND / byterate;
513 case GST_FORMAT_UNITS:
514 switch (*dest_format) {
515 case GST_FORMAT_BYTES:
516 *dest_value = src_value * bytes_per_sample;
518 case GST_FORMAT_DEFAULT:
519 *dest_format = GST_FORMAT_TIME;
520 case GST_FORMAT_TIME:
521 if (flacdec->frequency == 0)
523 *dest_value = src_value * GST_SECOND / flacdec->frequency;
529 case GST_FORMAT_TIME:
530 switch (*dest_format) {
531 case GST_FORMAT_DEFAULT:
532 *dest_format = GST_FORMAT_BYTES;
533 case GST_FORMAT_BYTES:
534 scale = bytes_per_sample;
535 case GST_FORMAT_UNITS:
536 *dest_value = src_value * scale * flacdec->frequency / GST_SECOND;
548 GST_PAD_QUERY_TYPE_FUNCTION (gst_flacdec_get_src_query_types,
550 GST_PAD_QUERY_POSITION
554 gst_flacdec_src_query (GstPad *pad, GstPadQueryType type,
555 GstFormat *format, gint64 *value)
558 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
561 case GST_PAD_QUERY_TOTAL:
565 if (flacdec->stream_samples == 0)
566 samples = flacdec->total_samples;
568 samples = flacdec->stream_samples;
570 gst_pad_convert (flacdec->srcpad,
576 case GST_PAD_QUERY_POSITION:
577 gst_pad_convert (flacdec->srcpad,
579 flacdec->total_samples,
590 GST_EVENT_MASK_FUNCTION (gst_flacdec_get_src_event_masks,
591 { GST_EVENT_SEEK, GST_SEEK_FLAG_ACCURATE }
595 gst_flacdec_src_event (GstPad *pad, GstEvent *event)
598 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
601 switch (GST_EVENT_TYPE (event)) {
603 format = GST_FORMAT_UNITS;
605 if (gst_pad_convert (flacdec->srcpad,
606 GST_EVENT_SEEK_FORMAT (event),
607 GST_EVENT_SEEK_OFFSET (event),
608 &format, &flacdec->seek_value))
609 flacdec->seek_pending = TRUE;
617 gst_event_unref (event);
621 static GstElementStateReturn
622 gst_flacdec_change_state (GstElement *element)
624 FlacDec *flacdec = GST_FLACDEC (element);
626 switch (GST_STATE_TRANSITION (element)) {
627 case GST_STATE_NULL_TO_READY:
628 case GST_STATE_READY_TO_PAUSED:
629 flacdec->bs = gst_bytestream_new (flacdec->sinkpad);
630 flacdec->seek_pending = FALSE;
631 flacdec->total_samples = 0;
632 flacdec->init = TRUE;
633 flacdec->eos = FALSE;
635 case GST_STATE_PAUSED_TO_PLAYING:
636 flacdec->eos = FALSE;
637 case GST_STATE_PLAYING_TO_PAUSED:
639 case GST_STATE_PAUSED_TO_READY:
640 gst_bytestream_destroy (flacdec->bs);
642 case GST_STATE_READY_TO_NULL:
647 if (GST_ELEMENT_CLASS (parent_class)->change_state)
648 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
650 return GST_STATE_SUCCESS;