2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2006> 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 filesrc location=media/small/dark.441-16-s.flac ! flacdec ! audioconvert ! audioresample ! autoaudiosink
36 * gst-launch gnomevfssrc location=http://gstreamer.freedesktop.org/media/small/dark.441-16-s.flac ! flacdec ! audioconvert ! audioresample ! queue min-threshold-buffers=10 ! autoaudiosink
41 /* TODO: add seeking when operating chain-based with unframed input */
42 /* FIXME: demote/remove granulepos handling and make more time-centric */
48 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
49 * with newer GLib versions (>= 2.31.0) */
50 #define GLIB_DISABLE_DEPRECATION_WARNINGS
54 #include "gstflacdec.h"
55 #include <gst/gst-i18n-plugin.h>
56 #include <gst/gsttagsetter.h>
57 #include <gst/base/gsttypefindhelper.h>
58 #include <gst/audio/multichannel.h>
59 #include <gst/tag/tag.h>
61 /* Taken from http://flac.sourceforge.net/format.html#frame_header */
62 static const GstAudioChannelPosition channel_positions[8][8] = {
63 {GST_AUDIO_CHANNEL_POSITION_FRONT_MONO},
64 {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
65 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
66 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
67 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
68 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
69 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
70 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
71 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
72 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
73 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
74 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
75 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
76 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
77 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
78 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
79 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
80 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
81 GST_AUDIO_CHANNEL_POSITION_LFE,
82 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
83 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
84 /* FIXME: 7/8 channel layouts are not defined in the FLAC specs */
86 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
87 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
88 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
89 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
90 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
91 GST_AUDIO_CHANNEL_POSITION_LFE,
92 GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
93 GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
94 GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
95 GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
96 GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
97 GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
98 GST_AUDIO_CHANNEL_POSITION_LFE,
99 GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
100 GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
103 GST_DEBUG_CATEGORY_STATIC (flacdec_debug);
104 #define GST_CAT_DEFAULT flacdec_debug
106 static void gst_flac_dec_finalize (GObject * object);
107 static void gst_flac_dec_loop (GstPad * pad);
109 static GstStateChangeReturn gst_flac_dec_change_state (GstElement * element,
110 GstStateChange transition);
111 static const GstQueryType *gst_flac_dec_get_src_query_types (GstPad * pad);
112 static const GstQueryType *gst_flac_dec_get_sink_query_types (GstPad * pad);
113 static gboolean gst_flac_dec_sink_query (GstPad * pad, GstQuery * query);
114 static gboolean gst_flac_dec_src_query (GstPad * pad, GstQuery * query);
115 static gboolean gst_flac_dec_convert_src (GstPad * pad, GstFormat src_format,
116 gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
117 static gboolean gst_flac_dec_src_event (GstPad * pad, GstEvent * event);
118 static gboolean gst_flac_dec_sink_activate (GstPad * sinkpad);
119 static gboolean gst_flac_dec_sink_activate_pull (GstPad * sinkpad,
121 static gboolean gst_flac_dec_sink_activate_push (GstPad * sinkpad,
123 static gboolean gst_flac_dec_sink_event (GstPad * pad, GstEvent * event);
124 static GstFlowReturn gst_flac_dec_chain (GstPad * pad, GstBuffer * buf);
126 static void gst_flac_dec_reset_decoders (GstFlacDec * flacdec);
127 static void gst_flac_dec_setup_decoder (GstFlacDec * flacdec);
129 static FLAC__StreamDecoderReadStatus
130 gst_flac_dec_read_seekable (const FLAC__StreamDecoder * decoder,
131 FLAC__byte buffer[], size_t * bytes, void *client_data);
132 static FLAC__StreamDecoderReadStatus
133 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
134 FLAC__byte buffer[], size_t * bytes, void *client_data);
135 static FLAC__StreamDecoderSeekStatus
136 gst_flac_dec_seek (const FLAC__StreamDecoder * decoder,
137 FLAC__uint64 position, void *client_data);
138 static FLAC__StreamDecoderTellStatus
139 gst_flac_dec_tell (const FLAC__StreamDecoder * decoder,
140 FLAC__uint64 * position, void *client_data);
141 static FLAC__StreamDecoderLengthStatus
142 gst_flac_dec_length (const FLAC__StreamDecoder * decoder,
143 FLAC__uint64 * length, void *client_data);
144 static FLAC__bool gst_flac_dec_eof (const FLAC__StreamDecoder * decoder,
146 static FLAC__StreamDecoderWriteStatus
147 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
148 const FLAC__Frame * frame,
149 const FLAC__int32 * const buffer[], void *client_data);
150 static void gst_flac_dec_metadata_cb (const FLAC__StreamDecoder *
151 decoder, const FLAC__StreamMetadata * metadata, void *client_data);
152 static void gst_flac_dec_error_cb (const FLAC__StreamDecoder *
153 decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
155 GST_BOILERPLATE (GstFlacDec, gst_flac_dec, GstElement, GST_TYPE_ELEMENT);
157 /* FIXME 0.11: Use width=32 for all depths and let audioconvert
158 * handle the conversions instead of doing it ourself.
160 #define GST_FLAC_DEC_SRC_CAPS \
161 "audio/x-raw-int, " \
162 "endianness = (int) BYTE_ORDER, " \
163 "signed = (boolean) true, " \
164 "width = (int) { 8, 16, 32 }, " \
165 "depth = (int) [ 4, 32 ], " \
166 "rate = (int) [ 1, 655350 ], " \
167 "channels = (int) [ 1, 8 ]"
169 static GstStaticPadTemplate flac_dec_src_factory =
170 GST_STATIC_PAD_TEMPLATE ("src",
173 GST_STATIC_CAPS (GST_FLAC_DEC_SRC_CAPS));
174 static GstStaticPadTemplate flac_dec_sink_factory =
175 GST_STATIC_PAD_TEMPLATE ("sink",
178 GST_STATIC_CAPS ("audio/x-flac")
182 gst_flac_dec_base_init (gpointer g_class)
184 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
186 gst_element_class_add_static_pad_template (element_class,
187 &flac_dec_src_factory);
188 gst_element_class_add_static_pad_template (element_class,
189 &flac_dec_sink_factory);
190 gst_element_class_set_details_simple (element_class, "FLAC audio decoder",
191 "Codec/Decoder/Audio",
192 "Decodes FLAC lossless audio streams", "Wim Taymans <wim@fluendo.com>");
194 GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
198 gst_flac_dec_class_init (GstFlacDecClass * klass)
200 GstElementClass *gstelement_class;
201 GObjectClass *gobject_class;
203 gstelement_class = (GstElementClass *) klass;
204 gobject_class = (GObjectClass *) klass;
206 gobject_class->finalize = gst_flac_dec_finalize;
208 gstelement_class->change_state =
209 GST_DEBUG_FUNCPTR (gst_flac_dec_change_state);
213 gst_flac_dec_init (GstFlacDec * flacdec, GstFlacDecClass * klass)
216 gst_pad_new_from_static_template (&flac_dec_sink_factory, "sink");
217 gst_pad_set_activate_function (flacdec->sinkpad,
218 GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate));
219 gst_pad_set_activatepull_function (flacdec->sinkpad,
220 GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate_pull));
221 gst_pad_set_activatepush_function (flacdec->sinkpad,
222 GST_DEBUG_FUNCPTR (gst_flac_dec_sink_activate_push));
223 gst_pad_set_query_type_function (flacdec->sinkpad,
224 GST_DEBUG_FUNCPTR (gst_flac_dec_get_sink_query_types));
225 gst_pad_set_query_function (flacdec->sinkpad,
226 GST_DEBUG_FUNCPTR (gst_flac_dec_sink_query));
227 gst_pad_set_event_function (flacdec->sinkpad,
228 GST_DEBUG_FUNCPTR (gst_flac_dec_sink_event));
229 gst_pad_set_chain_function (flacdec->sinkpad,
230 GST_DEBUG_FUNCPTR (gst_flac_dec_chain));
231 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->sinkpad);
234 gst_pad_new_from_static_template (&flac_dec_src_factory, "src");
235 gst_pad_set_query_type_function (flacdec->srcpad,
236 GST_DEBUG_FUNCPTR (gst_flac_dec_get_src_query_types));
237 gst_pad_set_query_function (flacdec->srcpad,
238 GST_DEBUG_FUNCPTR (gst_flac_dec_src_query));
239 gst_pad_set_event_function (flacdec->srcpad,
240 GST_DEBUG_FUNCPTR (gst_flac_dec_src_event));
241 gst_pad_use_fixed_caps (flacdec->srcpad);
242 gst_element_add_pad (GST_ELEMENT (flacdec), flacdec->srcpad);
244 gst_flac_dec_reset_decoders (flacdec);
248 gst_flac_dec_reset_decoders (GstFlacDec * flacdec)
250 /* Clean up the decoder */
251 if (flacdec->decoder) {
252 FLAC__stream_decoder_delete (flacdec->decoder);
253 flacdec->decoder = NULL;
256 if (flacdec->adapter) {
257 gst_adapter_clear (flacdec->adapter);
258 g_object_unref (flacdec->adapter);
259 flacdec->adapter = NULL;
262 if (flacdec->close_segment) {
263 gst_event_unref (flacdec->close_segment);
264 flacdec->close_segment = NULL;
266 if (flacdec->start_segment) {
267 gst_event_unref (flacdec->start_segment);
268 flacdec->start_segment = NULL;
271 gst_tag_list_free (flacdec->tags);
272 flacdec->tags = NULL;
274 if (flacdec->pending) {
275 gst_buffer_unref (flacdec->pending);
276 flacdec->pending = NULL;
279 flacdec->segment.last_stop = 0;
281 flacdec->init = TRUE;
285 gst_flac_dec_setup_decoder (GstFlacDec * dec)
287 gst_flac_dec_reset_decoders (dec);
289 dec->tags = gst_tag_list_new ();
290 gst_tag_list_add (dec->tags, GST_TAG_MERGE_REPLACE,
291 GST_TAG_AUDIO_CODEC, "FLAC", NULL);
293 dec->adapter = gst_adapter_new ();
295 dec->decoder = FLAC__stream_decoder_new ();
297 /* no point calculating since it's never checked here */
298 FLAC__stream_decoder_set_md5_checking (dec->decoder, false);
299 FLAC__stream_decoder_set_metadata_respond (dec->decoder,
300 FLAC__METADATA_TYPE_VORBIS_COMMENT);
301 FLAC__stream_decoder_set_metadata_respond (dec->decoder,
302 FLAC__METADATA_TYPE_PICTURE);
306 gst_flac_dec_finalize (GObject * object)
310 flacdec = GST_FLAC_DEC (object);
312 gst_flac_dec_reset_decoders (flacdec);
314 G_OBJECT_CLASS (parent_class)->finalize (object);
319 gst_flac_dec_update_metadata (GstFlacDec * flacdec,
320 const FLAC__StreamMetadata * metadata)
326 list = flacdec->tags;
328 flacdec->tags = list = gst_tag_list_new ();
330 num = metadata->data.vorbis_comment.num_comments;
331 GST_DEBUG_OBJECT (flacdec, "%u tag(s) found", num);
333 for (i = 0; i < num; ++i) {
334 gchar *vc, *name, *value;
336 vc = g_strndup ((gchar *) metadata->data.vorbis_comment.comments[i].entry,
337 metadata->data.vorbis_comment.comments[i].length);
339 if (gst_tag_parse_extended_comment (vc, &name, NULL, &value, TRUE)) {
340 GST_DEBUG_OBJECT (flacdec, "%s : %s", name, value);
341 if (value && strlen (value))
342 gst_vorbis_tag_add (list, name, value);
353 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
354 static const guint8 crc8_table[256] = {
355 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
356 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
357 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
358 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
359 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
360 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
361 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
362 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
363 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
364 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
365 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
366 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
367 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
368 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
369 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
370 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
371 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
372 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
373 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
374 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
375 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
376 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
377 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
378 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
379 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
380 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
381 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
382 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
383 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
384 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
385 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
386 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
390 gst_flac_calculate_crc8 (guint8 * data, guint length)
395 crc = crc8_table[crc ^ *data];
403 gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,
404 gint64 * last_sample_num)
407 guint sr_from_end = 0; /* can be 0, 8 or 16 */
408 guint bs_from_end = 0; /* can be 0, 8 or 16 */
410 guint8 bs, sr, ca, ss, pb;
416 if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
419 GST_WARNING_OBJECT (flacdec, "Variable block size FLAC unsupported");
423 bs = (data[2] & 0xF0) >> 4; /* blocksize marker */
424 sr = (data[2] & 0x0F); /* samplerate marker */
425 ca = (data[3] & 0xF0) >> 4; /* channel assignment */
426 ss = (data[3] & 0x0F) >> 1; /* sample size marker */
427 pb = (data[3] & 0x01); /* padding bit */
429 GST_LOG_OBJECT (flacdec,
430 "got sync, bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", bs, sr, ca, ss, pb);
432 if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
436 /* read block size from end of header? */
442 /* read sample rate from end of header? */
445 else if (sr == 0x0D || sr == 0x0E)
448 /* FIXME: This is can be 36 bit if variable block size is used,
449 * fortunately not encoder supports this yet and we check for that
452 val = (guint32) g_utf8_get_char_validated ((gchar *) data + 4, -1);
454 if (val == (guint32) - 1 || val == (guint32) - 2) {
455 GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
459 headerlen = 4 + g_unichar_to_utf8 ((gunichar) val, NULL) +
460 (bs_from_end / 8) + (sr_from_end / 8);
462 if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
463 GST_LOG_OBJECT (flacdec, "invalid checksum");
467 if (flacdec->min_blocksize == flacdec->max_blocksize) {
468 *last_sample_num = (val + 1) * flacdec->min_blocksize;
470 *last_sample_num = 0; /* FIXME: + length of last block in samples */
473 /* FIXME: only valid for fixed block size streams */
474 GST_DEBUG_OBJECT (flacdec, "frame number: %" G_GINT64_FORMAT,
477 if (flacdec->sample_rate > 0 && *last_sample_num != 0) {
478 GST_DEBUG_OBJECT (flacdec, "last sample %" G_GINT64_FORMAT " = %"
479 GST_TIME_FORMAT, *last_sample_num,
480 GST_TIME_ARGS (*last_sample_num * GST_SECOND / flacdec->sample_rate));
486 #define SCANBLOCK_SIZE (64*1024)
489 gst_flac_dec_scan_for_last_block (GstFlacDec * flacdec, gint64 * samples)
491 GstFormat format = GST_FORMAT_BYTES;
492 gint64 file_size, offset;
494 GST_INFO_OBJECT (flacdec, "total number of samples unknown, scanning file");
496 if (!gst_pad_query_peer_duration (flacdec->sinkpad, &format, &file_size)) {
497 GST_WARNING_OBJECT (flacdec, "failed to query upstream size!");
501 if (flacdec->min_blocksize != flacdec->max_blocksize) {
502 GST_WARNING_OBJECT (flacdec, "scanning for last sample only works "
503 "for FLAC files with constant blocksize");
507 GST_DEBUG_OBJECT (flacdec, "upstream size: %" G_GINT64_FORMAT, file_size);
509 offset = file_size - 1;
510 while (offset >= MAX (SCANBLOCK_SIZE / 2, file_size / 2)) {
512 GstBuffer *buf = NULL;
516 /* divide by 2 = not very sophisticated way to deal with overlapping */
517 offset -= SCANBLOCK_SIZE / 2;
518 GST_LOG_OBJECT (flacdec, "looking for frame at %" G_GINT64_FORMAT
519 "-%" G_GINT64_FORMAT, offset, offset + SCANBLOCK_SIZE);
521 flow = gst_pad_pull_range (flacdec->sinkpad, offset, SCANBLOCK_SIZE, &buf);
522 if (flow != GST_FLOW_OK) {
523 GST_DEBUG_OBJECT (flacdec, "flow = %s", gst_flow_get_name (flow));
527 size = GST_BUFFER_SIZE (buf);
528 data = GST_BUFFER_DATA (buf);
531 if (gst_flac_dec_scan_got_frame (flacdec, data, size, samples)) {
532 GST_DEBUG_OBJECT (flacdec, "frame sync at offset %" G_GINT64_FORMAT,
533 offset + GST_BUFFER_SIZE (buf) - size);
534 gst_buffer_unref (buf);
541 gst_buffer_unref (buf);
546 gst_flac_extract_picture_buffer (GstFlacDec * dec,
547 const FLAC__StreamMetadata * metadata)
549 FLAC__StreamMetadata_Picture picture;
552 g_return_if_fail (metadata->type == FLAC__METADATA_TYPE_PICTURE);
554 GST_LOG_OBJECT (dec, "Got PICTURE block");
555 picture = metadata->data.picture;
557 GST_DEBUG_OBJECT (dec, "declared MIME type is: '%s'",
558 GST_STR_NULL (picture.mime_type));
559 GST_DEBUG_OBJECT (dec, "image data is %u bytes", picture.data_length);
561 tags = gst_tag_list_new ();
563 gst_tag_list_add_id3_image (tags, (guint8 *) picture.data,
564 picture.data_length, picture.type);
566 if (!gst_tag_list_is_empty (tags)) {
567 gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, tags);
569 GST_DEBUG_OBJECT (dec, "problem parsing PICTURE block, skipping");
570 gst_tag_list_free (tags);
575 gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder,
576 const FLAC__StreamMetadata * metadata, void *client_data)
578 GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
580 GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type);
582 switch (metadata->type) {
583 case FLAC__METADATA_TYPE_STREAMINFO:{
587 samples = metadata->data.stream_info.total_samples;
589 flacdec->min_blocksize = metadata->data.stream_info.min_blocksize;
590 flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
591 flacdec->sample_rate = metadata->data.stream_info.sample_rate;
592 flacdec->depth = depth = metadata->data.stream_info.bits_per_sample;
593 flacdec->channels = metadata->data.stream_info.channels;
602 GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
603 flacdec->min_blocksize, flacdec->max_blocksize);
604 GST_DEBUG_OBJECT (flacdec, "sample rate: %u, channels: %u",
605 flacdec->sample_rate, flacdec->channels);
606 GST_DEBUG_OBJECT (flacdec, "depth: %u, width: %u", flacdec->depth,
609 /* Only scan for last block in pull-mode, since it uses pull_range() */
610 if (samples == 0 && !flacdec->streaming) {
611 gst_flac_dec_scan_for_last_block (flacdec, &samples);
614 GST_DEBUG_OBJECT (flacdec, "total samples = %" G_GINT64_FORMAT, samples);
616 /* in framed mode the demuxer/parser upstream has already pushed a
617 * newsegment event in TIME format which we've passed on */
618 if (samples > 0 && !flacdec->framed) {
621 gst_segment_set_duration (&flacdec->segment, GST_FORMAT_DEFAULT,
624 /* convert duration to time */
625 duration = gst_util_uint64_scale_int (samples, GST_SECOND,
626 flacdec->sample_rate);
628 /* fixme, at this time we could seek to the queued seek event if we have
630 if (flacdec->start_segment)
631 gst_event_unref (flacdec->start_segment);
632 flacdec->start_segment =
633 gst_event_new_new_segment_full (FALSE,
634 flacdec->segment.rate, flacdec->segment.applied_rate,
635 GST_FORMAT_TIME, 0, duration, 0);
639 case FLAC__METADATA_TYPE_PICTURE:{
640 gst_flac_extract_picture_buffer (flacdec, metadata);
643 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
644 gst_flac_dec_update_metadata (flacdec, metadata);
652 gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
653 FLAC__StreamDecoderErrorStatus status, void *client_data)
658 dec = GST_FLAC_DEC (client_data);
661 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
662 /* Ignore this error and keep processing */
664 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
665 error = "bad header";
667 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
668 error = "CRC mismatch";
671 error = "unknown error";
675 GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
676 dec->last_flow = GST_FLOW_ERROR;
679 static FLAC__StreamDecoderSeekStatus
680 gst_flac_dec_seek (const FLAC__StreamDecoder * decoder,
681 FLAC__uint64 position, void *client_data)
685 flacdec = GST_FLAC_DEC (client_data);
687 GST_DEBUG_OBJECT (flacdec, "seek %" G_GUINT64_FORMAT, (guint64) position);
688 flacdec->offset = position;
690 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
693 static FLAC__StreamDecoderTellStatus
694 gst_flac_dec_tell (const FLAC__StreamDecoder * decoder,
695 FLAC__uint64 * position, void *client_data)
699 flacdec = GST_FLAC_DEC (client_data);
701 *position = flacdec->offset;
703 GST_DEBUG_OBJECT (flacdec, "tell %" G_GINT64_FORMAT, (gint64) * position);
705 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
708 static FLAC__StreamDecoderLengthStatus
709 gst_flac_dec_length (const FLAC__StreamDecoder * decoder,
710 FLAC__uint64 * length, void *client_data)
713 GstFormat fmt = GST_FORMAT_BYTES;
716 flacdec = GST_FLAC_DEC (client_data);
718 if (!gst_pad_query_peer_duration (flacdec->sinkpad, &fmt, &len) ||
719 (fmt != GST_FORMAT_BYTES || len == -1))
720 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
724 GST_DEBUG_OBJECT (flacdec, "encoded byte length %" G_GINT64_FORMAT,
727 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
731 gst_flac_dec_eof (const FLAC__StreamDecoder * decoder, void *client_data)
736 gboolean ret = FALSE;
739 flacdec = GST_FLAC_DEC (client_data);
741 if (!(peer = gst_pad_get_peer (flacdec->sinkpad))) {
742 GST_WARNING_OBJECT (flacdec, "no peer pad, returning EOF");
746 fmt = GST_FORMAT_BYTES;
747 if (gst_pad_query_duration (peer, &fmt, &len) && fmt == GST_FORMAT_BYTES &&
748 len != -1 && flacdec->offset >= len) {
749 GST_DEBUG_OBJECT (flacdec,
750 "offset=%" G_GINT64_FORMAT ", len=%" G_GINT64_FORMAT
751 ", returning EOF", flacdec->offset, len);
755 gst_object_unref (peer);
760 static FLAC__StreamDecoderReadStatus
761 gst_flac_dec_read_seekable (const FLAC__StreamDecoder * decoder,
762 FLAC__byte buffer[], size_t * bytes, void *client_data)
768 flacdec = GST_FLAC_DEC (client_data);
770 flow = gst_pad_pull_range (flacdec->sinkpad, flacdec->offset, *bytes, &buf);
772 GST_PAD_STREAM_LOCK (flacdec->sinkpad);
773 flacdec->pull_flow = flow;
774 GST_PAD_STREAM_UNLOCK (flacdec->sinkpad);
776 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
777 GST_INFO_OBJECT (flacdec, "pull_range flow: %s", gst_flow_get_name (flow));
778 if (flow == GST_FLOW_UNEXPECTED)
779 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
781 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
784 GST_DEBUG_OBJECT (flacdec, "Read %d bytes at %" G_GUINT64_FORMAT,
785 GST_BUFFER_SIZE (buf), flacdec->offset);
786 memcpy (buffer, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
787 *bytes = GST_BUFFER_SIZE (buf);
788 gst_buffer_unref (buf);
789 flacdec->offset += *bytes;
791 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
794 static FLAC__StreamDecoderReadStatus
795 gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
796 FLAC__byte buffer[], size_t * bytes, void *client_data)
798 GstFlacDec *dec = GST_FLAC_DEC (client_data);
801 len = MIN (gst_adapter_available (dec->adapter), *bytes);
804 GST_LOG_OBJECT (dec, "0 bytes available at the moment");
805 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
808 GST_LOG_OBJECT (dec, "feeding %u bytes to decoder (available=%u, bytes=%u)",
809 len, gst_adapter_available (dec->adapter), (guint) * bytes);
810 gst_adapter_copy (dec->adapter, buffer, 0, len);
813 gst_adapter_flush (dec->adapter, len);
815 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
818 static FLAC__StreamDecoderWriteStatus
819 gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
820 const FLAC__int32 * const buffer[])
822 GstFlowReturn ret = GST_FLOW_OK;
824 guint depth = frame->header.bits_per_sample;
826 guint sample_rate = frame->header.sample_rate;
827 guint channels = frame->header.channels;
828 guint samples = frame->header.blocksize;
832 GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);
834 /* if a DEFAULT segment is configured, don't send samples past the end
836 if (flacdec->segment.format == GST_FORMAT_DEFAULT &&
837 flacdec->segment.stop != -1 &&
838 flacdec->segment.last_stop >= 0 &&
839 flacdec->segment.last_stop + samples > flacdec->segment.stop) {
840 samples = flacdec->segment.stop - flacdec->segment.last_stop;
841 GST_DEBUG_OBJECT (flacdec,
842 "clipping last buffer to %d samples because of segment", samples);
859 if (flacdec->depth < 4 || flacdec->depth > 32) {
860 GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
862 ret = GST_FLOW_ERROR;
866 depth = flacdec->depth;
876 GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
877 ret = GST_FLOW_ERROR;
881 if (sample_rate == 0) {
882 if (flacdec->sample_rate != 0) {
883 sample_rate = flacdec->sample_rate;
885 GST_ERROR_OBJECT (flacdec, "unknown sample rate");
886 ret = GST_FLOW_ERROR;
891 if (!GST_PAD_CAPS (flacdec->srcpad)) {
894 GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels",
895 frame->header.sample_rate, channels);
897 caps = gst_caps_new_simple ("audio/x-raw-int",
898 "endianness", G_TYPE_INT, G_BYTE_ORDER,
899 "signed", G_TYPE_BOOLEAN, TRUE,
900 "width", G_TYPE_INT, width,
901 "depth", G_TYPE_INT, depth,
902 "rate", G_TYPE_INT, frame->header.sample_rate,
903 "channels", G_TYPE_INT, channels, NULL);
906 GstStructure *s = gst_caps_get_structure (caps, 0);
908 gst_audio_set_channel_positions (s, channel_positions[channels - 1]);
911 flacdec->depth = depth;
912 flacdec->width = width;
913 flacdec->channels = channels;
914 flacdec->sample_rate = sample_rate;
916 gst_pad_set_caps (flacdec->srcpad, caps);
917 gst_caps_unref (caps);
920 if (flacdec->close_segment) {
921 GST_DEBUG_OBJECT (flacdec, "pushing close segment");
922 gst_pad_push_event (flacdec->srcpad, flacdec->close_segment);
923 flacdec->close_segment = NULL;
925 if (flacdec->start_segment) {
926 GST_DEBUG_OBJECT (flacdec, "pushing start segment");
927 gst_pad_push_event (flacdec->srcpad, flacdec->start_segment);
928 flacdec->start_segment = NULL;
932 gst_element_found_tags_for_pad (GST_ELEMENT (flacdec), flacdec->srcpad,
934 flacdec->tags = NULL;
937 if (flacdec->pending) {
938 GST_DEBUG_OBJECT (flacdec,
939 "pushing pending samples at offset %" G_GINT64_FORMAT " (%"
940 GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")",
941 GST_BUFFER_OFFSET (flacdec->pending),
942 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (flacdec->pending)),
943 GST_TIME_ARGS (GST_BUFFER_DURATION (flacdec->pending)));
944 /* Pending buffer was always allocated from the seeking thread,
945 * which means it wasn't gst_buffer_alloc'd. Do so now to let
946 * downstream negotiation work on older basetransform */
947 ret = gst_pad_alloc_buffer_and_set_caps (flacdec->srcpad,
948 GST_BUFFER_OFFSET (flacdec->pending),
949 GST_BUFFER_SIZE (flacdec->pending),
950 GST_BUFFER_CAPS (flacdec->pending), &outbuf);
951 if (ret == GST_FLOW_OK) {
952 gst_pad_push (flacdec->srcpad, flacdec->pending);
953 gst_buffer_unref (outbuf);
956 outbuf = flacdec->pending = NULL;
957 flacdec->segment.last_stop += flacdec->pending_samples;
958 flacdec->pending_samples = 0;
961 if (flacdec->seeking) {
962 GST_DEBUG_OBJECT (flacdec, "a pad_alloc would block here, do normal alloc");
963 outbuf = gst_buffer_new_and_alloc (samples * channels * (width / 8));
964 gst_buffer_set_caps (outbuf, GST_PAD_CAPS (flacdec->srcpad));
965 GST_BUFFER_OFFSET (outbuf) = flacdec->segment.last_stop;
967 GST_LOG_OBJECT (flacdec, "alloc_buffer_and_set_caps");
968 ret = gst_pad_alloc_buffer_and_set_caps (flacdec->srcpad,
969 flacdec->segment.last_stop, samples * channels * (width / 8),
970 GST_PAD_CAPS (flacdec->srcpad), &outbuf);
972 if (ret != GST_FLOW_OK) {
973 GST_DEBUG_OBJECT (flacdec, "gst_pad_alloc_buffer() returned %s",
974 gst_flow_get_name (ret));
979 if (flacdec->cur_granulepos != GST_BUFFER_OFFSET_NONE) {
980 /* this should be fine since it should be one flac frame per ogg packet */
981 /* note the + 1, as the granpos is the presentation time of the last sample,
982 whereas the last stop represents the end time of that sample */
983 flacdec->segment.last_stop = flacdec->cur_granulepos - samples + 1;
984 GST_LOG_OBJECT (flacdec, "granulepos = %" G_GINT64_FORMAT ", samples = %u",
985 flacdec->cur_granulepos, samples);
988 GST_BUFFER_TIMESTAMP (outbuf) =
989 gst_util_uint64_scale_int (flacdec->segment.last_stop, GST_SECOND,
990 frame->header.sample_rate);
992 /* get next timestamp to calculate the duration */
993 next = gst_util_uint64_scale_int (flacdec->segment.last_stop + samples,
994 GST_SECOND, frame->header.sample_rate);
996 GST_BUFFER_DURATION (outbuf) = next - GST_BUFFER_TIMESTAMP (outbuf);
999 gint8 *outbuffer = (gint8 *) GST_BUFFER_DATA (outbuf);
1001 for (i = 0; i < samples; i++) {
1002 for (j = 0; j < channels; j++) {
1003 *outbuffer++ = (gint8) buffer[j][i];
1006 } else if (width == 16) {
1007 gint16 *outbuffer = (gint16 *) GST_BUFFER_DATA (outbuf);
1009 for (i = 0; i < samples; i++) {
1010 for (j = 0; j < channels; j++) {
1011 *outbuffer++ = (gint16) buffer[j][i];
1014 } else if (width == 32) {
1015 gint32 *outbuffer = (gint32 *) GST_BUFFER_DATA (outbuf);
1017 for (i = 0; i < samples; i++) {
1018 for (j = 0; j < channels; j++) {
1019 *outbuffer++ = (gint32) buffer[j][i];
1023 g_assert_not_reached ();
1026 if (!flacdec->seeking) {
1027 GST_DEBUG_OBJECT (flacdec, "pushing %d samples at offset %" G_GINT64_FORMAT
1028 " (%" GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")",
1029 samples, GST_BUFFER_OFFSET (outbuf),
1030 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1031 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
1033 if (flacdec->discont) {
1034 GST_DEBUG_OBJECT (flacdec, "marking discont");
1035 outbuf = gst_buffer_make_metadata_writable (outbuf);
1036 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1037 flacdec->discont = FALSE;
1039 ret = gst_pad_push (flacdec->srcpad, outbuf);
1040 GST_DEBUG_OBJECT (flacdec, "returned %s", gst_flow_get_name (ret));
1041 flacdec->segment.last_stop += samples;
1043 GST_DEBUG_OBJECT (flacdec,
1044 "not pushing %d samples at offset %" G_GINT64_FORMAT
1045 " (in seek)", samples, GST_BUFFER_OFFSET (outbuf));
1046 gst_buffer_replace (&flacdec->pending, outbuf);
1047 gst_buffer_unref (outbuf);
1048 flacdec->pending_samples = samples;
1052 if (ret != GST_FLOW_OK) {
1053 GST_DEBUG_OBJECT (flacdec, "gst_pad_push() returned %s",
1054 gst_flow_get_name (ret));
1060 /* we act on the flow return value later in the loop function, as we don't
1061 * want to mess up the internal decoder state by returning ABORT when the
1062 * error is in fact non-fatal (like a pad in flushing mode) and we want
1063 * to continue later. So just pretend everything's dandy and act later. */
1064 flacdec->last_flow = ret;
1066 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
1069 static FLAC__StreamDecoderWriteStatus
1070 gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
1071 const FLAC__Frame * frame,
1072 const FLAC__int32 * const buffer[], void *client_data)
1074 return gst_flac_dec_write (GST_FLAC_DEC (client_data), frame, buffer);
1078 gst_flac_dec_loop (GstPad * sinkpad)
1080 GstFlacDec *flacdec;
1081 FLAC__StreamDecoderState s;
1082 FLAC__StreamDecoderInitStatus is;
1084 flacdec = GST_FLAC_DEC (GST_OBJECT_PARENT (sinkpad));
1086 GST_LOG_OBJECT (flacdec, "entering loop");
1089 GST_DEBUG_OBJECT (flacdec, "Seeked after end of file");
1091 if (flacdec->close_segment) {
1092 GST_DEBUG_OBJECT (flacdec, "pushing close segment");
1093 gst_pad_push_event (flacdec->srcpad, flacdec->close_segment);
1094 flacdec->close_segment = NULL;
1096 if (flacdec->start_segment) {
1097 GST_DEBUG_OBJECT (flacdec, "pushing start segment");
1098 gst_pad_push_event (flacdec->srcpad, flacdec->start_segment);
1099 flacdec->start_segment = NULL;
1102 if (flacdec->tags) {
1103 gst_element_found_tags_for_pad (GST_ELEMENT (flacdec), flacdec->srcpad,
1105 flacdec->tags = NULL;
1108 if ((flacdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0) {
1111 goto segment_done_and_pause;
1115 if (flacdec->init) {
1116 GST_DEBUG_OBJECT (flacdec, "initializing new decoder");
1117 is = FLAC__stream_decoder_init_stream (flacdec->decoder,
1118 gst_flac_dec_read_seekable, gst_flac_dec_seek, gst_flac_dec_tell,
1119 gst_flac_dec_length, gst_flac_dec_eof, gst_flac_dec_write_stream,
1120 gst_flac_dec_metadata_cb, gst_flac_dec_error_cb, flacdec);
1121 if (is != FLAC__STREAM_DECODER_INIT_STATUS_OK)
1124 /* FLAC__seekable_decoder_process_metadata (flacdec->decoder); */
1125 flacdec->init = FALSE;
1128 flacdec->cur_granulepos = GST_BUFFER_OFFSET_NONE;
1130 flacdec->last_flow = GST_FLOW_OK;
1132 GST_LOG_OBJECT (flacdec, "processing single");
1133 FLAC__stream_decoder_process_single (flacdec->decoder);
1137 GST_LOG_OBJECT (flacdec, "done processing, checking encoder state");
1138 s = FLAC__stream_decoder_get_state (flacdec->decoder);
1140 case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
1141 case FLAC__STREAM_DECODER_READ_METADATA:
1142 case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
1143 case FLAC__STREAM_DECODER_READ_FRAME:
1145 GST_DEBUG_OBJECT (flacdec, "everything ok");
1147 if (flacdec->last_flow < GST_FLOW_UNEXPECTED ||
1148 flacdec->last_flow == GST_FLOW_NOT_LINKED) {
1149 GST_ELEMENT_ERROR (flacdec, STREAM, FAILED,
1150 (_("Internal data stream error.")),
1151 ("stream stopped, reason %s",
1152 gst_flow_get_name (flacdec->last_flow)));
1154 } else if (flacdec->last_flow == GST_FLOW_UNEXPECTED) {
1156 } else if (flacdec->last_flow != GST_FLOW_OK) {
1160 /* check if we're at the end of a configured segment */
1161 if (flacdec->segment.stop != -1 &&
1162 flacdec->segment.last_stop > 0 &&
1163 flacdec->segment.last_stop >= flacdec->segment.stop) {
1164 GST_DEBUG_OBJECT (flacdec, "reached end of the configured segment");
1166 if ((flacdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0) {
1169 goto segment_done_and_pause;
1172 g_assert_not_reached ();
1178 case FLAC__STREAM_DECODER_END_OF_STREAM:{
1179 GST_DEBUG_OBJECT (flacdec, "EOS");
1180 FLAC__stream_decoder_reset (flacdec->decoder);
1182 if ((flacdec->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
1183 if (flacdec->segment.duration > 0) {
1184 flacdec->segment.stop = flacdec->segment.duration;
1186 flacdec->segment.stop = flacdec->segment.last_stop;
1188 goto segment_done_and_pause;
1194 /* gst_flac_dec_read_seekable() returned ABORTED */
1195 case FLAC__STREAM_DECODER_ABORTED:
1197 GST_INFO_OBJECT (flacdec, "read aborted: last pull_range flow = %s",
1198 gst_flow_get_name (flacdec->pull_flow));
1199 if (flacdec->pull_flow == GST_FLOW_WRONG_STATE) {
1200 /* it seems we need to flush the decoder here to reset the decoder
1201 * state after the abort for FLAC__stream_decoder_seek_absolute()
1202 * to work properly */
1203 GST_DEBUG_OBJECT (flacdec, "flushing decoder to reset decoder state");
1204 FLAC__stream_decoder_flush (flacdec->decoder);
1209 case FLAC__STREAM_DECODER_OGG_ERROR:
1210 case FLAC__STREAM_DECODER_SEEK_ERROR:
1211 case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
1212 case FLAC__STREAM_DECODER_UNINITIALIZED:
1214 /* fixme: this error sucks -- should try to figure out when/if an more
1215 specific error was already sent via the callback */
1216 GST_ELEMENT_ERROR (flacdec, STREAM, DECODE, (NULL),
1217 ("%s", FLAC__StreamDecoderStateString[s]));
1224 segment_done_and_pause:
1228 stop_time = gst_util_uint64_scale_int (flacdec->segment.stop,
1229 GST_SECOND, flacdec->sample_rate);
1231 GST_DEBUG_OBJECT (flacdec, "posting SEGMENT_DONE message, stop time %"
1232 GST_TIME_FORMAT, GST_TIME_ARGS (stop_time));
1234 gst_element_post_message (GST_ELEMENT (flacdec),
1235 gst_message_new_segment_done (GST_OBJECT (flacdec),
1236 GST_FORMAT_TIME, stop_time));
1242 GST_DEBUG_OBJECT (flacdec, "sending EOS event");
1243 flacdec->running = FALSE;
1244 gst_pad_push_event (flacdec->srcpad, gst_event_new_eos ());
1245 /* fall through to pause */
1249 GST_DEBUG_OBJECT (flacdec, "pausing");
1250 gst_pad_pause_task (sinkpad);
1256 gst_flac_dec_sink_event (GstPad * pad, GstEvent * event)
1261 dec = GST_FLAC_DEC (gst_pad_get_parent (pad));
1263 switch (GST_EVENT_TYPE (event)) {
1264 case GST_EVENT_FLUSH_STOP:{
1265 if (dec->init == FALSE) {
1266 FLAC__stream_decoder_flush (dec->decoder);
1267 gst_adapter_clear (dec->adapter);
1269 res = gst_pad_push_event (dec->srcpad, event);
1272 case GST_EVENT_NEWSEGMENT:{
1275 gdouble rate, applied_rate;
1276 gint64 cur, stop, time;
1278 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
1279 &fmt, &cur, &stop, &time);
1281 if (fmt == GST_FORMAT_TIME) {
1282 GstFormat dformat = GST_FORMAT_DEFAULT;
1284 GST_DEBUG_OBJECT (dec, "newsegment event in TIME format => framed");
1286 res = gst_pad_push_event (dec->srcpad, event);
1288 /* this won't work for the first newsegment event though ... */
1289 if (gst_flac_dec_convert_src (dec->srcpad, GST_FORMAT_TIME, cur,
1290 &dformat, &cur) && cur != -1 &&
1291 gst_flac_dec_convert_src (dec->srcpad, GST_FORMAT_TIME, stop,
1292 &dformat, &stop) && stop != -1) {
1293 gst_segment_set_newsegment_full (&dec->segment, update, rate,
1294 applied_rate, dformat, cur, stop, time);
1295 GST_DEBUG_OBJECT (dec, "segment %" GST_SEGMENT_FORMAT, &dec->segment);
1297 GST_WARNING_OBJECT (dec, "couldn't convert time => samples");
1299 } else if (fmt == GST_FORMAT_BYTES || TRUE) {
1300 GST_DEBUG_OBJECT (dec, "newsegment event in %s format => not framed",
1301 gst_format_get_name (fmt));
1302 dec->framed = FALSE;
1304 /* prepare generic newsegment event, for some reason our metadata
1305 * callback where we usually set this up is not being called in
1307 if (dec->start_segment)
1308 gst_event_unref (dec->start_segment);
1309 dec->start_segment = gst_event_new_new_segment (FALSE, 1.0,
1310 GST_FORMAT_TIME, 0, -1, 0);
1312 gst_event_unref (event);
1317 case GST_EVENT_EOS:{
1318 GST_LOG_OBJECT (dec, "EOS, with %u bytes available in adapter",
1319 gst_adapter_available (dec->adapter));
1320 if (dec->init == FALSE) {
1321 if (gst_adapter_available (dec->adapter) > 0) {
1322 FLAC__stream_decoder_process_until_end_of_stream (dec->decoder);
1324 FLAC__stream_decoder_flush (dec->decoder);
1326 gst_adapter_clear (dec->adapter);
1327 res = gst_pad_push_event (dec->srcpad, event);
1331 res = gst_pad_event_default (pad, event);
1335 gst_object_unref (dec);
1341 gst_flac_dec_chain_parse_headers (GstFlacDec * dec)
1346 avail = gst_adapter_available (dec->adapter);
1350 gst_adapter_copy (dec->adapter, marker, 0, 4);
1351 if (strncmp ((const gchar *) marker, "fLaC", 4) != 0) {
1352 GST_ERROR_OBJECT (dec, "Unexpected header, expected fLaC header");
1353 return TRUE; /* abort header parsing */
1356 GST_DEBUG_OBJECT (dec, "fLaC header : len 4 @ %7u", 0);
1359 while (avail > (off + 1 + 3)) {
1362 guint len, block_type;
1364 gst_adapter_copy (dec->adapter, mb_hdr, off, 4);
1366 is_last = ((mb_hdr[0] & 0x80) == 0x80);
1367 block_type = mb_hdr[0] & 0x7f;
1368 len = GST_READ_UINT24_BE (mb_hdr + 1);
1369 GST_DEBUG_OBJECT (dec, "Metadata block type %u: len %7u + 4 @ %7u%s",
1370 block_type, len, off, (is_last) ? " (last)" : "");
1377 GST_LOG_OBJECT (dec, "Need more data: next offset %u > avail %u", off,
1383 /* want metadata blocks plus at least one frame */
1384 return (off + FLAC__MAX_BLOCK_SIZE >= avail);
1387 static GstFlowReturn
1388 gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)
1390 FLAC__StreamDecoderInitStatus s;
1392 gboolean got_audio_frame;
1394 dec = GST_FLAC_DEC (GST_PAD_PARENT (pad));
1396 GST_LOG_OBJECT (dec,
1397 "buffer with ts=%" GST_TIME_FORMAT ", offset=%" G_GINT64_FORMAT
1398 ", end_offset=%" G_GINT64_FORMAT ", size=%u",
1399 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_OFFSET (buf),
1400 GST_BUFFER_OFFSET_END (buf), GST_BUFFER_SIZE (buf));
1403 GST_DEBUG_OBJECT (dec, "initializing decoder");
1404 s = FLAC__stream_decoder_init_stream (dec->decoder,
1405 gst_flac_dec_read_stream, NULL, NULL, NULL, NULL,
1406 gst_flac_dec_write_stream, gst_flac_dec_metadata_cb,
1407 gst_flac_dec_error_cb, dec);
1408 if (s != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
1409 GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL));
1410 return GST_FLOW_ERROR;
1412 GST_DEBUG_OBJECT (dec, "initialized (framed=%d)", dec->framed);
1414 } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
1415 /* Clear the adapter and the decoder */
1416 gst_adapter_clear (dec->adapter);
1417 FLAC__stream_decoder_flush (dec->decoder);
1423 /* check if this is a flac audio frame (rather than a header or junk) */
1424 got_audio_frame = gst_flac_dec_scan_got_frame (dec, GST_BUFFER_DATA (buf),
1425 GST_BUFFER_SIZE (buf), &unused);
1427 /* oggdemux will set granulepos in OFFSET_END instead of timestamp */
1428 if (G_LIKELY (got_audio_frame)) {
1429 /* old oggdemux for now */
1430 if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1431 dec->cur_granulepos = GST_BUFFER_OFFSET_END (buf);
1433 GstFormat dformat = GST_FORMAT_DEFAULT;
1435 /* upstream (e.g. demuxer) presents us time,
1436 * convert to default samples */
1437 gst_flac_dec_convert_src (dec->srcpad, GST_FORMAT_TIME,
1438 GST_BUFFER_TIMESTAMP (buf), &dformat, &dec->segment.last_stop);
1439 dec->cur_granulepos = GST_BUFFER_OFFSET_NONE;
1443 dec->cur_granulepos = GST_BUFFER_OFFSET_NONE;
1444 got_audio_frame = TRUE;
1447 gst_adapter_push (dec->adapter, buf);
1450 dec->last_flow = GST_FLOW_OK;
1453 if (G_UNLIKELY (!dec->got_headers)) {
1454 if (!gst_flac_dec_chain_parse_headers (dec)) {
1455 GST_LOG_OBJECT (dec, "don't have metadata blocks yet, need more data");
1458 GST_INFO_OBJECT (dec, "have all metadata blocks now");
1459 dec->got_headers = TRUE;
1462 /* wait until we have at least 64kB because libflac's StreamDecoder
1463 * interface is a bit dumb it seems (if we don't have as much data as
1464 * it wants it will call our read callback repeatedly and the only
1465 * way to stop that is to error out or EOS, which will affect the
1466 * decoder state). And the decoder seems to always ask for MAX_BLOCK_SIZE
1467 * bytes rather than the max. block size from the header). Requiring
1468 * MAX_BLOCK_SIZE bytes here should make sure it always gets enough data
1469 * to decode at least one block */
1470 while (gst_adapter_available (dec->adapter) >= FLAC__MAX_BLOCK_SIZE &&
1471 dec->last_flow == GST_FLOW_OK) {
1472 GST_LOG_OBJECT (dec, "%u bytes available",
1473 gst_adapter_available (dec->adapter));
1474 if (!FLAC__stream_decoder_process_single (dec->decoder)) {
1475 GST_DEBUG_OBJECT (dec, "process_single failed");
1479 if (FLAC__stream_decoder_get_state (dec->decoder) ==
1480 FLAC__STREAM_DECODER_ABORTED) {
1481 GST_WARNING_OBJECT (dec, "Read callback caused internal abort");
1482 dec->last_flow = GST_FLOW_ERROR;
1486 } else if (dec->framed && got_audio_frame) {
1487 /* framed - there should always be enough data to decode something */
1488 GST_LOG_OBJECT (dec, "%u bytes available",
1489 gst_adapter_available (dec->adapter));
1490 if (G_UNLIKELY (!dec->got_headers)) {
1491 /* The first time we get audio data, we know we got all the headers.
1492 * We then loop until all the metadata is processed, then do an extra
1493 * "process_single" step for the audio frame. */
1494 GST_DEBUG_OBJECT (dec,
1495 "First audio frame, ensuring all metadata is processed");
1496 if (!FLAC__stream_decoder_process_until_end_of_metadata (dec->decoder)) {
1497 GST_DEBUG_OBJECT (dec, "process_until_end_of_metadata failed");
1499 GST_DEBUG_OBJECT (dec,
1500 "All metadata is now processed, reading to process audio data");
1501 dec->got_headers = TRUE;
1503 if (!FLAC__stream_decoder_process_single (dec->decoder)) {
1504 GST_DEBUG_OBJECT (dec, "process_single failed");
1507 GST_DEBUG_OBJECT (dec, "don't have all headers yet");
1512 return dec->last_flow;
1516 gst_flac_dec_convert_sink (GstFlacDec * dec, GstFormat src_format,
1517 gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
1519 gboolean res = TRUE;
1521 if (dec->width == 0 || dec->channels == 0 || dec->sample_rate == 0) {
1522 /* no frame decoded yet */
1523 GST_DEBUG_OBJECT (dec, "cannot convert: not set up yet");
1527 switch (src_format) {
1528 case GST_FORMAT_BYTES:{
1532 case GST_FORMAT_DEFAULT:
1533 switch (*dest_format) {
1534 case GST_FORMAT_BYTES:
1537 case GST_FORMAT_TIME:
1538 /* granulepos = sample */
1539 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
1547 case GST_FORMAT_TIME:
1548 switch (*dest_format) {
1549 case GST_FORMAT_BYTES:
1552 case GST_FORMAT_DEFAULT:
1553 *dest_value = gst_util_uint64_scale_int (src_value,
1554 dec->sample_rate, GST_SECOND);
1568 static const GstQueryType *
1569 gst_flac_dec_get_sink_query_types (GstPad * pad)
1571 static const GstQueryType types[] = {
1580 gst_flac_dec_sink_query (GstPad * pad, GstQuery * query)
1583 gboolean res = FALSE;
1585 dec = GST_FLAC_DEC (gst_pad_get_parent (pad));
1587 GST_LOG_OBJECT (dec, "%s query", GST_QUERY_TYPE_NAME (query));
1589 switch (GST_QUERY_TYPE (query)) {
1590 case GST_QUERY_CONVERT:{
1591 GstFormat src_fmt, dest_fmt;
1593 gint64 src_val, dest_val;
1595 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
1597 res = gst_flac_dec_convert_sink (dec, src_fmt, src_val, &dest_fmt,
1601 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1603 GST_LOG_OBJECT (dec, "conversion %s", (res) ? "ok" : "FAILED");
1608 res = gst_pad_query_default (pad, query);
1613 gst_object_unref (dec);
1618 gst_flac_dec_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
1619 GstFormat * dest_format, gint64 * dest_value)
1621 GstFlacDec *flacdec = GST_FLAC_DEC (GST_PAD_PARENT (pad));
1622 gboolean res = TRUE;
1623 guint bytes_per_sample;
1626 if (flacdec->width == 0 || flacdec->channels == 0 ||
1627 flacdec->sample_rate == 0) {
1628 /* no frame decoded yet */
1629 GST_DEBUG_OBJECT (flacdec, "cannot convert: not set up yet");
1633 bytes_per_sample = flacdec->channels * (flacdec->width / 8);
1635 switch (src_format) {
1636 case GST_FORMAT_BYTES:{
1637 switch (*dest_format) {
1638 case GST_FORMAT_DEFAULT:
1640 gst_util_uint64_scale_int (src_value, 1, bytes_per_sample);
1642 case GST_FORMAT_TIME:
1644 gint byterate = bytes_per_sample * flacdec->sample_rate;
1646 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
1655 case GST_FORMAT_DEFAULT:
1656 switch (*dest_format) {
1657 case GST_FORMAT_BYTES:
1658 *dest_value = src_value * bytes_per_sample;
1660 case GST_FORMAT_TIME:
1661 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
1662 flacdec->sample_rate);
1668 case GST_FORMAT_TIME:
1669 switch (*dest_format) {
1670 case GST_FORMAT_BYTES:
1671 scale = bytes_per_sample;
1672 case GST_FORMAT_DEFAULT:
1673 *dest_value = gst_util_uint64_scale_int_round (src_value,
1674 scale * flacdec->sample_rate, GST_SECOND);
1686 static const GstQueryType *
1687 gst_flac_dec_get_src_query_types (GstPad * pad)
1689 static const GstQueryType types[] = {
1701 gst_flac_dec_src_query (GstPad * pad, GstQuery * query)
1703 GstFlacDec *flacdec;
1704 gboolean res = TRUE;
1707 flacdec = GST_FLAC_DEC (gst_pad_get_parent (pad));
1708 peer = gst_pad_get_peer (flacdec->sinkpad);
1710 switch (GST_QUERY_TYPE (query)) {
1711 case GST_QUERY_POSITION:{
1715 gst_query_parse_position (query, &fmt, NULL);
1717 /* there might be a demuxer in front of us who can handle this */
1718 if (fmt == GST_FORMAT_TIME && (res = gst_pad_query (peer, query)))
1721 if (fmt != GST_FORMAT_DEFAULT) {
1722 if (!gst_flac_dec_convert_src (flacdec->srcpad, GST_FORMAT_DEFAULT,
1723 flacdec->segment.last_stop, &fmt, &pos)) {
1724 GST_DEBUG_OBJECT (flacdec, "failed to convert position into %s "
1725 "format", gst_format_get_name (fmt));
1730 pos = flacdec->segment.last_stop;
1733 gst_query_set_position (query, fmt, pos);
1735 GST_DEBUG_OBJECT (flacdec, "returning position %" G_GUINT64_FORMAT
1736 " (format: %s)", pos, gst_format_get_name (fmt));
1742 case GST_QUERY_DURATION:{
1746 gst_query_parse_duration (query, &fmt, NULL);
1748 /* try any demuxers or parsers before us first */
1749 if ((fmt == GST_FORMAT_TIME || fmt == GST_FORMAT_DEFAULT) &&
1750 peer != NULL && gst_pad_query (peer, query)) {
1751 gst_query_parse_duration (query, NULL, &len);
1752 GST_DEBUG_OBJECT (flacdec, "peer returned duration %" GST_TIME_FORMAT,
1753 GST_TIME_ARGS (len));
1758 if (flacdec->segment.duration == 0 || flacdec->segment.duration == -1) {
1759 GST_DEBUG_OBJECT (flacdec, "duration not known yet");
1764 /* convert total number of samples to request format */
1765 if (fmt != GST_FORMAT_DEFAULT) {
1766 if (!gst_flac_dec_convert_src (flacdec->srcpad, GST_FORMAT_DEFAULT,
1767 flacdec->segment.duration, &fmt, &len)) {
1768 GST_DEBUG_OBJECT (flacdec, "failed to convert duration into %s "
1769 "format", gst_format_get_name (fmt));
1774 len = flacdec->segment.duration;
1777 gst_query_set_duration (query, fmt, len);
1779 GST_DEBUG_OBJECT (flacdec, "returning duration %" G_GUINT64_FORMAT
1780 " (format: %s)", len, gst_format_get_name (fmt));
1786 case GST_QUERY_CONVERT:{
1787 GstFormat src_fmt, dest_fmt;
1788 gint64 src_val, dest_val;
1790 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL);
1792 res = gst_flac_dec_convert_src (pad, src_fmt, src_val, &dest_fmt,
1796 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
1801 case GST_QUERY_SEEKING:{
1803 gboolean seekable = FALSE;
1806 /* If upstream can handle the query we're done */
1807 seekable = gst_pad_peer_query (flacdec->sinkpad, query);
1809 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
1813 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1814 if ((fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT) ||
1815 flacdec->streaming) {
1816 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
1818 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1);
1824 res = gst_pad_query_default (pad, query);
1832 gst_object_unref (peer);
1834 gst_object_unref (flacdec);
1840 gst_flac_dec_handle_seek_event (GstFlacDec * flacdec, GstEvent * event)
1843 GstSeekFlags seek_flags;
1844 GstSeekType start_type;
1845 GstSeekType stop_type;
1847 GstFormat seek_format;
1848 gboolean only_update = FALSE;
1851 gint64 start, last_stop;
1854 if (flacdec->streaming) {
1855 GST_DEBUG_OBJECT (flacdec, "seeking in streaming mode not implemented yet");
1859 gst_event_parse_seek (event, &rate, &seek_format, &seek_flags, &start_type,
1860 &start, &stop_type, &stop);
1862 if (seek_format != GST_FORMAT_DEFAULT && seek_format != GST_FORMAT_TIME) {
1863 GST_DEBUG_OBJECT (flacdec,
1864 "seeking is only supported in TIME or DEFAULT format");
1869 GST_DEBUG_OBJECT (flacdec,
1870 "only forward playback supported, rate %f not allowed", rate);
1874 if (seek_format != GST_FORMAT_DEFAULT) {
1875 GstFormat target_format = GST_FORMAT_DEFAULT;
1877 if (start_type != GST_SEEK_TYPE_NONE &&
1878 !gst_flac_dec_convert_src (flacdec->srcpad, seek_format, start,
1879 &target_format, &start)) {
1880 GST_DEBUG_OBJECT (flacdec, "failed to convert start to DEFAULT format");
1884 if (stop_type != GST_SEEK_TYPE_NONE &&
1885 !gst_flac_dec_convert_src (flacdec->srcpad, seek_format, stop,
1886 &target_format, &stop)) {
1887 GST_DEBUG_OBJECT (flacdec, "failed to convert stop to DEFAULT format");
1892 /* Check if we seeked after the end of file */
1893 if (start_type != GST_SEEK_TYPE_NONE && flacdec->segment.duration > 0 &&
1894 start >= flacdec->segment.duration) {
1895 flacdec->eos = TRUE;
1897 flacdec->eos = FALSE;
1900 flush = ((seek_flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
1903 /* flushing seek, clear the pipeline of stuff, we need a newsegment after
1905 GST_DEBUG_OBJECT (flacdec, "flushing");
1906 gst_pad_push_event (flacdec->sinkpad, gst_event_new_flush_start ());
1907 gst_pad_push_event (flacdec->srcpad, gst_event_new_flush_start ());
1909 /* non flushing seek, pause the task */
1910 GST_DEBUG_OBJECT (flacdec, "stopping task");
1911 gst_pad_stop_task (flacdec->sinkpad);
1914 /* acquire the stream lock, this either happens when the streaming thread
1915 * stopped because of the flush or when the task is paused after the loop
1916 * function finished an iteration, which can never happen when it's blocked
1917 * downstream in PAUSED, for example */
1918 GST_PAD_STREAM_LOCK (flacdec->sinkpad);
1920 /* start seek with clear state to avoid seeking thread pushing segments/data.
1921 * Note current state may have some pending,
1922 * e.g. multi-sink seek leads to immediate subsequent seek events */
1923 if (flacdec->start_segment) {
1924 gst_event_unref (flacdec->start_segment);
1925 flacdec->start_segment = NULL;
1927 gst_buffer_replace (&flacdec->pending, NULL);
1928 flacdec->pending_samples = 0;
1930 /* save a segment copy until we know the seek worked. The idea is that
1931 * when the seek fails, we want to restore with what we were doing. */
1932 segment = flacdec->segment;
1934 /* update the segment with the seek values, last_stop will contain the new
1935 * position we should seek to */
1936 gst_segment_set_seek (&flacdec->segment, rate, GST_FORMAT_DEFAULT,
1937 seek_flags, start_type, start, stop_type, stop, &only_update);
1939 GST_DEBUG_OBJECT (flacdec,
1940 "configured segment: [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
1941 "] = [%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "]",
1942 flacdec->segment.start, flacdec->segment.stop,
1943 GST_TIME_ARGS (flacdec->segment.start * GST_SECOND /
1944 flacdec->sample_rate),
1945 GST_TIME_ARGS (flacdec->segment.stop * GST_SECOND /
1946 flacdec->sample_rate));
1948 GST_DEBUG_OBJECT (flacdec, "performing seek to sample %" G_GINT64_FORMAT,
1949 flacdec->segment.last_stop);
1951 /* flush sinkpad again because we need to pull and push buffers while doing
1954 GST_DEBUG_OBJECT (flacdec, "flushing stop");
1955 gst_pad_push_event (flacdec->sinkpad, gst_event_new_flush_stop ());
1956 gst_pad_push_event (flacdec->srcpad, gst_event_new_flush_stop ());
1959 /* mark ourselves as seeking because the above lines will trigger some
1960 * callbacks that need to behave differently when seeking */
1961 flacdec->seeking = TRUE;
1963 if (!flacdec->eos) {
1964 GST_LOG_OBJECT (flacdec, "calling seek_absolute");
1965 seek_ok = FLAC__stream_decoder_seek_absolute (flacdec->decoder,
1966 flacdec->segment.last_stop);
1967 GST_LOG_OBJECT (flacdec, "done with seek_absolute, seek_ok=%d", seek_ok);
1969 GST_LOG_OBJECT (flacdec, "not seeking, seeked after end of file");
1973 flacdec->seeking = FALSE;
1975 GST_DEBUG_OBJECT (flacdec, "performed seek to sample %" G_GINT64_FORMAT,
1976 flacdec->segment.last_stop);
1979 GST_WARNING_OBJECT (flacdec, "seek failed");
1980 /* seek failed, restore the segment and start streaming again with
1981 * the previous segment values */
1982 flacdec->segment = segment;
1983 } else if (!flush && flacdec->running) {
1984 /* we are running the current segment and doing a non-flushing seek,
1985 * close the segment first based on the last_stop. */
1986 GST_DEBUG_OBJECT (flacdec, "closing running segment %" G_GINT64_FORMAT
1987 " to %" G_GINT64_FORMAT, segment.start, segment.last_stop);
1989 /* convert the old segment values to time to close the old segment */
1990 start = gst_util_uint64_scale_int (segment.start, GST_SECOND,
1991 flacdec->sample_rate);
1993 gst_util_uint64_scale_int (segment.last_stop, GST_SECOND,
1994 flacdec->sample_rate);
1996 /* queue the segment for sending in the stream thread, start and time are
1997 * always the same. */
1998 if (flacdec->close_segment)
1999 gst_event_unref (flacdec->close_segment);
2000 flacdec->close_segment =
2001 gst_event_new_new_segment_full (TRUE,
2002 segment.rate, segment.applied_rate, GST_FORMAT_TIME,
2003 start, last_stop, start);
2007 /* seek succeeded, flacdec->segment contains the new positions */
2008 GST_DEBUG_OBJECT (flacdec, "seek successful");
2011 /* convert the (new) segment values to time, we will need them to generate the
2012 * new segment events. */
2013 start = gst_util_uint64_scale_int (flacdec->segment.start, GST_SECOND,
2014 flacdec->sample_rate);
2015 last_stop = gst_util_uint64_scale_int (flacdec->segment.last_stop, GST_SECOND,
2016 flacdec->sample_rate);
2018 /* for deriving a stop position for the playback segment from the seek
2019 * segment, we must take the duration when the stop is not set */
2020 if (flacdec->segment.stop != -1)
2021 stop = gst_util_uint64_scale_int (flacdec->segment.stop, GST_SECOND,
2022 flacdec->sample_rate);
2024 stop = gst_util_uint64_scale_int (flacdec->segment.duration, GST_SECOND,
2025 flacdec->sample_rate);
2027 /* notify start of new segment when we were asked to do so. */
2028 if (flacdec->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2029 /* last_stop contains the position we start from */
2030 gst_element_post_message (GST_ELEMENT (flacdec),
2031 gst_message_new_segment_start (GST_OBJECT (flacdec),
2032 GST_FORMAT_TIME, last_stop));
2035 /* if the seek was ok or (when it failed) we are flushing, we need to send out
2036 * a new segment. If we did not flush and the seek failed, we simply do
2037 * nothing here and continue where we were. */
2038 if (seek_ok || flush) {
2039 GST_DEBUG_OBJECT (flacdec, "Creating newsegment from %" GST_TIME_FORMAT
2040 " to %" GST_TIME_FORMAT, GST_TIME_ARGS (last_stop),
2041 GST_TIME_ARGS (stop));
2042 /* now replace the old segment so that we send it in the stream thread the
2043 * next time it is scheduled. */
2044 if (flacdec->start_segment)
2045 gst_event_unref (flacdec->start_segment);
2046 flacdec->start_segment =
2047 gst_event_new_new_segment_full (FALSE,
2048 flacdec->segment.rate, flacdec->segment.applied_rate, GST_FORMAT_TIME,
2049 last_stop, stop, last_stop);
2052 /* we'll generate a discont on the next buffer */
2053 flacdec->discont = TRUE;
2054 /* the task is running again now */
2055 flacdec->running = TRUE;
2056 gst_pad_start_task (flacdec->sinkpad,
2057 (GstTaskFunction) gst_flac_dec_loop, flacdec->sinkpad);
2059 GST_PAD_STREAM_UNLOCK (flacdec->sinkpad);
2065 gst_flac_dec_src_event (GstPad * pad, GstEvent * event)
2067 gboolean res = TRUE;
2068 GstFlacDec *flacdec;
2070 flacdec = GST_FLAC_DEC (gst_pad_get_parent (pad));
2072 switch (GST_EVENT_TYPE (event)) {
2073 case GST_EVENT_SEEK:{
2074 GST_DEBUG_OBJECT (flacdec, "received seek event %p", event);
2075 /* first, see if we're before a demuxer that
2076 * might handle the seek for us */
2077 gst_event_ref (event);
2078 res = gst_pad_event_default (pad, event);
2079 /* if not, try to handle it ourselves */
2081 GST_DEBUG_OBJECT (flacdec, "default failed, handling ourselves");
2082 res = gst_flac_dec_handle_seek_event (flacdec, event);
2084 gst_event_unref (event);
2088 res = gst_pad_event_default (pad, event);
2092 gst_object_unref (flacdec);
2098 gst_flac_dec_sink_activate (GstPad * sinkpad)
2100 if (gst_pad_check_pull_range (sinkpad))
2101 return gst_pad_activate_pull (sinkpad, TRUE);
2103 return gst_pad_activate_push (sinkpad, TRUE);
2107 gst_flac_dec_sink_activate_push (GstPad * sinkpad, gboolean active)
2109 GstFlacDec *dec = GST_FLAC_DEC (GST_OBJECT_PARENT (sinkpad));
2112 gst_flac_dec_setup_decoder (dec);
2113 dec->streaming = TRUE;
2114 dec->got_headers = FALSE;
2120 gst_flac_dec_sink_activate_pull (GstPad * sinkpad, gboolean active)
2125 GstFlacDec *flacdec;
2127 flacdec = GST_FLAC_DEC (GST_PAD_PARENT (sinkpad));
2129 flacdec->offset = 0;
2130 gst_flac_dec_setup_decoder (flacdec);
2131 flacdec->running = TRUE;
2132 flacdec->streaming = FALSE;
2134 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flac_dec_loop,
2137 res = gst_pad_stop_task (sinkpad);
2142 static GstStateChangeReturn
2143 gst_flac_dec_change_state (GstElement * element, GstStateChange transition)
2145 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2146 GstFlacDec *flacdec = GST_FLAC_DEC (element);
2148 switch (transition) {
2149 case GST_STATE_CHANGE_READY_TO_PAUSED:
2150 flacdec->eos = FALSE;
2151 flacdec->seeking = FALSE;
2152 flacdec->channels = 0;
2155 flacdec->sample_rate = 0;
2156 gst_segment_init (&flacdec->segment, GST_FORMAT_DEFAULT);
2162 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2163 if (ret == GST_STATE_CHANGE_FAILURE)
2166 switch (transition) {
2167 case GST_STATE_CHANGE_PAUSED_TO_READY:
2168 gst_segment_init (&flacdec->segment, GST_FORMAT_UNDEFINED);
2169 gst_flac_dec_reset_decoders (flacdec);