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);
1139 gst_tag_list_add_id3_image (flacparse->tags,
1140 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1142 if (gst_tag_list_is_empty (flacparse->tags)) {
1143 gst_tag_list_unref (flacparse->tags);
1144 flacparse->tags = NULL;
1147 gst_buffer_unmap (buffer, &map);
1151 GST_ERROR_OBJECT (flacparse, "Error reading data");
1152 gst_buffer_unmap (buffer, &map);
1157 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1160 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1161 /* only store for now;
1162 * offset of the first frame is needed to get real info */
1163 flacparse->seektable = gst_buffer_ref (buffer);
1169 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1172 gint64 offset = 0, samples = 0;
1175 GST_DEBUG_OBJECT (flacparse,
1176 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1181 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1182 gst_byte_reader_init (&br, map.data, map.size);
1185 if (!gst_byte_reader_skip (&br, 4))
1189 while (gst_byte_reader_get_remaining (&br)) {
1190 if (!gst_byte_reader_get_int64_be (&br, &samples))
1192 if (!gst_byte_reader_get_int64_be (&br, &offset))
1194 if (!gst_byte_reader_skip (&br, 2))
1197 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1198 G_GINT64_FORMAT, samples, offset);
1201 if (G_LIKELY (offset > 0 && samples > 0)) {
1202 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1203 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1204 flacparse->samplerate), TRUE, FALSE);
1209 gst_buffer_unmap (flacparse->seektable, &map);
1211 gst_buffer_unref (flacparse->seektable);
1212 flacparse->seektable = NULL;
1216 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1218 GValue value = { 0, };
1220 g_value_init (&value, GST_TYPE_BUFFER);
1221 /* copy buffer to avoid problems with circular refcounts */
1222 buf = gst_buffer_copy (buf);
1223 /* again, for good measure */
1224 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1225 gst_value_set_buffer (&value, buf);
1226 gst_buffer_unref (buf);
1227 gst_value_array_append_value (array_val, &value);
1228 g_value_unset (&value);
1231 static GstFlowReturn
1232 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1234 GstBuffer *vorbiscomment = NULL;
1235 GstBuffer *streaminfo = NULL;
1236 GstBuffer *marker = NULL;
1237 GValue array = { 0, };
1240 GstFlowReturn res = GST_FLOW_OK;
1242 caps = gst_caps_new_simple ("audio/x-flac",
1243 "channels", G_TYPE_INT, flacparse->channels,
1244 "framed", G_TYPE_BOOLEAN, TRUE,
1245 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1247 if (!flacparse->headers)
1250 for (l = flacparse->headers; l; l = l->next) {
1251 GstBuffer *header = l->data;
1254 gst_buffer_map (header, &map, GST_MAP_READ);
1256 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1258 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1260 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1261 streaminfo = header;
1262 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1263 vorbiscomment = header;
1266 gst_buffer_unmap (header, &map);
1269 /* at least this one we can generate easily
1270 * to provide full headers downstream */
1271 if (vorbiscomment == NULL && streaminfo != NULL) {
1272 GST_DEBUG_OBJECT (flacparse,
1273 "missing vorbiscomment header; generating dummy");
1274 vorbiscomment = gst_flac_parse_generate_vorbiscomment (flacparse);
1275 flacparse->headers = g_list_insert (flacparse->headers, vorbiscomment,
1276 g_list_index (flacparse->headers, streaminfo) + 1);
1279 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1280 GST_WARNING_OBJECT (flacparse,
1281 "missing header %p %p %p, muxing into container "
1282 "formats may be broken", marker, streaminfo, vorbiscomment);
1286 g_value_init (&array, GST_TYPE_ARRAY);
1288 /* add marker including STREAMINFO header */
1292 GstMapInfo sinfomap, writemap;
1294 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1296 /* minus one for the marker that is merged with streaminfo here */
1297 num = g_list_length (flacparse->headers) - 1;
1299 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1300 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1302 writemap.data[0] = 0x7f;
1303 memcpy (writemap.data + 1, "FLAC", 4);
1304 writemap.data[5] = 0x01; /* mapping version major */
1305 writemap.data[6] = 0x00; /* mapping version minor */
1306 writemap.data[7] = (num & 0xFF00) >> 8;
1307 writemap.data[8] = (num & 0x00FF) >> 0;
1308 memcpy (writemap.data + 9, "fLaC", 4);
1309 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1310 _value_array_append_buffer (&array, buf);
1312 gst_buffer_unmap (streaminfo, &sinfomap);
1313 gst_buffer_unmap (buf, &writemap);
1314 gst_buffer_unref (buf);
1317 /* add VORBISCOMMENT header */
1318 _value_array_append_buffer (&array, vorbiscomment);
1320 /* add other headers, if there are any */
1321 for (l = flacparse->headers; l; l = l->next) {
1322 if (GST_BUFFER_CAST (l->data) != marker &&
1323 GST_BUFFER_CAST (l->data) != streaminfo &&
1324 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1325 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1329 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1330 "streamheader", &array);
1331 g_value_unset (&array);
1335 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1336 gst_caps_unref (caps);
1338 /* push header buffers; update caps, so when we push the first buffer the
1339 * negotiated caps will change to caps that include the streamheader field */
1340 while (flacparse->headers) {
1341 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1342 GstBaseParseFrame frame;
1344 flacparse->headers =
1345 g_list_delete_link (flacparse->headers, flacparse->headers);
1346 buf = gst_buffer_make_writable (buf);
1348 /* init, set and give away frame */
1349 gst_base_parse_frame_init (&frame);
1351 frame.overhead = -1;
1352 res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1353 gst_base_parse_frame_free (&frame);
1354 if (res != GST_FLOW_OK)
1357 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1358 g_list_free (flacparse->headers);
1359 flacparse->headers = NULL;
1364 /* empty vorbiscomment */
1366 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse)
1368 GstTagList *taglist = gst_tag_list_new_empty ();
1371 GstBuffer *vorbiscomment;
1374 header[0] = 0x84; /* is_last = 1; type = 4; */
1377 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1378 sizeof (header), NULL);
1379 gst_tag_list_unref (taglist);
1381 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1383 /* Get rid of framing bit */
1384 if (map.data[map.size - 1] == 1) {
1388 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1390 gst_buffer_unmap (vorbiscomment, &map);
1391 gst_buffer_unref (vorbiscomment);
1392 vorbiscomment = sub;
1393 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1396 size = map.size - 4;
1397 map.data[1] = ((size & 0xFF0000) >> 16);
1398 map.data[2] = ((size & 0x00FF00) >> 8);
1399 map.data[3] = (size & 0x0000FF);
1400 gst_buffer_unmap (vorbiscomment, &map);
1402 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1403 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1404 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1405 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1407 return vorbiscomment;
1411 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1413 GstBuffer *marker, *streaminfo;
1416 marker = gst_buffer_new_and_alloc (4);
1417 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1418 memcpy (map.data, "fLaC", 4);
1419 gst_buffer_unmap (marker, &map);
1420 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1421 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1422 GST_BUFFER_OFFSET (marker) = 0;
1423 GST_BUFFER_OFFSET_END (marker) = 0;
1424 flacparse->headers = g_list_append (flacparse->headers, marker);
1426 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1427 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1428 memset (map.data, 0, 4 + 34);
1430 /* metadata block header */
1431 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1432 map.data[1] = 0x00; /* length = 34; */
1438 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1439 map.data[5] = (flacparse->block_size) & 0xff;
1440 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1441 map.data[7] = (flacparse->block_size) & 0xff;
1443 map.data[8] = 0x00; /* min framesize = 0; */
1445 map.data[10] = 0x00;
1446 map.data[11] = 0x00; /* max framesize = 0; */
1447 map.data[12] = 0x00;
1448 map.data[13] = 0x00;
1450 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1451 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1452 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1454 map.data[16] |= (flacparse->channels - 1) << 1;
1456 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1457 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1462 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1463 GST_FORMAT_TIME, &duration)) {
1464 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1466 map.data[17] |= (duration >> 32) & 0xff;
1467 map.data[18] |= (duration >> 24) & 0xff;
1468 map.data[19] |= (duration >> 16) & 0xff;
1469 map.data[20] |= (duration >> 8) & 0xff;
1470 map.data[21] |= (duration >> 0) & 0xff;
1475 gst_buffer_unmap (streaminfo, &map);
1476 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1477 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1478 GST_BUFFER_OFFSET (streaminfo) = 0;
1479 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1480 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1482 flacparse->headers = g_list_append (flacparse->headers,
1483 gst_flac_parse_generate_vorbiscomment (flacparse));
1488 static GstFlowReturn
1489 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1492 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1493 GstBuffer *buffer = frame->buffer, *sbuffer;
1495 GstFlowReturn res = GST_FLOW_ERROR;
1497 gst_buffer_map (buffer, &map, GST_MAP_READ);
1499 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1500 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1501 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1502 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1503 GST_BUFFER_OFFSET (sbuffer) = 0;
1504 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1506 /* 32 bits metadata block */
1507 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1508 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1510 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1512 res = GST_BASE_PARSE_FLOW_DROPPED;
1513 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1514 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1515 guint type = (map.data[0] & 0x7F);
1516 gboolean hdr_ok = TRUE;
1519 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1520 res = GST_BASE_PARSE_FLOW_DROPPED;
1524 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1526 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1529 case 0: /* STREAMINFO */
1530 GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1531 hdr_ok = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1533 case 3: /* SEEKTABLE */
1534 GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1535 hdr_ok = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1537 case 4: /* VORBIS_COMMENT */
1538 GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1539 hdr_ok = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1541 case 5: /* CUESHEET */
1542 GST_INFO_OBJECT (flacparse, "CUESHEET header");
1543 hdr_ok = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1545 case 6: /* PICTURE */
1546 GST_INFO_OBJECT (flacparse, "PICTURE header");
1547 hdr_ok = gst_flac_parse_handle_picture (flacparse, sbuffer);
1549 case 1: /* PADDING */
1550 GST_INFO_OBJECT (flacparse, "PADDING header");
1552 case 2: /* APPLICATION */
1553 GST_INFO_OBJECT (flacparse, "APPLICATION header");
1555 default: /* RESERVED */
1556 GST_INFO_OBJECT (flacparse, "unhandled header of type %u", type);
1561 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1562 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1563 GST_BUFFER_OFFSET (sbuffer) = 0;
1564 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1566 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1568 GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1569 GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1571 gst_buffer_unref (sbuffer);
1573 /* error out unless we have a STREAMINFO header */
1574 if (flacparse->samplerate == 0 || flacparse->bps == 0)
1575 goto header_parsing_error;
1577 /* .. in which case just stop header parsing and try to find audio */
1582 res = gst_flac_parse_handle_headers (flacparse);
1584 /* Minimal size of a frame header */
1585 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1586 flacparse->min_framesize));
1587 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1589 if (res != GST_FLOW_OK)
1593 /* DROPPED because we pushed already or will push all headers manually */
1594 res = GST_BASE_PARSE_FLOW_DROPPED;
1596 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1597 FrameHeaderCheckReturn ret;
1599 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1601 gst_flac_parse_frame_header_is_valid (flacparse,
1602 map.data, map.size, TRUE, NULL, NULL);
1603 if (ret != FRAME_HEADER_VALID) {
1604 GST_ERROR_OBJECT (flacparse,
1605 "Baseclass didn't provide a complete frame");
1610 if (flacparse->block_size == 0) {
1611 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1615 if (flacparse->seektable)
1616 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1618 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1619 if (flacparse->blocking_strategy == 1) {
1620 GST_WARNING_OBJECT (flacparse,
1621 "Generating headers for variable blocksize streams not supported");
1623 res = gst_flac_parse_handle_headers (flacparse);
1625 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1627 if (!gst_flac_parse_generate_headers (flacparse))
1630 res = gst_flac_parse_handle_headers (flacparse);
1632 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1633 if (res != GST_FLOW_OK)
1637 /* also cater for oggmux metadata */
1638 if (flacparse->blocking_strategy == 0) {
1639 GST_BUFFER_TIMESTAMP (buffer) =
1640 gst_util_uint64_scale (flacparse->sample_number,
1641 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1642 GST_BUFFER_OFFSET_END (buffer) =
1643 flacparse->sample_number * flacparse->block_size +
1644 flacparse->block_size;
1646 GST_BUFFER_TIMESTAMP (buffer) =
1647 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1648 flacparse->samplerate);
1649 GST_BUFFER_OFFSET_END (buffer) =
1650 flacparse->sample_number + flacparse->block_size;
1652 GST_BUFFER_OFFSET (buffer) =
1653 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1654 flacparse->samplerate);
1655 GST_BUFFER_DURATION (buffer) =
1656 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1658 /* To simplify, we just assume that it's a fixed size header and ignore
1659 * subframe headers. The first could lead us to being off by 88 bits and
1660 * the second even less, so the total inaccuracy is negligible. */
1661 frame->overhead = 7;
1663 /* Minimal size of a frame header */
1664 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1665 flacparse->min_framesize));
1667 flacparse->offset = -1;
1668 flacparse->blocking_strategy = 0;
1669 flacparse->sample_number = 0;
1674 gst_buffer_unmap (buffer, &map);
1679 header_parsing_error:
1681 GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1682 ("Failed to parse headers"));
1687 static GstFlowReturn
1688 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1690 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1692 if (!flacparse->sent_codec_tag) {
1693 GstTagList *taglist;
1696 taglist = gst_tag_list_new_empty ();
1699 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1700 gst_pb_utils_add_codec_description_to_tag_list (taglist,
1701 GST_TAG_AUDIO_CODEC, caps);
1702 gst_caps_unref (caps);
1704 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1705 gst_event_new_tag (taglist));
1707 /* also signals the end of first-frame processing */
1708 flacparse->sent_codec_tag = TRUE;
1712 if (flacparse->tags) {
1713 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1714 gst_event_new_tag (flacparse->tags));
1715 flacparse->tags = NULL;
1718 if (flacparse->toc) {
1719 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1720 gst_event_new_toc (flacparse->toc, FALSE));
1723 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1729 gst_flac_parse_convert (GstBaseParse * parse,
1730 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1731 gint64 * dest_value)
1733 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1735 if (flacparse->samplerate > 0) {
1736 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1737 if (src_value != -1)
1739 gst_util_uint64_scale (src_value, GST_SECOND,
1740 flacparse->samplerate);
1744 } else if (src_format == GST_FORMAT_TIME &&
1745 dest_format == GST_FORMAT_DEFAULT) {
1746 if (src_value != -1)
1748 gst_util_uint64_scale (src_value, flacparse->samplerate,
1756 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1757 src_value, dest_format, dest_value);
1761 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1763 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1764 gboolean res = FALSE;
1766 switch (GST_EVENT_TYPE (event)) {
1767 case GST_EVENT_TOC_SELECT:
1769 GstTocEntry *entry = NULL;
1770 GstEvent *seek_event;
1775 /* FIXME: some locking would be good */
1777 toc = gst_toc_ref (flacparse->toc);
1780 gst_event_parse_toc_select (event, &uid);
1782 entry = gst_toc_find_entry (toc, uid);
1783 if (entry != NULL) {
1784 gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1786 /* FIXME: use segment rate here instead? */
1787 seek_event = gst_event_new_seek (1.0,
1789 GST_SEEK_FLAG_FLUSH,
1790 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1793 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1798 GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1801 gst_toc_unref (toc);
1803 GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1805 gst_event_unref (event);
1809 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1816 remove_fields (GstCaps * caps)
1820 n = gst_caps_get_size (caps);
1821 for (i = 0; i < n; i++) {
1822 GstStructure *s = gst_caps_get_structure (caps, i);
1824 gst_structure_remove_field (s, "framed");
1829 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1831 GstCaps *peercaps, *templ;
1834 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1836 GstCaps *fcopy = gst_caps_copy (filter);
1837 /* Remove the fields we convert */
1838 remove_fields (fcopy);
1839 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1840 gst_caps_unref (fcopy);
1842 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1845 /* Remove the framed field */
1846 peercaps = gst_caps_make_writable (peercaps);
1847 remove_fields (peercaps);
1849 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1850 gst_caps_unref (peercaps);
1851 gst_caps_unref (templ);
1857 GstCaps *intersection;
1860 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1861 gst_caps_unref (res);