25769bcfc4faefc8fe07e15367a048e9c5e832eb
[platform/upstream/gst-plugins-good.git] / ext / flac / gstflacdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <string.h>
24
25 /*#define DEBUG_ENABLED */
26 #include "gstflacdec.h"
27 #include <gst/gsttaginterface.h>
28
29 #include <gst/tag/tag.h>
30
31 #include "flac_compat.h"
32
33 static GstPadTemplate *src_template, *sink_template;
34
35 /* elementfactory information */
36 GstElementDetails flacdec_details = {
37   "FLAC decoder",
38   "Codec/Decoder/Audio",
39   "Decodes FLAC lossless audio streams",
40   "Wim Taymans <wim.taymans@chello.be>",
41 };
42
43 /* FlacDec signals and args */
44 enum {
45   /* FILL ME */
46   LAST_SIGNAL
47 };
48
49 enum {
50   ARG_0,
51   ARG_METADATA
52 };
53
54 static void             gst_flacdec_base_init           (gpointer g_class);
55 static void             gst_flacdec_class_init          (FlacDecClass *klass);
56 static void             gst_flacdec_init                (FlacDec *flacdec);
57
58 static void             gst_flacdec_loop                (GstElement *element);
59 static GstElementStateReturn
60                         gst_flacdec_change_state        (GstElement *element);
61 static const GstFormat* gst_flacdec_get_src_formats     (GstPad *pad);
62 static gboolean         gst_flacdec_convert_src         (GstPad *pad, GstFormat src_format, gint64 src_value,
63                                                          GstFormat *dest_format, gint64 *dest_value);
64 static const GstQueryType* 
65                         gst_flacdec_get_src_query_types (GstPad *pad);
66 static gboolean         gst_flacdec_src_query           (GstPad *pad, GstQueryType type,
67                                                          GstFormat *format, gint64 *value);
68 static const GstEventMask* 
69                         gst_flacdec_get_src_event_masks (GstPad *pad);
70 static gboolean         gst_flacdec_src_event           (GstPad *pad, GstEvent *event);
71
72 static FLAC__SeekableStreamDecoderReadStatus    
73                         gst_flacdec_read                (const FLAC__SeekableStreamDecoder *decoder, 
74                                                          FLAC__byte buffer[], unsigned *bytes, 
75                                                          void *client_data);
76 static FLAC__SeekableStreamDecoderSeekStatus    
77                         gst_flacdec_seek                (const FLAC__SeekableStreamDecoder *decoder, 
78                                                          FLAC__uint64 position, void *client_data);
79 static FLAC__SeekableStreamDecoderTellStatus    
80                         gst_flacdec_tell                (const FLAC__SeekableStreamDecoder *decoder, 
81                                                          FLAC__uint64 *position, void *client_data);
82 static FLAC__SeekableStreamDecoderLengthStatus  
83                         gst_flacdec_length              (const FLAC__SeekableStreamDecoder *decoder, 
84                                                          FLAC__uint64 *length, void *client_data);
85 static FLAC__bool       gst_flacdec_eof                 (const FLAC__SeekableStreamDecoder *decoder, 
86                                                          void *client_data);
87 static FLAC__StreamDecoderWriteStatus   
88                         gst_flacdec_write               (const FLAC__SeekableStreamDecoder *decoder, 
89                                                          const FLAC__Frame *frame, 
90                                                          const FLAC__int32 * const buffer[], 
91                                                          void *client_data);
92 static void             gst_flacdec_metadata_callback   (const FLAC__SeekableStreamDecoder *decoder, 
93                                                          const FLAC__StreamMetadata *metadata, 
94                                                          void *client_data);
95 static void             gst_flacdec_error_callback      (const FLAC__SeekableStreamDecoder *decoder, 
96                                                          FLAC__StreamDecoderErrorStatus status, 
97                                                          void *client_data);
98
99 static GstElementClass *parent_class = NULL;
100 /*static guint gst_flacdec_signals[LAST_SIGNAL] = { 0 }; */
101
102 GType
103 flacdec_get_type(void) {
104   static GType flacdec_type = 0;
105
106   if (!flacdec_type) {
107     static const GTypeInfo flacdec_info = {
108       sizeof(FlacDecClass),
109       gst_flacdec_base_init,
110       NULL,
111       (GClassInitFunc)gst_flacdec_class_init,
112       NULL,
113       NULL,
114       sizeof(FlacDec),
115       0,
116       (GInstanceInitFunc)gst_flacdec_init,
117     };
118     flacdec_type = g_type_register_static (GST_TYPE_ELEMENT, "FlacDec", &flacdec_info, 0);
119   }
120   return flacdec_type;
121 }
122
123 static GstCaps*
124 flac_caps_factory (void)
125 {
126   return gst_caps_new_simple ("audio/x-flac", NULL);
127   /* "rate",            GST_PROPS_INT_RANGE (11025, 48000),
128    * "channels",        GST_PROPS_INT_RANGE (1, 2), */
129 }
130
131 static GstCaps*
132 raw_caps_factory (void)
133 {
134   return gst_caps_new_simple ("audio/x-raw-int",
135       "endianness",     G_TYPE_INT, G_BYTE_ORDER,
136       "signed",         G_TYPE_BOOLEAN, TRUE,
137       "width",          G_TYPE_INT, 16,
138       "depth",          G_TYPE_INT, 16,
139       "rate",           GST_TYPE_INT_RANGE, 11025, 48000,
140       "channels",       GST_TYPE_INT_RANGE, 1, 2,
141       NULL);
142 }
143
144 static void
145 gst_flacdec_base_init (gpointer g_class)
146 {
147   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
148   GstCaps *raw_caps, *flac_caps;
149
150   raw_caps = raw_caps_factory ();
151   flac_caps = flac_caps_factory ();
152
153   sink_template = gst_pad_template_new ("sink", GST_PAD_SINK,
154       GST_PAD_ALWAYS, flac_caps);
155   src_template = gst_pad_template_new ("src", GST_PAD_SRC, 
156       GST_PAD_ALWAYS, raw_caps);
157   gst_element_class_add_pad_template (element_class, sink_template);
158   gst_element_class_add_pad_template (element_class, src_template);
159   gst_element_class_set_details (element_class, &flacdec_details);
160 }
161
162 static void
163 gst_flacdec_class_init (FlacDecClass *klass) 
164 {
165   GstElementClass *gstelement_class;
166   GObjectClass *gobject_class;
167
168   gstelement_class = (GstElementClass*)klass;
169   gobject_class = (GObjectClass*) klass;
170
171   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
172
173   gstelement_class->change_state = gst_flacdec_change_state;
174 }
175
176 static void 
177 gst_flacdec_init (FlacDec *flacdec) 
178 {
179   flacdec->sinkpad = gst_pad_new_from_template (sink_template, "sink");
180   gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
181   gst_pad_set_convert_function (flacdec->sinkpad, NULL);
182
183   gst_element_set_loop_function (GST_ELEMENT (flacdec), gst_flacdec_loop);
184   flacdec->srcpad = gst_pad_new_from_template (src_template, "src");
185   gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
186   gst_pad_set_formats_function (flacdec->srcpad, gst_flacdec_get_src_formats);
187   gst_pad_set_convert_function (flacdec->srcpad, gst_flacdec_convert_src);
188   gst_pad_set_query_type_function (flacdec->srcpad, gst_flacdec_get_src_query_types);
189   gst_pad_set_query_function (flacdec->srcpad, gst_flacdec_src_query);
190   gst_pad_set_event_mask_function (flacdec->srcpad, gst_flacdec_get_src_event_masks);
191   gst_pad_set_event_function (flacdec->srcpad, gst_flacdec_src_event);
192   gst_pad_use_explicit_caps (flacdec->srcpad);
193
194   flacdec->decoder = FLAC__seekable_stream_decoder_new ();
195   flacdec->total_samples = 0;
196   flacdec->init = TRUE;
197   flacdec->eos = FALSE;
198   flacdec->seek_pending = FALSE;
199
200   FLAC__seekable_stream_decoder_set_read_callback (flacdec->decoder, gst_flacdec_read);
201   FLAC__seekable_stream_decoder_set_seek_callback (flacdec->decoder, gst_flacdec_seek);
202   FLAC__seekable_stream_decoder_set_tell_callback (flacdec->decoder, gst_flacdec_tell);
203   FLAC__seekable_stream_decoder_set_length_callback (flacdec->decoder, gst_flacdec_length);  
204   FLAC__seekable_stream_decoder_set_eof_callback (flacdec->decoder, gst_flacdec_eof);
205 #if FLAC_VERSION >= 0x010003
206   FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder, gst_flacdec_write);
207 #else
208   FLAC__seekable_stream_decoder_set_write_callback (flacdec->decoder,
209         (FLAC__StreamDecoderWriteStatus (*)
210                 (const FLAC__SeekableStreamDecoder *decoder, 
211                  const FLAC__Frame *frame,
212                  const FLAC__int32 *buffer[], 
213                  void *client_data))
214                 (gst_flacdec_write));
215 #endif
216   FLAC__seekable_stream_decoder_set_metadata_respond (flacdec->decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
217   FLAC__seekable_stream_decoder_set_metadata_callback (flacdec->decoder, gst_flacdec_metadata_callback);
218   FLAC__seekable_stream_decoder_set_error_callback (flacdec->decoder, gst_flacdec_error_callback);
219   FLAC__seekable_stream_decoder_set_client_data (flacdec->decoder, flacdec);
220 }
221
222 static gboolean
223 gst_flacdec_update_metadata (FlacDec *flacdec, const FLAC__StreamMetadata *metadata)
224 {
225   GstTagList *list;
226   guint32 number_of_comments, cursor, str_len;
227   gchar *p_value, *value, *name, *str_ptr;
228
229   list = gst_tag_list_new ();
230   if (list == NULL) {
231     return FALSE;
232   }
233
234   number_of_comments = metadata->data.vorbis_comment.num_comments;
235   value = NULL;
236   GST_DEBUG ("%d tag(s) found",  number_of_comments);
237   for (cursor = 0; cursor < number_of_comments; cursor++)
238   {                     
239     str_ptr = metadata->data.vorbis_comment.comments[cursor].entry;
240     str_len = metadata->data.vorbis_comment.comments[cursor].length;
241     p_value = g_strstr_len ( str_ptr, str_len , "=" );
242     if (p_value)
243     {                   
244       name = g_strndup (str_ptr, p_value - str_ptr);
245       value = g_strndup (p_value + 1, str_ptr + str_len - p_value - 1);
246                         
247       GST_DEBUG ("%s : %s", name, value);
248       gst_vorbis_tag_add (list, name, value);
249       g_free (name);
250       g_free (value);
251     }
252   }
253
254
255   gst_element_found_tags (GST_ELEMENT (flacdec), list);
256   if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
257     gst_pad_push (flacdec->srcpad, GST_DATA (gst_event_new_tag (list)));
258   }
259   return TRUE;
260 }
261
262
263 static void 
264 gst_flacdec_metadata_callback (const FLAC__SeekableStreamDecoder *decoder,
265                                const FLAC__StreamMetadata *metadata, void *client_data)
266 {
267   FlacDec *flacdec;
268         
269   flacdec = GST_FLACDEC (client_data);
270
271   switch (metadata->type)
272   {
273     case FLAC__METADATA_TYPE_STREAMINFO:
274          flacdec->stream_samples = metadata->data.stream_info.total_samples;
275          break;
276     case FLAC__METADATA_TYPE_VORBIS_COMMENT:
277          gst_flacdec_update_metadata (flacdec, metadata);                 
278          break;
279     default:
280          break;
281   }
282 }
283
284 static void 
285 gst_flacdec_error_callback (const FLAC__SeekableStreamDecoder *decoder, 
286                             FLAC__StreamDecoderErrorStatus status, void *client_data)
287 {
288   FlacDec *flacdec;
289   gchar *error;
290
291   flacdec = GST_FLACDEC (client_data);
292
293   switch (status) {
294     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
295       error = "lost sync";
296       break;
297     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
298       error = "bad header";
299       break;
300     case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
301       error = "CRC mismatch";
302       break;
303     default:
304       error = "unknown error";
305       break;
306   }
307
308   GST_ELEMENT_ERROR (flacdec, STREAM, DECODE, (NULL), (error));
309 }
310
311 static FLAC__SeekableStreamDecoderSeekStatus    
312 gst_flacdec_seek (const FLAC__SeekableStreamDecoder *decoder, 
313                   FLAC__uint64 position, void *client_data)
314 {
315   FlacDec *flacdec;
316
317   flacdec = GST_FLACDEC (client_data);
318
319   GST_DEBUG ("seek %" G_GINT64_FORMAT, position);
320   if (!gst_bytestream_seek (flacdec->bs, position, GST_SEEK_METHOD_SET)) {
321     return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
322   }
323   return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
324 }
325
326 static FLAC__SeekableStreamDecoderTellStatus    
327 gst_flacdec_tell (const FLAC__SeekableStreamDecoder *decoder, 
328                   FLAC__uint64 *position, void *client_data)
329 {
330   FlacDec *flacdec;
331
332   flacdec = GST_FLACDEC (client_data);
333
334   *position = gst_bytestream_tell (flacdec->bs);
335   if (*position == -1)
336     return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
337
338   GST_DEBUG ("tell %" G_GINT64_FORMAT, *position);
339
340   return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
341 }
342
343 static FLAC__SeekableStreamDecoderLengthStatus  
344 gst_flacdec_length (const FLAC__SeekableStreamDecoder *decoder, 
345                     FLAC__uint64 *length, void *client_data)
346 {
347   FlacDec *flacdec;
348
349   flacdec = GST_FLACDEC (client_data);
350
351   *length = gst_bytestream_length (flacdec->bs);
352   if (*length == -1)
353     return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
354
355   GST_DEBUG ("length %" G_GINT64_FORMAT, *length);
356
357   return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
358 }
359
360 static FLAC__bool
361 gst_flacdec_eof (const FLAC__SeekableStreamDecoder *decoder, 
362                  void *client_data)
363 {
364   FlacDec *flacdec;
365
366   flacdec = GST_FLACDEC (client_data);
367   GST_DEBUG ("eof %d", flacdec->eos);
368
369   return flacdec->eos;
370 }
371
372 static FLAC__SeekableStreamDecoderReadStatus
373 gst_flacdec_read (const FLAC__SeekableStreamDecoder *decoder, 
374                   FLAC__byte buffer[], unsigned *bytes, 
375                   void *client_data)
376 {
377   FlacDec *flacdec;
378   gint insize = 0;
379   guint8 *indata;
380
381   flacdec = GST_FLACDEC (client_data);
382
383   //g_print ("read %u\n", *bytes);
384   
385   while (insize == 0) {
386     insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, *bytes);
387     if (insize < *bytes) {
388       GstEvent *event;
389       guint32 avail;
390                             
391       gst_bytestream_get_status (flacdec->bs, &avail, &event);
392
393       switch (GST_EVENT_TYPE (event)) {
394         case GST_EVENT_EOS:
395           GST_DEBUG ("eos");
396           flacdec->eos = TRUE; 
397           gst_event_unref (event);
398           if (avail == 0) {
399             return 0;
400           }
401           break;
402         case GST_EVENT_DISCONTINUOUS:
403           GST_DEBUG ("discont");
404
405           /* we are not yet sending the discont, we'll do that in the next write operation */
406           flacdec->need_discont = TRUE;
407           gst_event_unref (event);
408           break;
409         default:
410           gst_pad_event_default (flacdec->sinkpad, event);
411           break;
412       }
413       if (avail > 0)
414         insize = gst_bytestream_peek_bytes (flacdec->bs, &indata, avail);
415       else
416         insize = 0;
417     }
418   }
419
420   memcpy (buffer, indata, insize);
421   *bytes = insize;
422   gst_bytestream_flush_fast (flacdec->bs, insize);
423
424   return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
425 }
426
427 static FLAC__StreamDecoderWriteStatus
428 gst_flacdec_write (const FLAC__SeekableStreamDecoder *decoder, 
429                    const FLAC__Frame *frame, 
430                    const FLAC__int32 * const buffer[], 
431                    void *client_data)
432 {
433   FlacDec *flacdec;
434   GstBuffer *outbuf;
435   guint depth = frame->header.bits_per_sample;
436   guint channels = frame->header.channels;
437   guint samples = frame->header.blocksize;
438   guint j, i;
439
440   flacdec = GST_FLACDEC (client_data);
441
442   if (flacdec->need_discont) {
443     gint64 time = 0, bytes = 0;
444     GstFormat format;
445     GstEvent *discont;
446
447     flacdec->need_discont = FALSE;
448     
449     if (!GST_PAD_CAPS (flacdec->srcpad)) {
450       if (flacdec->seek_pending) {
451         flacdec->total_samples = flacdec->seek_value;
452       }
453
454       if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
455         GST_DEBUG ("send discont");
456
457         format = GST_FORMAT_TIME;
458         gst_pad_convert (flacdec->srcpad, GST_FORMAT_DEFAULT,
459                          flacdec->total_samples, &format, &time);
460         format = GST_FORMAT_BYTES;
461         gst_pad_convert (flacdec->srcpad, GST_FORMAT_DEFAULT,
462                          flacdec->total_samples, &format, &bytes);
463         discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME, time,
464                                              GST_FORMAT_BYTES, bytes,
465                                              GST_FORMAT_DEFAULT, flacdec->total_samples, 
466                                          NULL);
467           
468         gst_pad_push (flacdec->srcpad, GST_DATA (discont));
469       }
470     }
471   }
472   
473   if (!GST_PAD_CAPS (flacdec->srcpad)) {
474     gst_pad_set_explicit_caps (flacdec->srcpad,
475         gst_caps_new_simple ("audio/x-raw-int",
476           "endianness",  G_TYPE_INT, G_BYTE_ORDER,
477           "signed",      G_TYPE_BOOLEAN, TRUE,
478           "width",       G_TYPE_INT, depth,
479           "depth",       G_TYPE_INT, depth,
480           "rate",        G_TYPE_INT, frame->header.sample_rate,
481           "channels",    G_TYPE_INT, channels,
482           NULL));
483
484     flacdec->depth = depth;
485     flacdec->channels = channels;
486     flacdec->frequency = frame->header.sample_rate;
487   }
488
489   if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
490     outbuf = gst_buffer_new ();
491     GST_BUFFER_SIZE (outbuf) = samples * channels * ((depth+7)>>3);
492     GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (outbuf));
493     GST_BUFFER_TIMESTAMP (outbuf) = flacdec->total_samples * GST_SECOND / frame->header.sample_rate;
494   
495     if (depth == 8) {
496       guint8 *outbuffer = (guint8 *)GST_BUFFER_DATA (outbuf);
497   
498       for (i=0; i<samples; i++) {
499         for (j=0; j < channels; j++) {
500           *outbuffer++ = (guint8) buffer[j][i];
501         }
502       }
503     }
504     else if (depth == 16) {
505       guint16 *outbuffer = (guint16 *)GST_BUFFER_DATA (outbuf);
506   
507       for (i=0; i<samples; i++) {
508         for (j=0; j < channels; j++) {
509           *outbuffer++ = (guint16) buffer[j][i];
510         }
511       }
512     }
513     else {
514       g_warning ("flacdec: invalid depth %d found\n", depth);
515       return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
516     }
517     gst_pad_push (flacdec->srcpad, GST_DATA (outbuf));
518   }
519   flacdec->total_samples += samples;
520
521   return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
522 }
523
524 static void 
525 gst_flacdec_loop (GstElement *element) 
526 {
527   FlacDec *flacdec;
528   gboolean res;
529
530   flacdec = GST_FLACDEC (element);
531
532   GST_DEBUG ("flacdec: entering loop");
533   if (flacdec->init) {    
534     FLAC__StreamDecoderState res;
535     GST_DEBUG ("flacdec: initializing decoder");    
536     res = FLAC__seekable_stream_decoder_init (flacdec->decoder);
537     if (res != FLAC__SEEKABLE_STREAM_DECODER_OK) {
538       GST_ELEMENT_ERROR (flacdec, LIBRARY, INIT, (NULL),
539                          (FLAC__SeekableStreamDecoderStateString[res]));
540       return;
541     }
542     /*    FLAC__seekable_stream_decoder_process_metadata (flacdec->decoder);*/
543     flacdec->init = FALSE;
544   }
545
546   if (flacdec->seek_pending) {
547     GST_DEBUG ("perform seek to sample %" G_GINT64_FORMAT, 
548                               flacdec->seek_value);
549
550     if (FLAC__seekable_stream_decoder_seek_absolute (flacdec->decoder, 
551                                                      flacdec->seek_value)) 
552     {
553       flacdec->total_samples = flacdec->seek_value;
554       GST_DEBUG ("seek done");
555     }
556     else {
557       GST_DEBUG ("seek failed");
558     }
559     flacdec->seek_pending = FALSE;
560   }
561
562   GST_DEBUG ("flacdec: processing single");
563   res = FLAC__seekable_stream_decoder_process_single (flacdec->decoder);
564   GST_DEBUG ("flacdec: checking for EOS");
565   if (FLAC__seekable_stream_decoder_get_state (flacdec->decoder) == 
566                   FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) 
567   {
568     GstEvent *event;
569
570     GST_DEBUG ("flacdec: sending EOS event");
571     FLAC__seekable_stream_decoder_reset(flacdec->decoder);
572
573     if (GST_PAD_IS_USABLE (flacdec->srcpad)) {
574       event = gst_event_new (GST_EVENT_EOS);
575       gst_pad_push (flacdec->srcpad, GST_DATA (event));
576     }
577     gst_element_set_eos (element);
578   }
579   GST_DEBUG ("flacdec: _loop end");
580 }
581
582
583 static const GstFormat *
584 gst_flacdec_get_src_formats (GstPad *pad)
585
586   static const GstFormat formats[] = {
587     GST_FORMAT_DEFAULT,
588     GST_FORMAT_BYTES,
589     GST_FORMAT_TIME,
590     0,
591   };
592   return formats;
593
594
595 static gboolean
596 gst_flacdec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
597                          GstFormat *dest_format, gint64 *dest_value)
598 {
599   gboolean res = TRUE;
600   FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
601   guint scale = 1;
602   gint bytes_per_sample;
603
604   bytes_per_sample = flacdec->channels * ((flacdec->depth+7)>>3);
605
606   switch (src_format) {
607     case GST_FORMAT_BYTES:
608       switch (*dest_format) {
609         case GST_FORMAT_DEFAULT:
610           if (bytes_per_sample == 0)
611             return FALSE;
612           *dest_value = src_value / bytes_per_sample;
613           break;
614         case GST_FORMAT_TIME:
615         {
616           gint byterate = bytes_per_sample * flacdec->frequency;
617
618           if (byterate == 0)
619             return FALSE;
620           *dest_value = src_value * GST_SECOND / byterate;
621           break;
622         }
623         default:
624           res = FALSE;
625       }
626       break;
627     case GST_FORMAT_DEFAULT:
628       switch (*dest_format) {
629         case GST_FORMAT_BYTES:
630           *dest_value = src_value * bytes_per_sample;
631           break;
632         case GST_FORMAT_TIME:
633           if (flacdec->frequency == 0)
634             return FALSE;
635           *dest_value = src_value * GST_SECOND / flacdec->frequency;
636           break;
637         default:
638           res = FALSE;
639       }
640       break;
641     case GST_FORMAT_TIME:
642       switch (*dest_format) {
643         case GST_FORMAT_BYTES:
644           scale = bytes_per_sample;
645         case GST_FORMAT_DEFAULT:
646           *dest_value = src_value * scale * flacdec->frequency / GST_SECOND;
647           break;
648         default:
649           res = FALSE;
650       }
651       break;
652     default:
653       res = FALSE;
654   }
655   return res;
656 }
657
658 static const GstQueryType *
659 gst_flacdec_get_src_query_types (GstPad *pad)
660
661   static const GstQueryType types[] = {
662     GST_QUERY_TOTAL,
663     GST_QUERY_POSITION,
664     0,
665   };
666   return types;
667
668
669 static gboolean
670 gst_flacdec_src_query (GstPad *pad, GstQueryType type,
671                        GstFormat *format, gint64 *value)
672 {
673   gboolean res = TRUE;
674   FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
675
676   switch (type) {
677     case GST_QUERY_TOTAL:
678     {
679       guint64 samples;
680
681       if (flacdec->stream_samples == 0)
682         samples = flacdec->total_samples;
683       else
684         samples = flacdec->stream_samples;
685
686       gst_pad_convert (flacdec->srcpad, 
687                        GST_FORMAT_DEFAULT, 
688                        samples, 
689                        format, value);
690       break;
691     }
692     case GST_QUERY_POSITION:
693       gst_pad_convert (flacdec->srcpad, 
694                        GST_FORMAT_DEFAULT, 
695                        flacdec->total_samples, 
696                        format, value);
697       break;
698     default:
699       res = FALSE;
700       break;
701   }
702
703   return res;
704 }
705           
706 static const GstEventMask *
707 gst_flacdec_get_src_event_masks (GstPad *pad)
708 {
709   static const GstEventMask masks[] = {
710     { GST_EVENT_SEEK, GST_SEEK_FLAG_ACCURATE },
711     { 0, 0 },
712   };
713   return masks;
714 }
715
716 static gboolean
717 gst_flacdec_src_event (GstPad *pad, GstEvent *event)
718
719   gboolean res = TRUE;
720   FlacDec *flacdec = GST_FLACDEC (gst_pad_get_parent (pad));
721   GstFormat format;
722
723   switch (GST_EVENT_TYPE (event)) {
724     case GST_EVENT_SEEK:
725       format = GST_FORMAT_DEFAULT;
726
727       if (gst_pad_convert (flacdec->srcpad, 
728                            GST_EVENT_SEEK_FORMAT (event), 
729                            GST_EVENT_SEEK_OFFSET (event), 
730                            &format, &flacdec->seek_value))
731         flacdec->seek_pending = TRUE;
732       else
733         res = FALSE;
734       break;
735     default:
736       res = FALSE;
737       break;
738   }
739   gst_event_unref (event);
740   return res;
741 }
742
743 static GstElementStateReturn
744 gst_flacdec_change_state (GstElement *element)
745 {
746   FlacDec *flacdec = GST_FLACDEC (element);
747
748   switch (GST_STATE_TRANSITION (element)) {
749     case GST_STATE_NULL_TO_READY:
750     case GST_STATE_READY_TO_PAUSED:
751       flacdec->bs = gst_bytestream_new (flacdec->sinkpad);
752       flacdec->seek_pending = FALSE;
753       flacdec->total_samples = 0;
754       flacdec->eos = FALSE;
755       if (flacdec->init == FALSE) {
756         FLAC__seekable_stream_decoder_reset (flacdec->decoder);
757       }
758       break;
759     case GST_STATE_PAUSED_TO_PLAYING:
760       flacdec->eos = FALSE;
761     case GST_STATE_PLAYING_TO_PAUSED:
762       break;
763     case GST_STATE_PAUSED_TO_READY:
764       gst_bytestream_destroy (flacdec->bs);
765       break;
766     case GST_STATE_READY_TO_NULL:
767     default:
768       break;
769   }
770
771   if (GST_ELEMENT_CLASS (parent_class)->change_state)
772     return GST_ELEMENT_CLASS (parent_class)->change_state (element);
773
774   return GST_STATE_SUCCESS;
775 }