Merge branch 'master' into 0.11
[platform/upstream/gstreamer.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., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, 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 -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
62 #include <gst/base/gstbitreader.h>
63 #include <gst/base/gstbytereader.h>
64
65 GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
66 #define GST_CAT_DEFAULT flacparse_debug
67
68 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
69 static const guint8 crc8_table[256] = {
70   0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
71   0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
72   0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
73   0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
74   0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
75   0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
76   0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
77   0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
78   0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
79   0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
80   0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
81   0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
82   0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
83   0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
84   0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
85   0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
86   0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
87   0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
88   0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
89   0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
90   0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
91   0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
92   0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
93   0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
94   0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
95   0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
96   0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
97   0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
98   0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
99   0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
100   0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
101   0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
102 };
103
104 static guint8
105 gst_flac_calculate_crc8 (const guint8 * data, guint length)
106 {
107   guint8 crc = 0;
108
109   while (length--) {
110     crc = crc8_table[crc ^ *data];
111     ++data;
112   }
113
114   return crc;
115 }
116
117 /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
118 static const guint16 crc16_table[256] = {
119   0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
120   0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
121   0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
122   0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
123   0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
124   0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
125   0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
126   0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
127   0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
128   0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
129   0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
130   0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
131   0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
132   0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
133   0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
134   0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
135   0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
136   0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
137   0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
138   0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
139   0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
140   0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
141   0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
142   0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
143   0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
144   0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
145   0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
146   0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
147   0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
148   0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
149   0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
150   0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
151 };
152
153 static guint16
154 gst_flac_calculate_crc16 (const guint8 * data, guint length)
155 {
156   guint16 crc = 0;
157
158   while (length--) {
159     crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
160     data++;
161   }
162
163   return crc;
164 }
165
166 enum
167 {
168   PROP_0,
169   PROP_CHECK_FRAME_CHECKSUMS
170 };
171
172 #define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
173
174 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
175     GST_PAD_SRC,
176     GST_PAD_ALWAYS,
177     GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
178         "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
179     );
180
181 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
182     GST_PAD_SINK,
183     GST_PAD_ALWAYS,
184     GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) false")
185     );
186
187 static void gst_flac_parse_finalize (GObject * object);
188 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
189     const GValue * value, GParamSpec * pspec);
190 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
191     GValue * value, GParamSpec * pspec);
192
193 static gboolean gst_flac_parse_start (GstBaseParse * parse);
194 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
195 static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse,
196     GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
197 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
198     GstBaseParseFrame * frame);
199 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
200     GstBaseParseFrame * frame);
201 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
202     GstFormat src_format, gint64 src_value, GstFormat dest_format,
203     gint64 * dest_value);
204
205 #define gst_flac_parse_parent_class parent_class
206 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
207
208 static void
209 gst_flac_parse_class_init (GstFlacParseClass * klass)
210 {
211   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
212   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
213   GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
214
215   GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
216       "Flac parser element");
217
218   gobject_class->finalize = gst_flac_parse_finalize;
219   gobject_class->set_property = gst_flac_parse_set_property;
220   gobject_class->get_property = gst_flac_parse_get_property;
221
222   g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
223       g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
224           "Check the overall checksums of every frame",
225           DEFAULT_CHECK_FRAME_CHECKSUMS,
226           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
227
228   baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
229   baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
230   baseparse_class->check_valid_frame =
231       GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
232   baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
233   baseparse_class->pre_push_frame =
234       GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
235   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
236
237   gst_element_class_add_pad_template (element_class,
238       gst_static_pad_template_get (&src_factory));
239   gst_element_class_add_pad_template (element_class,
240       gst_static_pad_template_get (&sink_factory));
241
242   gst_element_class_set_details_simple (element_class, "FLAC audio parser",
243       "Codec/Parser/Audio",
244       "Parses audio with the FLAC lossless audio codec",
245       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
246 }
247
248 static void
249 gst_flac_parse_init (GstFlacParse * flacparse)
250 {
251   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
252 }
253
254 static void
255 gst_flac_parse_set_property (GObject * object, guint prop_id,
256     const GValue * value, GParamSpec * pspec)
257 {
258   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
259
260   switch (prop_id) {
261     case PROP_CHECK_FRAME_CHECKSUMS:
262       flacparse->check_frame_checksums = g_value_get_boolean (value);
263       break;
264     default:
265       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
266       break;
267   }
268 }
269
270 static void
271 gst_flac_parse_get_property (GObject * object, guint prop_id,
272     GValue * value, GParamSpec * pspec)
273 {
274   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
275
276   switch (prop_id) {
277     case PROP_CHECK_FRAME_CHECKSUMS:
278       g_value_set_boolean (value, flacparse->check_frame_checksums);
279       break;
280     default:
281       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
282       break;
283   }
284 }
285
286 static void
287 gst_flac_parse_finalize (GObject * object)
288 {
289   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
290
291   if (flacparse->tags) {
292     gst_tag_list_free (flacparse->tags);
293     flacparse->tags = NULL;
294   }
295
296   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
297   g_list_free (flacparse->headers);
298   flacparse->headers = NULL;
299
300   G_OBJECT_CLASS (parent_class)->finalize (object);
301 }
302
303 static gboolean
304 gst_flac_parse_start (GstBaseParse * parse)
305 {
306   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
307
308   flacparse->state = GST_FLAC_PARSE_STATE_INIT;
309   flacparse->min_blocksize = 0;
310   flacparse->max_blocksize = 0;
311   flacparse->min_framesize = 0;
312   flacparse->max_framesize = 0;
313
314   flacparse->upstream_length = -1;
315
316   flacparse->samplerate = 0;
317   flacparse->channels = 0;
318   flacparse->bps = 0;
319   flacparse->total_samples = 0;
320
321   flacparse->offset = GST_CLOCK_TIME_NONE;
322   flacparse->blocking_strategy = 0;
323   flacparse->block_size = 0;
324   flacparse->sample_number = 0;
325
326   /* "fLaC" marker */
327   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
328
329   /* inform baseclass we can come up with ts, based on counters in packets */
330   gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
331   gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
332
333   return TRUE;
334 }
335
336 static gboolean
337 gst_flac_parse_stop (GstBaseParse * parse)
338 {
339   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
340
341   if (flacparse->tags) {
342     gst_tag_list_free (flacparse->tags);
343     flacparse->tags = NULL;
344   }
345
346   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
347   g_list_free (flacparse->headers);
348   flacparse->headers = NULL;
349
350   return TRUE;
351 }
352
353 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
354
355 static const guint16 blocksize_table[16] = {
356   0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
357   256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
358   256 << 7,
359 };
360
361 static const guint32 sample_rate_table[16] = {
362   0,
363   88200, 176400, 192000,
364   8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
365   0, 0, 0, 0,
366 };
367
368 typedef enum
369 {
370   FRAME_HEADER_VALID,
371   FRAME_HEADER_INVALID,
372   FRAME_HEADER_MORE_DATA
373 } FrameHeaderCheckReturn;
374
375 static FrameHeaderCheckReturn
376 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
377     const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
378 {
379   GstBitReader reader = GST_BIT_READER_INIT (data, size);
380   guint8 blocking_strategy;
381   guint16 block_size;
382   guint32 samplerate = 0;
383   guint64 sample_number;
384   guint8 channels, bps;
385   guint8 tmp = 0;
386   guint8 actual_crc, expected_crc = 0;
387
388   /* Skip 14 bit sync code */
389   gst_bit_reader_skip_unchecked (&reader, 14);
390
391   /* Must be 0 */
392   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
393     goto error;
394
395   /* 0 == fixed block size, 1 == variable block size */
396   blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
397
398   /* block size index, calculation of the real blocksize below */
399   block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
400   if (block_size == 0)
401     goto error;
402
403   /* sample rate index, calculation of the real samplerate below */
404   samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
405   if (samplerate == 0x0f)
406     goto error;
407
408   /* channel assignment */
409   channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
410   if (channels < 8) {
411     channels++;
412   } else if (channels <= 10) {
413     channels = 2;
414   } else if (channels > 10) {
415     goto error;
416   }
417   if (flacparse->channels && flacparse->channels != channels)
418     goto error;
419
420   /* bits per sample */
421   bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
422   if (bps == 0x03 || bps == 0x07) {
423     goto error;
424   } else if (bps == 0 && flacparse->bps == 0) {
425     goto need_streaminfo;
426   }
427   bps = sample_size_table[bps];
428   if (flacparse->bps && bps != flacparse->bps)
429     goto error;
430
431   /* reserved, must be 0 */
432   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
433     goto error;
434
435   /* read "utf8" encoded sample/frame number */
436   {
437     gint len = 0;
438
439     len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
440
441     /* This is slightly faster than a loop */
442     if (!(len & 0x80)) {
443       sample_number = len;
444       len = 0;
445     } else if ((len & 0xc0) && !(len & 0x20)) {
446       sample_number = len & 0x1f;
447       len = 1;
448     } else if ((len & 0xe0) && !(len & 0x10)) {
449       sample_number = len & 0x0f;
450       len = 2;
451     } else if ((len & 0xf0) && !(len & 0x08)) {
452       sample_number = len & 0x07;
453       len = 3;
454     } else if ((len & 0xf8) && !(len & 0x04)) {
455       sample_number = len & 0x03;
456       len = 4;
457     } else if ((len & 0xfc) && !(len & 0x02)) {
458       sample_number = len & 0x01;
459       len = 5;
460     } else if ((len & 0xfe) && !(len & 0x01)) {
461       sample_number = len & 0x0;
462       len = 6;
463     } else {
464       goto error;
465     }
466
467     if ((blocking_strategy == 0 && len > 5) ||
468         (blocking_strategy == 1 && len > 6))
469       goto error;
470
471     while (len > 0) {
472       if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
473         goto need_more_data;
474
475       if ((tmp & 0xc0) != 0x80)
476         goto error;
477
478       sample_number <<= 6;
479       sample_number |= (tmp & 0x3f);
480       len--;
481     }
482   }
483
484   /* calculate real blocksize from the blocksize index */
485   if (block_size == 0) {
486     goto error;
487   } else if (block_size == 6) {
488     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
489       goto need_more_data;
490     block_size++;
491   } else if (block_size == 7) {
492     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
493       goto need_more_data;
494     block_size++;
495   } else {
496     block_size = blocksize_table[block_size];
497   }
498
499   /* calculate the real samplerate from the samplerate index */
500   if (samplerate == 0 && flacparse->samplerate == 0) {
501     goto need_streaminfo;
502   } else if (samplerate < 12) {
503     samplerate = sample_rate_table[samplerate];
504   } else if (samplerate == 12) {
505     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
506       goto need_more_data;
507     samplerate *= 1000;
508   } else if (samplerate == 13) {
509     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
510       goto need_more_data;
511   } else if (samplerate == 14) {
512     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
513       goto need_more_data;
514     samplerate *= 10;
515   }
516
517   if (flacparse->samplerate && flacparse->samplerate != samplerate)
518     goto error;
519
520   /* check crc-8 for the header */
521   if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
522     goto need_more_data;
523
524   actual_crc =
525       gst_flac_calculate_crc8 (data,
526       (gst_bit_reader_get_pos (&reader) / 8) - 1);
527   if (actual_crc != expected_crc)
528     goto error;
529
530   if (set) {
531     flacparse->block_size = block_size;
532     if (!flacparse->samplerate)
533       flacparse->samplerate = samplerate;
534     if (!flacparse->bps)
535       flacparse->bps = bps;
536     if (!flacparse->blocking_strategy)
537       flacparse->blocking_strategy = blocking_strategy;
538     if (!flacparse->channels)
539       flacparse->channels = channels;
540     if (!flacparse->sample_number)
541       flacparse->sample_number = sample_number;
542
543     GST_DEBUG_OBJECT (flacparse,
544         "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
545         "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
546         flacparse->block_size, flacparse->sample_number);
547   }
548
549   if (block_size_ret)
550     *block_size_ret = block_size;
551
552   return FRAME_HEADER_VALID;
553
554 need_streaminfo:
555   GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
556   return FRAME_HEADER_INVALID;
557 error:
558   return FRAME_HEADER_INVALID;
559
560 need_more_data:
561   return FRAME_HEADER_MORE_DATA;
562 }
563
564 static gboolean
565 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
566     GstBaseParseFrame * frame, guint * ret)
567 {
568   GstBuffer *buffer;
569   guint8 *data;
570   gsize size;
571   guint max, remaining;
572   guint i, search_start, search_end;
573   FrameHeaderCheckReturn header_ret;
574   guint16 block_size;
575   gboolean result = FALSE;
576
577   buffer = frame->buffer;
578   data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
579
580   if (size < flacparse->min_framesize)
581     goto need_more;
582
583   header_ret =
584       gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
585       &block_size);
586   if (header_ret == FRAME_HEADER_INVALID) {
587     *ret = 0;
588     goto cleanup;
589   }
590   if (header_ret == FRAME_HEADER_MORE_DATA)
591     goto need_more;
592
593   /* mind unknown framesize */
594   search_start = MAX (2, flacparse->min_framesize);
595   if (flacparse->max_framesize)
596     search_end = MIN (size, flacparse->max_framesize + 9 + 2);
597   else
598     search_end = size;
599   search_end -= 2;
600
601   remaining = size;
602
603   for (i = search_start; i < search_end; i++, remaining--) {
604     if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
605       header_ret =
606           gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
607           FALSE, NULL);
608       if (header_ret == FRAME_HEADER_VALID) {
609         if (flacparse->check_frame_checksums) {
610           guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
611           guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
612
613           if (actual_crc != expected_crc)
614             continue;
615         }
616         *ret = i;
617         flacparse->block_size = block_size;
618         result = TRUE;
619         goto cleanup;
620       } else if (header_ret == FRAME_HEADER_MORE_DATA) {
621         goto need_more;
622       }
623     }
624   }
625
626   /* For the last frame output everything to the end */
627   if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
628     if (flacparse->check_frame_checksums) {
629       guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
630       guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
631
632       if (actual_crc == expected_crc) {
633         *ret = size;
634         flacparse->block_size = block_size;
635         result = TRUE;
636         goto cleanup;
637       }
638     } else {
639       *ret = size;
640       flacparse->block_size = block_size;
641       result = TRUE;
642       goto cleanup;
643     }
644   }
645
646 need_more:
647   max = flacparse->max_framesize + 16;
648   if (max == 16)
649     max = 1 << 24;
650   *ret = MIN (size + 4096, max);
651   result = TRUE;
652
653 cleanup:
654   gst_buffer_unmap (buffer, data, size);
655   return result;
656 }
657
658 static gboolean
659 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
660     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
661 {
662   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
663   GstBuffer *buffer = frame->buffer;
664   guint8 *data;
665   gsize bufsize;
666   gboolean result = TRUE;
667
668   data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
669
670   if (G_UNLIKELY (bufsize < 4)) {
671     result = FALSE;
672     goto cleanup;
673   }
674
675   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
676     if (memcmp (data, "fLaC", 4) == 0) {
677       GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
678       *framesize = 4;
679       goto cleanup;
680     }
681     if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
682       GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
683       /* Minimal size of a frame header */
684       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
685       flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
686       *skipsize = 0;
687       result = FALSE;
688       goto cleanup;
689     }
690     GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
691     result = FALSE;
692     goto cleanup;
693   }
694
695   if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
696     guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
697
698     GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
699     *framesize = size;
700     goto cleanup;
701   }
702
703   if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
704     gboolean ret;
705     guint next;
706
707     flacparse->offset = GST_BUFFER_OFFSET (buffer);
708     flacparse->blocking_strategy = 0;
709     flacparse->block_size = 0;
710     flacparse->sample_number = 0;
711
712     GST_DEBUG_OBJECT (flacparse, "Found sync code");
713     ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
714     if (ret) {
715       *framesize = next;
716       goto cleanup;
717     } else {
718       /* If we're at EOS and the frame was not valid, drop it! */
719       if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
720         GST_WARNING_OBJECT (flacparse, "EOS");
721         result = FALSE;
722         goto cleanup;
723       }
724
725       if (next == 0) {
726       } else if (next > bufsize) {
727         GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
728         *skipsize = 0;
729         gst_base_parse_set_min_frame_size (parse, next);
730         result = FALSE;
731         goto cleanup;
732       } else {
733         GST_ERROR_OBJECT (flacparse,
734             "Giving up on invalid frame (%d bytes)", bufsize);
735         result = FALSE;
736         goto cleanup;
737       }
738     }
739   } else {
740     GstByteReader reader;
741     gint off;
742
743     gst_byte_reader_init (&reader, data, bufsize);
744     off =
745         gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
746         0, bufsize);
747
748     if (off > 0) {
749       GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
750       *skipsize = off;
751       result = FALSE;
752       goto cleanup;
753     } else {
754       GST_DEBUG_OBJECT (flacparse, "Sync code not found");
755       *skipsize = bufsize - 3;
756       result = FALSE;
757       goto cleanup;
758     }
759   }
760
761   result = FALSE;
762
763 cleanup:
764   gst_buffer_unmap (buffer, data, bufsize);
765   return result;
766 }
767
768 static gboolean
769 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
770 {
771   GstBitReader reader;
772   guint8 *data;
773   gsize size;
774
775   data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
776   gst_bit_reader_init (&reader, data, size);
777
778   if (size != 4 + 34) {
779     GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
780         size);
781     goto failure;
782   }
783
784   /* Skip metadata block header */
785   gst_bit_reader_skip (&reader, 32);
786
787   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
788     goto error;
789   if (flacparse->min_blocksize < 16) {
790     GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
791         flacparse->min_blocksize);
792   }
793
794   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
795     goto error;
796   if (flacparse->max_blocksize < 16) {
797     GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
798         flacparse->max_blocksize);
799   }
800
801   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
802     goto error;
803   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
804     goto error;
805
806   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
807     goto error;
808   if (flacparse->samplerate == 0) {
809     GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
810     goto failure;
811   }
812
813   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
814     goto error;
815   flacparse->channels++;
816   if (flacparse->channels > 8) {
817     GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
818         flacparse->channels);
819     goto failure;
820   }
821
822   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
823     goto error;
824   flacparse->bps++;
825
826   if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
827     goto error;
828   if (flacparse->total_samples) {
829     gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
830         GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
831   }
832
833   gst_buffer_unmap (buffer, data, size);
834
835   GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
836       "\tmin/max blocksize: %u/%u,\n"
837       "\tmin/max framesize: %u/%u,\n"
838       "\tsamplerate: %u,\n"
839       "\tchannels: %u,\n"
840       "\tbits per sample: %u,\n"
841       "\ttotal samples: %" G_GUINT64_FORMAT,
842       flacparse->min_blocksize, flacparse->max_blocksize,
843       flacparse->min_framesize, flacparse->max_framesize,
844       flacparse->samplerate,
845       flacparse->channels, flacparse->bps, flacparse->total_samples);
846
847   return TRUE;
848
849 error:
850   GST_ERROR_OBJECT (flacparse, "Failed to read data");
851 failure:
852   gst_buffer_unmap (buffer, data, size);
853   return FALSE;
854 }
855
856 static gboolean
857 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
858     GstBuffer * buffer)
859 {
860   guint8 *data;
861   gsize size;
862
863   data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
864
865   flacparse->tags = gst_tag_list_from_vorbiscomment (data, size, data, 4, NULL);
866   gst_buffer_unmap (buffer, data, size);
867
868   if (flacparse->tags == NULL) {
869     GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
870   } else if (gst_tag_list_is_empty (flacparse->tags)) {
871     gst_tag_list_free (flacparse->tags);
872     flacparse->tags = NULL;
873   }
874
875   return TRUE;
876 }
877
878 static gboolean
879 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
880 {
881   GstByteReader reader;
882   guint8 *data;
883   gsize bufsize;
884   guint32 img_len = 0, img_type = 0;
885   guint32 img_mimetype_len = 0, img_description_len = 0;
886
887   data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
888   gst_byte_reader_init (&reader, data, bufsize);
889
890   if (!gst_byte_reader_skip (&reader, 4))
891     goto error;
892
893   if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
894     goto error;
895
896   if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
897     goto error;
898   if (!gst_byte_reader_skip (&reader, img_mimetype_len))
899     goto error;
900
901   if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
902     goto error;
903   if (!gst_byte_reader_skip (&reader, img_description_len))
904     goto error;
905
906   if (!gst_byte_reader_skip (&reader, 4 * 4))
907     goto error;
908
909   if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
910     goto error;
911
912   if (!flacparse->tags)
913     flacparse->tags = gst_tag_list_new ();
914
915   gst_tag_list_add_id3_image (flacparse->tags,
916       data + gst_byte_reader_get_pos (&reader), img_len, img_type);
917
918   if (gst_tag_list_is_empty (flacparse->tags)) {
919     gst_tag_list_free (flacparse->tags);
920     flacparse->tags = NULL;
921   }
922
923   gst_buffer_unmap (buffer, data, bufsize);
924   return TRUE;
925
926 error:
927   GST_ERROR_OBJECT (flacparse, "Error reading data");
928   gst_buffer_unmap (buffer, data, bufsize);
929   return FALSE;
930 }
931
932 static gboolean
933 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
934 {
935
936   GST_DEBUG_OBJECT (flacparse, "storing seektable");
937   /* only store for now;
938    * offset of the first frame is needed to get real info */
939   flacparse->seektable = gst_buffer_ref (buffer);
940
941   return TRUE;
942 }
943
944 static void
945 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
946 {
947   GstByteReader br;
948   gint64 offset = 0, samples = 0;
949   gpointer data;
950   gsize bufsize;
951
952   GST_DEBUG_OBJECT (flacparse,
953       "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
954
955   if (boffset <= 0)
956     goto exit;
957
958   data = gst_buffer_map (flacparse->seektable, &bufsize, NULL, GST_MAP_READ);
959   gst_byte_reader_init (&br, data, bufsize);
960
961   /* skip header */
962   if (!gst_byte_reader_skip (&br, 4))
963     goto done;
964
965   /* seekpoints */
966   while (gst_byte_reader_get_remaining (&br)) {
967     if (!gst_byte_reader_get_int64_be (&br, &samples))
968       break;
969     if (!gst_byte_reader_get_int64_be (&br, &offset))
970       break;
971     if (!gst_byte_reader_skip (&br, 2))
972       break;
973
974     GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
975         G_GINT64_FORMAT, samples, offset);
976
977     /* sanity check */
978     if (G_LIKELY (offset > 0 && samples > 0)) {
979       gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
980           boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
981               flacparse->samplerate), TRUE, FALSE);
982     }
983   }
984
985 done:
986   gst_buffer_unmap (flacparse->seektable, data, bufsize);
987 exit:
988   gst_buffer_unref (flacparse->seektable);
989   flacparse->seektable = NULL;
990 }
991
992 static void
993 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
994 {
995   GValue value = { 0, };
996
997   g_value_init (&value, GST_TYPE_BUFFER);
998   /* copy buffer to avoid problems with circular refcounts */
999   buf = gst_buffer_copy (buf);
1000   /* again, for good measure */
1001   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
1002   gst_value_set_buffer (&value, buf);
1003   gst_buffer_unref (buf);
1004   gst_value_array_append_value (array_val, &value);
1005   g_value_unset (&value);
1006 }
1007
1008 static gboolean
1009 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1010 {
1011   GstBuffer *vorbiscomment = NULL;
1012   GstBuffer *streaminfo = NULL;
1013   GstBuffer *marker = NULL;
1014   GValue array = { 0, };
1015   GstCaps *caps;
1016   GList *l;
1017   gboolean res = TRUE;
1018
1019   caps = gst_caps_new_simple ("audio/x-flac",
1020       "channels", G_TYPE_INT, flacparse->channels,
1021       "framed", G_TYPE_BOOLEAN, TRUE,
1022       "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1023
1024   if (!flacparse->headers)
1025     goto push_headers;
1026
1027   for (l = flacparse->headers; l; l = l->next) {
1028     GstBuffer *header = l->data;
1029     guint8 *data;
1030     gsize size;
1031
1032     data = gst_buffer_map (header, &size, NULL, GST_MAP_READ);
1033
1034     GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
1035
1036     if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
1037       marker = header;
1038     } else if (size > 1 && (data[0] & 0x7f) == 0) {
1039       streaminfo = header;
1040     } else if (size > 1 && (data[0] & 0x7f) == 4) {
1041       vorbiscomment = header;
1042     }
1043
1044     gst_buffer_unmap (header, data, size);
1045   }
1046
1047   if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1048     GST_WARNING_OBJECT (flacparse,
1049         "missing header %p %p %p, muxing into container "
1050         "formats may be broken", marker, streaminfo, vorbiscomment);
1051     goto push_headers;
1052   }
1053
1054   g_value_init (&array, GST_TYPE_ARRAY);
1055
1056   /* add marker including STREAMINFO header */
1057   {
1058     GstBuffer *buf;
1059     guint16 num;
1060     guint8 *sinfodata, *writedata;
1061     gsize sinfosize, writesize;
1062
1063     sinfodata = gst_buffer_map (streaminfo, &sinfosize, NULL, GST_MAP_READ);
1064
1065     /* minus one for the marker that is merged with streaminfo here */
1066     num = g_list_length (flacparse->headers) - 1;
1067
1068     buf = gst_buffer_new_and_alloc (13 + sinfosize);
1069     writedata = gst_buffer_map (buf, &writesize, NULL, GST_MAP_WRITE);
1070
1071     writedata[0] = 0x7f;
1072     memcpy (writedata + 1, "FLAC", 4);
1073     writedata[5] = 0x01;        /* mapping version major */
1074     writedata[6] = 0x00;        /* mapping version minor */
1075     writedata[7] = (num & 0xFF00) >> 8;
1076     writedata[8] = (num & 0x00FF) >> 0;
1077     memcpy (writedata + 9, "fLaC", 4);
1078     memcpy (writedata + 13, sinfodata, sinfosize);
1079     _value_array_append_buffer (&array, buf);
1080
1081     gst_buffer_unmap (streaminfo, sinfodata, sinfosize);
1082     gst_buffer_unmap (buf, writedata, writesize);
1083     gst_buffer_unref (buf);
1084   }
1085
1086   /* add VORBISCOMMENT header */
1087   _value_array_append_buffer (&array, vorbiscomment);
1088
1089   /* add other headers, if there are any */
1090   for (l = flacparse->headers; l; l = l->next) {
1091     if (GST_BUFFER_CAST (l->data) != marker &&
1092         GST_BUFFER_CAST (l->data) != streaminfo &&
1093         GST_BUFFER_CAST (l->data) != vorbiscomment) {
1094       _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1095     }
1096   }
1097
1098   gst_structure_set_value (gst_caps_get_structure (caps, 0),
1099       "streamheader", &array);
1100   g_value_unset (&array);
1101
1102 push_headers:
1103
1104   gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1105   gst_caps_unref (caps);
1106
1107   /* push header buffers; update caps, so when we push the first buffer the
1108    * negotiated caps will change to caps that include the streamheader field */
1109   while (flacparse->headers) {
1110     GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1111     GstFlowReturn ret;
1112     GstBaseParseFrame frame;
1113
1114     flacparse->headers =
1115         g_list_delete_link (flacparse->headers, flacparse->headers);
1116     buf = gst_buffer_make_writable (buf);
1117
1118     /* init, set and give away frame */
1119     gst_base_parse_frame_init (&frame);
1120     frame.buffer = buf;
1121     frame.overhead = -1;
1122     ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1123     if (ret != GST_FLOW_OK) {
1124       res = FALSE;
1125       break;
1126     }
1127   }
1128   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1129   g_list_free (flacparse->headers);
1130   flacparse->headers = NULL;
1131
1132   return res;
1133 }
1134
1135 static gboolean
1136 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1137 {
1138   GstBuffer *marker, *streaminfo, *vorbiscomment;
1139   guint8 *data;
1140   gsize bufsize;
1141
1142   marker = gst_buffer_new_and_alloc (4);
1143   data = gst_buffer_map (marker, &bufsize, NULL, GST_MAP_WRITE);
1144   memcpy (data, "fLaC", 4);
1145   gst_buffer_unmap (marker, data, bufsize);
1146   GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1147   GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1148   GST_BUFFER_OFFSET (marker) = 0;
1149   GST_BUFFER_OFFSET_END (marker) = 0;
1150   flacparse->headers = g_list_append (flacparse->headers, marker);
1151
1152   streaminfo = gst_buffer_new_and_alloc (4 + 34);
1153   data = gst_buffer_map (streaminfo, &bufsize, NULL, GST_MAP_WRITE);
1154   memset (data, 0, 4 + 34);
1155
1156   /* metadata block header */
1157   data[0] = 0x00;               /* is_last = 0; type = 0; */
1158   data[1] = 0x00;               /* length = 34; */
1159   data[2] = 0x00;
1160   data[3] = 0x22;
1161
1162   /* streaminfo */
1163
1164   data[4] = (flacparse->block_size >> 8) & 0xff;        /* min blocksize = blocksize; */
1165   data[5] = (flacparse->block_size) & 0xff;
1166   data[6] = (flacparse->block_size >> 8) & 0xff;        /* max blocksize = blocksize; */
1167   data[7] = (flacparse->block_size) & 0xff;
1168
1169   data[8] = 0x00;               /* min framesize = 0; */
1170   data[9] = 0x00;
1171   data[10] = 0x00;
1172   data[11] = 0x00;              /* max framesize = 0; */
1173   data[12] = 0x00;
1174   data[13] = 0x00;
1175
1176   data[14] = (flacparse->samplerate >> 12) & 0xff;
1177   data[15] = (flacparse->samplerate >> 4) & 0xff;
1178   data[16] = (flacparse->samplerate >> 0) & 0xf0;
1179
1180   data[16] |= (flacparse->channels - 1) << 1;
1181
1182   data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1183   data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1184
1185   {
1186     gint64 duration;
1187
1188     if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1189             GST_FORMAT_TIME, &duration)) {
1190       duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1191
1192       data[17] |= (duration >> 32) & 0xff;
1193       data[18] |= (duration >> 24) & 0xff;
1194       data[19] |= (duration >> 16) & 0xff;
1195       data[20] |= (duration >> 8) & 0xff;
1196       data[21] |= (duration >> 0) & 0xff;
1197     }
1198   }
1199   /* MD5 = 0; */
1200
1201   gst_buffer_unmap (streaminfo, data, bufsize);
1202   GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1203   GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1204   GST_BUFFER_OFFSET (streaminfo) = 0;
1205   GST_BUFFER_OFFSET_END (streaminfo) = 0;
1206   flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1207
1208   /* empty vorbiscomment */
1209   {
1210     GstTagList *taglist = gst_tag_list_new ();
1211     guchar header[4];
1212     guint size;
1213
1214     header[0] = 0x84;           /* is_last = 1; type = 4; */
1215
1216     vorbiscomment =
1217         gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1218         sizeof (header), NULL);
1219     gst_tag_list_free (taglist);
1220
1221     data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
1222
1223     /* Get rid of framing bit */
1224     if (data[bufsize - 1] == 1) {
1225       GstBuffer *sub;
1226
1227       sub =
1228           gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1229           bufsize - 1);
1230       gst_buffer_unmap (vorbiscomment, data, bufsize);
1231       gst_buffer_unref (vorbiscomment);
1232       vorbiscomment = sub;
1233       data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
1234     }
1235
1236     size = bufsize - 4;
1237     data[1] = ((size & 0xFF0000) >> 16);
1238     data[2] = ((size & 0x00FF00) >> 8);
1239     data[3] = (size & 0x0000FF);
1240
1241     gst_buffer_unmap (vorbiscomment, data, bufsize);
1242     GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1243     GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1244     GST_BUFFER_OFFSET (vorbiscomment) = 0;
1245     GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1246     flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1247   }
1248
1249   return TRUE;
1250 }
1251
1252 static GstFlowReturn
1253 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1254 {
1255   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1256   GstBuffer *buffer = frame->buffer;
1257   guint8 *data = NULL;
1258   gsize bufsize;
1259   GstFlowReturn res = GST_FLOW_ERROR;
1260
1261   data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
1262
1263   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1264     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1265     GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1266     GST_BUFFER_OFFSET (buffer) = 0;
1267     GST_BUFFER_OFFSET_END (buffer) = 0;
1268
1269     /* 32 bits metadata block */
1270     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1271     flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1272
1273     flacparse->headers =
1274         g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1275
1276     res = GST_BASE_PARSE_FLOW_DROPPED;
1277   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1278     gboolean is_last = ((data[0] & 0x80) == 0x80);
1279     guint type = (data[0] & 0x7F);
1280
1281     if (type == 127) {
1282       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1283       res = GST_BASE_PARSE_FLOW_DROPPED;
1284       goto cleanup;
1285     }
1286
1287     GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1288
1289     switch (type) {
1290       case 0:                  /* STREAMINFO */
1291         if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1292           goto cleanup;
1293         break;
1294       case 3:                  /* SEEKTABLE */
1295         if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1296           goto cleanup;
1297         break;
1298       case 4:                  /* VORBIS_COMMENT */
1299         if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1300           goto cleanup;
1301         break;
1302       case 6:                  /* PICTURE */
1303         if (!gst_flac_parse_handle_picture (flacparse, buffer))
1304           goto cleanup;
1305         break;
1306       case 1:                  /* PADDING */
1307       case 2:                  /* APPLICATION */
1308       case 5:                  /* CUESHEET */
1309       default:                 /* RESERVED */
1310         break;
1311     }
1312
1313     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1314     GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1315     GST_BUFFER_OFFSET (buffer) = 0;
1316     GST_BUFFER_OFFSET_END (buffer) = 0;
1317
1318     flacparse->headers =
1319         g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1320
1321     if (is_last) {
1322       if (!gst_flac_parse_handle_headers (flacparse))
1323         goto cleanup;
1324
1325       /* Minimal size of a frame header */
1326       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1327               flacparse->min_framesize));
1328       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1329     }
1330
1331     /* DROPPED because we pushed already or will push all headers manually */
1332     res = GST_BASE_PARSE_FLOW_DROPPED;
1333   } else {
1334     if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1335       FrameHeaderCheckReturn ret;
1336
1337       flacparse->offset = GST_BUFFER_OFFSET (buffer);
1338       ret =
1339           gst_flac_parse_frame_header_is_valid (flacparse,
1340           data, bufsize, TRUE, NULL);
1341       if (ret != FRAME_HEADER_VALID) {
1342         GST_ERROR_OBJECT (flacparse,
1343             "Baseclass didn't provide a complete frame");
1344         goto cleanup;
1345       }
1346     }
1347
1348     if (flacparse->block_size == 0) {
1349       GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1350       goto cleanup;
1351     }
1352
1353     if (flacparse->seektable)
1354       gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1355
1356     if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1357       if (flacparse->blocking_strategy == 1) {
1358         GST_WARNING_OBJECT (flacparse,
1359             "Generating headers for variable blocksize streams not supported");
1360
1361         if (!gst_flac_parse_handle_headers (flacparse))
1362           goto cleanup;
1363       } else {
1364         GST_DEBUG_OBJECT (flacparse, "Generating headers");
1365
1366         if (!gst_flac_parse_generate_headers (flacparse))
1367           goto cleanup;
1368
1369         if (!gst_flac_parse_handle_headers (flacparse))
1370           goto cleanup;
1371       }
1372       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1373     }
1374
1375     /* also cater for oggmux metadata */
1376     if (flacparse->blocking_strategy == 0) {
1377       GST_BUFFER_TIMESTAMP (buffer) =
1378           gst_util_uint64_scale (flacparse->sample_number,
1379           flacparse->block_size * GST_SECOND, flacparse->samplerate);
1380       GST_BUFFER_OFFSET_END (buffer) =
1381           flacparse->sample_number * flacparse->block_size +
1382           flacparse->block_size;
1383     } else {
1384       GST_BUFFER_TIMESTAMP (buffer) =
1385           gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1386           flacparse->samplerate);
1387       GST_BUFFER_OFFSET_END (buffer) =
1388           flacparse->sample_number + flacparse->block_size;
1389     }
1390     GST_BUFFER_OFFSET (buffer) =
1391         gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1392         flacparse->samplerate);
1393     GST_BUFFER_DURATION (buffer) =
1394         GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1395
1396     /* To simplify, we just assume that it's a fixed size header and ignore
1397      * subframe headers. The first could lead us to being off by 88 bits and
1398      * the second even less, so the total inaccuracy is negligible. */
1399     frame->overhead = 7;
1400
1401     /* Minimal size of a frame header */
1402     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1403             flacparse->min_framesize));
1404
1405     flacparse->offset = -1;
1406     flacparse->blocking_strategy = 0;
1407     flacparse->block_size = 0;
1408     flacparse->sample_number = 0;
1409     res = GST_FLOW_OK;
1410   }
1411
1412 cleanup:
1413   if (data)
1414     gst_buffer_unmap (buffer, data, bufsize);
1415
1416   return res;
1417 }
1418
1419 static GstFlowReturn
1420 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1421 {
1422   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1423
1424   /* Push tags */
1425   if (flacparse->tags) {
1426     gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1427     flacparse->tags = NULL;
1428   }
1429
1430   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1431
1432   return GST_FLOW_OK;
1433 }
1434
1435 static gboolean
1436 gst_flac_parse_convert (GstBaseParse * parse,
1437     GstFormat src_format, gint64 src_value, GstFormat dest_format,
1438     gint64 * dest_value)
1439 {
1440   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1441
1442   if (flacparse->samplerate > 0) {
1443     if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1444       if (src_value != -1)
1445         *dest_value =
1446             gst_util_uint64_scale (src_value, GST_SECOND,
1447             flacparse->samplerate);
1448       else
1449         *dest_value = -1;
1450       return TRUE;
1451     } else if (src_format == GST_FORMAT_TIME &&
1452         dest_format == GST_FORMAT_DEFAULT) {
1453       if (src_value != -1)
1454         *dest_value =
1455             gst_util_uint64_scale (src_value, flacparse->samplerate,
1456             GST_SECOND);
1457       else
1458         *dest_value = -1;
1459       return TRUE;
1460     }
1461   }
1462
1463   return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1464       src_value, dest_format, dest_value);
1465 }