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