aacparse: Properly report in the CAPS query that we can convert ADTS<->RAW
[platform/upstream/gst-plugins-good.git] / gst / audioparsers / gstflacparse.c
1 /* GStreamer
2  *
3  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4  * Copyright (C) 2009 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
5  * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6  *   Contact: Stefan Kost <stefan.kost@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23
24 /**
25  * SECTION:element-flacparse
26  * @see_also: flacdec, oggdemux, vorbisparse
27  *
28  * The flacparse element will parse the header packets of the FLAC
29  * stream and put them as the streamheader in the caps. This is used in the
30  * multifdsink case where you want to stream live FLAC streams to multiple
31  * clients, each client has to receive the streamheaders first before they can
32  * consume the FLAC packets.
33  *
34  * This element also makes sure that the buffers that it pushes out are properly
35  * timestamped and that their offset and offset_end are set. The buffers that
36  * flacparse outputs have all of the metadata that oggmux expects to receive,
37  * which allows you to (for example) remux an ogg/flac or convert a native FLAC
38  * format file to an ogg bitstream.
39  *
40  * <refsect2>
41  * <title>Example pipelines</title>
42  * |[
43  * gst-launch-1.0 -v filesrc location=sine.flac ! flacparse ! identity \
44  *            ! oggmux ! filesink location=sine-remuxed.ogg
45  * ]| This pipeline converts a native FLAC format file to an ogg bitstream.
46  * It also illustrates that the streamheader is set in the caps, and that each
47  * buffer has the timestamp, duration, offset, and offset_end set.
48  * </refsect2>
49  *
50  */
51
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55
56 #include "gstflacparse.h"
57
58 #include <string.h>
59 #include <gst/tag/tag.h>
60 #include <gst/audio/audio.h>
61 #include <gst/base/base.h>
62 #include <gst/pbutils/pbutils.h>
63
64 GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
65 #define GST_CAT_DEFAULT flacparse_debug
66
67 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
68 static const guint8 crc8_table[256] = {
69   0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
70   0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
71   0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
72   0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
73   0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
74   0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
75   0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
76   0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
77   0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
78   0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
79   0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
80   0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
81   0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
82   0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
83   0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
84   0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
85   0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
86   0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
87   0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
88   0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
89   0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
90   0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
91   0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
92   0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
93   0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
94   0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
95   0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
96   0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
97   0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
98   0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
99   0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
100   0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
101 };
102
103 static guint8
104 gst_flac_calculate_crc8 (const guint8 * data, guint length)
105 {
106   guint8 crc = 0;
107
108   while (length--) {
109     crc = crc8_table[crc ^ *data];
110     ++data;
111   }
112
113   return crc;
114 }
115
116 /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
117 static const guint16 crc16_table[256] = {
118   0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
119   0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
120   0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
121   0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
122   0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
123   0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
124   0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
125   0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
126   0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
127   0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
128   0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
129   0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
130   0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
131   0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
132   0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
133   0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
134   0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
135   0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
136   0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
137   0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
138   0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
139   0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
140   0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
141   0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
142   0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
143   0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
144   0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
145   0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
146   0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
147   0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
148   0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
149   0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
150 };
151
152 static guint16
153 gst_flac_calculate_crc16 (const guint8 * data, guint length)
154 {
155   guint16 crc = 0;
156
157   while (length--) {
158     crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
159     data++;
160   }
161
162   return crc;
163 }
164
165 enum
166 {
167   PROP_0,
168   PROP_CHECK_FRAME_CHECKSUMS
169 };
170
171 #define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
172
173 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
174     GST_PAD_SRC,
175     GST_PAD_ALWAYS,
176     GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
177         "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
178     );
179
180 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
181     GST_PAD_SINK,
182     GST_PAD_ALWAYS,
183     GST_STATIC_CAPS ("audio/x-flac")
184     );
185
186 static GstBuffer *gst_flac_parse_generate_vorbiscomment (GstFlacParse *
187     flacparse);
188
189 static void gst_flac_parse_finalize (GObject * object);
190 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
191     const GValue * value, GParamSpec * pspec);
192 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
193     GValue * value, GParamSpec * pspec);
194
195 static gboolean gst_flac_parse_start (GstBaseParse * parse);
196 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
197 static GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
198     GstBaseParseFrame * frame, gint * skipsize);
199 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
200     GstBaseParseFrame * frame, gint size);
201 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
202     GstBaseParseFrame * frame);
203 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
204     GstFormat src_format, gint64 src_value, GstFormat dest_format,
205     gint64 * dest_value);
206 static gboolean gst_flac_parse_src_event (GstBaseParse * parse,
207     GstEvent * event);
208 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
209     GstCaps * filter);
210
211 #define gst_flac_parse_parent_class parent_class
212 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
213
214 static void
215 gst_flac_parse_class_init (GstFlacParseClass * klass)
216 {
217   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
218   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
219   GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
220
221   GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
222       "Flac parser element");
223
224   gobject_class->finalize = gst_flac_parse_finalize;
225   gobject_class->set_property = gst_flac_parse_set_property;
226   gobject_class->get_property = gst_flac_parse_get_property;
227
228   g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
229       g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
230           "Check the overall checksums of every frame",
231           DEFAULT_CHECK_FRAME_CHECKSUMS,
232           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
233
234   baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
235   baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
236   baseparse_class->handle_frame =
237       GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
238   baseparse_class->pre_push_frame =
239       GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
240   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
241   baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_event);
242   baseparse_class->get_sink_caps =
243       GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
244
245   gst_element_class_add_pad_template (element_class,
246       gst_static_pad_template_get (&src_factory));
247   gst_element_class_add_pad_template (element_class,
248       gst_static_pad_template_get (&sink_factory));
249
250   gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
251       "Codec/Parser/Audio",
252       "Parses audio with the FLAC lossless audio codec",
253       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
254 }
255
256 static void
257 gst_flac_parse_init (GstFlacParse * flacparse)
258 {
259   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
260   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (flacparse));
261 }
262
263 static void
264 gst_flac_parse_set_property (GObject * object, guint prop_id,
265     const GValue * value, GParamSpec * pspec)
266 {
267   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
268
269   switch (prop_id) {
270     case PROP_CHECK_FRAME_CHECKSUMS:
271       flacparse->check_frame_checksums = g_value_get_boolean (value);
272       break;
273     default:
274       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275       break;
276   }
277 }
278
279 static void
280 gst_flac_parse_get_property (GObject * object, guint prop_id,
281     GValue * value, GParamSpec * pspec)
282 {
283   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
284
285   switch (prop_id) {
286     case PROP_CHECK_FRAME_CHECKSUMS:
287       g_value_set_boolean (value, flacparse->check_frame_checksums);
288       break;
289     default:
290       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291       break;
292   }
293 }
294
295 static void
296 gst_flac_parse_finalize (GObject * object)
297 {
298   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
299
300   if (flacparse->tags) {
301     gst_tag_list_unref (flacparse->tags);
302     flacparse->tags = NULL;
303   }
304   if (flacparse->toc) {
305     gst_toc_unref (flacparse->toc);
306     flacparse->toc = NULL;
307   }
308
309   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
310   g_list_free (flacparse->headers);
311   flacparse->headers = NULL;
312
313   G_OBJECT_CLASS (parent_class)->finalize (object);
314 }
315
316 static gboolean
317 gst_flac_parse_start (GstBaseParse * parse)
318 {
319   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
320
321   flacparse->state = GST_FLAC_PARSE_STATE_INIT;
322   flacparse->min_blocksize = 0;
323   flacparse->max_blocksize = 0;
324   flacparse->min_framesize = 0;
325   flacparse->max_framesize = 0;
326
327   flacparse->upstream_length = -1;
328
329   flacparse->samplerate = 0;
330   flacparse->channels = 0;
331   flacparse->bps = 0;
332   flacparse->total_samples = 0;
333
334   flacparse->offset = GST_CLOCK_TIME_NONE;
335   flacparse->blocking_strategy = 0;
336   flacparse->block_size = 0;
337   flacparse->sample_number = 0;
338   flacparse->strategy_checked = FALSE;
339
340   flacparse->sent_codec_tag = FALSE;
341
342   /* "fLaC" marker */
343   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
344
345   /* inform baseclass we can come up with ts, based on counters in packets */
346   gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
347   gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
348
349   return TRUE;
350 }
351
352 static gboolean
353 gst_flac_parse_stop (GstBaseParse * parse)
354 {
355   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
356
357   if (flacparse->tags) {
358     gst_tag_list_unref (flacparse->tags);
359     flacparse->tags = NULL;
360   }
361   if (flacparse->toc) {
362     gst_toc_unref (flacparse->toc);
363     flacparse->toc = NULL;
364   }
365
366   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
367   g_list_free (flacparse->headers);
368   flacparse->headers = NULL;
369
370   return TRUE;
371 }
372
373 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
374
375 static const guint16 blocksize_table[16] = {
376   0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
377   256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
378   256 << 7,
379 };
380
381 static const guint32 sample_rate_table[16] = {
382   0,
383   88200, 176400, 192000,
384   8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
385   0, 0, 0, 0,
386 };
387
388 typedef enum
389 {
390   FRAME_HEADER_VALID,
391   FRAME_HEADER_INVALID,
392   FRAME_HEADER_MORE_DATA
393 } FrameHeaderCheckReturn;
394
395 static FrameHeaderCheckReturn
396 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
397     const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
398     gboolean * suspect)
399 {
400   GstBitReader reader = GST_BIT_READER_INIT (data, size);
401   guint8 blocking_strategy;
402   guint16 block_size;
403   guint32 samplerate = 0;
404   guint64 sample_number;
405   guint8 channels, bps;
406   guint8 tmp = 0;
407   guint8 actual_crc, expected_crc = 0;
408
409   /* Skip 14 bit sync code */
410   gst_bit_reader_skip_unchecked (&reader, 14);
411
412   /* Must be 0 */
413   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
414     goto error;
415
416   /* 0 == fixed block size, 1 == variable block size */
417   blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
418   if (flacparse->force_variable_block_size)
419     blocking_strategy = 1;
420
421   /* block size index, calculation of the real blocksize below */
422   block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
423   if (block_size == 0)
424     goto error;
425
426   /* sample rate index, calculation of the real samplerate below */
427   samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
428   if (samplerate == 0x0f)
429     goto error;
430
431   /* channel assignment */
432   channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
433   if (channels < 8) {
434     channels++;
435   } else if (channels <= 10) {
436     channels = 2;
437   } else if (channels > 10) {
438     goto error;
439   }
440   if (flacparse->channels && flacparse->channels != channels)
441     goto error;
442
443   /* bits per sample */
444   bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
445   if (bps == 0x03 || bps == 0x07) {
446     goto error;
447   } else if (bps == 0 && flacparse->bps == 0) {
448     goto need_streaminfo;
449   }
450   bps = sample_size_table[bps];
451   if (flacparse->bps && bps != flacparse->bps)
452     goto error;
453
454   /* reserved, must be 0 */
455   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
456     goto error;
457
458   /* read "utf8" encoded sample/frame number */
459   {
460     gint len = 0;
461
462     len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
463
464     /* This is slightly faster than a loop */
465     if (!(len & 0x80)) {
466       sample_number = len;
467       len = 0;
468     } else if ((len & 0xc0) && !(len & 0x20)) {
469       sample_number = len & 0x1f;
470       len = 1;
471     } else if ((len & 0xe0) && !(len & 0x10)) {
472       sample_number = len & 0x0f;
473       len = 2;
474     } else if ((len & 0xf0) && !(len & 0x08)) {
475       sample_number = len & 0x07;
476       len = 3;
477     } else if ((len & 0xf8) && !(len & 0x04)) {
478       sample_number = len & 0x03;
479       len = 4;
480     } else if ((len & 0xfc) && !(len & 0x02)) {
481       sample_number = len & 0x01;
482       len = 5;
483     } else if ((len & 0xfe) && !(len & 0x01)) {
484       sample_number = len & 0x0;
485       len = 6;
486     } else {
487       goto error;
488     }
489
490     if ((blocking_strategy == 0 && len > 5) ||
491         (blocking_strategy == 1 && len > 6))
492       goto error;
493
494     while (len > 0) {
495       if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
496         goto need_more_data;
497
498       if ((tmp & 0xc0) != 0x80)
499         goto error;
500
501       sample_number <<= 6;
502       sample_number |= (tmp & 0x3f);
503       len--;
504     }
505   }
506
507   /* calculate real blocksize from the blocksize index */
508   if (block_size == 6) {
509     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
510       goto need_more_data;
511     block_size++;
512   } else if (block_size == 7) {
513     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
514       goto need_more_data;
515     block_size++;
516   } else {
517     block_size = blocksize_table[block_size];
518   }
519
520   /* calculate the real samplerate from the samplerate index */
521   if (samplerate == 0 && flacparse->samplerate == 0) {
522     goto need_streaminfo;
523   } else if (samplerate < 12) {
524     samplerate = sample_rate_table[samplerate];
525   } else if (samplerate == 12) {
526     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
527       goto need_more_data;
528     samplerate *= 1000;
529   } else if (samplerate == 13) {
530     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
531       goto need_more_data;
532   } else if (samplerate == 14) {
533     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
534       goto need_more_data;
535     samplerate *= 10;
536   }
537
538   if (flacparse->samplerate && flacparse->samplerate != samplerate)
539     goto error;
540
541   /* check crc-8 for the header */
542   if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
543     goto need_more_data;
544
545   actual_crc =
546       gst_flac_calculate_crc8 (data,
547       (gst_bit_reader_get_pos (&reader) / 8) - 1);
548   if (actual_crc != expected_crc)
549     goto error;
550
551   /* Sanity check sample number against blocking strategy, as it seems
552      some files claim fixed block size but supply sample numbers,
553      rather than block numbers. */
554   if (blocking_strategy == 0 && flacparse->block_size != 0) {
555     if (!flacparse->strategy_checked) {
556       if (block_size == sample_number) {
557         GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
558             "but seems to be lying: assuming variable block size");
559         flacparse->force_variable_block_size = TRUE;
560         blocking_strategy = 1;
561       }
562       flacparse->strategy_checked = TRUE;
563     }
564   }
565
566   /* documentation says:
567    * The "blocking strategy" bit must be the same throughout the entire stream. */
568   if (flacparse->blocking_strategy != blocking_strategy) {
569     if (flacparse->block_size != 0) {
570       GST_WARNING_OBJECT (flacparse, "blocking strategy is not constant");
571       if (suspect)
572         *suspect = TRUE;
573     }
574   }
575
576   /* 
577      The FLAC format documentation says:
578      The "blocking strategy" bit determines how to calculate the sample number
579      of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
580      frame header encodes the frame number as above, and the frame's starting
581      sample number will be the frame number times the blocksize. If it is 1
582      (variable-blocksize), the frame header encodes the frame's starting
583      sample number itself. (In the case of a fixed-blocksize stream, only the
584      last block may be shorter than the stream blocksize; its starting sample
585      number will be calculated as the frame number times the previous frame's
586      blocksize, or zero if it is the first frame). 
587
588      Therefore, when in fixed block size mode, we only update the block size
589      the first time, then reuse that block size for subsequent calls.
590      This will also fix a timestamp problem with the last block's timestamp
591      being miscalculated by scaling the block number by a "wrong" block size.
592    */
593   if (blocking_strategy == 0) {
594     if (flacparse->block_size != 0) {
595       /* after first block */
596       if (flacparse->block_size != block_size) {
597         /* TODO: can we know we're on the last frame, to avoid warning ? */
598         GST_WARNING_OBJECT (flacparse, "Block size is not constant");
599         block_size = flacparse->block_size;
600         if (suspect)
601           *suspect = TRUE;
602       }
603     }
604   }
605
606   if (set) {
607     flacparse->block_size = block_size;
608     if (!flacparse->samplerate)
609       flacparse->samplerate = samplerate;
610     if (!flacparse->bps)
611       flacparse->bps = bps;
612     if (!flacparse->blocking_strategy)
613       flacparse->blocking_strategy = blocking_strategy;
614     if (!flacparse->channels)
615       flacparse->channels = channels;
616     if (!flacparse->sample_number)
617       flacparse->sample_number = sample_number;
618
619     GST_DEBUG_OBJECT (flacparse,
620         "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
621         "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
622         flacparse->block_size, flacparse->sample_number);
623   }
624
625   if (block_size_ret)
626     *block_size_ret = block_size;
627
628   return FRAME_HEADER_VALID;
629
630 need_streaminfo:
631   GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
632   return FRAME_HEADER_INVALID;
633 error:
634   return FRAME_HEADER_INVALID;
635
636 need_more_data:
637   return FRAME_HEADER_MORE_DATA;
638 }
639
640 static gboolean
641 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
642     GstBaseParseFrame * frame, guint * ret)
643 {
644   GstBuffer *buffer;
645   GstMapInfo map;
646   guint max, remaining;
647   guint i, search_start, search_end;
648   FrameHeaderCheckReturn header_ret;
649   guint16 block_size;
650   gboolean suspect_start = FALSE, suspect_end = FALSE;
651   gboolean result = FALSE;
652
653   buffer = frame->buffer;
654   gst_buffer_map (buffer, &map, GST_MAP_READ);
655
656   if (map.size < flacparse->min_framesize)
657     goto need_more;
658
659   header_ret =
660       gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
661       &block_size, &suspect_start);
662   if (header_ret == FRAME_HEADER_INVALID) {
663     *ret = 0;
664     goto cleanup;
665   }
666   if (header_ret == FRAME_HEADER_MORE_DATA)
667     goto need_more;
668
669   /* mind unknown framesize */
670   search_start = MAX (2, flacparse->min_framesize);
671   if (flacparse->max_framesize)
672     search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
673   else
674     search_end = map.size;
675   search_end -= 2;
676
677   remaining = map.size;
678
679   for (i = search_start; i < search_end; i++, remaining--) {
680     if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
681       GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
682       suspect_end = FALSE;
683       header_ret =
684           gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
685           remaining, FALSE, NULL, &suspect_end);
686       if (header_ret == FRAME_HEADER_VALID) {
687         if (flacparse->check_frame_checksums || suspect_start || suspect_end) {
688           guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
689           guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
690
691           GST_LOG_OBJECT (flacparse,
692               "checking checksum, frame suspect (%d, %d)",
693               suspect_start, suspect_end);
694           if (actual_crc != expected_crc) {
695             GST_DEBUG_OBJECT (flacparse, "checksum did not match");
696             continue;
697           }
698         }
699         *ret = i;
700         flacparse->block_size = block_size;
701         result = TRUE;
702         goto cleanup;
703       } else if (header_ret == FRAME_HEADER_MORE_DATA) {
704         goto need_more;
705       }
706     }
707   }
708
709   /* For the last frame output everything to the end */
710   if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
711     if (flacparse->check_frame_checksums) {
712       guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
713       guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
714
715       if (actual_crc == expected_crc) {
716         *ret = map.size;
717         flacparse->block_size = block_size;
718         result = TRUE;
719         goto cleanup;
720       }
721     } else {
722       *ret = map.size;
723       flacparse->block_size = block_size;
724       result = TRUE;
725       goto cleanup;
726     }
727   }
728
729   /* so we searched to expected end and found nothing,
730    * give up on this frame (start) */
731   if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
732     GST_LOG_OBJECT (flacparse,
733         "could not determine valid frame end, discarding frame (start)");
734     *ret = 1;
735     return FALSE;
736   }
737
738 need_more:
739   max = flacparse->max_framesize + 16;
740   if (max == 16)
741     max = 1 << 24;
742   *ret = MIN (map.size + 4096, max);
743   result = TRUE;
744
745 cleanup:
746   gst_buffer_unmap (buffer, &map);
747   return result;
748 }
749
750 static GstFlowReturn
751 gst_flac_parse_handle_frame (GstBaseParse * parse,
752     GstBaseParseFrame * frame, gint * skipsize)
753 {
754   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
755   GstBuffer *buffer = frame->buffer;
756   GstMapInfo map;
757   gboolean result = TRUE;
758   GstFlowReturn ret = GST_FLOW_OK;
759   guint framesize = 0;
760
761   gst_buffer_map (buffer, &map, GST_MAP_READ);
762
763   *skipsize = 1;
764
765   if (G_UNLIKELY (map.size < 4)) {
766     result = FALSE;
767     goto cleanup;
768   }
769
770   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
771     if (memcmp (map.data, "fLaC", 4) == 0) {
772       GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
773       framesize = 4;
774       goto cleanup;
775     }
776     if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
777       GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
778       /* Minimal size of a frame header */
779       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
780       flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
781       *skipsize = 0;
782       result = FALSE;
783       goto cleanup;
784     }
785     GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
786     result = FALSE;
787     goto cleanup;
788   }
789
790   if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
791     guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
792
793     GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
794     framesize = size;
795     goto cleanup;
796   }
797
798   if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
799     gboolean ret;
800     guint next;
801
802     flacparse->offset = GST_BUFFER_OFFSET (buffer);
803     flacparse->blocking_strategy = 0;
804     flacparse->sample_number = 0;
805
806     GST_DEBUG_OBJECT (flacparse, "Found sync code");
807     ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
808     if (ret) {
809       framesize = next;
810       goto cleanup;
811     } else {
812       /* If we're at EOS and the frame was not valid, drop it! */
813       if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
814         GST_WARNING_OBJECT (flacparse, "EOS");
815         result = FALSE;
816         goto cleanup;
817       }
818
819       if (next == 0) {
820       } else if (next > map.size) {
821         GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
822         *skipsize = 0;
823         gst_base_parse_set_min_frame_size (parse, next);
824         result = FALSE;
825         goto cleanup;
826       } else {
827         GST_ERROR_OBJECT (flacparse,
828             "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
829         result = FALSE;
830         goto cleanup;
831       }
832     }
833   } else {
834     GstByteReader reader;
835     gint off;
836
837     gst_byte_reader_init (&reader, map.data, map.size);
838     off =
839         gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
840         0, map.size);
841
842     if (off > 0) {
843       GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
844       *skipsize = off;
845       result = FALSE;
846       goto cleanup;
847     } else {
848       GST_DEBUG_OBJECT (flacparse, "Sync code not found");
849       *skipsize = map.size - 3;
850       result = FALSE;
851       goto cleanup;
852     }
853   }
854
855   result = FALSE;
856
857 cleanup:
858   gst_buffer_unmap (buffer, &map);
859
860   if (result)
861     *skipsize = 0;
862
863   if (result && framesize <= map.size) {
864     ret = gst_flac_parse_parse_frame (parse, frame, framesize);
865     if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
866       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
867       ret = GST_FLOW_OK;
868     }
869     if (ret == GST_FLOW_OK)
870       ret = gst_base_parse_finish_frame (parse, frame, framesize);
871   }
872
873   return ret;
874 }
875
876 static gboolean
877 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
878 {
879   GstBitReader reader;
880   GstMapInfo map;
881
882   gst_buffer_map (buffer, &map, GST_MAP_READ);
883   gst_bit_reader_init (&reader, map.data, map.size);
884
885   if (map.size != 4 + 34) {
886     GST_ERROR_OBJECT (flacparse,
887         "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
888     goto failure;
889   }
890
891   /* Skip metadata block header */
892   if (!gst_bit_reader_skip (&reader, 32))
893     goto error;
894
895   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
896     goto error;
897   if (flacparse->min_blocksize < 16) {
898     GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
899         flacparse->min_blocksize);
900   }
901
902   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
903     goto error;
904   if (flacparse->max_blocksize < 16) {
905     GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
906         flacparse->max_blocksize);
907   }
908
909   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
910     goto error;
911   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
912     goto error;
913
914   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
915     goto error;
916   if (flacparse->samplerate == 0) {
917     GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
918     goto failure;
919   }
920
921   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
922     goto error;
923   flacparse->channels++;
924   if (flacparse->channels > 8) {
925     GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
926         flacparse->channels);
927     goto failure;
928   }
929
930   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
931     goto error;
932   flacparse->bps++;
933
934   if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
935     goto error;
936   if (flacparse->total_samples) {
937     gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
938         GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
939   }
940
941   gst_buffer_unmap (buffer, &map);
942
943   GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
944       "\tmin/max blocksize: %u/%u,\n"
945       "\tmin/max framesize: %u/%u,\n"
946       "\tsamplerate: %u,\n"
947       "\tchannels: %u,\n"
948       "\tbits per sample: %u,\n"
949       "\ttotal samples: %" G_GUINT64_FORMAT,
950       flacparse->min_blocksize, flacparse->max_blocksize,
951       flacparse->min_framesize, flacparse->max_framesize,
952       flacparse->samplerate,
953       flacparse->channels, flacparse->bps, flacparse->total_samples);
954
955   return TRUE;
956
957 error:
958   GST_ERROR_OBJECT (flacparse, "Failed to read data");
959 failure:
960   gst_buffer_unmap (buffer, &map);
961   return FALSE;
962 }
963
964 static gboolean
965 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
966     GstBuffer * buffer)
967 {
968   GstTagList *tags;
969   GstMapInfo map;
970
971   gst_buffer_map (buffer, &map, GST_MAP_READ);
972
973   tags =
974       gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
975   gst_buffer_unmap (buffer, &map);
976
977   if (tags == NULL) {
978     GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
979   } else if (gst_tag_list_is_empty (tags)) {
980     gst_tag_list_unref (tags);
981   } else if (flacparse->tags == NULL) {
982     flacparse->tags = tags;
983   } else {
984     gst_tag_list_insert (flacparse->tags, tags, GST_TAG_MERGE_APPEND);
985     gst_tag_list_unref (tags);
986   }
987
988   return TRUE;
989 }
990
991 static gboolean
992 gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
993 {
994   GstByteReader reader;
995   GstMapInfo map;
996   guint i, j;
997   guint8 n_tracks, track_num, index;
998   guint64 offset;
999   gint64 start, stop;
1000   gchar *id;
1001   gchar isrc[13];
1002   GstTagList *tags;
1003   GstToc *toc;
1004   GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
1005
1006   gst_buffer_map (buffer, &map, GST_MAP_READ);
1007   gst_byte_reader_init (&reader, map.data, map.size);
1008
1009   toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1010
1011   /* skip 4 bytes METADATA_BLOCK_HEADER */
1012   /* http://flac.sourceforge.net/format.html#metadata_block_header */
1013   if (!gst_byte_reader_skip (&reader, 4))
1014     goto error;
1015
1016   /* skip 395 bytes from METADATA_BLOCK_CUESHEET */
1017   /* http://flac.sourceforge.net/format.html#metadata_block_cuesheet */
1018   if (!gst_byte_reader_skip (&reader, 395))
1019     goto error;
1020
1021   if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
1022     goto error;
1023
1024   /* CUESHEET_TRACK */
1025   /* http://flac.sourceforge.net/format.html#cuesheet_track */
1026   for (i = 0; i < n_tracks; i++) {
1027     if (!gst_byte_reader_get_uint64_be (&reader, &offset))
1028       goto error;
1029     if (!gst_byte_reader_get_uint8 (&reader, &track_num))
1030       goto error;
1031
1032     if (gst_byte_reader_get_remaining (&reader) < 12)
1033       goto error;
1034     memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
1035     /* \0-terminate the string */
1036     isrc[12] = '\0';
1037     if (!gst_byte_reader_skip (&reader, 12))
1038       goto error;
1039
1040     /* skip 14 bytes from CUESHEET_TRACK */
1041     if (!gst_byte_reader_skip (&reader, 14))
1042       goto error;
1043     if (!gst_byte_reader_get_uint8 (&reader, &index))
1044       goto error;
1045     /* add tracks in TOC */
1046     /* lead-out tack has number 170 or 255 */
1047     if (track_num != 170 && track_num != 255) {
1048       prev_entry = cur_entry;
1049       /* previous track stop time = current track start time */
1050       if (prev_entry != NULL) {
1051         gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
1052         stop =
1053             gst_util_uint64_scale_round (offset, GST_SECOND,
1054             flacparse->samplerate);
1055         gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
1056       }
1057       id = g_strdup_printf ("%08x", track_num);
1058       cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
1059       g_free (id);
1060       start =
1061           gst_util_uint64_scale_round (offset, GST_SECOND,
1062           flacparse->samplerate);
1063       gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
1064       /* add ISRC as tag in track */
1065       if (strlen (isrc) != 0) {
1066         tags = gst_tag_list_new_empty ();
1067         gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
1068         gst_toc_entry_set_tags (cur_entry, tags);
1069       }
1070       gst_toc_append_entry (toc, cur_entry);
1071       /* CUESHEET_TRACK_INDEX */
1072       /* http://flac.sourceforge.net/format.html#cuesheet_track_index */
1073       for (j = 0; j < index; j++) {
1074         if (!gst_byte_reader_skip (&reader, 12))
1075           goto error;
1076       }
1077     } else {
1078       /* set stop time in last track */
1079       stop =
1080           gst_util_uint64_scale_round (offset, GST_SECOND,
1081           flacparse->samplerate);
1082       gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
1083     }
1084   }
1085
1086   /* send data as TOC */
1087   if (!flacparse->toc)
1088     flacparse->toc = toc;
1089
1090   gst_buffer_unmap (buffer, &map);
1091   return TRUE;
1092
1093 error:
1094   GST_ERROR_OBJECT (flacparse, "Error reading data");
1095   gst_buffer_unmap (buffer, &map);
1096   return FALSE;
1097 }
1098
1099 static gboolean
1100 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
1101 {
1102   GstByteReader reader;
1103   GstMapInfo map;
1104   guint32 img_len = 0, img_type = 0;
1105   guint32 img_mimetype_len = 0, img_description_len = 0;
1106
1107   gst_buffer_map (buffer, &map, GST_MAP_READ);
1108   gst_byte_reader_init (&reader, map.data, map.size);
1109
1110   if (!gst_byte_reader_skip (&reader, 4))
1111     goto error;
1112
1113   if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1114     goto error;
1115
1116   if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1117     goto error;
1118   if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1119     goto error;
1120
1121   if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1122     goto error;
1123   if (!gst_byte_reader_skip (&reader, img_description_len))
1124     goto error;
1125
1126   if (!gst_byte_reader_skip (&reader, 4 * 4))
1127     goto error;
1128
1129   if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1130     goto error;
1131
1132   if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1133     goto error;
1134
1135   if (!flacparse->tags)
1136     flacparse->tags = gst_tag_list_new_empty ();
1137
1138   GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1139
1140   if (img_len > 0) {
1141     gst_tag_list_add_id3_image (flacparse->tags,
1142         map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1143   }
1144
1145   if (gst_tag_list_is_empty (flacparse->tags)) {
1146     gst_tag_list_unref (flacparse->tags);
1147     flacparse->tags = NULL;
1148   }
1149
1150   gst_buffer_unmap (buffer, &map);
1151   return TRUE;
1152
1153 error:
1154   GST_ERROR_OBJECT (flacparse, "Error reading data");
1155   gst_buffer_unmap (buffer, &map);
1156   return FALSE;
1157 }
1158
1159 static gboolean
1160 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1161 {
1162
1163   GST_DEBUG_OBJECT (flacparse, "storing seektable");
1164   /* only store for now;
1165    * offset of the first frame is needed to get real info */
1166   flacparse->seektable = gst_buffer_ref (buffer);
1167
1168   return TRUE;
1169 }
1170
1171 static void
1172 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1173 {
1174   GstByteReader br;
1175   gint64 offset = 0, samples = 0;
1176   GstMapInfo map;
1177
1178   GST_DEBUG_OBJECT (flacparse,
1179       "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1180
1181   if (boffset <= 0)
1182     goto exit;
1183
1184   gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1185   gst_byte_reader_init (&br, map.data, map.size);
1186
1187   /* skip header */
1188   if (!gst_byte_reader_skip (&br, 4))
1189     goto done;
1190
1191   /* seekpoints */
1192   while (gst_byte_reader_get_remaining (&br)) {
1193     if (!gst_byte_reader_get_int64_be (&br, &samples))
1194       break;
1195     if (!gst_byte_reader_get_int64_be (&br, &offset))
1196       break;
1197     if (!gst_byte_reader_skip (&br, 2))
1198       break;
1199
1200     GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1201         G_GINT64_FORMAT, samples, offset);
1202
1203     /* sanity check */
1204     if (G_LIKELY (offset > 0 && samples > 0)) {
1205       gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1206           boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1207               flacparse->samplerate), TRUE, FALSE);
1208     }
1209   }
1210
1211 done:
1212   gst_buffer_unmap (flacparse->seektable, &map);
1213 exit:
1214   gst_buffer_unref (flacparse->seektable);
1215   flacparse->seektable = NULL;
1216 }
1217
1218 static void
1219 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1220 {
1221   GValue value = { 0, };
1222
1223   g_value_init (&value, GST_TYPE_BUFFER);
1224   /* copy buffer to avoid problems with circular refcounts */
1225   buf = gst_buffer_copy (buf);
1226   /* again, for good measure */
1227   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1228   gst_value_set_buffer (&value, buf);
1229   gst_buffer_unref (buf);
1230   gst_value_array_append_value (array_val, &value);
1231   g_value_unset (&value);
1232 }
1233
1234 static GstFlowReturn
1235 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1236 {
1237   GstBuffer *vorbiscomment = NULL;
1238   GstBuffer *streaminfo = NULL;
1239   GstBuffer *marker = NULL;
1240   GValue array = { 0, };
1241   GstCaps *caps;
1242   GList *l;
1243   GstFlowReturn res = GST_FLOW_OK;
1244
1245   caps = gst_caps_new_simple ("audio/x-flac",
1246       "channels", G_TYPE_INT, flacparse->channels,
1247       "framed", G_TYPE_BOOLEAN, TRUE,
1248       "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1249
1250   if (!flacparse->headers)
1251     goto push_headers;
1252
1253   for (l = flacparse->headers; l; l = l->next) {
1254     GstBuffer *header = l->data;
1255     GstMapInfo map;
1256
1257     gst_buffer_map (header, &map, GST_MAP_READ);
1258
1259     GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1260
1261     if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1262       marker = header;
1263     } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1264       streaminfo = header;
1265     } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1266       vorbiscomment = header;
1267     }
1268
1269     gst_buffer_unmap (header, &map);
1270   }
1271
1272   /* at least this one we can generate easily
1273    * to provide full headers downstream */
1274   if (vorbiscomment == NULL && streaminfo != NULL) {
1275     GST_DEBUG_OBJECT (flacparse,
1276         "missing vorbiscomment header; generating dummy");
1277     vorbiscomment = gst_flac_parse_generate_vorbiscomment (flacparse);
1278     flacparse->headers = g_list_insert (flacparse->headers, vorbiscomment,
1279         g_list_index (flacparse->headers, streaminfo) + 1);
1280   }
1281
1282   if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1283     GST_WARNING_OBJECT (flacparse,
1284         "missing header %p %p %p, muxing into container "
1285         "formats may be broken", marker, streaminfo, vorbiscomment);
1286     goto push_headers;
1287   }
1288
1289   g_value_init (&array, GST_TYPE_ARRAY);
1290
1291   /* add marker including STREAMINFO header */
1292   {
1293     GstBuffer *buf;
1294     guint16 num;
1295     GstMapInfo sinfomap, writemap;
1296
1297     gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1298
1299     /* minus one for the marker that is merged with streaminfo here */
1300     num = g_list_length (flacparse->headers) - 1;
1301
1302     buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1303     gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1304
1305     writemap.data[0] = 0x7f;
1306     memcpy (writemap.data + 1, "FLAC", 4);
1307     writemap.data[5] = 0x01;    /* mapping version major */
1308     writemap.data[6] = 0x00;    /* mapping version minor */
1309     writemap.data[7] = (num & 0xFF00) >> 8;
1310     writemap.data[8] = (num & 0x00FF) >> 0;
1311     memcpy (writemap.data + 9, "fLaC", 4);
1312     memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1313     _value_array_append_buffer (&array, buf);
1314
1315     gst_buffer_unmap (streaminfo, &sinfomap);
1316     gst_buffer_unmap (buf, &writemap);
1317     gst_buffer_unref (buf);
1318   }
1319
1320   /* add VORBISCOMMENT header */
1321   _value_array_append_buffer (&array, vorbiscomment);
1322
1323   /* add other headers, if there are any */
1324   for (l = flacparse->headers; l; l = l->next) {
1325     if (GST_BUFFER_CAST (l->data) != marker &&
1326         GST_BUFFER_CAST (l->data) != streaminfo &&
1327         GST_BUFFER_CAST (l->data) != vorbiscomment) {
1328       _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1329     }
1330   }
1331
1332   gst_structure_set_value (gst_caps_get_structure (caps, 0),
1333       "streamheader", &array);
1334   g_value_unset (&array);
1335
1336 push_headers:
1337
1338   gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1339   gst_caps_unref (caps);
1340
1341   /* push header buffers; update caps, so when we push the first buffer the
1342    * negotiated caps will change to caps that include the streamheader field */
1343   while (flacparse->headers) {
1344     GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1345     GstBaseParseFrame frame;
1346
1347     flacparse->headers =
1348         g_list_delete_link (flacparse->headers, flacparse->headers);
1349     buf = gst_buffer_make_writable (buf);
1350
1351     /* init, set and give away frame */
1352     gst_base_parse_frame_init (&frame);
1353     frame.buffer = buf;
1354     frame.overhead = -1;
1355     res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1356     gst_base_parse_frame_free (&frame);
1357     if (res != GST_FLOW_OK)
1358       break;
1359   }
1360   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1361   g_list_free (flacparse->headers);
1362   flacparse->headers = NULL;
1363
1364   return res;
1365 }
1366
1367 /* empty vorbiscomment */
1368 static GstBuffer *
1369 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse)
1370 {
1371   GstTagList *taglist = gst_tag_list_new_empty ();
1372   guchar header[4];
1373   guint size;
1374   GstBuffer *vorbiscomment;
1375   GstMapInfo map;
1376
1377   header[0] = 0x84;             /* is_last = 1; type = 4; */
1378
1379   vorbiscomment =
1380       gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1381       sizeof (header), NULL);
1382   gst_tag_list_unref (taglist);
1383
1384   gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1385
1386   /* Get rid of framing bit */
1387   if (map.data[map.size - 1] == 1) {
1388     GstBuffer *sub;
1389
1390     sub =
1391         gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1392         map.size - 1);
1393     gst_buffer_unmap (vorbiscomment, &map);
1394     gst_buffer_unref (vorbiscomment);
1395     vorbiscomment = sub;
1396     gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1397   }
1398
1399   size = map.size - 4;
1400   map.data[1] = ((size & 0xFF0000) >> 16);
1401   map.data[2] = ((size & 0x00FF00) >> 8);
1402   map.data[3] = (size & 0x0000FF);
1403   gst_buffer_unmap (vorbiscomment, &map);
1404
1405   GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1406   GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1407   GST_BUFFER_OFFSET (vorbiscomment) = 0;
1408   GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1409
1410   return vorbiscomment;
1411 }
1412
1413 static gboolean
1414 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1415 {
1416   GstBuffer *marker, *streaminfo;
1417   GstMapInfo map;
1418
1419   marker = gst_buffer_new_and_alloc (4);
1420   gst_buffer_map (marker, &map, GST_MAP_WRITE);
1421   memcpy (map.data, "fLaC", 4);
1422   gst_buffer_unmap (marker, &map);
1423   GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1424   GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1425   GST_BUFFER_OFFSET (marker) = 0;
1426   GST_BUFFER_OFFSET_END (marker) = 0;
1427   flacparse->headers = g_list_append (flacparse->headers, marker);
1428
1429   streaminfo = gst_buffer_new_and_alloc (4 + 34);
1430   gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1431   memset (map.data, 0, 4 + 34);
1432
1433   /* metadata block header */
1434   map.data[0] = 0x00;           /* is_last = 0; type = 0; */
1435   map.data[1] = 0x00;           /* length = 34; */
1436   map.data[2] = 0x00;
1437   map.data[3] = 0x22;
1438
1439   /* streaminfo */
1440
1441   map.data[4] = (flacparse->block_size >> 8) & 0xff;    /* min blocksize = blocksize; */
1442   map.data[5] = (flacparse->block_size) & 0xff;
1443   map.data[6] = (flacparse->block_size >> 8) & 0xff;    /* max blocksize = blocksize; */
1444   map.data[7] = (flacparse->block_size) & 0xff;
1445
1446   map.data[8] = 0x00;           /* min framesize = 0; */
1447   map.data[9] = 0x00;
1448   map.data[10] = 0x00;
1449   map.data[11] = 0x00;          /* max framesize = 0; */
1450   map.data[12] = 0x00;
1451   map.data[13] = 0x00;
1452
1453   map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1454   map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1455   map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1456
1457   map.data[16] |= (flacparse->channels - 1) << 1;
1458
1459   map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1460   map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1461
1462   {
1463     gint64 duration;
1464
1465     if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1466             GST_FORMAT_TIME, &duration)) {
1467       duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1468
1469       map.data[17] |= (duration >> 32) & 0xff;
1470       map.data[18] |= (duration >> 24) & 0xff;
1471       map.data[19] |= (duration >> 16) & 0xff;
1472       map.data[20] |= (duration >> 8) & 0xff;
1473       map.data[21] |= (duration >> 0) & 0xff;
1474     }
1475   }
1476   /* MD5 = 0; */
1477
1478   gst_buffer_unmap (streaminfo, &map);
1479   GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1480   GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1481   GST_BUFFER_OFFSET (streaminfo) = 0;
1482   GST_BUFFER_OFFSET_END (streaminfo) = 0;
1483   flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1484
1485   flacparse->headers = g_list_append (flacparse->headers,
1486       gst_flac_parse_generate_vorbiscomment (flacparse));
1487
1488   return TRUE;
1489 }
1490
1491 static GstFlowReturn
1492 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1493     gint size)
1494 {
1495   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1496   GstBuffer *buffer = frame->buffer, *sbuffer;
1497   GstMapInfo map;
1498   GstFlowReturn res = GST_FLOW_ERROR;
1499
1500   gst_buffer_map (buffer, &map, GST_MAP_READ);
1501
1502   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1503     sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1504     GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1505     GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1506     GST_BUFFER_OFFSET (sbuffer) = 0;
1507     GST_BUFFER_OFFSET_END (sbuffer) = 0;
1508
1509     /* 32 bits metadata block */
1510     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1511     flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1512
1513     flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1514
1515     res = GST_BASE_PARSE_FLOW_DROPPED;
1516   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1517     gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1518     guint type = (map.data[0] & 0x7F);
1519     gboolean hdr_ok = TRUE;
1520
1521     if (type == 127) {
1522       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1523       res = GST_BASE_PARSE_FLOW_DROPPED;
1524       goto cleanup;
1525     }
1526
1527     GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1528
1529     sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1530
1531     switch (type) {
1532       case 0:                  /* STREAMINFO */
1533         GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1534         hdr_ok = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1535         break;
1536       case 3:                  /* SEEKTABLE */
1537         GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1538         hdr_ok = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1539         break;
1540       case 4:                  /* VORBIS_COMMENT */
1541         GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1542         hdr_ok = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1543         break;
1544       case 5:                  /* CUESHEET */
1545         GST_INFO_OBJECT (flacparse, "CUESHEET header");
1546         hdr_ok = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1547         break;
1548       case 6:                  /* PICTURE */
1549         GST_INFO_OBJECT (flacparse, "PICTURE header");
1550         hdr_ok = gst_flac_parse_handle_picture (flacparse, sbuffer);
1551         break;
1552       case 1:                  /* PADDING */
1553         GST_INFO_OBJECT (flacparse, "PADDING header");
1554         break;
1555       case 2:                  /* APPLICATION */
1556         GST_INFO_OBJECT (flacparse, "APPLICATION header");
1557         break;
1558       default:                 /* RESERVED */
1559         GST_INFO_OBJECT (flacparse, "unhandled header of type %u", type);
1560         break;
1561     }
1562
1563     if (hdr_ok) {
1564       GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1565       GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1566       GST_BUFFER_OFFSET (sbuffer) = 0;
1567       GST_BUFFER_OFFSET_END (sbuffer) = 0;
1568
1569       flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1570     } else {
1571       GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1572       GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1573
1574       gst_buffer_unref (sbuffer);
1575
1576       /* error out unless we have a STREAMINFO header */
1577       if (flacparse->samplerate == 0 || flacparse->bps == 0)
1578         goto header_parsing_error;
1579
1580       /* .. in which case just stop header parsing and try to find audio */
1581       is_last = TRUE;
1582     }
1583
1584     if (is_last) {
1585       res = gst_flac_parse_handle_headers (flacparse);
1586
1587       /* Minimal size of a frame header */
1588       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1589               flacparse->min_framesize));
1590       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1591
1592       if (res != GST_FLOW_OK)
1593         goto cleanup;
1594     }
1595
1596     /* DROPPED because we pushed already or will push all headers manually */
1597     res = GST_BASE_PARSE_FLOW_DROPPED;
1598   } else {
1599     if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1600       FrameHeaderCheckReturn ret;
1601
1602       flacparse->offset = GST_BUFFER_OFFSET (buffer);
1603       ret =
1604           gst_flac_parse_frame_header_is_valid (flacparse,
1605           map.data, map.size, TRUE, NULL, NULL);
1606       if (ret != FRAME_HEADER_VALID) {
1607         GST_ERROR_OBJECT (flacparse,
1608             "Baseclass didn't provide a complete frame");
1609         goto cleanup;
1610       }
1611     }
1612
1613     if (flacparse->block_size == 0) {
1614       GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1615       goto cleanup;
1616     }
1617
1618     if (flacparse->seektable)
1619       gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1620
1621     if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1622       if (flacparse->blocking_strategy == 1) {
1623         GST_WARNING_OBJECT (flacparse,
1624             "Generating headers for variable blocksize streams not supported");
1625
1626         res = gst_flac_parse_handle_headers (flacparse);
1627       } else {
1628         GST_DEBUG_OBJECT (flacparse, "Generating headers");
1629
1630         if (!gst_flac_parse_generate_headers (flacparse))
1631           goto cleanup;
1632
1633         res = gst_flac_parse_handle_headers (flacparse);
1634       }
1635       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1636       if (res != GST_FLOW_OK)
1637         goto cleanup;
1638     }
1639
1640     /* also cater for oggmux metadata */
1641     if (flacparse->blocking_strategy == 0) {
1642       GST_BUFFER_TIMESTAMP (buffer) =
1643           gst_util_uint64_scale (flacparse->sample_number,
1644           flacparse->block_size * GST_SECOND, flacparse->samplerate);
1645       GST_BUFFER_OFFSET_END (buffer) =
1646           flacparse->sample_number * flacparse->block_size +
1647           flacparse->block_size;
1648     } else {
1649       GST_BUFFER_TIMESTAMP (buffer) =
1650           gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1651           flacparse->samplerate);
1652       GST_BUFFER_OFFSET_END (buffer) =
1653           flacparse->sample_number + flacparse->block_size;
1654     }
1655     GST_BUFFER_OFFSET (buffer) =
1656         gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1657         flacparse->samplerate);
1658     GST_BUFFER_DURATION (buffer) =
1659         GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1660
1661     /* To simplify, we just assume that it's a fixed size header and ignore
1662      * subframe headers. The first could lead us to being off by 88 bits and
1663      * the second even less, so the total inaccuracy is negligible. */
1664     frame->overhead = 7;
1665
1666     /* Minimal size of a frame header */
1667     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1668             flacparse->min_framesize));
1669
1670     flacparse->offset = -1;
1671     flacparse->blocking_strategy = 0;
1672     flacparse->sample_number = 0;
1673     res = GST_FLOW_OK;
1674   }
1675
1676 cleanup:
1677   gst_buffer_unmap (buffer, &map);
1678
1679   return res;
1680
1681 /* ERRORS */
1682 header_parsing_error:
1683   {
1684     GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1685         ("Failed to parse headers"));
1686     goto cleanup;
1687   }
1688 }
1689
1690 static GstFlowReturn
1691 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1692 {
1693   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1694
1695   if (!flacparse->sent_codec_tag) {
1696     GstTagList *taglist;
1697     GstCaps *caps;
1698
1699     taglist = gst_tag_list_new_empty ();
1700
1701     /* codec tag */
1702     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1703     gst_pb_utils_add_codec_description_to_tag_list (taglist,
1704         GST_TAG_AUDIO_CODEC, caps);
1705     gst_caps_unref (caps);
1706
1707     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1708         gst_event_new_tag (taglist));
1709
1710     /* also signals the end of first-frame processing */
1711     flacparse->sent_codec_tag = TRUE;
1712   }
1713
1714   /* Push tags */
1715   if (flacparse->tags) {
1716     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1717         gst_event_new_tag (flacparse->tags));
1718     flacparse->tags = NULL;
1719   }
1720   /* Push toc */
1721   if (flacparse->toc) {
1722     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1723         gst_event_new_toc (flacparse->toc, FALSE));
1724   }
1725
1726   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1727
1728   return GST_FLOW_OK;
1729 }
1730
1731 static gboolean
1732 gst_flac_parse_convert (GstBaseParse * parse,
1733     GstFormat src_format, gint64 src_value, GstFormat dest_format,
1734     gint64 * dest_value)
1735 {
1736   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1737
1738   if (flacparse->samplerate > 0) {
1739     if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1740       if (src_value != -1)
1741         *dest_value =
1742             gst_util_uint64_scale (src_value, GST_SECOND,
1743             flacparse->samplerate);
1744       else
1745         *dest_value = -1;
1746       return TRUE;
1747     } else if (src_format == GST_FORMAT_TIME &&
1748         dest_format == GST_FORMAT_DEFAULT) {
1749       if (src_value != -1)
1750         *dest_value =
1751             gst_util_uint64_scale (src_value, flacparse->samplerate,
1752             GST_SECOND);
1753       else
1754         *dest_value = -1;
1755       return TRUE;
1756     }
1757   }
1758
1759   return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1760       src_value, dest_format, dest_value);
1761 }
1762
1763 static gboolean
1764 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1765 {
1766   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1767   gboolean res = FALSE;
1768
1769   switch (GST_EVENT_TYPE (event)) {
1770     case GST_EVENT_TOC_SELECT:
1771     {
1772       GstTocEntry *entry = NULL;
1773       GstEvent *seek_event;
1774       GstToc *toc = NULL;
1775       gint64 start_pos;
1776       gchar *uid = NULL;
1777
1778       /* FIXME: some locking would be good */
1779       if (flacparse->toc)
1780         toc = gst_toc_ref (flacparse->toc);
1781
1782       if (toc != NULL) {
1783         gst_event_parse_toc_select (event, &uid);
1784         if (uid != NULL) {
1785           entry = gst_toc_find_entry (toc, uid);
1786           if (entry != NULL) {
1787             gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1788
1789             /* FIXME: use segment rate here instead? */
1790             seek_event = gst_event_new_seek (1.0,
1791                 GST_FORMAT_TIME,
1792                 GST_SEEK_FLAG_FLUSH,
1793                 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1794
1795             res =
1796                 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1797                 seek_event);
1798
1799             g_free (uid);
1800           } else {
1801             GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1802           }
1803         }
1804         gst_toc_unref (toc);
1805       } else {
1806         GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1807       }
1808       gst_event_unref (event);
1809       break;
1810     }
1811     default:
1812       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1813       break;
1814   }
1815   return res;
1816 }
1817
1818 static void
1819 remove_fields (GstCaps * caps)
1820 {
1821   guint i, n;
1822
1823   n = gst_caps_get_size (caps);
1824   for (i = 0; i < n; i++) {
1825     GstStructure *s = gst_caps_get_structure (caps, i);
1826
1827     gst_structure_remove_field (s, "framed");
1828   }
1829 }
1830
1831 static GstCaps *
1832 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1833 {
1834   GstCaps *peercaps, *templ;
1835   GstCaps *res;
1836
1837   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1838   if (filter) {
1839     GstCaps *fcopy = gst_caps_copy (filter);
1840     /* Remove the fields we convert */
1841     remove_fields (fcopy);
1842     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1843     gst_caps_unref (fcopy);
1844   } else
1845     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1846
1847   if (peercaps) {
1848     /* Remove the framed field */
1849     peercaps = gst_caps_make_writable (peercaps);
1850     remove_fields (peercaps);
1851
1852     res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1853     gst_caps_unref (peercaps);
1854     gst_caps_unref (templ);
1855   } else {
1856     res = templ;
1857   }
1858
1859   if (filter) {
1860     GstCaps *intersection;
1861
1862     intersection =
1863         gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1864     gst_caps_unref (res);
1865     res = intersection;
1866   }
1867
1868   return res;
1869 }