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>
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.
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.
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.
25 * SECTION:element-flacparse
26 * @see_also: flacdec, oggdemux, vorbisparse
28 * The flacparse element will parse the header packets of the FLAC
29 * stream and put them as the streamheader in the caps. This is used in the
30 * multifdsink case where you want to stream live FLAC streams to multiple
31 * clients, each client has to receive the streamheaders first before they can
32 * consume the FLAC packets.
34 * This element also makes sure that the buffers that it pushes out are properly
35 * timestamped and that their offset and offset_end are set. The buffers that
36 * flacparse outputs have all of the metadata that oggmux expects to receive,
37 * which allows you to (for example) remux an ogg/flac or convert a native FLAC
38 * format file to an ogg bitstream.
41 * <title>Example pipelines</title>
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.
56 #include "gstflacparse.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>
64 GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
65 #define GST_CAT_DEFAULT flacparse_debug
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
104 gst_flac_calculate_crc8 (const guint8 * data, guint length)
109 crc = crc8_table[crc ^ *data];
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
153 gst_flac_calculate_crc16 (const guint8 * data, guint length)
158 crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
168 PROP_CHECK_FRAME_CHECKSUMS
171 #define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
173 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
176 GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
177 "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
180 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
183 GST_STATIC_CAPS ("audio/x-flac")
186 static GstBuffer *gst_flac_parse_generate_vorbiscomment (GstFlacParse *
189 static void gst_flac_parse_finalize (GObject * object);
190 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
191 const GValue * value, GParamSpec * pspec);
192 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
193 GValue * value, GParamSpec * pspec);
195 static gboolean gst_flac_parse_start (GstBaseParse * parse);
196 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
197 static GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
198 GstBaseParseFrame * frame, gint * skipsize);
199 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
200 GstBaseParseFrame * frame, gint size);
201 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
202 GstBaseParseFrame * frame);
203 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
204 GstFormat src_format, gint64 src_value, GstFormat dest_format,
205 gint64 * dest_value);
206 static gboolean gst_flac_parse_src_event (GstBaseParse * parse,
208 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
211 #define gst_flac_parse_parent_class parent_class
212 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
215 gst_flac_parse_class_init (GstFlacParseClass * klass)
217 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
218 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
219 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
221 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
222 "Flac parser element");
224 gobject_class->finalize = gst_flac_parse_finalize;
225 gobject_class->set_property = gst_flac_parse_set_property;
226 gobject_class->get_property = gst_flac_parse_get_property;
228 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
229 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
230 "Check the overall checksums of every frame",
231 DEFAULT_CHECK_FRAME_CHECKSUMS,
232 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
234 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
235 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
236 baseparse_class->handle_frame =
237 GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
238 baseparse_class->pre_push_frame =
239 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
240 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
241 baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_event);
242 baseparse_class->get_sink_caps =
243 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
245 gst_element_class_add_pad_template (element_class,
246 gst_static_pad_template_get (&src_factory));
247 gst_element_class_add_pad_template (element_class,
248 gst_static_pad_template_get (&sink_factory));
250 gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
251 "Codec/Parser/Audio",
252 "Parses audio with the FLAC lossless audio codec",
253 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
257 gst_flac_parse_init (GstFlacParse * flacparse)
259 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
260 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (flacparse));
264 gst_flac_parse_set_property (GObject * object, guint prop_id,
265 const GValue * value, GParamSpec * pspec)
267 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
270 case PROP_CHECK_FRAME_CHECKSUMS:
271 flacparse->check_frame_checksums = g_value_get_boolean (value);
274 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
280 gst_flac_parse_get_property (GObject * object, guint prop_id,
281 GValue * value, GParamSpec * pspec)
283 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
286 case PROP_CHECK_FRAME_CHECKSUMS:
287 g_value_set_boolean (value, flacparse->check_frame_checksums);
290 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
296 gst_flac_parse_finalize (GObject * object)
298 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
300 if (flacparse->tags) {
301 gst_tag_list_unref (flacparse->tags);
302 flacparse->tags = NULL;
304 if (flacparse->toc) {
305 gst_toc_unref (flacparse->toc);
306 flacparse->toc = NULL;
309 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
310 g_list_free (flacparse->headers);
311 flacparse->headers = NULL;
313 G_OBJECT_CLASS (parent_class)->finalize (object);
317 gst_flac_parse_start (GstBaseParse * parse)
319 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
321 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
322 flacparse->min_blocksize = 0;
323 flacparse->max_blocksize = 0;
324 flacparse->min_framesize = 0;
325 flacparse->max_framesize = 0;
327 flacparse->upstream_length = -1;
329 flacparse->samplerate = 0;
330 flacparse->channels = 0;
332 flacparse->total_samples = 0;
334 flacparse->offset = GST_CLOCK_TIME_NONE;
335 flacparse->blocking_strategy = 0;
336 flacparse->block_size = 0;
337 flacparse->sample_number = 0;
338 flacparse->strategy_checked = FALSE;
340 flacparse->sent_codec_tag = FALSE;
343 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
345 /* inform baseclass we can come up with ts, based on counters in packets */
346 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
347 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
353 gst_flac_parse_stop (GstBaseParse * parse)
355 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
357 if (flacparse->tags) {
358 gst_tag_list_unref (flacparse->tags);
359 flacparse->tags = NULL;
361 if (flacparse->toc) {
362 gst_toc_unref (flacparse->toc);
363 flacparse->toc = NULL;
366 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
367 g_list_free (flacparse->headers);
368 flacparse->headers = NULL;
373 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
375 static const guint16 blocksize_table[16] = {
376 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
377 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
381 static const guint32 sample_rate_table[16] = {
383 88200, 176400, 192000,
384 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
391 FRAME_HEADER_INVALID,
392 FRAME_HEADER_MORE_DATA
393 } FrameHeaderCheckReturn;
395 static FrameHeaderCheckReturn
396 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
397 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
400 GstBitReader reader = GST_BIT_READER_INIT (data, size);
401 guint8 blocking_strategy;
403 guint32 samplerate = 0;
404 guint64 sample_number;
405 guint8 channels, bps;
407 guint8 actual_crc, expected_crc = 0;
409 /* Skip 14 bit sync code */
410 gst_bit_reader_skip_unchecked (&reader, 14);
413 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
416 /* 0 == fixed block size, 1 == variable block size */
417 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
418 if (flacparse->force_variable_block_size)
419 blocking_strategy = 1;
421 /* block size index, calculation of the real blocksize below */
422 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
426 /* sample rate index, calculation of the real samplerate below */
427 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
428 if (samplerate == 0x0f)
431 /* channel assignment */
432 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
435 } else if (channels <= 10) {
437 } else if (channels > 10) {
440 if (flacparse->channels && flacparse->channels != channels)
443 /* bits per sample */
444 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
445 if (bps == 0x03 || bps == 0x07) {
447 } else if (bps == 0 && flacparse->bps == 0) {
448 goto need_streaminfo;
450 bps = sample_size_table[bps];
451 if (flacparse->bps && bps != flacparse->bps)
454 /* reserved, must be 0 */
455 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
458 /* read "utf8" encoded sample/frame number */
462 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
464 /* This is slightly faster than a loop */
468 } else if ((len & 0xc0) && !(len & 0x20)) {
469 sample_number = len & 0x1f;
471 } else if ((len & 0xe0) && !(len & 0x10)) {
472 sample_number = len & 0x0f;
474 } else if ((len & 0xf0) && !(len & 0x08)) {
475 sample_number = len & 0x07;
477 } else if ((len & 0xf8) && !(len & 0x04)) {
478 sample_number = len & 0x03;
480 } else if ((len & 0xfc) && !(len & 0x02)) {
481 sample_number = len & 0x01;
483 } else if ((len & 0xfe) && !(len & 0x01)) {
484 sample_number = len & 0x0;
490 if ((blocking_strategy == 0 && len > 5) ||
491 (blocking_strategy == 1 && len > 6))
495 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
498 if ((tmp & 0xc0) != 0x80)
502 sample_number |= (tmp & 0x3f);
507 /* calculate real blocksize from the blocksize index */
508 if (block_size == 6) {
509 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
512 } else if (block_size == 7) {
513 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
517 block_size = blocksize_table[block_size];
520 /* calculate the real samplerate from the samplerate index */
521 if (samplerate == 0 && flacparse->samplerate == 0) {
522 goto need_streaminfo;
523 } else if (samplerate < 12) {
524 samplerate = sample_rate_table[samplerate];
525 } else if (samplerate == 12) {
526 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
529 } else if (samplerate == 13) {
530 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
532 } else if (samplerate == 14) {
533 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
538 if (flacparse->samplerate && flacparse->samplerate != samplerate)
541 /* check crc-8 for the header */
542 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
546 gst_flac_calculate_crc8 (data,
547 (gst_bit_reader_get_pos (&reader) / 8) - 1);
548 if (actual_crc != expected_crc)
551 /* Sanity check sample number against blocking strategy, as it seems
552 some files claim fixed block size but supply sample numbers,
553 rather than block numbers. */
554 if (blocking_strategy == 0 && flacparse->block_size != 0) {
555 if (!flacparse->strategy_checked) {
556 if (block_size == sample_number) {
557 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
558 "but seems to be lying: assuming variable block size");
559 flacparse->force_variable_block_size = TRUE;
560 blocking_strategy = 1;
562 flacparse->strategy_checked = TRUE;
566 /* documentation says:
567 * The "blocking strategy" bit must be the same throughout the entire stream. */
568 if (flacparse->blocking_strategy != blocking_strategy) {
569 if (flacparse->block_size != 0) {
570 GST_WARNING_OBJECT (flacparse, "blocking strategy is not constant");
577 The FLAC format documentation says:
578 The "blocking strategy" bit determines how to calculate the sample number
579 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
580 frame header encodes the frame number as above, and the frame's starting
581 sample number will be the frame number times the blocksize. If it is 1
582 (variable-blocksize), the frame header encodes the frame's starting
583 sample number itself. (In the case of a fixed-blocksize stream, only the
584 last block may be shorter than the stream blocksize; its starting sample
585 number will be calculated as the frame number times the previous frame's
586 blocksize, or zero if it is the first frame).
588 Therefore, when in fixed block size mode, we only update the block size
589 the first time, then reuse that block size for subsequent calls.
590 This will also fix a timestamp problem with the last block's timestamp
591 being miscalculated by scaling the block number by a "wrong" block size.
593 if (blocking_strategy == 0) {
594 if (flacparse->block_size != 0) {
595 /* after first block */
596 if (flacparse->block_size != block_size) {
597 /* TODO: can we know we're on the last frame, to avoid warning ? */
598 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
599 block_size = flacparse->block_size;
607 flacparse->block_size = block_size;
608 if (!flacparse->samplerate)
609 flacparse->samplerate = samplerate;
611 flacparse->bps = bps;
612 if (!flacparse->blocking_strategy)
613 flacparse->blocking_strategy = blocking_strategy;
614 if (!flacparse->channels)
615 flacparse->channels = channels;
616 if (!flacparse->sample_number)
617 flacparse->sample_number = sample_number;
619 GST_DEBUG_OBJECT (flacparse,
620 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
621 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
622 flacparse->block_size, flacparse->sample_number);
626 *block_size_ret = block_size;
628 return FRAME_HEADER_VALID;
631 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
632 return FRAME_HEADER_INVALID;
634 return FRAME_HEADER_INVALID;
637 return FRAME_HEADER_MORE_DATA;
641 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
642 GstBaseParseFrame * frame, guint * ret)
646 guint max, remaining;
647 guint i, search_start, search_end;
648 FrameHeaderCheckReturn header_ret;
650 gboolean suspect_start = FALSE, suspect_end = FALSE;
651 gboolean result = FALSE;
653 buffer = frame->buffer;
654 gst_buffer_map (buffer, &map, GST_MAP_READ);
656 if (map.size < flacparse->min_framesize)
660 gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
661 &block_size, &suspect_start);
662 if (header_ret == FRAME_HEADER_INVALID) {
666 if (header_ret == FRAME_HEADER_MORE_DATA)
669 /* mind unknown framesize */
670 search_start = MAX (2, flacparse->min_framesize);
671 if (flacparse->max_framesize)
672 search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
674 search_end = map.size;
677 remaining = map.size;
679 for (i = search_start; i < search_end; i++, remaining--) {
680 if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
681 GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
684 gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
685 remaining, FALSE, NULL, &suspect_end);
686 if (header_ret == FRAME_HEADER_VALID) {
687 if (flacparse->check_frame_checksums || suspect_start || suspect_end) {
688 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
689 guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
691 GST_LOG_OBJECT (flacparse,
692 "checking checksum, frame suspect (%d, %d)",
693 suspect_start, suspect_end);
694 if (actual_crc != expected_crc) {
695 GST_DEBUG_OBJECT (flacparse, "checksum did not match");
700 flacparse->block_size = block_size;
703 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
709 /* For the last frame output everything to the end */
710 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
711 if (flacparse->check_frame_checksums) {
712 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
713 guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
715 if (actual_crc == expected_crc) {
717 flacparse->block_size = block_size;
723 flacparse->block_size = block_size;
729 /* so we searched to expected end and found nothing,
730 * give up on this frame (start) */
731 if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
732 GST_LOG_OBJECT (flacparse,
733 "could not determine valid frame end, discarding frame (start)");
739 max = flacparse->max_framesize + 16;
742 *ret = MIN (map.size + 4096, max);
746 gst_buffer_unmap (buffer, &map);
751 gst_flac_parse_handle_frame (GstBaseParse * parse,
752 GstBaseParseFrame * frame, gint * skipsize)
754 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
755 GstBuffer *buffer = frame->buffer;
757 gboolean result = TRUE;
758 GstFlowReturn ret = GST_FLOW_OK;
761 gst_buffer_map (buffer, &map, GST_MAP_READ);
765 if (G_UNLIKELY (map.size < 4)) {
770 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
771 if (memcmp (map.data, "fLaC", 4) == 0) {
772 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
776 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
777 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
778 /* Minimal size of a frame header */
779 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
780 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
785 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
790 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
791 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
793 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
798 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
802 flacparse->offset = GST_BUFFER_OFFSET (buffer);
803 flacparse->blocking_strategy = 0;
804 flacparse->sample_number = 0;
806 GST_DEBUG_OBJECT (flacparse, "Found sync code");
807 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
812 /* If we're at EOS and the frame was not valid, drop it! */
813 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
814 GST_WARNING_OBJECT (flacparse, "EOS");
820 } else if (next > map.size) {
821 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
823 gst_base_parse_set_min_frame_size (parse, next);
827 GST_ERROR_OBJECT (flacparse,
828 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
834 GstByteReader reader;
837 gst_byte_reader_init (&reader, map.data, map.size);
839 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
843 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
848 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
849 *skipsize = map.size - 3;
858 gst_buffer_unmap (buffer, &map);
863 if (result && framesize <= map.size) {
864 ret = gst_flac_parse_parse_frame (parse, frame, framesize);
865 if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
866 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
869 if (ret == GST_FLOW_OK)
870 ret = gst_base_parse_finish_frame (parse, frame, framesize);
877 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
882 gst_buffer_map (buffer, &map, GST_MAP_READ);
883 gst_bit_reader_init (&reader, map.data, map.size);
885 if (map.size != 4 + 34) {
886 GST_ERROR_OBJECT (flacparse,
887 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
891 /* Skip metadata block header */
892 if (!gst_bit_reader_skip (&reader, 32))
895 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
897 if (flacparse->min_blocksize < 16) {
898 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
899 flacparse->min_blocksize);
902 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
904 if (flacparse->max_blocksize < 16) {
905 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
906 flacparse->max_blocksize);
909 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
911 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
914 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
916 if (flacparse->samplerate == 0) {
917 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
921 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
923 flacparse->channels++;
924 if (flacparse->channels > 8) {
925 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
926 flacparse->channels);
930 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
934 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
936 if (flacparse->total_samples) {
937 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
938 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
941 gst_buffer_unmap (buffer, &map);
943 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
944 "\tmin/max blocksize: %u/%u,\n"
945 "\tmin/max framesize: %u/%u,\n"
946 "\tsamplerate: %u,\n"
948 "\tbits per sample: %u,\n"
949 "\ttotal samples: %" G_GUINT64_FORMAT,
950 flacparse->min_blocksize, flacparse->max_blocksize,
951 flacparse->min_framesize, flacparse->max_framesize,
952 flacparse->samplerate,
953 flacparse->channels, flacparse->bps, flacparse->total_samples);
958 GST_ERROR_OBJECT (flacparse, "Failed to read data");
960 gst_buffer_unmap (buffer, &map);
965 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
971 gst_buffer_map (buffer, &map, GST_MAP_READ);
974 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
975 gst_buffer_unmap (buffer, &map);
978 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
979 } else if (gst_tag_list_is_empty (tags)) {
980 gst_tag_list_unref (tags);
981 } else if (flacparse->tags == NULL) {
982 flacparse->tags = tags;
984 gst_tag_list_insert (flacparse->tags, tags, GST_TAG_MERGE_APPEND);
985 gst_tag_list_unref (tags);
992 gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
994 GstByteReader reader;
997 guint8 n_tracks, track_num, index;
1004 GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
1006 gst_buffer_map (buffer, &map, GST_MAP_READ);
1007 gst_byte_reader_init (&reader, map.data, map.size);
1009 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1011 /* skip 4 bytes METADATA_BLOCK_HEADER */
1012 /* http://flac.sourceforge.net/format.html#metadata_block_header */
1013 if (!gst_byte_reader_skip (&reader, 4))
1016 /* skip 395 bytes from METADATA_BLOCK_CUESHEET */
1017 /* http://flac.sourceforge.net/format.html#metadata_block_cuesheet */
1018 if (!gst_byte_reader_skip (&reader, 395))
1021 if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
1024 /* CUESHEET_TRACK */
1025 /* http://flac.sourceforge.net/format.html#cuesheet_track */
1026 for (i = 0; i < n_tracks; i++) {
1027 if (!gst_byte_reader_get_uint64_be (&reader, &offset))
1029 if (!gst_byte_reader_get_uint8 (&reader, &track_num))
1032 if (gst_byte_reader_get_remaining (&reader) < 12)
1034 memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
1035 /* \0-terminate the string */
1037 if (!gst_byte_reader_skip (&reader, 12))
1040 /* skip 14 bytes from CUESHEET_TRACK */
1041 if (!gst_byte_reader_skip (&reader, 14))
1043 if (!gst_byte_reader_get_uint8 (&reader, &index))
1045 /* add tracks in TOC */
1046 /* lead-out tack has number 170 or 255 */
1047 if (track_num != 170 && track_num != 255) {
1048 prev_entry = cur_entry;
1049 /* previous track stop time = current track start time */
1050 if (prev_entry != NULL) {
1051 gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
1053 gst_util_uint64_scale_round (offset, GST_SECOND,
1054 flacparse->samplerate);
1055 gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
1057 id = g_strdup_printf ("%08x", track_num);
1058 cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
1061 gst_util_uint64_scale_round (offset, GST_SECOND,
1062 flacparse->samplerate);
1063 gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
1064 /* add ISRC as tag in track */
1065 if (strlen (isrc) != 0) {
1066 tags = gst_tag_list_new_empty ();
1067 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
1068 gst_toc_entry_set_tags (cur_entry, tags);
1070 gst_toc_append_entry (toc, cur_entry);
1071 /* CUESHEET_TRACK_INDEX */
1072 /* http://flac.sourceforge.net/format.html#cuesheet_track_index */
1073 for (j = 0; j < index; j++) {
1074 if (!gst_byte_reader_skip (&reader, 12))
1078 /* set stop time in last track */
1080 gst_util_uint64_scale_round (offset, GST_SECOND,
1081 flacparse->samplerate);
1082 gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
1086 /* send data as TOC */
1087 if (!flacparse->toc)
1088 flacparse->toc = toc;
1090 gst_buffer_unmap (buffer, &map);
1094 GST_ERROR_OBJECT (flacparse, "Error reading data");
1095 gst_buffer_unmap (buffer, &map);
1100 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
1102 GstByteReader reader;
1104 guint32 img_len = 0, img_type = 0;
1105 guint32 img_mimetype_len = 0, img_description_len = 0;
1107 gst_buffer_map (buffer, &map, GST_MAP_READ);
1108 gst_byte_reader_init (&reader, map.data, map.size);
1110 if (!gst_byte_reader_skip (&reader, 4))
1113 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1116 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1118 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1121 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1123 if (!gst_byte_reader_skip (&reader, img_description_len))
1126 if (!gst_byte_reader_skip (&reader, 4 * 4))
1129 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1132 if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1135 if (!flacparse->tags)
1136 flacparse->tags = gst_tag_list_new_empty ();
1138 GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1141 gst_tag_list_add_id3_image (flacparse->tags,
1142 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1145 if (gst_tag_list_is_empty (flacparse->tags)) {
1146 gst_tag_list_unref (flacparse->tags);
1147 flacparse->tags = NULL;
1150 gst_buffer_unmap (buffer, &map);
1154 GST_ERROR_OBJECT (flacparse, "Error reading data");
1155 gst_buffer_unmap (buffer, &map);
1160 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1163 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1164 /* only store for now;
1165 * offset of the first frame is needed to get real info */
1166 flacparse->seektable = gst_buffer_ref (buffer);
1172 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1175 gint64 offset = 0, samples = 0;
1178 GST_DEBUG_OBJECT (flacparse,
1179 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1184 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1185 gst_byte_reader_init (&br, map.data, map.size);
1188 if (!gst_byte_reader_skip (&br, 4))
1192 while (gst_byte_reader_get_remaining (&br)) {
1193 if (!gst_byte_reader_get_int64_be (&br, &samples))
1195 if (!gst_byte_reader_get_int64_be (&br, &offset))
1197 if (!gst_byte_reader_skip (&br, 2))
1200 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1201 G_GINT64_FORMAT, samples, offset);
1204 if (G_LIKELY (offset > 0 && samples > 0)) {
1205 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1206 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1207 flacparse->samplerate), TRUE, FALSE);
1212 gst_buffer_unmap (flacparse->seektable, &map);
1214 gst_buffer_unref (flacparse->seektable);
1215 flacparse->seektable = NULL;
1219 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1221 GValue value = { 0, };
1223 g_value_init (&value, GST_TYPE_BUFFER);
1224 /* copy buffer to avoid problems with circular refcounts */
1225 buf = gst_buffer_copy (buf);
1226 /* again, for good measure */
1227 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1228 gst_value_set_buffer (&value, buf);
1229 gst_buffer_unref (buf);
1230 gst_value_array_append_value (array_val, &value);
1231 g_value_unset (&value);
1234 static GstFlowReturn
1235 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1237 GstBuffer *vorbiscomment = NULL;
1238 GstBuffer *streaminfo = NULL;
1239 GstBuffer *marker = NULL;
1240 GValue array = { 0, };
1243 GstFlowReturn res = GST_FLOW_OK;
1245 caps = gst_caps_new_simple ("audio/x-flac",
1246 "channels", G_TYPE_INT, flacparse->channels,
1247 "framed", G_TYPE_BOOLEAN, TRUE,
1248 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1250 if (!flacparse->headers)
1253 for (l = flacparse->headers; l; l = l->next) {
1254 GstBuffer *header = l->data;
1257 gst_buffer_map (header, &map, GST_MAP_READ);
1259 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1261 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1263 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1264 streaminfo = header;
1265 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1266 vorbiscomment = header;
1269 gst_buffer_unmap (header, &map);
1272 /* at least this one we can generate easily
1273 * to provide full headers downstream */
1274 if (vorbiscomment == NULL && streaminfo != NULL) {
1275 GST_DEBUG_OBJECT (flacparse,
1276 "missing vorbiscomment header; generating dummy");
1277 vorbiscomment = gst_flac_parse_generate_vorbiscomment (flacparse);
1278 flacparse->headers = g_list_insert (flacparse->headers, vorbiscomment,
1279 g_list_index (flacparse->headers, streaminfo) + 1);
1282 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1283 GST_WARNING_OBJECT (flacparse,
1284 "missing header %p %p %p, muxing into container "
1285 "formats may be broken", marker, streaminfo, vorbiscomment);
1289 g_value_init (&array, GST_TYPE_ARRAY);
1291 /* add marker including STREAMINFO header */
1295 GstMapInfo sinfomap, writemap;
1297 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1299 /* minus one for the marker that is merged with streaminfo here */
1300 num = g_list_length (flacparse->headers) - 1;
1302 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1303 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1305 writemap.data[0] = 0x7f;
1306 memcpy (writemap.data + 1, "FLAC", 4);
1307 writemap.data[5] = 0x01; /* mapping version major */
1308 writemap.data[6] = 0x00; /* mapping version minor */
1309 writemap.data[7] = (num & 0xFF00) >> 8;
1310 writemap.data[8] = (num & 0x00FF) >> 0;
1311 memcpy (writemap.data + 9, "fLaC", 4);
1312 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1313 _value_array_append_buffer (&array, buf);
1315 gst_buffer_unmap (streaminfo, &sinfomap);
1316 gst_buffer_unmap (buf, &writemap);
1317 gst_buffer_unref (buf);
1320 /* add VORBISCOMMENT header */
1321 _value_array_append_buffer (&array, vorbiscomment);
1323 /* add other headers, if there are any */
1324 for (l = flacparse->headers; l; l = l->next) {
1325 if (GST_BUFFER_CAST (l->data) != marker &&
1326 GST_BUFFER_CAST (l->data) != streaminfo &&
1327 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1328 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1332 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1333 "streamheader", &array);
1334 g_value_unset (&array);
1338 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1339 gst_caps_unref (caps);
1341 /* push header buffers; update caps, so when we push the first buffer the
1342 * negotiated caps will change to caps that include the streamheader field */
1343 while (flacparse->headers) {
1344 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1345 GstBaseParseFrame frame;
1347 flacparse->headers =
1348 g_list_delete_link (flacparse->headers, flacparse->headers);
1349 buf = gst_buffer_make_writable (buf);
1351 /* init, set and give away frame */
1352 gst_base_parse_frame_init (&frame);
1354 frame.overhead = -1;
1355 res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1356 gst_base_parse_frame_free (&frame);
1357 if (res != GST_FLOW_OK)
1360 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1361 g_list_free (flacparse->headers);
1362 flacparse->headers = NULL;
1367 /* empty vorbiscomment */
1369 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse)
1371 GstTagList *taglist = gst_tag_list_new_empty ();
1374 GstBuffer *vorbiscomment;
1377 header[0] = 0x84; /* is_last = 1; type = 4; */
1380 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1381 sizeof (header), NULL);
1382 gst_tag_list_unref (taglist);
1384 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1386 /* Get rid of framing bit */
1387 if (map.data[map.size - 1] == 1) {
1391 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1393 gst_buffer_unmap (vorbiscomment, &map);
1394 gst_buffer_unref (vorbiscomment);
1395 vorbiscomment = sub;
1396 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1399 size = map.size - 4;
1400 map.data[1] = ((size & 0xFF0000) >> 16);
1401 map.data[2] = ((size & 0x00FF00) >> 8);
1402 map.data[3] = (size & 0x0000FF);
1403 gst_buffer_unmap (vorbiscomment, &map);
1405 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1406 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1407 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1408 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1410 return vorbiscomment;
1414 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1416 GstBuffer *marker, *streaminfo;
1419 marker = gst_buffer_new_and_alloc (4);
1420 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1421 memcpy (map.data, "fLaC", 4);
1422 gst_buffer_unmap (marker, &map);
1423 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1424 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1425 GST_BUFFER_OFFSET (marker) = 0;
1426 GST_BUFFER_OFFSET_END (marker) = 0;
1427 flacparse->headers = g_list_append (flacparse->headers, marker);
1429 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1430 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1431 memset (map.data, 0, 4 + 34);
1433 /* metadata block header */
1434 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1435 map.data[1] = 0x00; /* length = 34; */
1441 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1442 map.data[5] = (flacparse->block_size) & 0xff;
1443 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1444 map.data[7] = (flacparse->block_size) & 0xff;
1446 map.data[8] = 0x00; /* min framesize = 0; */
1448 map.data[10] = 0x00;
1449 map.data[11] = 0x00; /* max framesize = 0; */
1450 map.data[12] = 0x00;
1451 map.data[13] = 0x00;
1453 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1454 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1455 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1457 map.data[16] |= (flacparse->channels - 1) << 1;
1459 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1460 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1465 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1466 GST_FORMAT_TIME, &duration)) {
1467 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1469 map.data[17] |= (duration >> 32) & 0xff;
1470 map.data[18] |= (duration >> 24) & 0xff;
1471 map.data[19] |= (duration >> 16) & 0xff;
1472 map.data[20] |= (duration >> 8) & 0xff;
1473 map.data[21] |= (duration >> 0) & 0xff;
1478 gst_buffer_unmap (streaminfo, &map);
1479 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1480 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1481 GST_BUFFER_OFFSET (streaminfo) = 0;
1482 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1483 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1485 flacparse->headers = g_list_append (flacparse->headers,
1486 gst_flac_parse_generate_vorbiscomment (flacparse));
1491 static GstFlowReturn
1492 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1495 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1496 GstBuffer *buffer = frame->buffer, *sbuffer;
1498 GstFlowReturn res = GST_FLOW_ERROR;
1500 gst_buffer_map (buffer, &map, GST_MAP_READ);
1502 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1503 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1504 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1505 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1506 GST_BUFFER_OFFSET (sbuffer) = 0;
1507 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1509 /* 32 bits metadata block */
1510 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1511 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1513 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1515 res = GST_BASE_PARSE_FLOW_DROPPED;
1516 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1517 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1518 guint type = (map.data[0] & 0x7F);
1519 gboolean hdr_ok = TRUE;
1522 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1523 res = GST_BASE_PARSE_FLOW_DROPPED;
1527 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1529 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1532 case 0: /* STREAMINFO */
1533 GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1534 hdr_ok = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1536 case 3: /* SEEKTABLE */
1537 GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1538 hdr_ok = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1540 case 4: /* VORBIS_COMMENT */
1541 GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1542 hdr_ok = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1544 case 5: /* CUESHEET */
1545 GST_INFO_OBJECT (flacparse, "CUESHEET header");
1546 hdr_ok = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1548 case 6: /* PICTURE */
1549 GST_INFO_OBJECT (flacparse, "PICTURE header");
1550 hdr_ok = gst_flac_parse_handle_picture (flacparse, sbuffer);
1552 case 1: /* PADDING */
1553 GST_INFO_OBJECT (flacparse, "PADDING header");
1555 case 2: /* APPLICATION */
1556 GST_INFO_OBJECT (flacparse, "APPLICATION header");
1558 default: /* RESERVED */
1559 GST_INFO_OBJECT (flacparse, "unhandled header of type %u", type);
1564 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1565 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1566 GST_BUFFER_OFFSET (sbuffer) = 0;
1567 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1569 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1571 GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1572 GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1574 gst_buffer_unref (sbuffer);
1576 /* error out unless we have a STREAMINFO header */
1577 if (flacparse->samplerate == 0 || flacparse->bps == 0)
1578 goto header_parsing_error;
1580 /* .. in which case just stop header parsing and try to find audio */
1585 res = gst_flac_parse_handle_headers (flacparse);
1587 /* Minimal size of a frame header */
1588 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1589 flacparse->min_framesize));
1590 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1592 if (res != GST_FLOW_OK)
1596 /* DROPPED because we pushed already or will push all headers manually */
1597 res = GST_BASE_PARSE_FLOW_DROPPED;
1599 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1600 FrameHeaderCheckReturn ret;
1602 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1604 gst_flac_parse_frame_header_is_valid (flacparse,
1605 map.data, map.size, TRUE, NULL, NULL);
1606 if (ret != FRAME_HEADER_VALID) {
1607 GST_ERROR_OBJECT (flacparse,
1608 "Baseclass didn't provide a complete frame");
1613 if (flacparse->block_size == 0) {
1614 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1618 if (flacparse->seektable)
1619 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1621 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1622 if (flacparse->blocking_strategy == 1) {
1623 GST_WARNING_OBJECT (flacparse,
1624 "Generating headers for variable blocksize streams not supported");
1626 res = gst_flac_parse_handle_headers (flacparse);
1628 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1630 if (!gst_flac_parse_generate_headers (flacparse))
1633 res = gst_flac_parse_handle_headers (flacparse);
1635 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1636 if (res != GST_FLOW_OK)
1640 /* also cater for oggmux metadata */
1641 if (flacparse->blocking_strategy == 0) {
1642 GST_BUFFER_TIMESTAMP (buffer) =
1643 gst_util_uint64_scale (flacparse->sample_number,
1644 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1645 GST_BUFFER_OFFSET_END (buffer) =
1646 flacparse->sample_number * flacparse->block_size +
1647 flacparse->block_size;
1649 GST_BUFFER_TIMESTAMP (buffer) =
1650 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1651 flacparse->samplerate);
1652 GST_BUFFER_OFFSET_END (buffer) =
1653 flacparse->sample_number + flacparse->block_size;
1655 GST_BUFFER_OFFSET (buffer) =
1656 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1657 flacparse->samplerate);
1658 GST_BUFFER_DURATION (buffer) =
1659 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1661 /* To simplify, we just assume that it's a fixed size header and ignore
1662 * subframe headers. The first could lead us to being off by 88 bits and
1663 * the second even less, so the total inaccuracy is negligible. */
1664 frame->overhead = 7;
1666 /* Minimal size of a frame header */
1667 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1668 flacparse->min_framesize));
1670 flacparse->offset = -1;
1671 flacparse->blocking_strategy = 0;
1672 flacparse->sample_number = 0;
1677 gst_buffer_unmap (buffer, &map);
1682 header_parsing_error:
1684 GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1685 ("Failed to parse headers"));
1690 static GstFlowReturn
1691 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1693 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1695 if (!flacparse->sent_codec_tag) {
1696 GstTagList *taglist;
1699 taglist = gst_tag_list_new_empty ();
1702 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1703 gst_pb_utils_add_codec_description_to_tag_list (taglist,
1704 GST_TAG_AUDIO_CODEC, caps);
1705 gst_caps_unref (caps);
1707 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1708 gst_event_new_tag (taglist));
1710 /* also signals the end of first-frame processing */
1711 flacparse->sent_codec_tag = TRUE;
1715 if (flacparse->tags) {
1716 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1717 gst_event_new_tag (flacparse->tags));
1718 flacparse->tags = NULL;
1721 if (flacparse->toc) {
1722 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1723 gst_event_new_toc (flacparse->toc, FALSE));
1726 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1732 gst_flac_parse_convert (GstBaseParse * parse,
1733 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1734 gint64 * dest_value)
1736 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1738 if (flacparse->samplerate > 0) {
1739 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1740 if (src_value != -1)
1742 gst_util_uint64_scale (src_value, GST_SECOND,
1743 flacparse->samplerate);
1747 } else if (src_format == GST_FORMAT_TIME &&
1748 dest_format == GST_FORMAT_DEFAULT) {
1749 if (src_value != -1)
1751 gst_util_uint64_scale (src_value, flacparse->samplerate,
1759 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1760 src_value, dest_format, dest_value);
1764 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1766 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1767 gboolean res = FALSE;
1769 switch (GST_EVENT_TYPE (event)) {
1770 case GST_EVENT_TOC_SELECT:
1772 GstTocEntry *entry = NULL;
1773 GstEvent *seek_event;
1778 /* FIXME: some locking would be good */
1780 toc = gst_toc_ref (flacparse->toc);
1783 gst_event_parse_toc_select (event, &uid);
1785 entry = gst_toc_find_entry (toc, uid);
1786 if (entry != NULL) {
1787 gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1789 /* FIXME: use segment rate here instead? */
1790 seek_event = gst_event_new_seek (1.0,
1792 GST_SEEK_FLAG_FLUSH,
1793 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1796 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1801 GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1804 gst_toc_unref (toc);
1806 GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1808 gst_event_unref (event);
1812 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1819 remove_fields (GstCaps * caps)
1823 n = gst_caps_get_size (caps);
1824 for (i = 0; i < n; i++) {
1825 GstStructure *s = gst_caps_get_structure (caps, i);
1827 gst_structure_remove_field (s, "framed");
1832 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1834 GstCaps *peercaps, *templ;
1837 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1839 GstCaps *fcopy = gst_caps_copy (filter);
1840 /* Remove the fields we convert */
1841 remove_fields (fcopy);
1842 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1843 gst_caps_unref (fcopy);
1845 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1848 /* Remove the framed field */
1849 peercaps = gst_caps_make_writable (peercaps);
1850 remove_fields (peercaps);
1852 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1853 gst_caps_unref (peercaps);
1854 gst_caps_unref (templ);
1860 GstCaps *intersection;
1863 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1864 gst_caps_unref (res);