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