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 #ifdef OHOS_OPT_CVE
1115 const guint8 *img_data;
1116 #endif
1117
1118 gst_buffer_map (buffer, &map, GST_MAP_READ);
1119 gst_byte_reader_init (&reader, map.data, map.size);
1120
1121 if (!gst_byte_reader_skip (&reader, 4))
1122 goto error;
1123
1124 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1125 goto error;
1126
1127 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1128 goto error;
1129 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1130 goto error;
1131
1132 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1133 goto error;
1134 if (!gst_byte_reader_skip (&reader, img_description_len))
1135 goto error;
1136
1137 if (!gst_byte_reader_skip (&reader, 4 * 4))
1138 goto error;
1139
1140 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1141 goto error;
1142
1143 #ifdef OHOS_OPT_CVE
1144 if (!gst_byte_reader_get_data (&reader, img_len, &img_data))
1145 #else
1146 if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1147 #endif
1148 goto error;
1149
1150 GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1151
1152 if (img_len > 0) {
1153 if (flacparse->tags == NULL)
1154 flacparse->tags = gst_tag_list_new_empty ();
1155
1156 #ifdef OHOS_OPT_CVE
1157 gst_tag_list_add_id3_image (flacparse->tags, img_data, img_len, img_type);
1158 #else
1159 gst_tag_list_add_id3_image (flacparse->tags,
1160 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1161 #endif
1162 }
1163
1164 gst_buffer_unmap (buffer, &map);
1165 return TRUE;
1166
1167 error:
1168 GST_ERROR_OBJECT (flacparse, "Error reading data");
1169 gst_buffer_unmap (buffer, &map);
1170 return FALSE;
1171 }
1172
1173 static gboolean
gst_flac_parse_handle_seektable(GstFlacParse * flacparse,GstBuffer * buffer)1174 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1175 {
1176
1177 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1178 /* only store for now;
1179 * offset of the first frame is needed to get real info */
1180 if (flacparse->seektable)
1181 gst_buffer_unref (flacparse->seektable);
1182 flacparse->seektable = gst_buffer_ref (buffer);
1183
1184 return TRUE;
1185 }
1186
1187 static void
gst_flac_parse_process_seektable(GstFlacParse * flacparse,gint64 boffset)1188 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1189 {
1190 GstByteReader br;
1191 gint64 offset = 0, samples = 0;
1192 GstMapInfo map;
1193
1194 GST_DEBUG_OBJECT (flacparse,
1195 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1196
1197 if (boffset <= 0)
1198 goto exit;
1199
1200 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1201 gst_byte_reader_init (&br, map.data, map.size);
1202
1203 /* skip header */
1204 if (!gst_byte_reader_skip (&br, 4))
1205 goto done;
1206
1207 /* seekpoints */
1208 while (gst_byte_reader_get_remaining (&br)) {
1209 if (!gst_byte_reader_get_int64_be (&br, &samples))
1210 break;
1211 if (!gst_byte_reader_get_int64_be (&br, &offset))
1212 break;
1213 if (!gst_byte_reader_skip (&br, 2))
1214 break;
1215
1216 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1217 G_GINT64_FORMAT, samples, offset);
1218
1219 /* sanity check */
1220 if (G_LIKELY (offset > 0 && samples > 0)) {
1221 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1222 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1223 flacparse->samplerate), TRUE, FALSE);
1224 }
1225 }
1226
1227 done:
1228 gst_buffer_unmap (flacparse->seektable, &map);
1229 exit:
1230 gst_buffer_unref (flacparse->seektable);
1231 flacparse->seektable = NULL;
1232 }
1233
1234 static void
_value_array_append_buffer(GValue * array_val,GstBuffer * buf)1235 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1236 {
1237 GValue value = { 0, };
1238
1239 g_value_init (&value, GST_TYPE_BUFFER);
1240 /* copy buffer to avoid problems with circular refcounts */
1241 buf = gst_buffer_copy (buf);
1242 /* again, for good measure */
1243 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1244 gst_value_set_buffer (&value, buf);
1245 gst_buffer_unref (buf);
1246 gst_value_array_append_value (array_val, &value);
1247 g_value_unset (&value);
1248 }
1249
1250 static GstFlowReturn
gst_flac_parse_handle_headers(GstFlacParse * flacparse)1251 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1252 {
1253 GstBuffer *vorbiscomment = NULL;
1254 GstBuffer *streaminfo = NULL;
1255 GstBuffer *marker = NULL;
1256 GValue array = { 0, };
1257 GstCaps *caps;
1258 GList *l;
1259 GstFlowReturn res = GST_FLOW_OK;
1260 gboolean is_streaminfo_last = FALSE;
1261
1262 caps = gst_caps_new_simple ("audio/x-flac",
1263 "channels", G_TYPE_INT, flacparse->channels,
1264 "framed", G_TYPE_BOOLEAN, TRUE,
1265 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1266
1267 if (!flacparse->headers)
1268 goto push_headers;
1269
1270 for (l = flacparse->headers; l; l = l->next) {
1271 GstBuffer *header = l->data;
1272 GstMapInfo map;
1273
1274 gst_buffer_map (header, &map, GST_MAP_READ);
1275
1276 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1277
1278 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1279 marker = header;
1280 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1281 streaminfo = header;
1282 is_streaminfo_last = (map.data[0] & 0x80) != 0;
1283 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1284 vorbiscomment = header;
1285 }
1286
1287 gst_buffer_unmap (header, &map);
1288 }
1289
1290 /* at least this one we can generate easily
1291 * to provide full headers downstream */
1292 if (vorbiscomment == NULL && streaminfo != NULL) {
1293 GST_DEBUG_OBJECT (flacparse,
1294 "missing vorbiscomment header; generating dummy");
1295 /* this vorbiscomment header is inserted after streaminfo and inherits its last-metadata-block flag */
1296 vorbiscomment =
1297 gst_flac_parse_generate_vorbiscomment (flacparse, is_streaminfo_last);
1298 flacparse->headers =
1299 g_list_insert (flacparse->headers, vorbiscomment,
1300 g_list_index (flacparse->headers, streaminfo) + 1);
1301 }
1302
1303 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1304 GST_WARNING_OBJECT (flacparse,
1305 "missing header %p %p %p, muxing into container "
1306 "formats may be broken", marker, streaminfo, vorbiscomment);
1307 goto push_headers;
1308 }
1309
1310 g_value_init (&array, GST_TYPE_ARRAY);
1311
1312 /* add marker including STREAMINFO header */
1313 {
1314 GstBuffer *buf;
1315 guint16 num;
1316 GstMapInfo sinfomap, writemap;
1317
1318 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1319
1320 /* minus one for the marker that is merged with streaminfo here */
1321 num = g_list_length (flacparse->headers) - 1;
1322
1323 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1324 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1325
1326 writemap.data[0] = 0x7f;
1327 memcpy (writemap.data + 1, "FLAC", 4);
1328 writemap.data[5] = 0x01; /* mapping version major */
1329 writemap.data[6] = 0x00; /* mapping version minor */
1330 writemap.data[7] = (num & 0xFF00) >> 8;
1331 writemap.data[8] = (num & 0x00FF) >> 0;
1332 memcpy (writemap.data + 9, "fLaC", 4);
1333 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1334 /* clear the last-metadata-block flag because a VORBISCOMMENT always follows */
1335 writemap.data[13] = 0x00; /* is_last = 0; type = 0; */
1336 _value_array_append_buffer (&array, buf);
1337
1338 gst_buffer_unmap (streaminfo, &sinfomap);
1339 gst_buffer_unmap (buf, &writemap);
1340 gst_buffer_unref (buf);
1341 }
1342
1343 /* add other headers, including VORBISCOMMENT */
1344 for (l = flacparse->headers; l; l = l->next) {
1345 if (GST_BUFFER_CAST (l->data) != marker &&
1346 GST_BUFFER_CAST (l->data) != streaminfo) {
1347 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1348 }
1349 }
1350
1351 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1352 "streamheader", &array);
1353 g_value_unset (&array);
1354
1355 push_headers:
1356
1357 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1358 gst_caps_unref (caps);
1359
1360 /* push header buffers; update caps, so when we push the first buffer the
1361 * negotiated caps will change to caps that include the streamheader field */
1362 while (flacparse->headers) {
1363 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1364 GstBaseParseFrame frame;
1365
1366 flacparse->headers =
1367 g_list_delete_link (flacparse->headers, flacparse->headers);
1368 buf = gst_buffer_make_writable (buf);
1369
1370 /* init, set and give away frame */
1371 gst_base_parse_frame_init (&frame);
1372 frame.buffer = buf;
1373 frame.overhead = -1;
1374 res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1375 gst_base_parse_frame_free (&frame);
1376 if (res != GST_FLOW_OK)
1377 break;
1378 }
1379 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1380 g_list_free (flacparse->headers);
1381 flacparse->headers = NULL;
1382
1383 return res;
1384 }
1385
1386 /* empty vorbiscomment */
1387 static GstBuffer *
gst_flac_parse_generate_vorbiscomment(GstFlacParse * flacparse,gboolean is_last)1388 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse,
1389 gboolean is_last)
1390 {
1391 GstTagList *taglist = gst_tag_list_new_empty ();
1392 guchar header[4];
1393 guint size;
1394 GstBuffer *vorbiscomment;
1395 GstMapInfo map;
1396
1397 header[0] = (is_last ? 0x80 : 0x00) | 0x04; /* is_last may vary; type = 4; */
1398
1399 vorbiscomment =
1400 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1401 sizeof (header), NULL);
1402 gst_tag_list_unref (taglist);
1403
1404 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1405
1406 /* Get rid of framing bit */
1407 if (map.data[map.size - 1] == 1) {
1408 GstBuffer *sub;
1409
1410 sub =
1411 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1412 map.size - 1);
1413 gst_buffer_unmap (vorbiscomment, &map);
1414 gst_buffer_unref (vorbiscomment);
1415 vorbiscomment = sub;
1416 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1417 }
1418
1419 size = map.size - 4;
1420 map.data[1] = ((size & 0xFF0000) >> 16);
1421 map.data[2] = ((size & 0x00FF00) >> 8);
1422 map.data[3] = (size & 0x0000FF);
1423 gst_buffer_unmap (vorbiscomment, &map);
1424 gst_flac_parse_reset_buffer_time_and_offset (vorbiscomment);
1425
1426 return vorbiscomment;
1427 }
1428
1429 static gboolean
gst_flac_parse_generate_headers(GstFlacParse * flacparse)1430 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1431 {
1432 GstBuffer *marker, *streaminfo;
1433 GstMapInfo map;
1434
1435 marker = gst_buffer_new_and_alloc (4);
1436 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1437 memcpy (map.data, "fLaC", 4);
1438 gst_buffer_unmap (marker, &map);
1439 gst_flac_parse_reset_buffer_time_and_offset (marker);
1440 flacparse->headers = g_list_append (flacparse->headers, marker);
1441
1442 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1443 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1444 memset (map.data, 0, 4 + 34);
1445
1446 /* metadata block header */
1447 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1448 map.data[1] = 0x00; /* length = 34; */
1449 map.data[2] = 0x00;
1450 map.data[3] = 0x22;
1451
1452 /* streaminfo */
1453
1454 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1455 map.data[5] = (flacparse->block_size) & 0xff;
1456 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1457 map.data[7] = (flacparse->block_size) & 0xff;
1458
1459 map.data[8] = 0x00; /* min framesize = 0; */
1460 map.data[9] = 0x00;
1461 map.data[10] = 0x00;
1462 map.data[11] = 0x00; /* max framesize = 0; */
1463 map.data[12] = 0x00;
1464 map.data[13] = 0x00;
1465
1466 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1467 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1468 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1469
1470 map.data[16] |= (flacparse->channels - 1) << 1;
1471
1472 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1473 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1474
1475 {
1476 gint64 duration;
1477
1478 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1479 GST_FORMAT_TIME, &duration) && duration != -1) {
1480 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1481
1482 map.data[17] |= (duration >> 32) & 0xff;
1483 map.data[18] |= (duration >> 24) & 0xff;
1484 map.data[19] |= (duration >> 16) & 0xff;
1485 map.data[20] |= (duration >> 8) & 0xff;
1486 map.data[21] |= (duration >> 0) & 0xff;
1487 }
1488 }
1489 /* MD5 = 0; */
1490
1491 gst_buffer_unmap (streaminfo, &map);
1492 gst_flac_parse_reset_buffer_time_and_offset (streaminfo);
1493 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1494
1495 flacparse->headers = g_list_append (flacparse->headers,
1496 gst_flac_parse_generate_vorbiscomment (flacparse, TRUE));
1497
1498 return TRUE;
1499 }
1500
1501 static inline void
gst_flac_parse_reset_buffer_time_and_offset(GstBuffer * buffer)1502 gst_flac_parse_reset_buffer_time_and_offset (GstBuffer * buffer)
1503 {
1504 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1505 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1506 GST_BUFFER_OFFSET (buffer) = 0;
1507 GST_BUFFER_OFFSET_END (buffer) = 0;
1508 }
1509
1510 /* Type 127 is invalid for a metadata block header & should
1511 * be discarded _before_ calling this function */
1512 static gboolean
gst_flac_parse_handle_block_type(GstFlacParse * flacparse,guint type,GstBuffer * sbuffer)1513 gst_flac_parse_handle_block_type (GstFlacParse * flacparse, guint type,
1514 GstBuffer * sbuffer)
1515 {
1516 gboolean ret = TRUE;
1517
1518 switch (type) {
1519 case 0: /* STREAMINFO */
1520 GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1521 ret = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1522 break;
1523 case 3: /* SEEKTABLE */
1524 GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1525 ret = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1526 break;
1527 case 4: /* VORBIS_COMMENT */
1528 GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1529 ret = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1530 break;
1531 case 5: /* CUESHEET */
1532 GST_INFO_OBJECT (flacparse, "CUESHEET header");
1533 ret = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1534 break;
1535 case 6: /* PICTURE */
1536 GST_INFO_OBJECT (flacparse, "PICTURE header");
1537 ret = gst_flac_parse_handle_picture (flacparse, sbuffer);
1538 break;
1539 case 1: /* PADDING */
1540 GST_INFO_OBJECT (flacparse, "PADDING header");
1541 break;
1542 case 2: /* APPLICATION */
1543 GST_INFO_OBJECT (flacparse, "APPLICATION header");
1544 break;
1545 default: /* RESERVED */
1546 GST_INFO_OBJECT (flacparse, "Unhandled metadata header type '%u'", type);
1547 GST_FIXME_OBJECT (flacparse, "FLAC version might not be fully supported");
1548 break;
1549 }
1550
1551 return ret;
1552 }
1553
1554 static GstFlowReturn
gst_flac_parse_parse_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint size)1555 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1556 gint size)
1557 {
1558 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1559 GstBuffer *buffer = frame->buffer, *sbuffer;
1560 GstMapInfo map;
1561 GstFlowReturn res = GST_FLOW_ERROR;
1562 guint64 relative_sample_number;
1563
1564 gst_buffer_map (buffer, &map, GST_MAP_READ);
1565
1566 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1567 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1568 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1569
1570 /* 32 bits metadata block */
1571 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1572 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1573
1574 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1575
1576 res = GST_BASE_PARSE_FLOW_DROPPED;
1577 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1578 gboolean is_last = map.data[0] >> 7;
1579 guint type = (map.data[0] & 0x7F);
1580
1581 if (type == 127) {
1582 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type 127");
1583 res = GST_BASE_PARSE_FLOW_DROPPED;
1584 goto cleanup;
1585 }
1586
1587 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1588
1589 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1590
1591 if (gst_flac_parse_handle_block_type (flacparse, type, sbuffer)) {
1592 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1593 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1594 } else {
1595 GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1596 GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1597
1598 gst_buffer_unref (sbuffer);
1599
1600 /* error out unless we have a STREAMINFO header */
1601 if (flacparse->samplerate == 0 || flacparse->bps == 0)
1602 goto header_parsing_error;
1603
1604 /* .. in which case just stop header parsing and try to find audio */
1605 is_last = TRUE;
1606 }
1607
1608 if (is_last) {
1609 res = gst_flac_parse_handle_headers (flacparse);
1610
1611 /* Minimal size of a frame header */
1612 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1613 flacparse->min_framesize));
1614 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1615
1616 if (res != GST_FLOW_OK)
1617 goto cleanup;
1618 } else {
1619 /* Header length */
1620 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1621 }
1622
1623 /* DROPPED because we pushed already or will push all headers manually */
1624 res = GST_BASE_PARSE_FLOW_DROPPED;
1625 } else {
1626 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1627 FrameHeaderCheckReturn ret;
1628
1629 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1630 ret =
1631 gst_flac_parse_frame_header_is_valid (flacparse,
1632 map.data, map.size, TRUE, NULL, NULL);
1633 if (ret != FRAME_HEADER_VALID) {
1634 GST_ERROR_OBJECT (flacparse,
1635 "Baseclass didn't provide a complete frame");
1636 goto cleanup;
1637 }
1638 }
1639
1640 if (flacparse->block_size == 0) {
1641 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1642 goto cleanup;
1643 }
1644
1645 if (flacparse->seektable)
1646 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1647
1648 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1649 if (flacparse->blocking_strategy == 1) {
1650 GST_WARNING_OBJECT (flacparse,
1651 "Generating headers for variable blocksize streams not supported");
1652
1653 res = gst_flac_parse_handle_headers (flacparse);
1654 } else {
1655 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1656
1657 if (!gst_flac_parse_generate_headers (flacparse))
1658 goto cleanup;
1659
1660 res = gst_flac_parse_handle_headers (flacparse);
1661 }
1662 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1663 if (res != GST_FLOW_OK)
1664 goto cleanup;
1665 }
1666
1667 /* also cater for oggmux metadata */
1668 relative_sample_number =
1669 flacparse->sample_number - flacparse->first_sample_number;
1670 if (flacparse->blocking_strategy == 0) {
1671 GST_BUFFER_PTS (buffer) =
1672 gst_util_uint64_scale (relative_sample_number,
1673 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1674 GST_BUFFER_OFFSET_END (buffer) =
1675 relative_sample_number * flacparse->block_size +
1676 flacparse->block_size;
1677 } else {
1678 GST_BUFFER_PTS (buffer) =
1679 gst_util_uint64_scale (relative_sample_number, GST_SECOND,
1680 flacparse->samplerate);
1681 GST_BUFFER_OFFSET_END (buffer) =
1682 relative_sample_number + flacparse->block_size;
1683 }
1684
1685 GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
1686 GST_BUFFER_OFFSET (buffer) =
1687 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1688 flacparse->samplerate);
1689 GST_BUFFER_DURATION (buffer) =
1690 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_PTS (buffer);
1691
1692 /* To simplify, we just assume that it's a fixed size header and ignore
1693 * subframe headers. The first could lead us to be off by 88 bits and
1694 * the second even less, so the total inaccuracy is negligible. */
1695 frame->overhead = 7;
1696
1697 /* Minimal size of a frame header */
1698 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1699 flacparse->min_framesize));
1700
1701 flacparse->offset = -1;
1702 flacparse->blocking_strategy = 0;
1703 flacparse->sample_number = 0;
1704 res = GST_FLOW_OK;
1705 }
1706
1707 cleanup:
1708 gst_buffer_unmap (buffer, &map);
1709 return res;
1710
1711 header_parsing_error:
1712 GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1713 ("Failed to parse headers"));
1714 goto cleanup;
1715 }
1716
1717 static GstFlowReturn
gst_flac_parse_pre_push_frame(GstBaseParse * parse,GstBaseParseFrame * frame)1718 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1719 {
1720 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1721
1722 if (!flacparse->sent_codec_tag) {
1723 GstCaps *caps;
1724
1725 if (flacparse->tags == NULL)
1726 flacparse->tags = gst_tag_list_new_empty ();
1727
1728 /* codec tag */
1729 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1730 if (G_UNLIKELY (caps == NULL)) {
1731 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1732 GST_INFO_OBJECT (parse, "Src pad is flushing");
1733 return GST_FLOW_FLUSHING;
1734 }
1735 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1736 return GST_FLOW_NOT_NEGOTIATED;
1737 }
1738 gst_pb_utils_add_codec_description_to_tag_list (flacparse->tags,
1739 GST_TAG_AUDIO_CODEC, caps);
1740 gst_caps_unref (caps);
1741
1742 /* Announce our pending tags */
1743 gst_base_parse_merge_tags (parse, flacparse->tags, GST_TAG_MERGE_REPLACE);
1744
1745 /* also signals the end of first-frame processing */
1746 flacparse->sent_codec_tag = TRUE;
1747 }
1748
1749 /* Push toc */
1750 if (flacparse->toc) {
1751 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1752 gst_event_new_toc (flacparse->toc, FALSE));
1753 }
1754
1755 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1756
1757 return GST_FLOW_OK;
1758 }
1759
1760 static gboolean
gst_flac_parse_convert(GstBaseParse * parse,GstFormat src_format,gint64 src_value,GstFormat dest_format,gint64 * dest_value)1761 gst_flac_parse_convert (GstBaseParse * parse,
1762 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1763 gint64 * dest_value)
1764 {
1765 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1766
1767 if (flacparse->samplerate > 0) {
1768 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1769 if (src_value != -1)
1770 *dest_value =
1771 gst_util_uint64_scale (src_value, GST_SECOND,
1772 flacparse->samplerate);
1773 else
1774 *dest_value = -1;
1775 return TRUE;
1776 } else if (src_format == GST_FORMAT_TIME &&
1777 dest_format == GST_FORMAT_DEFAULT) {
1778 if (src_value != -1)
1779 *dest_value =
1780 gst_util_uint64_scale (src_value, flacparse->samplerate,
1781 GST_SECOND);
1782 else
1783 *dest_value = -1;
1784 return TRUE;
1785 }
1786 }
1787
1788 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1789 src_value, dest_format, dest_value);
1790 }
1791
1792 static gboolean
gst_flac_parse_src_event(GstBaseParse * parse,GstEvent * event)1793 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1794 {
1795 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1796 gboolean res = FALSE;
1797
1798 switch (GST_EVENT_TYPE (event)) {
1799 case GST_EVENT_TOC_SELECT:
1800 {
1801 GstTocEntry *entry = NULL;
1802 GstEvent *seek_event;
1803 GstToc *toc = NULL;
1804 gint64 start_pos;
1805 gchar *uid = NULL;
1806
1807 /* FIXME: some locking would be good */
1808 if (flacparse->toc)
1809 toc = gst_toc_ref (flacparse->toc);
1810
1811 if (toc != NULL) {
1812 gst_event_parse_toc_select (event, &uid);
1813 if (uid != NULL) {
1814 entry = gst_toc_find_entry (toc, uid);
1815 if (entry != NULL) {
1816 gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1817
1818 /* FIXME: use segment rate here instead? */
1819 seek_event = gst_event_new_seek (1.0,
1820 GST_FORMAT_TIME,
1821 GST_SEEK_FLAG_FLUSH,
1822 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1823
1824 res =
1825 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1826 seek_event);
1827
1828 } else {
1829 GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1830 }
1831 g_free (uid);
1832 }
1833 gst_toc_unref (toc);
1834 } else {
1835 GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1836 }
1837 gst_event_unref (event);
1838 break;
1839 }
1840 default:
1841 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1842 break;
1843 }
1844 return res;
1845 }
1846
1847 static void
remove_fields(GstCaps * caps)1848 remove_fields (GstCaps * caps)
1849 {
1850 guint i, n;
1851
1852 n = gst_caps_get_size (caps);
1853 for (i = 0; i < n; i++) {
1854 GstStructure *s = gst_caps_get_structure (caps, i);
1855
1856 gst_structure_remove_field (s, "framed");
1857 }
1858 }
1859
1860 static GstCaps *
gst_flac_parse_get_sink_caps(GstBaseParse * parse,GstCaps * filter)1861 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1862 {
1863 GstCaps *peercaps, *templ;
1864 GstCaps *res;
1865
1866 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1867 if (filter) {
1868 GstCaps *fcopy = gst_caps_copy (filter);
1869 /* Remove the fields we convert */
1870 remove_fields (fcopy);
1871 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1872 gst_caps_unref (fcopy);
1873 } else
1874 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1875
1876 if (peercaps) {
1877 /* Remove the framed field */
1878 peercaps = gst_caps_make_writable (peercaps);
1879 remove_fields (peercaps);
1880
1881 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1882 gst_caps_unref (peercaps);
1883 gst_caps_unref (templ);
1884 } else {
1885 res = templ;
1886 }
1887
1888 if (filter) {
1889 GstCaps *intersection;
1890
1891 intersection =
1892 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1893 gst_caps_unref (res);
1894 res = intersection;
1895 }
1896
1897 return res;
1898 }
1899
1900 static gboolean
gst_flac_parse_set_sink_caps(GstBaseParse * parse,GstCaps * caps)1901 gst_flac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
1902 {
1903 GstCaps *current_caps;
1904 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1905
1906 /* If caps are changing, drain any pending frames we have so that afterwards
1907 * we can potentially accept a new stream that is starting with the FLAC
1908 * headers again. If headers appear in the middle of the stream we can't
1909 * detect them
1910 */
1911 gst_base_parse_drain (parse);
1912
1913 /* If the caps did really change we need to reset the parser */
1914 current_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
1915 if (current_caps) {
1916 if (!gst_caps_is_strictly_equal (caps, current_caps)) {
1917 GST_DEBUG_OBJECT (flacparse, "Reset parser on sink pad caps change");
1918 gst_flac_parse_stop (parse);
1919 gst_flac_parse_start (parse);
1920 }
1921 gst_caps_unref (current_caps);
1922 }
1923
1924 return TRUE;
1925 }
1926