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"
27 extern GstPadTemplate *gst_flacdec_src_template, *gst_flacdec_sink_template;
29 /* elementfactory information */
30 GstElementDetails flacdec_details = {
32 "Codec/Audio/Decoder",
33 "Decodes FLAC lossless audio streams",
35 "Wim Taymans <wim.taymans@chello.be>",
39 /* FlacDec signals and args */
49 static void gst_flacdec_class_init (FlacDecClass *klass);
50 static void gst_flacdec_init (FlacDec *flacdec);
52 static void gst_flacdec_loop (GstElement *element);
53 static GstElementStateReturn
54 gst_flacdec_change_state (GstElement *element);
55 static const GstFormat* gst_flacdec_get_src_formats (GstPad *pad);
56 static gboolean gst_flacdec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
57 GstFormat *dest_format, gint64 *dest_value);
58 static const GstPadQueryType*
59 gst_flacdec_get_src_query_types (GstPad *pad);
60 static gboolean gst_flacdec_src_query (GstPad *pad, GstPadQueryType type,
61 GstFormat *format, gint64 *value);
62 static const GstEventMask*
63 gst_flacdec_get_src_event_masks (GstPad *pad);
64 static gboolean gst_flacdec_src_event (GstPad *pad, GstEvent *event);
66 static FLAC__SeekableStreamDecoderReadStatus
67 gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder,
68 FLAC__byte buffer[], unsigned *bytes,
70 static FLAC__SeekableStreamDecoderSeekStatus
71 gst_flacdec_seek (const FLAC__SeekableStreamDecoder *decoder,
72 FLAC__uint64 position, void *client_data);
73 static FLAC__SeekableStreamDecoderTellStatus
74 gst_flacdec_tell (const FLAC__SeekableStreamDecoder *decoder,
75 FLAC__uint64 *position, void *client_data);
76 static FLAC__SeekableStreamDecoderLengthStatus
77 gst_flacdec_length (const FLAC__SeekableStreamDecoder *decoder,
78 FLAC__uint64 *length, void *client_data);
79 static FLAC__bool gst_flacdec_eof (const FLAC__SeekableStreamDecoder *decoder,
81 static FLAC__StreamDecoderWriteStatus
82 gst_flacdec_write (const FLAC__SeekableStreamDecoder *decoder,
83 const FLAC__Frame *frame,
84 const FLAC__int32 * const buffer[],
86 static void gst_flacdec_metadata_callback (const FLAC__SeekableStreamDecoder *decoder,
87 const FLAC__StreamMetadata *metadata,
89 static void gst_flacdec_error_callback (const FLAC__SeekableStreamDecoder *decoder,
90 FLAC__StreamDecoderErrorStatus status,
93 static GstElementClass *parent_class = NULL;
94 /*static guint gst_flacdec_signals[LAST_SIGNAL] = { 0 }; */
97 flacdec_get_type(void) {
98 static GType flacdec_type = 0;
101 static const GTypeInfo flacdec_info = {
102 sizeof(FlacDecClass),
105 (GClassInitFunc)gst_flacdec_class_init,
110 (GInstanceInitFunc)gst_flacdec_init,
112 flacdec_type = g_type_register_static (GST_TYPE_ELEMENT, "FlacDec", &flacdec_info, 0);
118 gst_flacdec_class_init (FlacDecClass *klass)
120 GstElementClass *gstelement_class;
122 gstelement_class = (GstElementClass*)klass;
124 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
126 gstelement_class->change_state = gst_flacdec_change_state;
130 gst_flacdec_init (FlacDec *flacdec)
132 flacdec->sinkpad = gst_pad_new_from_template (gst_flacdec_sink_template, "sink");
133 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
134 gst_pad_set_convert_function (flacdec->sinkpad, NULL);
136 gst_element_set_loop_function (GST_ELEMENT (flacdec), gst_flacdec_loop);
137 flacdec->srcpad = gst_pad_new_from_template (gst_flacdec_src_template, "src");
138 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
139 gst_pad_set_formats_function (flacdec->srcpad, gst_flacdec_get_src_formats);
140 gst_pad_set_convert_function (flacdec->srcpad, gst_flacdec_convert_src);
141 gst_pad_set_query_type_function (flacdec->srcpad, gst_flacdec_get_src_query_types);
142 gst_pad_set_query_function (flacdec->srcpad, gst_flacdec_src_query);
143 gst_pad_set_event_mask_function (flacdec->srcpad, gst_flacdec_get_src_event_masks);
144 gst_pad_set_event_function (flacdec->srcpad, gst_flacdec_src_event);
146 flacdec->decoder = FLAC__seekable_stream_decoder_new ();
147 flacdec->total_samples = 0;
148 flacdec->init = TRUE;
149 flacdec->eos = FALSE;
150 flacdec->seek_pending = FALSE;
152 FLAC__seekable_stream_decoder_set_read_callback (flacdec->decoder, gst_flacdec_read);
153 FLAC__seekable_stream_decoder_set_seek_callback (flacdec->decoder, gst_flacdec_seek);
154 FLAC__seekable_stream_decoder_set_tell_callback (flacdec->decoder, gst_flacdec_tell);
155 FLAC__seekable_stream_decoder_set_length_callback (flacdec->decoder, gst_flacdec_length);
156 FLAC__seekable_stream_decoder_set_eof_callback (flacdec->decoder, gst_flacdec_eof);
157 FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder, gst_flacdec_write);
158 FLAC__seekable_stream_decoder_set_metadata_callback (flacdec->decoder, gst_flacdec_metadata_callback);
159 FLAC__seekable_stream_decoder_set_error_callback (flacdec->decoder, gst_flacdec_error_callback);
160 FLAC__seekable_stream_decoder_set_client_data (flacdec->decoder, flacdec);
164 gst_flacdec_metadata_callback (const FLAC__SeekableStreamDecoder *decoder,
165 const FLAC__StreamMetadata *metadata, void *client_data)
169 flacdec = GST_FLACDEC (client_data);
171 flacdec->stream_samples = metadata->data.stream_info.total_samples;
175 gst_flacdec_error_callback (const FLAC__SeekableStreamDecoder *decoder,
176 FLAC__StreamDecoderErrorStatus status, void *client_data)
181 flacdec = GST_FLACDEC (client_data);
184 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
187 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
188 error = "bad header";
190 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
191 error = "CRC mismatch";
194 error = "unkown error";
198 GST_DEBUG (0, error);
200 gst_element_error (GST_ELEMENT (flacdec), error);
203 static FLAC__SeekableStreamDecoderSeekStatus
204 gst_flacdec_seek (const FLAC__SeekableStreamDecoder *decoder,
205 FLAC__uint64 position, void *client_data)
209 flacdec = GST_FLACDEC (client_data);
211 GST_DEBUG (0, "seek %lld\n", position);
212 if (!gst_bytestream_seek (flacdec->bs, position, GST_SEEK_METHOD_SET)) {
213 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
215 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
218 static FLAC__SeekableStreamDecoderTellStatus
219 gst_flacdec_tell (const FLAC__SeekableStreamDecoder *decoder,
220 FLAC__uint64 *position, void *client_data)
224 flacdec = GST_FLACDEC (client_data);
226 *position = gst_bytestream_tell (flacdec->bs);
228 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
230 GST_DEBUG (0, "tell %lld\n", *position);
232 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
235 static FLAC__SeekableStreamDecoderLengthStatus
236 gst_flacdec_length (const FLAC__SeekableStreamDecoder *decoder,
237 FLAC__uint64 *length, void *client_data)
241 flacdec = GST_FLACDEC (client_data);
243 *length = gst_bytestream_length (flacdec->bs);
245 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
247 GST_DEBUG (0, "length %lld\n", *length);
249 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
253 gst_flacdec_eof (const FLAC__SeekableStreamDecoder *decoder,
258 flacdec = GST_FLACDEC (client_data);
259 GST_DEBUG (0, "eof %d\n", flacdec->eos);
264 static FLAC__SeekableStreamDecoderReadStatus
265 gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder,
266 FLAC__byte buffer[], unsigned *bytes,
273 flacdec = GST_FLACDEC (client_data);
275 //g_print ("read %u\n", *bytes);
277 while (insize == 0) {
278 insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, *bytes);
279 if (insize < *bytes) {
283 gst_bytestream_get_status (flacdec->bs, &avail, &event);
285 switch (GST_EVENT_TYPE (event)) {
287 GST_DEBUG (0, "eos");
289 gst_event_unref (event);
294 case GST_EVENT_DISCONTINUOUS:
295 GST_DEBUG (0, "discont");
297 /* we are not yet sending the discont, we'll do that in the next write operation */
298 flacdec->need_discont = TRUE;
299 gst_event_unref (event);
302 gst_pad_event_default (flacdec->sinkpad, event);
306 insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, avail);
312 memcpy (buffer, indata, insize);
314 gst_bytestream_flush_fast (flacdec->bs, insize);
316 return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
319 static FLAC__StreamDecoderWriteStatus
320 gst_flacdec_write (const FLAC__SeekableStreamDecoder *decoder,
321 const FLAC__Frame *frame,
322 const FLAC__int32 * const buffer[],
327 guint depth = frame->header.bits_per_sample;
328 guint channels = frame->header.channels;
329 guint samples = frame->header.blocksize;
332 flacdec = GST_FLACDEC (client_data);
334 if (flacdec->need_discont) {
335 gint64 time = 0, bytes = 0;
339 flacdec->need_discont = FALSE;
341 if (flacdec->seek_pending) {
342 flacdec->total_samples = flacdec->seek_value;
345 GST_DEBUG (0, "send discont");
347 format = GST_FORMAT_TIME;
348 gst_pad_convert (flacdec->srcpad, GST_FORMAT_UNITS, flacdec->total_samples,
350 format = GST_FORMAT_BYTES;
351 gst_pad_convert (flacdec->srcpad, GST_FORMAT_UNITS, flacdec->total_samples,
353 discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
354 GST_FORMAT_BYTES, bytes,
355 GST_FORMAT_UNITS, flacdec->total_samples,
358 gst_pad_push (flacdec->srcpad, GST_BUFFER (discont));
361 if (!GST_PAD_CAPS (flacdec->srcpad)) {
362 gst_pad_try_set_caps (flacdec->srcpad,
366 "format", GST_PROPS_STRING ("int"),
367 "law", GST_PROPS_INT (0),
368 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
369 "signed", GST_PROPS_BOOLEAN (TRUE),
370 "width", GST_PROPS_INT (depth),
371 "depth", GST_PROPS_INT (depth),
372 "rate", GST_PROPS_INT (frame->header.sample_rate),
373 "channels", GST_PROPS_INT (channels)
376 flacdec->depth = depth;
377 flacdec->channels = channels;
378 flacdec->frequency = frame->header.sample_rate;
381 outbuf = gst_buffer_new ();
382 GST_BUFFER_SIZE (outbuf) = samples * channels * ((depth+7)>>3);
383 GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
384 GST_BUFFER_TIMESTAMP (outbuf) = flacdec->total_samples * GST_SECOND / frame->header.sample_rate;
387 guint8 *outbuffer = (guint8 *)GST_BUFFER_DATA (outbuf);
389 for (i=0; i<samples; i++) {
390 for (j=0; j < channels; j++) {
391 *outbuffer++ = (guint8) buffer[j][i];
395 else if (depth == 16) {
396 guint16 *outbuffer = (guint16 *)GST_BUFFER_DATA (outbuf);
398 for (i=0; i<samples; i++) {
399 for (j=0; j < channels; j++) {
400 *outbuffer++ = (guint16) buffer[j][i];
405 g_warning ("flacdec: invalid depth %d found\n", depth);
406 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
409 flacdec->total_samples += samples;
411 gst_pad_push (flacdec->srcpad, outbuf);
413 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
417 gst_flacdec_loop (GstElement *element)
422 flacdec = GST_FLACDEC (element);
425 FLAC__seekable_stream_decoder_init (flacdec->decoder);
426 FLAC__seekable_stream_decoder_process_metadata (flacdec->decoder);
427 flacdec->init = FALSE;
430 if (flacdec->seek_pending) {
431 GST_DEBUG (GST_CAT_EVENT, "perform seek to sample %lld\n",
432 flacdec->seek_value);
434 if (FLAC__seekable_stream_decoder_seek_absolute (flacdec->decoder,
435 flacdec->seek_value))
437 flacdec->total_samples = flacdec->seek_value;
438 GST_DEBUG (GST_CAT_EVENT, "seek done\n");
441 GST_DEBUG (GST_CAT_EVENT, "seek failed\n");
443 flacdec->seek_pending = FALSE;
446 res = FLAC__seekable_stream_decoder_process_one_frame (flacdec->decoder);
447 if (FLAC__seekable_stream_decoder_get_state (flacdec->decoder) ==
448 FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
452 FLAC__seekable_stream_decoder_finish(flacdec->decoder);
453 flacdec->init = TRUE;
455 event = gst_event_new(GST_EVENT_EOS);
456 gst_pad_push (flacdec->srcpad, GST_BUFFER (event));
457 gst_element_set_eos (element);
461 GST_FORMATS_FUNCTION (gst_flacdec_get_src_formats,
468 gst_flacdec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
469 GstFormat *dest_format, gint64 *dest_value)
472 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
474 gint bytes_per_sample;
476 bytes_per_sample = flacdec->channels * ((flacdec->depth+7)>>3);
478 switch (src_format) {
479 case GST_FORMAT_BYTES:
480 switch (*dest_format) {
481 case GST_FORMAT_UNITS:
482 if (bytes_per_sample == 0)
484 *dest_value = src_value / bytes_per_sample;
486 case GST_FORMAT_DEFAULT:
487 *dest_format = GST_FORMAT_TIME;
488 case GST_FORMAT_TIME:
490 gint byterate = bytes_per_sample * flacdec->frequency;
494 *dest_value = src_value * GST_SECOND / byterate;
501 case GST_FORMAT_UNITS:
502 switch (*dest_format) {
503 case GST_FORMAT_BYTES:
504 *dest_value = src_value * bytes_per_sample;
506 case GST_FORMAT_DEFAULT:
507 *dest_format = GST_FORMAT_TIME;
508 case GST_FORMAT_TIME:
509 if (flacdec->frequency == 0)
511 *dest_value = src_value * GST_SECOND / flacdec->frequency;
517 case GST_FORMAT_TIME:
518 switch (*dest_format) {
519 case GST_FORMAT_DEFAULT:
520 *dest_format = GST_FORMAT_BYTES;
521 case GST_FORMAT_BYTES:
522 scale = bytes_per_sample;
523 case GST_FORMAT_UNITS:
524 *dest_value = src_value * scale * flacdec->frequency / GST_SECOND;
536 GST_PAD_QUERY_TYPE_FUNCTION (gst_flacdec_get_src_query_types,
538 GST_PAD_QUERY_POSITION
542 gst_flacdec_src_query (GstPad *pad, GstPadQueryType type,
543 GstFormat *format, gint64 *value)
546 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
549 case GST_PAD_QUERY_TOTAL:
553 if (flacdec->stream_samples == 0)
554 samples = flacdec->total_samples;
556 samples = flacdec->stream_samples;
558 gst_pad_convert (flacdec->srcpad,
564 case GST_PAD_QUERY_POSITION:
565 gst_pad_convert (flacdec->srcpad,
567 flacdec->total_samples,
578 GST_EVENT_MASK_FUNCTION (gst_flacdec_get_src_event_masks,
579 { GST_EVENT_SEEK, GST_SEEK_FLAG_ACCURATE }
583 gst_flacdec_src_event (GstPad *pad, GstEvent *event)
586 FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
589 switch (GST_EVENT_TYPE (event)) {
591 format = GST_FORMAT_UNITS;
593 if (gst_pad_convert (flacdec->srcpad,
594 GST_EVENT_SEEK_FORMAT (event),
595 GST_EVENT_SEEK_OFFSET (event),
596 &format, &flacdec->seek_value))
597 flacdec->seek_pending = TRUE;
605 gst_event_unref (event);
609 static GstElementStateReturn
610 gst_flacdec_change_state (GstElement *element)
612 FlacDec *flacdec = GST_FLACDEC (element);
614 switch (GST_STATE_TRANSITION (element)) {
615 case GST_STATE_NULL_TO_READY:
616 case GST_STATE_READY_TO_PAUSED:
617 flacdec->bs = gst_bytestream_new (flacdec->sinkpad);
618 flacdec->seek_pending = FALSE;
619 flacdec->total_samples = 0;
620 flacdec->init = TRUE;
621 flacdec->eos = FALSE;
623 case GST_STATE_PAUSED_TO_PLAYING:
624 flacdec->eos = FALSE;
625 case GST_STATE_PLAYING_TO_PAUSED:
627 case GST_STATE_PAUSED_TO_READY:
628 gst_bytestream_destroy (flacdec->bs);
630 case GST_STATE_READY_TO_NULL:
635 if (GST_ELEMENT_CLASS (parent_class)->change_state)
636 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
638 return GST_STATE_SUCCESS;