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