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