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