upload tizen1.0 source
[framework/multimedia/gst-plugins-good0.10.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
202 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
203     GST_TYPE_BASE_PARSE);
204
205 static void
206 gst_flac_parse_base_init (gpointer g_class)
207 {
208   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
209
210   gst_element_class_add_pad_template (element_class,
211       gst_static_pad_template_get (&src_factory));
212   gst_element_class_add_pad_template (element_class,
213       gst_static_pad_template_get (&sink_factory));
214
215   gst_element_class_set_details_simple (element_class, "FLAC audio parser",
216       "Codec/Parser/Audio",
217       "Parses audio with the FLAC lossless audio codec",
218       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
219
220   GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
221       "Flac parser element");
222 }
223
224 static void
225 gst_flac_parse_class_init (GstFlacParseClass * klass)
226 {
227   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
228   GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
229
230   gobject_class->finalize = gst_flac_parse_finalize;
231   gobject_class->set_property = gst_flac_parse_set_property;
232   gobject_class->get_property = gst_flac_parse_get_property;
233
234   g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
235       g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
236           "Check the overall checksums of every frame",
237           DEFAULT_CHECK_FRAME_CHECKSUMS,
238           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
239
240   baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
241   baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
242   baseparse_class->check_valid_frame =
243       GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
244   baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
245   baseparse_class->pre_push_frame =
246       GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
247 }
248
249 static void
250 gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
251 {
252   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
253 }
254
255 static void
256 gst_flac_parse_set_property (GObject * object, guint prop_id,
257     const GValue * value, GParamSpec * pspec)
258 {
259   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
260
261   switch (prop_id) {
262     case PROP_CHECK_FRAME_CHECKSUMS:
263       flacparse->check_frame_checksums = g_value_get_boolean (value);
264       break;
265     default:
266       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
267       break;
268   }
269 }
270
271 static void
272 gst_flac_parse_get_property (GObject * object, guint prop_id,
273     GValue * value, GParamSpec * pspec)
274 {
275   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
276
277   switch (prop_id) {
278     case PROP_CHECK_FRAME_CHECKSUMS:
279       g_value_set_boolean (value, flacparse->check_frame_checksums);
280       break;
281     default:
282       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
283       break;
284   }
285 }
286
287 static void
288 gst_flac_parse_finalize (GObject * object)
289 {
290   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
291
292   if (flacparse->tags) {
293     gst_tag_list_free (flacparse->tags);
294     flacparse->tags = NULL;
295   }
296
297   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
298   g_list_free (flacparse->headers);
299   flacparse->headers = NULL;
300
301   G_OBJECT_CLASS (parent_class)->finalize (object);
302 }
303
304 static gboolean
305 gst_flac_parse_start (GstBaseParse * parse)
306 {
307   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
308
309   flacparse->state = GST_FLAC_PARSE_STATE_INIT;
310   flacparse->min_blocksize = 0;
311   flacparse->max_blocksize = 0;
312   flacparse->min_framesize = 0;
313   flacparse->max_framesize = 0;
314
315   flacparse->upstream_length = -1;
316
317   flacparse->samplerate = 0;
318   flacparse->channels = 0;
319   flacparse->bps = 0;
320   flacparse->total_samples = 0;
321
322   flacparse->offset = GST_CLOCK_TIME_NONE;
323   flacparse->blocking_strategy = 0;
324   flacparse->block_size = 0;
325   flacparse->sample_number = 0;
326
327   /* "fLaC" marker */
328   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
329
330   /* inform baseclass we can come up with ts, based on counters in packets */
331   gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
332   gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
333
334   return TRUE;
335 }
336
337 static gboolean
338 gst_flac_parse_stop (GstBaseParse * parse)
339 {
340   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
341
342   if (flacparse->tags) {
343     gst_tag_list_free (flacparse->tags);
344     flacparse->tags = NULL;
345   }
346
347   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
348   g_list_free (flacparse->headers);
349   flacparse->headers = NULL;
350
351   return TRUE;
352 }
353
354 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
355
356 static const guint16 blocksize_table[16] = {
357   0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
358   256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
359   256 << 7,
360 };
361
362 static const guint32 sample_rate_table[16] = {
363   0,
364   88200, 176400, 192000,
365   8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
366   0, 0, 0, 0,
367 };
368
369 typedef enum
370 {
371   FRAME_HEADER_VALID,
372   FRAME_HEADER_INVALID,
373   FRAME_HEADER_MORE_DATA
374 } FrameHeaderCheckReturn;
375
376 static FrameHeaderCheckReturn
377 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
378     const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
379 {
380   GstBitReader reader = GST_BIT_READER_INIT (data, size);
381   guint8 blocking_strategy;
382   guint16 block_size;
383   guint32 samplerate = 0;
384   guint64 sample_number;
385   guint8 channels, bps;
386   guint8 tmp = 0;
387   guint8 actual_crc, expected_crc = 0;
388
389   /* Skip 14 bit sync code */
390   gst_bit_reader_skip_unchecked (&reader, 14);
391
392   /* Must be 0 */
393   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
394     goto error;
395
396   /* 0 == fixed block size, 1 == variable block size */
397   blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
398
399   /* block size index, calculation of the real blocksize below */
400   block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
401   if (block_size == 0)
402     goto error;
403
404   /* sample rate index, calculation of the real samplerate below */
405   samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
406   if (samplerate == 0x0f)
407     goto error;
408
409   /* channel assignment */
410   channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
411   if (channels < 8) {
412     channels++;
413   } else if (channels <= 10) {
414     channels = 2;
415   } else if (channels > 10) {
416     goto error;
417   }
418   if (flacparse->channels && flacparse->channels != channels)
419     goto error;
420
421   /* bits per sample */
422   bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
423   if (bps == 0x03 || bps == 0x07) {
424     goto error;
425   } else if (bps == 0 && flacparse->bps == 0) {
426     goto need_streaminfo;
427   }
428   bps = sample_size_table[bps];
429   if (flacparse->bps && bps != flacparse->bps)
430     goto error;
431
432   /* reserved, must be 0 */
433   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
434     goto error;
435
436   /* read "utf8" encoded sample/frame number */
437   {
438     gint len = 0;
439
440     len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
441
442     /* This is slightly faster than a loop */
443     if (!(len & 0x80)) {
444       sample_number = len;
445       len = 0;
446     } else if ((len & 0xc0) && !(len & 0x20)) {
447       sample_number = len & 0x1f;
448       len = 1;
449     } else if ((len & 0xe0) && !(len & 0x10)) {
450       sample_number = len & 0x0f;
451       len = 2;
452     } else if ((len & 0xf0) && !(len & 0x08)) {
453       sample_number = len & 0x07;
454       len = 3;
455     } else if ((len & 0xf8) && !(len & 0x04)) {
456       sample_number = len & 0x03;
457       len = 4;
458     } else if ((len & 0xfc) && !(len & 0x02)) {
459       sample_number = len & 0x01;
460       len = 5;
461     } else if ((len & 0xfe) && !(len & 0x01)) {
462       sample_number = len & 0x0;
463       len = 6;
464     } else {
465       goto error;
466     }
467
468     if ((blocking_strategy == 0 && len > 5) ||
469         (blocking_strategy == 1 && len > 6))
470       goto error;
471
472     while (len > 0) {
473       if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
474         goto need_more_data;
475
476       if ((tmp & 0xc0) != 0x80)
477         goto error;
478
479       sample_number <<= 6;
480       sample_number |= (tmp & 0x3f);
481       len--;
482     }
483   }
484
485   /* calculate real blocksize from the blocksize index */
486   if (block_size == 0) {
487     goto error;
488   } else if (block_size == 6) {
489     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
490       goto need_more_data;
491     block_size++;
492   } else if (block_size == 7) {
493     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
494       goto need_more_data;
495     block_size++;
496   } else {
497     block_size = blocksize_table[block_size];
498   }
499
500   /* calculate the real samplerate from the samplerate index */
501   if (samplerate == 0 && flacparse->samplerate == 0) {
502     goto need_streaminfo;
503   } else if (samplerate < 12) {
504     samplerate = sample_rate_table[samplerate];
505   } else if (samplerate == 12) {
506     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
507       goto need_more_data;
508     samplerate *= 1000;
509   } else if (samplerate == 13) {
510     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
511       goto need_more_data;
512   } else if (samplerate == 14) {
513     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
514       goto need_more_data;
515     samplerate *= 10;
516   }
517
518   if (flacparse->samplerate && flacparse->samplerate != samplerate)
519     goto error;
520
521   /* check crc-8 for the header */
522   if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
523     goto need_more_data;
524
525   actual_crc =
526       gst_flac_calculate_crc8 (data,
527       (gst_bit_reader_get_pos (&reader) / 8) - 1);
528   if (actual_crc != expected_crc)
529     goto error;
530
531   if (set) {
532     flacparse->block_size = block_size;
533     if (!flacparse->samplerate)
534       flacparse->samplerate = samplerate;
535     if (!flacparse->bps)
536       flacparse->bps = bps;
537     if (!flacparse->blocking_strategy)
538       flacparse->blocking_strategy = blocking_strategy;
539     if (!flacparse->channels)
540       flacparse->channels = channels;
541     if (!flacparse->sample_number)
542       flacparse->sample_number = sample_number;
543
544     GST_DEBUG_OBJECT (flacparse,
545         "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
546         "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
547         flacparse->block_size, flacparse->sample_number);
548   }
549
550   if (block_size_ret)
551     *block_size_ret = block_size;
552
553   return FRAME_HEADER_VALID;
554
555 need_streaminfo:
556   GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
557   return FRAME_HEADER_INVALID;
558 error:
559   return FRAME_HEADER_INVALID;
560
561 need_more_data:
562   return FRAME_HEADER_MORE_DATA;
563 }
564
565 static gboolean
566 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
567     GstBaseParseFrame * frame, guint * ret)
568 {
569   GstBuffer *buffer;
570   const guint8 *data;
571   guint max, size, remaining;
572   guint i, search_start, search_end;
573   FrameHeaderCheckReturn header_ret;
574   guint16 block_size;
575
576   buffer = frame->buffer;
577   data = GST_BUFFER_DATA (buffer);
578   size = GST_BUFFER_SIZE (buffer);
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     return FALSE;
589   } else if (header_ret == FRAME_HEADER_MORE_DATA) {
590     goto need_more;
591   }
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         return TRUE;
619       } else if (header_ret == FRAME_HEADER_MORE_DATA) {
620         goto need_more;
621       }
622     }
623   }
624
625   /* For the last frame output everything to the end */
626   if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
627     if (flacparse->check_frame_checksums) {
628       guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
629       guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
630
631       if (actual_crc == expected_crc) {
632         *ret = size;
633         flacparse->block_size = block_size;
634         return TRUE;
635       }
636     } else {
637       *ret = size;
638       flacparse->block_size = block_size;
639       return TRUE;
640     }
641   }
642
643 need_more:
644   max = flacparse->max_framesize + 16;
645   if (max == 16)
646     max = 1 << 24;
647   *ret = MIN (size + 4096, max);
648   return FALSE;
649 }
650
651 static gboolean
652 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
653     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
654 {
655   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
656   GstBuffer *buffer = frame->buffer;
657   const guint8 *data = GST_BUFFER_DATA (buffer);
658
659   if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
660     return FALSE;
661
662   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
663     if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
664       GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
665       *framesize = 4;
666       return TRUE;
667     } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
668       GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
669       /* Minimal size of a frame header */
670       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
671       flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
672       *skipsize = 0;
673       return FALSE;
674     } else {
675       GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
676       return FALSE;
677     }
678   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
679     guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
680
681     GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
682     *framesize = size;
683     return TRUE;
684   } else {
685     if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
686       gboolean ret;
687       guint next;
688
689       flacparse->offset = GST_BUFFER_OFFSET (buffer);
690       flacparse->blocking_strategy = 0;
691       flacparse->block_size = 0;
692       flacparse->sample_number = 0;
693
694       GST_DEBUG_OBJECT (flacparse, "Found sync code");
695       ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
696       if (ret) {
697         *framesize = next;
698         return TRUE;
699       } else {
700         /* If we're at EOS and the frame was not valid, drop it! */
701         if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
702           GST_WARNING_OBJECT (flacparse, "EOS");
703           return FALSE;
704         }
705
706         if (next == 0) {
707         } else if (next > GST_BUFFER_SIZE (buffer)) {
708           GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
709           *skipsize = 0;
710           gst_base_parse_set_min_frame_size (parse, next);
711           return FALSE;
712         } else {
713           GST_ERROR_OBJECT (flacparse,
714               "Giving up on invalid frame (%d bytes)",
715               GST_BUFFER_SIZE (buffer));
716           return FALSE;
717         }
718       }
719     } else {
720       GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
721       gint off;
722
723       off =
724           gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
725           0, GST_BUFFER_SIZE (buffer));
726
727       if (off > 0) {
728         GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
729         *skipsize = off;
730         return FALSE;
731       } else {
732         GST_DEBUG_OBJECT (flacparse, "Sync code not found");
733         *skipsize = GST_BUFFER_SIZE (buffer) - 3;
734         return FALSE;
735       }
736     }
737   }
738
739   return FALSE;
740 }
741
742 static gboolean
743 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
744 {
745   GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
746
747   if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
748     GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
749         GST_BUFFER_SIZE (buffer));
750     return FALSE;
751   }
752
753   /* Skip metadata block header */
754   gst_bit_reader_skip (&reader, 32);
755
756   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
757     goto error;
758   if (flacparse->min_blocksize < 16) {
759     GST_ERROR_OBJECT (flacparse, "Invalid minimum block size: %u",
760         flacparse->min_blocksize);
761     return FALSE;
762   }
763
764   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
765     goto error;
766   if (flacparse->max_blocksize < 16) {
767     GST_ERROR_OBJECT (flacparse, "Invalid maximum block size: %u",
768         flacparse->max_blocksize);
769     return FALSE;
770   }
771
772   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
773     goto error;
774   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
775     goto error;
776
777   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
778     goto error;
779   if (flacparse->samplerate == 0) {
780     GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
781     return FALSE;
782   }
783
784   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
785     goto error;
786   flacparse->channels++;
787   if (flacparse->channels > 8) {
788     GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
789         flacparse->channels);
790     return FALSE;
791   }
792
793   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
794     goto error;
795   flacparse->bps++;
796
797   if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
798     goto error;
799   if (flacparse->total_samples)
800     gst_base_parse_set_duration (GST_BASE_PARSE (flacparse), GST_FORMAT_TIME,
801         GST_FRAMES_TO_CLOCK_TIME (flacparse->total_samples,
802             flacparse->samplerate), 0);
803
804   GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
805       "\tmin/max blocksize: %u/%u,\n"
806       "\tmin/max framesize: %u/%u,\n"
807       "\tsamplerate: %u,\n"
808       "\tchannels: %u,\n"
809       "\tbits per sample: %u,\n"
810       "\ttotal samples: %" G_GUINT64_FORMAT,
811       flacparse->min_blocksize, flacparse->max_blocksize,
812       flacparse->min_framesize, flacparse->max_framesize,
813       flacparse->samplerate,
814       flacparse->channels, flacparse->bps, flacparse->total_samples);
815
816   return TRUE;
817
818 error:
819   GST_ERROR_OBJECT (flacparse, "Failed to read data");
820   return FALSE;
821 }
822
823 static gboolean
824 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
825     GstBuffer * buffer)
826 {
827   flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
828       GST_BUFFER_DATA (buffer), 4, NULL);
829
830   if (flacparse->tags == NULL) {
831     GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
832   } else if (gst_tag_list_is_empty (flacparse->tags)) {
833     gst_tag_list_free (flacparse->tags);
834     flacparse->tags = NULL;
835   }
836
837   return TRUE;
838 }
839
840 static gboolean
841 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
842 {
843   GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
844   const guint8 *data = GST_BUFFER_DATA (buffer);
845   guint32 img_len = 0, img_type = 0;
846   guint32 img_mimetype_len = 0, img_description_len = 0;
847
848   if (!gst_byte_reader_skip (&reader, 4))
849     goto error;
850
851   if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
852     goto error;
853
854   if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
855     goto error;
856   if (!gst_byte_reader_skip (&reader, img_mimetype_len))
857     goto error;
858
859   if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
860     goto error;
861   if (!gst_byte_reader_skip (&reader, img_description_len))
862     goto error;
863
864   if (!gst_byte_reader_skip (&reader, 4 * 4))
865     goto error;
866
867   if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
868     goto error;
869
870   if (!flacparse->tags)
871     flacparse->tags = gst_tag_list_new ();
872
873   gst_tag_list_add_id3_image (flacparse->tags,
874       data + gst_byte_reader_get_pos (&reader), img_len, img_type);
875
876   if (gst_tag_list_is_empty (flacparse->tags)) {
877     gst_tag_list_free (flacparse->tags);
878     flacparse->tags = NULL;
879   }
880
881   return TRUE;
882
883 error:
884   GST_ERROR_OBJECT (flacparse, "Error reading data");
885   return FALSE;
886 }
887
888 static gboolean
889 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
890 {
891
892   GST_DEBUG_OBJECT (flacparse, "storing seektable");
893   /* only store for now;
894    * offset of the first frame is needed to get real info */
895   flacparse->seektable = gst_buffer_ref (buffer);
896
897   return TRUE;
898 }
899
900 static void
901 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
902 {
903   GstByteReader br;
904   gint64 offset = 0, samples = 0;
905
906   GST_DEBUG_OBJECT (flacparse,
907       "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
908
909   if (boffset <= 0)
910     goto done;
911
912   gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
913   /* skip header */
914   if (!gst_byte_reader_skip (&br, 4))
915     goto done;
916
917   /* seekpoints */
918   while (gst_byte_reader_get_remaining (&br)) {
919     if (!gst_byte_reader_get_int64_be (&br, &samples))
920       break;
921     if (!gst_byte_reader_get_int64_be (&br, &offset))
922       break;
923     if (!gst_byte_reader_skip (&br, 2))
924       break;
925
926     GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
927         G_GINT64_FORMAT, samples, offset);
928
929     /* sanity check */
930     if (G_LIKELY (offset > 0 && samples > 0)) {
931       gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
932           boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
933               flacparse->samplerate), TRUE, FALSE);
934     }
935   }
936
937 done:
938   gst_buffer_unref (flacparse->seektable);
939   flacparse->seektable = NULL;
940 }
941
942 static void
943 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
944 {
945   GValue value = { 0, };
946
947   g_value_init (&value, GST_TYPE_BUFFER);
948   /* copy buffer to avoid problems with circular refcounts */
949   buf = gst_buffer_copy (buf);
950   /* again, for good measure */
951   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
952   gst_value_set_buffer (&value, buf);
953   gst_buffer_unref (buf);
954   gst_value_array_append_value (array_val, &value);
955   g_value_unset (&value);
956 }
957
958 static gboolean
959 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
960 {
961   GstBuffer *vorbiscomment = NULL;
962   GstBuffer *streaminfo = NULL;
963   GstBuffer *marker = NULL;
964   GValue array = { 0, };
965   GstCaps *caps;
966   GList *l;
967   gboolean res = TRUE;
968
969   caps = gst_caps_new_simple ("audio/x-flac",
970       "channels", G_TYPE_INT, flacparse->channels,
971       "framed", G_TYPE_BOOLEAN, TRUE,
972       "rate", G_TYPE_INT, flacparse->samplerate, NULL);
973
974   if (!flacparse->headers)
975     goto push_headers;
976
977   for (l = flacparse->headers; l; l = l->next) {
978     GstBuffer *header = l->data;
979     const guint8 *data = GST_BUFFER_DATA (header);
980     guint size = GST_BUFFER_SIZE (header);
981
982     GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
983
984     if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
985       marker = header;
986     } else if (size > 1 && (data[0] & 0x7f) == 0) {
987       streaminfo = header;
988     } else if (size > 1 && (data[0] & 0x7f) == 4) {
989       vorbiscomment = header;
990     }
991   }
992
993   if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
994     GST_WARNING_OBJECT (flacparse,
995         "missing header %p %p %p, muxing into container "
996         "formats may be broken", marker, streaminfo, vorbiscomment);
997     goto push_headers;
998   }
999
1000   g_value_init (&array, GST_TYPE_ARRAY);
1001
1002   /* add marker including STREAMINFO header */
1003   {
1004     GstBuffer *buf;
1005     guint16 num;
1006
1007     /* minus one for the marker that is merged with streaminfo here */
1008     num = g_list_length (flacparse->headers) - 1;
1009
1010     buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1011     GST_BUFFER_DATA (buf)[0] = 0x7f;
1012     memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1013     GST_BUFFER_DATA (buf)[5] = 0x01;    /* mapping version major */
1014     GST_BUFFER_DATA (buf)[6] = 0x00;    /* mapping version minor */
1015     GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1016     GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1017     memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1018     memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1019         GST_BUFFER_SIZE (streaminfo));
1020     _value_array_append_buffer (&array, buf);
1021     gst_buffer_unref (buf);
1022   }
1023
1024   /* add VORBISCOMMENT header */
1025   _value_array_append_buffer (&array, vorbiscomment);
1026
1027   /* add other headers, if there are any */
1028   for (l = flacparse->headers; l; l = l->next) {
1029     if (GST_BUFFER_CAST (l->data) != marker &&
1030         GST_BUFFER_CAST (l->data) != streaminfo &&
1031         GST_BUFFER_CAST (l->data) != vorbiscomment) {
1032       _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1033     }
1034   }
1035
1036   gst_structure_set_value (gst_caps_get_structure (caps, 0),
1037       "streamheader", &array);
1038   g_value_unset (&array);
1039
1040 push_headers:
1041
1042   gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1043   gst_caps_unref (caps);
1044
1045   /* push header buffers; update caps, so when we push the first buffer the
1046    * negotiated caps will change to caps that include the streamheader field */
1047   while (flacparse->headers) {
1048     GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1049     GstFlowReturn ret;
1050     GstBaseParseFrame frame;
1051
1052     flacparse->headers =
1053         g_list_delete_link (flacparse->headers, flacparse->headers);
1054     buf = gst_buffer_make_metadata_writable (buf);
1055     gst_buffer_set_caps (buf,
1056         GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1057
1058     /* init, set and give away frame */
1059     gst_base_parse_frame_init (&frame);
1060     frame.buffer = buf;
1061     frame.overhead = -1;
1062     ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1063     if (ret != GST_FLOW_OK) {
1064       res = FALSE;
1065       break;
1066     }
1067   }
1068   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1069   g_list_free (flacparse->headers);
1070   flacparse->headers = NULL;
1071
1072   return res;
1073 }
1074
1075 static gboolean
1076 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1077 {
1078   GstBuffer *marker, *streaminfo, *vorbiscomment;
1079   guint8 *data;
1080
1081   marker = gst_buffer_new_and_alloc (4);
1082   memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1083   GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1084   GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1085   GST_BUFFER_OFFSET (marker) = 0;
1086   GST_BUFFER_OFFSET_END (marker) = 0;
1087   flacparse->headers = g_list_append (flacparse->headers, marker);
1088
1089   streaminfo = gst_buffer_new_and_alloc (4 + 34);
1090   data = GST_BUFFER_DATA (streaminfo);
1091   memset (data, 0, 4 + 34);
1092
1093   /* metadata block header */
1094   data[0] = 0x00;               /* is_last = 0; type = 0; */
1095   data[1] = 0x00;               /* length = 34; */
1096   data[2] = 0x00;
1097   data[3] = 0x22;
1098
1099   /* streaminfo */
1100
1101   data[4] = (flacparse->block_size >> 8) & 0xff;        /* min blocksize = blocksize; */
1102   data[5] = (flacparse->block_size) & 0xff;
1103   data[6] = (flacparse->block_size >> 8) & 0xff;        /* max blocksize = blocksize; */
1104   data[7] = (flacparse->block_size) & 0xff;
1105
1106   data[8] = 0x00;               /* min framesize = 0; */
1107   data[9] = 0x00;
1108   data[10] = 0x00;
1109   data[11] = 0x00;              /* max framesize = 0; */
1110   data[12] = 0x00;
1111   data[13] = 0x00;
1112
1113   data[14] = (flacparse->samplerate >> 12) & 0xff;
1114   data[15] = (flacparse->samplerate >> 4) & 0xff;
1115   data[16] = (flacparse->samplerate >> 0) & 0xf0;
1116
1117   data[16] |= (flacparse->channels - 1) << 1;
1118
1119   data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1120   data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1121
1122   {
1123     gint64 duration;
1124     GstFormat fmt = GST_FORMAT_TIME;
1125
1126     if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1127                 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1128       duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1129
1130       data[17] |= (duration >> 32) & 0xff;
1131       data[18] |= (duration >> 24) & 0xff;
1132       data[19] |= (duration >> 16) & 0xff;
1133       data[20] |= (duration >> 8) & 0xff;
1134       data[21] |= (duration >> 0) & 0xff;
1135     }
1136   }
1137   /* MD5 = 0; */
1138
1139   GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1140   GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1141   GST_BUFFER_OFFSET (streaminfo) = 0;
1142   GST_BUFFER_OFFSET_END (streaminfo) = 0;
1143   flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1144
1145   /* empty vorbiscomment */
1146   {
1147     GstTagList *taglist = gst_tag_list_new ();
1148     guchar header[4];
1149     guint size;
1150
1151     header[0] = 0x84;           /* is_last = 1; type = 4; */
1152
1153     vorbiscomment =
1154         gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1155         sizeof (header), NULL);
1156     gst_tag_list_free (taglist);
1157
1158     /* Get rid of framing bit */
1159     if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1160             1] == 1) {
1161       GstBuffer *sub;
1162
1163       sub =
1164           gst_buffer_create_sub (vorbiscomment, 0,
1165           GST_BUFFER_SIZE (vorbiscomment) - 1);
1166       gst_buffer_unref (vorbiscomment);
1167       vorbiscomment = sub;
1168     }
1169
1170     size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1171     GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1172     GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1173     GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1174
1175     GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1176     GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1177     GST_BUFFER_OFFSET (vorbiscomment) = 0;
1178     GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1179     flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1180   }
1181
1182   return TRUE;
1183 }
1184
1185 static GstFlowReturn
1186 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1187 {
1188   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1189   GstBuffer *buffer = frame->buffer;
1190   const guint8 *data = GST_BUFFER_DATA (buffer);
1191
1192   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1193     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1194     GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1195     GST_BUFFER_OFFSET (buffer) = 0;
1196     GST_BUFFER_OFFSET_END (buffer) = 0;
1197
1198     /* 32 bits metadata block */
1199     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1200     flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1201
1202     flacparse->headers =
1203         g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1204
1205     return GST_BASE_PARSE_FLOW_DROPPED;
1206   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1207     gboolean is_last = ((data[0] & 0x80) == 0x80);
1208     guint type = (data[0] & 0x7F);
1209
1210     if (type == 127) {
1211       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1212       return GST_BASE_PARSE_FLOW_DROPPED;
1213     }
1214
1215     GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1216
1217     switch (type) {
1218       case 0:                  /* STREAMINFO */
1219         if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1220           return GST_FLOW_ERROR;
1221         break;
1222       case 3:                  /* SEEKTABLE */
1223         if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1224           return GST_FLOW_ERROR;
1225         break;
1226       case 4:                  /* VORBIS_COMMENT */
1227         if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1228           return GST_FLOW_ERROR;
1229         break;
1230       case 6:                  /* PICTURE */
1231         if (!gst_flac_parse_handle_picture (flacparse, buffer))
1232           return GST_FLOW_ERROR;
1233         break;
1234       case 1:                  /* PADDING */
1235       case 2:                  /* APPLICATION */
1236       case 5:                  /* CUESHEET */
1237       default:                 /* RESERVED */
1238         break;
1239     }
1240
1241     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1242     GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1243     GST_BUFFER_OFFSET (buffer) = 0;
1244     GST_BUFFER_OFFSET_END (buffer) = 0;
1245
1246     flacparse->headers =
1247         g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1248
1249     if (is_last) {
1250       if (!gst_flac_parse_handle_headers (flacparse))
1251         return GST_FLOW_ERROR;
1252
1253       /* Minimal size of a frame header */
1254       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1255               flacparse->min_framesize));
1256       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1257     }
1258
1259     /* DROPPED because we pushed already or will push all headers manually */
1260     return GST_BASE_PARSE_FLOW_DROPPED;
1261   } else {
1262     if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1263       FrameHeaderCheckReturn ret;
1264
1265       flacparse->offset = GST_BUFFER_OFFSET (buffer);
1266       ret =
1267           gst_flac_parse_frame_header_is_valid (flacparse,
1268           GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1269       if (ret != FRAME_HEADER_VALID) {
1270         GST_ERROR_OBJECT (flacparse,
1271             "Baseclass didn't provide a complete frame");
1272         return GST_FLOW_ERROR;
1273       }
1274     }
1275
1276     if (flacparse->block_size == 0) {
1277       GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1278       return GST_FLOW_ERROR;
1279     }
1280
1281     if (flacparse->seektable)
1282       gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1283
1284     if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1285       if (flacparse->blocking_strategy == 1) {
1286         GST_WARNING_OBJECT (flacparse,
1287             "Generating headers for variable blocksize streams not supported");
1288
1289         if (!gst_flac_parse_handle_headers (flacparse))
1290           return GST_FLOW_ERROR;
1291       } else {
1292         GST_DEBUG_OBJECT (flacparse, "Generating headers");
1293
1294         if (!gst_flac_parse_generate_headers (flacparse))
1295           return GST_FLOW_ERROR;
1296
1297         if (!gst_flac_parse_handle_headers (flacparse))
1298           return GST_FLOW_ERROR;
1299       }
1300       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1301     }
1302
1303     /* also cater for oggmux metadata */
1304     if (flacparse->blocking_strategy == 0) {
1305       GST_BUFFER_TIMESTAMP (buffer) =
1306           gst_util_uint64_scale (flacparse->sample_number,
1307           flacparse->block_size * GST_SECOND, flacparse->samplerate);
1308       GST_BUFFER_OFFSET_END (buffer) =
1309           flacparse->sample_number * flacparse->block_size +
1310           flacparse->block_size;
1311     } else {
1312       GST_BUFFER_TIMESTAMP (buffer) =
1313           gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1314           flacparse->samplerate);
1315       GST_BUFFER_OFFSET_END (buffer) =
1316           flacparse->sample_number + flacparse->block_size;
1317     }
1318     GST_BUFFER_OFFSET (buffer) =
1319         gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1320         flacparse->samplerate);
1321     GST_BUFFER_DURATION (buffer) =
1322         GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1323
1324     /* To simplify, we just assume that it's a fixed size header and ignore
1325      * subframe headers. The first could lead us to being off by 88 bits and
1326      * the second even less, so the total inaccuracy is negligible. */
1327     frame->overhead = 7;
1328
1329     /* Minimal size of a frame header */
1330     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1331             flacparse->min_framesize));
1332
1333     flacparse->offset = -1;
1334     flacparse->blocking_strategy = 0;
1335     flacparse->block_size = 0;
1336     flacparse->sample_number = 0;
1337     return GST_FLOW_OK;
1338   }
1339 }
1340
1341 static GstFlowReturn
1342 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1343 {
1344   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1345
1346   /* Push tags */
1347   if (flacparse->tags) {
1348     gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1349     flacparse->tags = NULL;
1350   }
1351
1352   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1353
1354   return GST_FLOW_OK;
1355 }