Merging gst-build
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-good / 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  * @title: flacparse
27  * @see_also: flacdec, oggdemux, vorbisparse
28  *
29  * The flacparse element will parse the header packets of the FLAC
30  * stream and put them as the streamheader in the caps. This is used in the
31  * multifdsink case where you want to stream live FLAC streams to multiple
32  * clients, each client has to receive the streamheaders first before they can
33  * consume the FLAC packets.
34  *
35  * This element also makes sure that the buffers that it pushes out are properly
36  * timestamped and that their offset and offset_end are set. The buffers that
37  * flacparse outputs have all of the metadata that oggmux expects to receive,
38  * which allows you to (for example) remux an ogg/flac or convert a native FLAC
39  * format file to an ogg bitstream.
40  *
41  * ## Example pipelines
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  *
49  */
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "gstaudioparserselements.h"
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, gboolean is_last);
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_src_event (GstBaseParse * parse,
212     GstEvent * event);
213 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
214     GstCaps * filter);
215 static gboolean gst_flac_parse_set_sink_caps (GstBaseParse * parse,
216     GstCaps * caps);
217
218 #define gst_flac_parse_parent_class parent_class
219 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
220 GST_ELEMENT_REGISTER_DEFINE (flacparse, "flacparse",
221     GST_RANK_PRIMARY + 1, GST_TYPE_FLAC_PARSE);
222
223 static void
224 gst_flac_parse_class_init (GstFlacParseClass * klass)
225 {
226   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
227   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
228   GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
229
230   GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
231       "Flac parser element");
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->handle_frame =
246       GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
247   baseparse_class->pre_push_frame =
248       GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
249   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
250   baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_event);
251   baseparse_class->get_sink_caps =
252       GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
253   baseparse_class->set_sink_caps =
254       GST_DEBUG_FUNCPTR (gst_flac_parse_set_sink_caps);
255
256   gst_element_class_add_static_pad_template (element_class, &src_factory);
257   gst_element_class_add_static_pad_template (element_class, &sink_factory);
258
259   gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
260       "Codec/Parser/Audio",
261       "Parses audio with the FLAC lossless audio codec",
262       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
263 }
264
265 static void
266 gst_flac_parse_init (GstFlacParse * flacparse)
267 {
268   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
269   GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (flacparse));
270   GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (flacparse));
271 }
272
273 static void
274 gst_flac_parse_set_property (GObject * object, guint prop_id,
275     const GValue * value, GParamSpec * pspec)
276 {
277   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
278
279   switch (prop_id) {
280     case PROP_CHECK_FRAME_CHECKSUMS:
281       flacparse->check_frame_checksums = g_value_get_boolean (value);
282       break;
283     default:
284       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285       break;
286   }
287 }
288
289 static void
290 gst_flac_parse_get_property (GObject * object, guint prop_id,
291     GValue * value, GParamSpec * pspec)
292 {
293   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
294
295   switch (prop_id) {
296     case PROP_CHECK_FRAME_CHECKSUMS:
297       g_value_set_boolean (value, flacparse->check_frame_checksums);
298       break;
299     default:
300       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
301       break;
302   }
303 }
304
305 static void
306 gst_flac_parse_reset (GstFlacParse * parser)
307 {
308   if (parser->tags) {
309     gst_tag_list_unref (parser->tags);
310     parser->tags = NULL;
311   }
312   if (parser->toc) {
313     gst_toc_unref (parser->toc);
314     parser->toc = NULL;
315   }
316   if (parser->seektable) {
317     gst_buffer_unref (parser->seektable);
318     parser->seektable = NULL;
319   }
320
321   g_list_foreach (parser->headers, (GFunc) gst_mini_object_unref, NULL);
322   g_list_free (parser->headers);
323   parser->headers = NULL;
324 }
325
326 static void
327 gst_flac_parse_finalize (GObject * object)
328 {
329   GstFlacParse *flacparse = GST_FLAC_PARSE (object);
330
331   gst_flac_parse_reset (flacparse);
332   G_OBJECT_CLASS (parent_class)->finalize (object);
333 }
334
335 static gboolean
336 gst_flac_parse_start (GstBaseParse * parse)
337 {
338   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
339
340   flacparse->state = GST_FLAC_PARSE_STATE_INIT;
341   flacparse->min_blocksize = 0;
342   flacparse->max_blocksize = 0;
343   flacparse->min_framesize = 0;
344   flacparse->max_framesize = 0;
345
346   flacparse->upstream_length = -1;
347
348   flacparse->samplerate = 0;
349   flacparse->channels = 0;
350   flacparse->bps = 0;
351   flacparse->total_samples = 0;
352
353   flacparse->offset = GST_CLOCK_TIME_NONE;
354   flacparse->blocking_strategy = 0;
355   flacparse->block_size = 0;
356   flacparse->sample_number = 0;
357   flacparse->strategy_checked = FALSE;
358
359   flacparse->sent_codec_tag = FALSE;
360
361   /* "fLaC" marker */
362   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
363
364   /* inform baseclass we can come up with ts, based on counters in packets */
365   gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
366   gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
367
368   return TRUE;
369 }
370
371 static gboolean
372 gst_flac_parse_stop (GstBaseParse * parse)
373 {
374   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
375
376   gst_flac_parse_reset (flacparse);
377   return TRUE;
378 }
379
380 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
381
382 static const guint16 blocksize_table[16] = {
383   0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
384   256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
385   256 << 7,
386 };
387
388 static const guint32 sample_rate_table[16] = {
389   0,
390   88200, 176400, 192000,
391   8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
392   0, 0, 0, 0,
393 };
394
395 typedef enum
396 {
397   FRAME_HEADER_VALID,
398   FRAME_HEADER_INVALID,
399   FRAME_HEADER_MORE_DATA
400 } FrameHeaderCheckReturn;
401
402 static FrameHeaderCheckReturn
403 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
404     const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
405     gboolean * suspect)
406 {
407   GstBitReader reader = GST_BIT_READER_INIT (data, size);
408   guint8 blocking_strategy;
409   guint16 block_size;
410   guint32 samplerate = 0;
411   guint64 sample_number;
412   guint8 channels, bps;
413   guint8 tmp = 0;
414   guint8 actual_crc, expected_crc = 0;
415
416   /* Skip 14 bit sync code */
417   gst_bit_reader_skip_unchecked (&reader, 14);
418
419   /* Must be 0 */
420   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
421     goto error;
422
423   /* 0 == fixed block size, 1 == variable block size */
424   blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
425   if (flacparse->force_variable_block_size)
426     blocking_strategy = 1;
427
428   /* block size index, calculation of the real blocksize below */
429   block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
430   if (block_size == 0)
431     goto error;
432
433   /* sample rate index, calculation of the real samplerate below */
434   samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
435   if (samplerate == 0x0f)
436     goto error;
437
438   /* channel assignment */
439   channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
440   if (channels < 8) {
441     channels++;
442   } else if (channels <= 10) {
443     channels = 2;
444   } else if (channels > 10) {
445     goto error;
446   }
447   if (flacparse->channels && flacparse->channels != channels)
448     goto error;
449
450   /* bits per sample */
451   bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
452   if (bps == 0x03 || bps == 0x07) {
453     goto error;
454   } else if (bps == 0 && flacparse->bps == 0) {
455     goto need_streaminfo;
456   }
457   bps = sample_size_table[bps];
458   if (flacparse->bps && bps != flacparse->bps)
459     goto error;
460
461   /* reserved, must be 0 */
462   if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
463     goto error;
464
465   /* read "utf8" encoded sample/frame number */
466   {
467     gint len = 0;
468
469     len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
470
471     /* This is slightly faster than a loop */
472     if (!(len & 0x80)) {
473       sample_number = len;
474       len = 0;
475     } else if ((len & 0xc0) && !(len & 0x20)) {
476       sample_number = len & 0x1f;
477       len = 1;
478     } else if ((len & 0xe0) && !(len & 0x10)) {
479       sample_number = len & 0x0f;
480       len = 2;
481     } else if ((len & 0xf0) && !(len & 0x08)) {
482       sample_number = len & 0x07;
483       len = 3;
484     } else if ((len & 0xf8) && !(len & 0x04)) {
485       sample_number = len & 0x03;
486       len = 4;
487     } else if ((len & 0xfc) && !(len & 0x02)) {
488       sample_number = len & 0x01;
489       len = 5;
490     } else if ((len & 0xfe) && !(len & 0x01)) {
491       sample_number = len & 0x0;
492       len = 6;
493     } else {
494       goto error;
495     }
496
497     if ((blocking_strategy == 0 && len > 5) ||
498         (blocking_strategy == 1 && len > 6))
499       goto error;
500
501     while (len > 0) {
502       if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
503         goto need_more_data;
504
505       if ((tmp & 0xc0) != 0x80)
506         goto error;
507
508       sample_number <<= 6;
509       sample_number |= (tmp & 0x3f);
510       len--;
511     }
512   }
513
514   /* calculate real blocksize from the blocksize index */
515   if (block_size == 6) {
516     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
517       goto need_more_data;
518     block_size++;
519   } else if (block_size == 7) {
520     if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
521       goto need_more_data;
522     block_size++;
523   } else {
524     block_size = blocksize_table[block_size];
525   }
526
527   /* calculate the real samplerate from the samplerate index */
528   if (samplerate == 0 && flacparse->samplerate == 0) {
529     goto need_streaminfo;
530   } else if (samplerate < 12) {
531     samplerate = sample_rate_table[samplerate];
532   } else if (samplerate == 12) {
533     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
534       goto need_more_data;
535     samplerate *= 1000;
536   } else if (samplerate == 13) {
537     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
538       goto need_more_data;
539   } else if (samplerate == 14) {
540     if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
541       goto need_more_data;
542     samplerate *= 10;
543   }
544
545   if (flacparse->samplerate && flacparse->samplerate != samplerate)
546     goto error;
547
548   /* check crc-8 for the header */
549   if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
550     goto need_more_data;
551
552   actual_crc =
553       gst_flac_calculate_crc8 (data,
554       (gst_bit_reader_get_pos (&reader) / 8) - 1);
555   if (actual_crc != expected_crc) {
556     GST_DEBUG_OBJECT (flacparse,
557         "Checksum mismatch. Header CRC was '%d' but frame has '%d'",
558         expected_crc, actual_crc);
559     goto error;
560   }
561
562   /* Sanity check sample number against blocking strategy, as it seems
563      some files claim fixed block size but supply sample numbers,
564      rather than block numbers. */
565   if (blocking_strategy == 0 && flacparse->block_size != 0) {
566     if (!flacparse->strategy_checked) {
567       if (block_size == sample_number) {
568         GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
569             "but seems to be lying: assuming variable block size");
570         flacparse->force_variable_block_size = TRUE;
571         blocking_strategy = 1;
572       }
573       flacparse->strategy_checked = TRUE;
574     }
575   }
576
577   /* documentation says:
578    * The "blocking strategy" bit must be the same throughout the entire stream. */
579   if (flacparse->blocking_strategy != blocking_strategy) {
580     if (flacparse->block_size != 0) {
581       GST_WARNING_OBJECT (flacparse, "blocking strategy is not constant");
582       if (suspect)
583         *suspect = TRUE;
584     }
585   }
586
587   /*
588      The FLAC format documentation says:
589      The "blocking strategy" bit determines how to calculate the sample number
590      of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
591      frame header encodes the frame number as above, and the frame's starting
592      sample number will be the frame number times the blocksize. If it is 1
593      (variable-blocksize), the frame header encodes the frame's starting
594      sample number itself. (In the case of a fixed-blocksize stream, only the
595      last block may be shorter than the stream blocksize; its starting sample
596      number will be calculated as the frame number times the previous frame's
597      blocksize, or zero if it is the first frame).
598
599      Therefore, when in fixed block size mode, we only update the block size
600      the first time, then reuse that block size for subsequent calls.
601      This will also fix a timestamp problem with the last block's timestamp
602      being miscalculated by scaling the block number by a "wrong" block size.
603    */
604   if (blocking_strategy == 0) {
605     if (flacparse->block_size != 0) {
606       /* after first block */
607       if (flacparse->block_size != block_size) {
608         /* TODO: can we know we're on the last frame, to avoid warning ? */
609         GST_WARNING_OBJECT (flacparse, "Block size is not constant");
610         block_size = flacparse->block_size;
611         if (suspect)
612           *suspect = TRUE;
613       }
614     }
615   }
616
617   if (set) {
618     flacparse->block_size = block_size;
619     if (!flacparse->samplerate)
620       flacparse->samplerate = samplerate;
621     if (!flacparse->bps)
622       flacparse->bps = bps;
623     if (!flacparse->blocking_strategy)
624       flacparse->blocking_strategy = blocking_strategy;
625     if (!flacparse->channels)
626       flacparse->channels = channels;
627     if (!flacparse->sample_number)
628       flacparse->sample_number = sample_number;
629
630     GST_DEBUG_OBJECT (flacparse,
631         "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
632         "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
633         flacparse->block_size, flacparse->sample_number);
634   }
635
636   if (block_size_ret)
637     *block_size_ret = block_size;
638
639   return FRAME_HEADER_VALID;
640
641 need_streaminfo:
642   GST_ERROR_OBJECT (flacparse, "Need STREAMINFO metadata. Bits per sample "
643       "or sample rate not in frame header");
644 error:
645   return FRAME_HEADER_INVALID;
646
647 need_more_data:
648   return FRAME_HEADER_MORE_DATA;
649 }
650
651 static gboolean
652 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
653     const guint8 * data, gsize size, guint * ret)
654 {
655   guint max, remaining;
656   guint i, search_start, search_end;
657   FrameHeaderCheckReturn header_ret;
658   guint16 block_size;
659   gboolean suspect_start = FALSE, suspect_end = FALSE;
660
661   if (size < flacparse->min_framesize)
662     goto need_more;
663
664   header_ret =
665       gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
666       &block_size, &suspect_start);
667   if (header_ret == FRAME_HEADER_INVALID) {
668     *ret = 0;
669     return FALSE;
670   }
671   if (header_ret == FRAME_HEADER_MORE_DATA)
672     goto need_more;
673
674   /* mind unknown framesize */
675   search_start = MAX (2, flacparse->min_framesize);
676   if (flacparse->max_framesize)
677     search_end = MIN (size, flacparse->max_framesize + 9 + 2);
678   else
679     search_end = size;
680   search_end -= 2;
681
682   remaining = size;
683
684   for (i = search_start; i < search_end; i++, remaining--) {
685
686     if ((GST_READ_UINT16_BE (data + i) & 0xfffe) != 0xfff8)
687       continue;
688
689     GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
690     suspect_end = FALSE;
691     header_ret =
692         gst_flac_parse_frame_header_is_valid (flacparse, data + i,
693         remaining, FALSE, NULL, &suspect_end);
694     if (header_ret == FRAME_HEADER_VALID) {
695       if (flacparse->check_frame_checksums || suspect_start || suspect_end) {
696         guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
697         guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
698
699         GST_LOG_OBJECT (flacparse,
700             "Found possible frame (%d, %d). Checking for CRC match",
701             suspect_start, suspect_end);
702         if (actual_crc != expected_crc) {
703           GST_DEBUG_OBJECT (flacparse,
704               "Checksum mismatch. Header CRC was '%d' but frame has '%d'",
705               expected_crc, actual_crc);
706           continue;
707         }
708       }
709       *ret = i;
710       flacparse->block_size = block_size;
711       return TRUE;
712     } else if (header_ret == FRAME_HEADER_MORE_DATA) {
713       goto need_more;
714     }
715   }
716
717   /* For the last frame output everything to the end */
718   if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
719     if (flacparse->check_frame_checksums) {
720       guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
721       guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
722
723       if (actual_crc == expected_crc) {
724         *ret = size;
725         flacparse->block_size = block_size;
726         return TRUE;
727       }
728     } else {
729       *ret = size;
730       flacparse->block_size = block_size;
731       return TRUE;
732     }
733   }
734
735   /* so we searched to expected end and found nothing,
736    * give up on this frame (start) */
737   if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
738     GST_LOG_OBJECT (flacparse,
739         "could not determine valid frame end, discarding frame (start)");
740     *ret = 1;
741     return FALSE;
742   }
743
744 need_more:
745   max = flacparse->max_framesize + 16;
746   if (max == 16)
747     max = 1 << 24;
748   *ret = MIN (size + 4096, max);
749   return TRUE;
750 }
751
752 static GstFlowReturn
753 gst_flac_parse_handle_frame (GstBaseParse * parse,
754     GstBaseParseFrame * frame, gint * skipsize)
755 {
756   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
757   GstBuffer *buffer = frame->buffer;
758   GstMapInfo map;
759   gboolean result = TRUE;
760   GstFlowReturn ret = GST_FLOW_OK;
761   guint framesize = 0;
762
763   gst_buffer_map (buffer, &map, GST_MAP_READ);
764
765   *skipsize = 1;
766
767   if (G_UNLIKELY (map.size < 4)) {
768     result = FALSE;
769     goto cleanup;
770   }
771
772   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
773     if (memcmp (map.data, "fLaC", 4) == 0) {
774       GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
775       framesize = 4;
776       goto cleanup;
777     }
778     if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
779       GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
780       /* Minimal size of a frame header */
781       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
782       flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
783       *skipsize = 0;
784       result = FALSE;
785       goto cleanup;
786     }
787     GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
788     result = FALSE;
789     goto cleanup;
790   }
791
792   if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
793     guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
794
795     GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
796     framesize = size;
797     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), framesize);
798     goto cleanup;
799   }
800
801   if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
802     gboolean ret, is_first = !flacparse->strategy_checked;
803     guint next;
804
805     flacparse->offset = GST_BUFFER_OFFSET (buffer);
806     flacparse->blocking_strategy = 0;
807     flacparse->sample_number = 0;
808
809     GST_DEBUG_OBJECT (flacparse, "Found sync code");
810     ret = gst_flac_parse_frame_is_valid (flacparse, map.data, map.size, &next);
811     if (ret) {
812       if (is_first) {
813         GST_INFO_OBJECT (flacparse, "First sample number is %" G_GUINT64_FORMAT,
814             flacparse->sample_number);
815         flacparse->first_sample_number = flacparse->sample_number;
816       }
817       framesize = next;
818       goto cleanup;
819     }
820
821     /* If we're at EOS and the frame was not valid, drop it! */
822     if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
823       GST_WARNING_OBJECT (flacparse, "EOS");
824       result = FALSE;
825       goto cleanup;
826     }
827
828     if (next == 0) {
829     } else if (next > map.size) {
830       GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
831       *skipsize = 0;
832       gst_base_parse_set_min_frame_size (parse, next);
833       result = FALSE;
834       goto cleanup;
835     } else {
836       GST_ERROR_OBJECT (flacparse,
837           "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
838       result = FALSE;
839       goto cleanup;
840     }
841   } else {
842     GstByteReader reader;
843     gint off;
844
845     gst_byte_reader_init (&reader, map.data, map.size);
846     off =
847         gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
848         0, map.size);
849
850     if (off > 0) {
851       GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
852       *skipsize = off;
853       result = FALSE;
854       goto cleanup;
855     }
856
857     GST_DEBUG_OBJECT (flacparse, "Sync code not found");
858     *skipsize = map.size - 3;
859     result = FALSE;
860     goto cleanup;
861   }
862
863   result = FALSE;
864
865 cleanup:
866   gst_buffer_unmap (buffer, &map);
867
868   if (result)
869     *skipsize = 0;
870
871   if (result && framesize <= map.size) {
872     ret = gst_flac_parse_parse_frame (parse, frame, framesize);
873     if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
874       frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
875       ret = GST_FLOW_OK;
876     }
877     if (ret == GST_FLOW_OK)
878       ret = gst_base_parse_finish_frame (parse, frame, framesize);
879   }
880
881   return ret;
882 }
883
884 static gboolean
885 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
886 {
887   GstBitReader reader;
888   GstMapInfo map;
889
890   gst_buffer_map (buffer, &map, GST_MAP_READ);
891   gst_bit_reader_init (&reader, map.data, map.size);
892
893   if (map.size != 4 + 34) {
894     GST_ERROR_OBJECT (flacparse,
895         "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
896     goto failure;
897   }
898
899   /* Skip metadata block header */
900   if (!gst_bit_reader_skip (&reader, 32))
901     goto error;
902
903   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
904     goto error;
905   if (flacparse->min_blocksize < 16) {
906     GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
907         flacparse->min_blocksize);
908   }
909
910   if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
911     goto error;
912   if (flacparse->max_blocksize < 16) {
913     GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
914         flacparse->max_blocksize);
915   }
916
917   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
918     goto error;
919   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
920     goto error;
921
922   if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
923     goto error;
924   if (flacparse->samplerate == 0) {
925     GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
926     goto failure;
927   }
928
929   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
930     goto error;
931   flacparse->channels++;
932   if (flacparse->channels > 8) {
933     GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
934         flacparse->channels);
935     goto failure;
936   }
937
938   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
939     goto error;
940   flacparse->bps++;
941
942   if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
943     goto error;
944   if (flacparse->total_samples) {
945     gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
946         GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
947   }
948
949   gst_buffer_unmap (buffer, &map);
950
951   GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
952       "\tmin/max blocksize: %u/%u,\n"
953       "\tmin/max framesize: %u/%u,\n"
954       "\tsamplerate: %u,\n"
955       "\tchannels: %u,\n"
956       "\tbits per sample: %u,\n"
957       "\ttotal samples: %" G_GUINT64_FORMAT,
958       flacparse->min_blocksize, flacparse->max_blocksize,
959       flacparse->min_framesize, flacparse->max_framesize,
960       flacparse->samplerate,
961       flacparse->channels, flacparse->bps, flacparse->total_samples);
962
963   return TRUE;
964
965 error:
966   GST_ERROR_OBJECT (flacparse, "Failed to read data");
967 failure:
968   gst_buffer_unmap (buffer, &map);
969   return FALSE;
970 }
971
972 static gboolean
973 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
974     GstBuffer * buffer)
975 {
976   GstTagList *tags;
977   GstMapInfo map;
978
979   gst_buffer_map (buffer, &map, GST_MAP_READ);
980
981   tags =
982       gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
983   gst_buffer_unmap (buffer, &map);
984
985   if (tags == NULL) {
986     GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
987   } else if (gst_tag_list_is_empty (tags)) {
988     gst_tag_list_unref (tags);
989   } else if (flacparse->tags == NULL) {
990     flacparse->tags = tags;
991   } else {
992     gst_tag_list_insert (flacparse->tags, tags, GST_TAG_MERGE_APPEND);
993     gst_tag_list_unref (tags);
994   }
995
996   return TRUE;
997 }
998
999 static gboolean
1000 gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
1001 {
1002   GstByteReader reader;
1003   GstMapInfo map;
1004   guint i, j;
1005   guint8 n_tracks, track_num, index;
1006   guint64 offset;
1007   gint64 start, stop;
1008   gchar *id;
1009   gchar isrc[13];
1010   GstTagList *tags;
1011   GstToc *toc;
1012   GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
1013
1014   gst_buffer_map (buffer, &map, GST_MAP_READ);
1015   gst_byte_reader_init (&reader, map.data, map.size);
1016
1017   toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1018
1019   /* skip 4 bytes METADATA_BLOCK_HEADER */
1020   /* https://xiph.org/flac/format.html#metadata_block_header */
1021   if (!gst_byte_reader_skip (&reader, 4))
1022     goto error;
1023
1024   /* skip 395 bytes from METADATA_BLOCK_CUESHEET */
1025   /* https://xiph.org/flac/format.html#metadata_block_cuesheet */
1026   if (!gst_byte_reader_skip (&reader, 395))
1027     goto error;
1028
1029   if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
1030     goto error;
1031
1032   /* CUESHEET_TRACK */
1033   /* https://xiph.org/flac/format.html#cuesheet_track */
1034   for (i = 0; i < n_tracks; i++) {
1035     if (!gst_byte_reader_get_uint64_be (&reader, &offset))
1036       goto error;
1037     if (!gst_byte_reader_get_uint8 (&reader, &track_num))
1038       goto error;
1039
1040     if (gst_byte_reader_get_remaining (&reader) < 12)
1041       goto error;
1042     memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
1043     /* \0-terminate the string */
1044     isrc[12] = '\0';
1045     if (!gst_byte_reader_skip (&reader, 12))
1046       goto error;
1047
1048     /* skip 14 bytes from CUESHEET_TRACK */
1049     if (!gst_byte_reader_skip (&reader, 14))
1050       goto error;
1051     if (!gst_byte_reader_get_uint8 (&reader, &index))
1052       goto error;
1053     /* add tracks in TOC */
1054     /* lead-out tack has number 170 or 255 */
1055     if (track_num != 170 && track_num != 255) {
1056       prev_entry = cur_entry;
1057       /* previous track stop time = current track start time */
1058       if (prev_entry != NULL) {
1059         gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
1060         stop =
1061             gst_util_uint64_scale_round (offset, GST_SECOND,
1062             flacparse->samplerate);
1063         gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
1064       }
1065       id = g_strdup_printf ("%08x", track_num);
1066       cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
1067       g_free (id);
1068       start =
1069           gst_util_uint64_scale_round (offset, GST_SECOND,
1070           flacparse->samplerate);
1071       gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
1072       /* add ISRC as tag in track */
1073       if (strlen (isrc) != 0) {
1074         tags = gst_tag_list_new_empty ();
1075         gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
1076         gst_toc_entry_set_tags (cur_entry, tags);
1077       }
1078       gst_toc_append_entry (toc, cur_entry);
1079       /* CUESHEET_TRACK_INDEX */
1080       /* https://xiph.org/flac/format.html#cuesheet_track_index */
1081       for (j = 0; j < index; j++) {
1082         if (!gst_byte_reader_skip (&reader, 12))
1083           goto error;
1084       }
1085     } else {
1086       /* set stop time in last track */
1087       stop =
1088           gst_util_uint64_scale_round (offset, GST_SECOND,
1089           flacparse->samplerate);
1090       gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
1091     }
1092   }
1093
1094   /* send data as TOC */
1095   if (!flacparse->toc)
1096     flacparse->toc = toc;
1097
1098   gst_buffer_unmap (buffer, &map);
1099   return TRUE;
1100
1101 error:
1102   GST_ERROR_OBJECT (flacparse, "Error reading data");
1103   gst_buffer_unmap (buffer, &map);
1104   return FALSE;
1105 }
1106
1107 static gboolean
1108 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
1109 {
1110   GstByteReader reader;
1111   GstMapInfo map;
1112   guint32 img_len = 0, img_type = 0;
1113   guint32 img_mimetype_len = 0, img_description_len = 0;
1114
1115   gst_buffer_map (buffer, &map, GST_MAP_READ);
1116   gst_byte_reader_init (&reader, map.data, map.size);
1117
1118   if (!gst_byte_reader_skip (&reader, 4))
1119     goto error;
1120
1121   if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1122     goto error;
1123
1124   if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1125     goto error;
1126   if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1127     goto error;
1128
1129   if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1130     goto error;
1131   if (!gst_byte_reader_skip (&reader, img_description_len))
1132     goto error;
1133
1134   if (!gst_byte_reader_skip (&reader, 4 * 4))
1135     goto error;
1136
1137   if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1138     goto error;
1139
1140   if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1141     goto error;
1142
1143   GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1144
1145   if (img_len > 0) {
1146     if (flacparse->tags == NULL)
1147       flacparse->tags = gst_tag_list_new_empty ();
1148
1149     gst_tag_list_add_id3_image (flacparse->tags,
1150         map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1151   }
1152
1153   gst_buffer_unmap (buffer, &map);
1154   return TRUE;
1155
1156 error:
1157   GST_ERROR_OBJECT (flacparse, "Error reading data");
1158   gst_buffer_unmap (buffer, &map);
1159   return FALSE;
1160 }
1161
1162 static gboolean
1163 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1164 {
1165
1166   GST_DEBUG_OBJECT (flacparse, "storing seektable");
1167   /* only store for now;
1168    * offset of the first frame is needed to get real info */
1169   if (flacparse->seektable)
1170     gst_buffer_unref (flacparse->seektable);
1171   flacparse->seektable = gst_buffer_ref (buffer);
1172
1173   return TRUE;
1174 }
1175
1176 static void
1177 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1178 {
1179   GstByteReader br;
1180   gint64 offset = 0, samples = 0;
1181   GstMapInfo map;
1182
1183   GST_DEBUG_OBJECT (flacparse,
1184       "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1185
1186   if (boffset <= 0)
1187     goto exit;
1188
1189   gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1190   gst_byte_reader_init (&br, map.data, map.size);
1191
1192   /* skip header */
1193   if (!gst_byte_reader_skip (&br, 4))
1194     goto done;
1195
1196   /* seekpoints */
1197   while (gst_byte_reader_get_remaining (&br)) {
1198     if (!gst_byte_reader_get_int64_be (&br, &samples))
1199       break;
1200     if (!gst_byte_reader_get_int64_be (&br, &offset))
1201       break;
1202     if (!gst_byte_reader_skip (&br, 2))
1203       break;
1204
1205     GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1206         G_GINT64_FORMAT, samples, offset);
1207
1208     /* sanity check */
1209     if (G_LIKELY (offset > 0 && samples > 0)) {
1210       gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1211           boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1212               flacparse->samplerate), TRUE, FALSE);
1213     }
1214   }
1215
1216 done:
1217   gst_buffer_unmap (flacparse->seektable, &map);
1218 exit:
1219   gst_buffer_unref (flacparse->seektable);
1220   flacparse->seektable = NULL;
1221 }
1222
1223 static void
1224 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1225 {
1226   GValue value = { 0, };
1227
1228   g_value_init (&value, GST_TYPE_BUFFER);
1229   /* copy buffer to avoid problems with circular refcounts */
1230   buf = gst_buffer_copy (buf);
1231   /* again, for good measure */
1232   GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1233   gst_value_set_buffer (&value, buf);
1234   gst_buffer_unref (buf);
1235   gst_value_array_append_value (array_val, &value);
1236   g_value_unset (&value);
1237 }
1238
1239 static GstFlowReturn
1240 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1241 {
1242   GstBuffer *vorbiscomment = NULL;
1243   GstBuffer *streaminfo = NULL;
1244   GstBuffer *marker = NULL;
1245   GValue array = { 0, };
1246   GstCaps *caps;
1247   GList *l;
1248   GstFlowReturn res = GST_FLOW_OK;
1249   gboolean is_streaminfo_last = FALSE;
1250
1251   caps = gst_caps_new_simple ("audio/x-flac",
1252       "channels", G_TYPE_INT, flacparse->channels,
1253       "framed", G_TYPE_BOOLEAN, TRUE,
1254       "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1255
1256   if (!flacparse->headers)
1257     goto push_headers;
1258
1259   for (l = flacparse->headers; l; l = l->next) {
1260     GstBuffer *header = l->data;
1261     GstMapInfo map;
1262
1263     gst_buffer_map (header, &map, GST_MAP_READ);
1264
1265     GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1266
1267     if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1268       marker = header;
1269     } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1270       streaminfo = header;
1271       is_streaminfo_last = (map.data[0] & 0x80) != 0;
1272     } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1273       vorbiscomment = header;
1274     }
1275
1276     gst_buffer_unmap (header, &map);
1277   }
1278
1279   /* at least this one we can generate easily
1280    * to provide full headers downstream */
1281   if (vorbiscomment == NULL && streaminfo != NULL) {
1282     GST_DEBUG_OBJECT (flacparse,
1283         "missing vorbiscomment header; generating dummy");
1284     /* this vorbiscomment header is inserted after streaminfo and inherits its last-metadata-block flag */
1285     vorbiscomment =
1286         gst_flac_parse_generate_vorbiscomment (flacparse, is_streaminfo_last);
1287     flacparse->headers =
1288         g_list_insert (flacparse->headers, vorbiscomment,
1289         g_list_index (flacparse->headers, streaminfo) + 1);
1290   }
1291
1292   if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1293     GST_WARNING_OBJECT (flacparse,
1294         "missing header %p %p %p, muxing into container "
1295         "formats may be broken", marker, streaminfo, vorbiscomment);
1296     goto push_headers;
1297   }
1298
1299   g_value_init (&array, GST_TYPE_ARRAY);
1300
1301   /* add marker including STREAMINFO header */
1302   {
1303     GstBuffer *buf;
1304     guint16 num;
1305     GstMapInfo sinfomap, writemap;
1306
1307     gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1308
1309     /* minus one for the marker that is merged with streaminfo here */
1310     num = g_list_length (flacparse->headers) - 1;
1311
1312     buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1313     gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1314
1315     writemap.data[0] = 0x7f;
1316     memcpy (writemap.data + 1, "FLAC", 4);
1317     writemap.data[5] = 0x01;    /* mapping version major */
1318     writemap.data[6] = 0x00;    /* mapping version minor */
1319     writemap.data[7] = (num & 0xFF00) >> 8;
1320     writemap.data[8] = (num & 0x00FF) >> 0;
1321     memcpy (writemap.data + 9, "fLaC", 4);
1322     memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1323     /* clear the last-metadata-block flag because a VORBISCOMMENT always follows */
1324     writemap.data[13] = 0x00;   /* is_last = 0; type = 0; */
1325     _value_array_append_buffer (&array, buf);
1326
1327     gst_buffer_unmap (streaminfo, &sinfomap);
1328     gst_buffer_unmap (buf, &writemap);
1329     gst_buffer_unref (buf);
1330   }
1331
1332   /* add other headers, including VORBISCOMMENT */
1333   for (l = flacparse->headers; l; l = l->next) {
1334     if (GST_BUFFER_CAST (l->data) != marker &&
1335         GST_BUFFER_CAST (l->data) != streaminfo) {
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   while (flacparse->headers) {
1352     GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1353     GstBaseParseFrame frame;
1354
1355     flacparse->headers =
1356         g_list_delete_link (flacparse->headers, flacparse->headers);
1357     buf = gst_buffer_make_writable (buf);
1358
1359     /* init, set and give away frame */
1360     gst_base_parse_frame_init (&frame);
1361     frame.buffer = buf;
1362     frame.overhead = -1;
1363     res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1364     gst_base_parse_frame_free (&frame);
1365     if (res != GST_FLOW_OK)
1366       break;
1367   }
1368   g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1369   g_list_free (flacparse->headers);
1370   flacparse->headers = NULL;
1371
1372   return res;
1373 }
1374
1375 /* empty vorbiscomment */
1376 static GstBuffer *
1377 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse,
1378     gboolean is_last)
1379 {
1380   GstTagList *taglist = gst_tag_list_new_empty ();
1381   guchar header[4];
1382   guint size;
1383   GstBuffer *vorbiscomment;
1384   GstMapInfo map;
1385
1386   header[0] = (is_last ? 0x80 : 0x00) | 0x04;   /* is_last may vary; type = 4; */
1387
1388   vorbiscomment =
1389       gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1390       sizeof (header), NULL);
1391   gst_tag_list_unref (taglist);
1392
1393   gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1394
1395   /* Get rid of framing bit */
1396   if (map.data[map.size - 1] == 1) {
1397     GstBuffer *sub;
1398
1399     sub =
1400         gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1401         map.size - 1);
1402     gst_buffer_unmap (vorbiscomment, &map);
1403     gst_buffer_unref (vorbiscomment);
1404     vorbiscomment = sub;
1405     gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1406   }
1407
1408   size = map.size - 4;
1409   map.data[1] = ((size & 0xFF0000) >> 16);
1410   map.data[2] = ((size & 0x00FF00) >> 8);
1411   map.data[3] = (size & 0x0000FF);
1412   gst_buffer_unmap (vorbiscomment, &map);
1413   gst_flac_parse_reset_buffer_time_and_offset (vorbiscomment);
1414
1415   return vorbiscomment;
1416 }
1417
1418 static gboolean
1419 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1420 {
1421   GstBuffer *marker, *streaminfo;
1422   GstMapInfo map;
1423
1424   marker = gst_buffer_new_and_alloc (4);
1425   gst_buffer_map (marker, &map, GST_MAP_WRITE);
1426   memcpy (map.data, "fLaC", 4);
1427   gst_buffer_unmap (marker, &map);
1428   gst_flac_parse_reset_buffer_time_and_offset (marker);
1429   flacparse->headers = g_list_append (flacparse->headers, marker);
1430
1431   streaminfo = gst_buffer_new_and_alloc (4 + 34);
1432   gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1433   memset (map.data, 0, 4 + 34);
1434
1435   /* metadata block header */
1436   map.data[0] = 0x00;           /* is_last = 0; type = 0; */
1437   map.data[1] = 0x00;           /* length = 34; */
1438   map.data[2] = 0x00;
1439   map.data[3] = 0x22;
1440
1441   /* streaminfo */
1442
1443   map.data[4] = (flacparse->block_size >> 8) & 0xff;    /* min blocksize = blocksize; */
1444   map.data[5] = (flacparse->block_size) & 0xff;
1445   map.data[6] = (flacparse->block_size >> 8) & 0xff;    /* max blocksize = blocksize; */
1446   map.data[7] = (flacparse->block_size) & 0xff;
1447
1448   map.data[8] = 0x00;           /* min framesize = 0; */
1449   map.data[9] = 0x00;
1450   map.data[10] = 0x00;
1451   map.data[11] = 0x00;          /* max framesize = 0; */
1452   map.data[12] = 0x00;
1453   map.data[13] = 0x00;
1454
1455   map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1456   map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1457   map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1458
1459   map.data[16] |= (flacparse->channels - 1) << 1;
1460
1461   map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1462   map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1463
1464   {
1465     gint64 duration;
1466
1467     if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1468             GST_FORMAT_TIME, &duration) && duration != -1) {
1469       duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1470
1471       map.data[17] |= (duration >> 32) & 0xff;
1472       map.data[18] |= (duration >> 24) & 0xff;
1473       map.data[19] |= (duration >> 16) & 0xff;
1474       map.data[20] |= (duration >> 8) & 0xff;
1475       map.data[21] |= (duration >> 0) & 0xff;
1476     }
1477   }
1478   /* MD5 = 0; */
1479
1480   gst_buffer_unmap (streaminfo, &map);
1481   gst_flac_parse_reset_buffer_time_and_offset (streaminfo);
1482   flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1483
1484   flacparse->headers = g_list_append (flacparse->headers,
1485       gst_flac_parse_generate_vorbiscomment (flacparse, TRUE));
1486
1487   return TRUE;
1488 }
1489
1490 static inline void
1491 gst_flac_parse_reset_buffer_time_and_offset (GstBuffer * buffer)
1492 {
1493   GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1494   GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1495   GST_BUFFER_OFFSET (buffer) = 0;
1496   GST_BUFFER_OFFSET_END (buffer) = 0;
1497 }
1498
1499 /* Type 127 is invalid for a metadata block header & should
1500  * be discarded _before_ calling this function */
1501 static gboolean
1502 gst_flac_parse_handle_block_type (GstFlacParse * flacparse, guint type,
1503     GstBuffer * sbuffer)
1504 {
1505   gboolean ret = TRUE;
1506
1507   switch (type) {
1508     case 0:                    /* STREAMINFO */
1509       GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1510       ret = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1511       break;
1512     case 3:                    /* SEEKTABLE */
1513       GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1514       ret = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1515       break;
1516     case 4:                    /* VORBIS_COMMENT */
1517       GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1518       ret = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1519       break;
1520     case 5:                    /* CUESHEET */
1521       GST_INFO_OBJECT (flacparse, "CUESHEET header");
1522       ret = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1523       break;
1524     case 6:                    /* PICTURE */
1525       GST_INFO_OBJECT (flacparse, "PICTURE header");
1526       ret = gst_flac_parse_handle_picture (flacparse, sbuffer);
1527       break;
1528     case 1:                    /* PADDING */
1529       GST_INFO_OBJECT (flacparse, "PADDING header");
1530       break;
1531     case 2:                    /* APPLICATION */
1532       GST_INFO_OBJECT (flacparse, "APPLICATION header");
1533       break;
1534     default:                   /* RESERVED */
1535       GST_INFO_OBJECT (flacparse, "Unhandled metadata header type '%u'", type);
1536       GST_FIXME_OBJECT (flacparse, "FLAC version might not be fully supported");
1537       break;
1538   }
1539
1540   return ret;
1541 }
1542
1543 static GstFlowReturn
1544 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1545     gint size)
1546 {
1547   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1548   GstBuffer *buffer = frame->buffer, *sbuffer;
1549   GstMapInfo map;
1550   GstFlowReturn res = GST_FLOW_ERROR;
1551   guint64 relative_sample_number;
1552
1553   gst_buffer_map (buffer, &map, GST_MAP_READ);
1554
1555   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1556     sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1557     gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1558
1559     /* 32 bits metadata block */
1560     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1561     flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1562
1563     flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1564
1565     res = GST_BASE_PARSE_FLOW_DROPPED;
1566   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1567     gboolean is_last = map.data[0] >> 7;
1568     guint type = (map.data[0] & 0x7F);
1569
1570     if (type == 127) {
1571       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type 127");
1572       res = GST_BASE_PARSE_FLOW_DROPPED;
1573       goto cleanup;
1574     }
1575
1576     GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1577
1578     sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1579
1580     if (gst_flac_parse_handle_block_type (flacparse, type, sbuffer)) {
1581       gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1582       flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1583     } else {
1584       GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1585       GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1586
1587       gst_buffer_unref (sbuffer);
1588
1589       /* error out unless we have a STREAMINFO header */
1590       if (flacparse->samplerate == 0 || flacparse->bps == 0)
1591         goto header_parsing_error;
1592
1593       /* .. in which case just stop header parsing and try to find audio */
1594       is_last = TRUE;
1595     }
1596
1597     if (is_last) {
1598       res = gst_flac_parse_handle_headers (flacparse);
1599
1600       /* Minimal size of a frame header */
1601       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1602               flacparse->min_framesize));
1603       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1604
1605       if (res != GST_FLOW_OK)
1606         goto cleanup;
1607     } else {
1608       /* Header length */
1609       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1610     }
1611
1612     /* DROPPED because we pushed already or will push all headers manually */
1613     res = GST_BASE_PARSE_FLOW_DROPPED;
1614   } else {
1615     if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1616       FrameHeaderCheckReturn ret;
1617
1618       flacparse->offset = GST_BUFFER_OFFSET (buffer);
1619       ret =
1620           gst_flac_parse_frame_header_is_valid (flacparse,
1621           map.data, map.size, TRUE, NULL, NULL);
1622       if (ret != FRAME_HEADER_VALID) {
1623         GST_ERROR_OBJECT (flacparse,
1624             "Baseclass didn't provide a complete frame");
1625         goto cleanup;
1626       }
1627     }
1628
1629     if (flacparse->block_size == 0) {
1630       GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1631       goto cleanup;
1632     }
1633
1634     if (flacparse->seektable)
1635       gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1636
1637     if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1638       if (flacparse->blocking_strategy == 1) {
1639         GST_WARNING_OBJECT (flacparse,
1640             "Generating headers for variable blocksize streams not supported");
1641
1642         res = gst_flac_parse_handle_headers (flacparse);
1643       } else {
1644         GST_DEBUG_OBJECT (flacparse, "Generating headers");
1645
1646         if (!gst_flac_parse_generate_headers (flacparse))
1647           goto cleanup;
1648
1649         res = gst_flac_parse_handle_headers (flacparse);
1650       }
1651       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1652       if (res != GST_FLOW_OK)
1653         goto cleanup;
1654     }
1655
1656     /* also cater for oggmux metadata */
1657     relative_sample_number =
1658         flacparse->sample_number - flacparse->first_sample_number;
1659     if (flacparse->blocking_strategy == 0) {
1660       GST_BUFFER_PTS (buffer) =
1661           gst_util_uint64_scale (relative_sample_number,
1662           flacparse->block_size * GST_SECOND, flacparse->samplerate);
1663       GST_BUFFER_OFFSET_END (buffer) =
1664           relative_sample_number * flacparse->block_size +
1665           flacparse->block_size;
1666     } else {
1667       GST_BUFFER_PTS (buffer) =
1668           gst_util_uint64_scale (relative_sample_number, GST_SECOND,
1669           flacparse->samplerate);
1670       GST_BUFFER_OFFSET_END (buffer) =
1671           relative_sample_number + flacparse->block_size;
1672     }
1673
1674     GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
1675     GST_BUFFER_OFFSET (buffer) =
1676         gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1677         flacparse->samplerate);
1678     GST_BUFFER_DURATION (buffer) =
1679         GST_BUFFER_OFFSET (buffer) - GST_BUFFER_PTS (buffer);
1680
1681     /* To simplify, we just assume that it's a fixed size header and ignore
1682      * subframe headers. The first could lead us to be off by 88 bits and
1683      * the second even less, so the total inaccuracy is negligible. */
1684     frame->overhead = 7;
1685
1686     /* Minimal size of a frame header */
1687     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1688             flacparse->min_framesize));
1689
1690     flacparse->offset = -1;
1691     flacparse->blocking_strategy = 0;
1692     flacparse->sample_number = 0;
1693     res = GST_FLOW_OK;
1694   }
1695
1696 cleanup:
1697   gst_buffer_unmap (buffer, &map);
1698   return res;
1699
1700 header_parsing_error:
1701   GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1702       ("Failed to parse headers"));
1703   goto cleanup;
1704 }
1705
1706 static GstFlowReturn
1707 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1708 {
1709   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1710
1711   if (!flacparse->sent_codec_tag) {
1712     GstCaps *caps;
1713
1714     if (flacparse->tags == NULL)
1715       flacparse->tags = gst_tag_list_new_empty ();
1716
1717     /* codec tag */
1718     caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1719     if (G_UNLIKELY (caps == NULL)) {
1720       if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1721         GST_INFO_OBJECT (parse, "Src pad is flushing");
1722         return GST_FLOW_FLUSHING;
1723       }
1724       GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1725       return GST_FLOW_NOT_NEGOTIATED;
1726     }
1727     gst_pb_utils_add_codec_description_to_tag_list (flacparse->tags,
1728         GST_TAG_AUDIO_CODEC, caps);
1729     gst_caps_unref (caps);
1730
1731     /* Announce our pending tags */
1732     gst_base_parse_merge_tags (parse, flacparse->tags, GST_TAG_MERGE_REPLACE);
1733
1734     /* also signals the end of first-frame processing */
1735     flacparse->sent_codec_tag = TRUE;
1736   }
1737
1738   /* Push toc */
1739   if (flacparse->toc) {
1740     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1741         gst_event_new_toc (flacparse->toc, FALSE));
1742   }
1743
1744   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1745
1746   return GST_FLOW_OK;
1747 }
1748
1749 static gboolean
1750 gst_flac_parse_convert (GstBaseParse * parse,
1751     GstFormat src_format, gint64 src_value, GstFormat dest_format,
1752     gint64 * dest_value)
1753 {
1754   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1755
1756   if (flacparse->samplerate > 0) {
1757     if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1758       if (src_value != -1)
1759         *dest_value =
1760             gst_util_uint64_scale (src_value, GST_SECOND,
1761             flacparse->samplerate);
1762       else
1763         *dest_value = -1;
1764       return TRUE;
1765     } else if (src_format == GST_FORMAT_TIME &&
1766         dest_format == GST_FORMAT_DEFAULT) {
1767       if (src_value != -1)
1768         *dest_value =
1769             gst_util_uint64_scale (src_value, flacparse->samplerate,
1770             GST_SECOND);
1771       else
1772         *dest_value = -1;
1773       return TRUE;
1774     }
1775   }
1776
1777   return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1778       src_value, dest_format, dest_value);
1779 }
1780
1781 static gboolean
1782 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1783 {
1784   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1785   gboolean res = FALSE;
1786
1787   switch (GST_EVENT_TYPE (event)) {
1788     case GST_EVENT_TOC_SELECT:
1789     {
1790       GstTocEntry *entry = NULL;
1791       GstEvent *seek_event;
1792       GstToc *toc = NULL;
1793       gint64 start_pos;
1794       gchar *uid = NULL;
1795
1796       /* FIXME: some locking would be good */
1797       if (flacparse->toc)
1798         toc = gst_toc_ref (flacparse->toc);
1799
1800       if (toc != NULL) {
1801         gst_event_parse_toc_select (event, &uid);
1802         if (uid != NULL) {
1803           entry = gst_toc_find_entry (toc, uid);
1804           if (entry != NULL) {
1805             gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1806
1807             /* FIXME: use segment rate here instead? */
1808             seek_event = gst_event_new_seek (1.0,
1809                 GST_FORMAT_TIME,
1810                 GST_SEEK_FLAG_FLUSH,
1811                 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1812
1813             res =
1814                 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1815                 seek_event);
1816
1817           } else {
1818             GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1819           }
1820           g_free (uid);
1821         }
1822         gst_toc_unref (toc);
1823       } else {
1824         GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1825       }
1826       gst_event_unref (event);
1827       break;
1828     }
1829     default:
1830       res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1831       break;
1832   }
1833   return res;
1834 }
1835
1836 static void
1837 remove_fields (GstCaps * caps)
1838 {
1839   guint i, n;
1840
1841   n = gst_caps_get_size (caps);
1842   for (i = 0; i < n; i++) {
1843     GstStructure *s = gst_caps_get_structure (caps, i);
1844
1845     gst_structure_remove_field (s, "framed");
1846   }
1847 }
1848
1849 static GstCaps *
1850 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1851 {
1852   GstCaps *peercaps, *templ;
1853   GstCaps *res;
1854
1855   templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1856   if (filter) {
1857     GstCaps *fcopy = gst_caps_copy (filter);
1858     /* Remove the fields we convert */
1859     remove_fields (fcopy);
1860     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1861     gst_caps_unref (fcopy);
1862   } else
1863     peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1864
1865   if (peercaps) {
1866     /* Remove the framed field */
1867     peercaps = gst_caps_make_writable (peercaps);
1868     remove_fields (peercaps);
1869
1870     res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1871     gst_caps_unref (peercaps);
1872     gst_caps_unref (templ);
1873   } else {
1874     res = templ;
1875   }
1876
1877   if (filter) {
1878     GstCaps *intersection;
1879
1880     intersection =
1881         gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1882     gst_caps_unref (res);
1883     res = intersection;
1884   }
1885
1886   return res;
1887 }
1888
1889 static gboolean
1890 gst_flac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
1891 {
1892   GstCaps *current_caps;
1893   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1894
1895   /* If caps are changing, drain any pending frames we have so that afterwards
1896    * we can potentially accept a new stream that is starting with the FLAC
1897    * headers again. If headers appear in the middle of the stream we can't
1898    * detect them
1899    */
1900   gst_base_parse_drain (parse);
1901
1902   /* If the caps did really change we need to reset the parser */
1903   current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
1904   if (current_caps) {
1905     if (!gst_caps_is_strictly_equal (caps, current_caps)) {
1906       GST_DEBUG_OBJECT (flacparse, "Reset parser on sink pad caps change");
1907       gst_flac_parse_stop (parse);
1908       gst_flac_parse_start (parse);
1909     }
1910     gst_caps_unref (current_caps);
1911   }
1912
1913   return TRUE;
1914 }