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