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