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 inline void gst_flac_parse_reset_buffer_time_and_offset (GstBuffer *
191 static void gst_flac_parse_reset (GstFlacParse * parser);
192 static gboolean gst_flac_parse_handle_block_type (GstFlacParse * flacparse,
193 guint type, GstBuffer * sbuffer);
194 static void gst_flac_parse_finalize (GObject * object);
195 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
196 const GValue * value, GParamSpec * pspec);
197 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
198 GValue * value, GParamSpec * pspec);
200 static gboolean gst_flac_parse_start (GstBaseParse * parse);
201 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
202 static GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
203 GstBaseParseFrame * frame, gint * skipsize);
204 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
205 GstBaseParseFrame * frame, gint size);
206 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
207 GstBaseParseFrame * frame);
208 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
209 GstFormat src_format, gint64 src_value, GstFormat dest_format,
210 gint64 * dest_value);
211 static gboolean gst_flac_parse_src_event (GstBaseParse * parse,
213 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
216 #define gst_flac_parse_parent_class parent_class
217 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
220 gst_flac_parse_class_init (GstFlacParseClass * klass)
222 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
223 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
224 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
226 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
227 "Flac parser element");
229 gobject_class->finalize = gst_flac_parse_finalize;
230 gobject_class->set_property = gst_flac_parse_set_property;
231 gobject_class->get_property = gst_flac_parse_get_property;
233 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
234 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
235 "Check the overall checksums of every frame",
236 DEFAULT_CHECK_FRAME_CHECKSUMS,
237 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
239 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
240 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
241 baseparse_class->handle_frame =
242 GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
243 baseparse_class->pre_push_frame =
244 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
245 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
246 baseparse_class->src_event = GST_DEBUG_FUNCPTR (gst_flac_parse_src_event);
247 baseparse_class->get_sink_caps =
248 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
250 gst_element_class_add_static_pad_template (element_class, &src_factory);
251 gst_element_class_add_static_pad_template (element_class, &sink_factory);
253 gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
254 "Codec/Parser/Audio",
255 "Parses audio with the FLAC lossless audio codec",
256 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
260 gst_flac_parse_init (GstFlacParse * flacparse)
262 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
263 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (flacparse));
264 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (flacparse));
268 gst_flac_parse_set_property (GObject * object, guint prop_id,
269 const GValue * value, GParamSpec * pspec)
271 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
274 case PROP_CHECK_FRAME_CHECKSUMS:
275 flacparse->check_frame_checksums = g_value_get_boolean (value);
278 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
284 gst_flac_parse_get_property (GObject * object, guint prop_id,
285 GValue * value, GParamSpec * pspec)
287 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
290 case PROP_CHECK_FRAME_CHECKSUMS:
291 g_value_set_boolean (value, flacparse->check_frame_checksums);
294 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
300 gst_flac_parse_reset (GstFlacParse * parser)
303 gst_tag_list_unref (parser->tags);
307 gst_toc_unref (parser->toc);
310 if (parser->seektable) {
311 gst_buffer_unref (parser->seektable);
312 parser->seektable = NULL;
315 g_list_foreach (parser->headers, (GFunc) gst_mini_object_unref, NULL);
316 g_list_free (parser->headers);
317 parser->headers = NULL;
321 gst_flac_parse_finalize (GObject * object)
323 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
325 gst_flac_parse_reset (flacparse);
326 G_OBJECT_CLASS (parent_class)->finalize (object);
330 gst_flac_parse_start (GstBaseParse * parse)
332 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
334 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
335 flacparse->min_blocksize = 0;
336 flacparse->max_blocksize = 0;
337 flacparse->min_framesize = 0;
338 flacparse->max_framesize = 0;
340 flacparse->upstream_length = -1;
342 flacparse->samplerate = 0;
343 flacparse->channels = 0;
345 flacparse->total_samples = 0;
347 flacparse->offset = GST_CLOCK_TIME_NONE;
348 flacparse->blocking_strategy = 0;
349 flacparse->block_size = 0;
350 flacparse->sample_number = 0;
351 flacparse->strategy_checked = FALSE;
353 flacparse->sent_codec_tag = FALSE;
356 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
358 /* inform baseclass we can come up with ts, based on counters in packets */
359 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
360 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
366 gst_flac_parse_stop (GstBaseParse * parse)
368 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
370 gst_flac_parse_reset (flacparse);
374 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
376 static const guint16 blocksize_table[16] = {
377 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
378 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
382 static const guint32 sample_rate_table[16] = {
384 88200, 176400, 192000,
385 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
392 FRAME_HEADER_INVALID,
393 FRAME_HEADER_MORE_DATA
394 } FrameHeaderCheckReturn;
396 static FrameHeaderCheckReturn
397 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
398 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
401 GstBitReader reader = GST_BIT_READER_INIT (data, size);
402 guint8 blocking_strategy;
404 guint32 samplerate = 0;
405 guint64 sample_number;
406 guint8 channels, bps;
408 guint8 actual_crc, expected_crc = 0;
410 /* Skip 14 bit sync code */
411 gst_bit_reader_skip_unchecked (&reader, 14);
414 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
417 /* 0 == fixed block size, 1 == variable block size */
418 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
419 if (flacparse->force_variable_block_size)
420 blocking_strategy = 1;
422 /* block size index, calculation of the real blocksize below */
423 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
427 /* sample rate index, calculation of the real samplerate below */
428 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
429 if (samplerate == 0x0f)
432 /* channel assignment */
433 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
436 } else if (channels <= 10) {
438 } else if (channels > 10) {
441 if (flacparse->channels && flacparse->channels != channels)
444 /* bits per sample */
445 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
446 if (bps == 0x03 || bps == 0x07) {
448 } else if (bps == 0 && flacparse->bps == 0) {
449 goto need_streaminfo;
451 bps = sample_size_table[bps];
452 if (flacparse->bps && bps != flacparse->bps)
455 /* reserved, must be 0 */
456 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
459 /* read "utf8" encoded sample/frame number */
463 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
465 /* This is slightly faster than a loop */
469 } else if ((len & 0xc0) && !(len & 0x20)) {
470 sample_number = len & 0x1f;
472 } else if ((len & 0xe0) && !(len & 0x10)) {
473 sample_number = len & 0x0f;
475 } else if ((len & 0xf0) && !(len & 0x08)) {
476 sample_number = len & 0x07;
478 } else if ((len & 0xf8) && !(len & 0x04)) {
479 sample_number = len & 0x03;
481 } else if ((len & 0xfc) && !(len & 0x02)) {
482 sample_number = len & 0x01;
484 } else if ((len & 0xfe) && !(len & 0x01)) {
485 sample_number = len & 0x0;
491 if ((blocking_strategy == 0 && len > 5) ||
492 (blocking_strategy == 1 && len > 6))
496 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
499 if ((tmp & 0xc0) != 0x80)
503 sample_number |= (tmp & 0x3f);
508 /* calculate real blocksize from the blocksize index */
509 if (block_size == 6) {
510 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
513 } else if (block_size == 7) {
514 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
518 block_size = blocksize_table[block_size];
521 /* calculate the real samplerate from the samplerate index */
522 if (samplerate == 0 && flacparse->samplerate == 0) {
523 goto need_streaminfo;
524 } else if (samplerate < 12) {
525 samplerate = sample_rate_table[samplerate];
526 } else if (samplerate == 12) {
527 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
530 } else if (samplerate == 13) {
531 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
533 } else if (samplerate == 14) {
534 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
539 if (flacparse->samplerate && flacparse->samplerate != samplerate)
542 /* check crc-8 for the header */
543 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
547 gst_flac_calculate_crc8 (data,
548 (gst_bit_reader_get_pos (&reader) / 8) - 1);
549 if (actual_crc != expected_crc) {
550 GST_DEBUG_OBJECT (flacparse,
551 "Checksum mismatch. Header CRC was '%d' but frame has '%d'",
552 expected_crc, actual_crc);
556 /* Sanity check sample number against blocking strategy, as it seems
557 some files claim fixed block size but supply sample numbers,
558 rather than block numbers. */
559 if (blocking_strategy == 0 && flacparse->block_size != 0) {
560 if (!flacparse->strategy_checked) {
561 if (block_size == sample_number) {
562 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
563 "but seems to be lying: assuming variable block size");
564 flacparse->force_variable_block_size = TRUE;
565 blocking_strategy = 1;
567 flacparse->strategy_checked = TRUE;
571 /* documentation says:
572 * The "blocking strategy" bit must be the same throughout the entire stream. */
573 if (flacparse->blocking_strategy != blocking_strategy) {
574 if (flacparse->block_size != 0) {
575 GST_WARNING_OBJECT (flacparse, "blocking strategy is not constant");
582 The FLAC format documentation says:
583 The "blocking strategy" bit determines how to calculate the sample number
584 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
585 frame header encodes the frame number as above, and the frame's starting
586 sample number will be the frame number times the blocksize. If it is 1
587 (variable-blocksize), the frame header encodes the frame's starting
588 sample number itself. (In the case of a fixed-blocksize stream, only the
589 last block may be shorter than the stream blocksize; its starting sample
590 number will be calculated as the frame number times the previous frame's
591 blocksize, or zero if it is the first frame).
593 Therefore, when in fixed block size mode, we only update the block size
594 the first time, then reuse that block size for subsequent calls.
595 This will also fix a timestamp problem with the last block's timestamp
596 being miscalculated by scaling the block number by a "wrong" block size.
598 if (blocking_strategy == 0) {
599 if (flacparse->block_size != 0) {
600 /* after first block */
601 if (flacparse->block_size != block_size) {
602 /* TODO: can we know we're on the last frame, to avoid warning ? */
603 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
604 block_size = flacparse->block_size;
612 flacparse->block_size = block_size;
613 if (!flacparse->samplerate)
614 flacparse->samplerate = samplerate;
616 flacparse->bps = bps;
617 if (!flacparse->blocking_strategy)
618 flacparse->blocking_strategy = blocking_strategy;
619 if (!flacparse->channels)
620 flacparse->channels = channels;
621 if (!flacparse->sample_number)
622 flacparse->sample_number = sample_number;
624 GST_DEBUG_OBJECT (flacparse,
625 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
626 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
627 flacparse->block_size, flacparse->sample_number);
631 *block_size_ret = block_size;
633 return FRAME_HEADER_VALID;
636 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO metadata. Bits per sample "
637 "or sample rate not in frame header");
639 return FRAME_HEADER_INVALID;
642 return FRAME_HEADER_MORE_DATA;
646 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
647 const guint8 * data, gsize size, guint * ret)
649 guint max, remaining;
650 guint i, search_start, search_end;
651 FrameHeaderCheckReturn header_ret;
653 gboolean suspect_start = FALSE, suspect_end = FALSE;
655 if (size < flacparse->min_framesize)
659 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
660 &block_size, &suspect_start);
661 if (header_ret == FRAME_HEADER_INVALID) {
665 if (header_ret == FRAME_HEADER_MORE_DATA)
668 /* mind unknown framesize */
669 search_start = MAX (2, flacparse->min_framesize);
670 if (flacparse->max_framesize)
671 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
678 for (i = search_start; i < search_end; i++, remaining--) {
680 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) != 0xfff8)
683 GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
686 gst_flac_parse_frame_header_is_valid (flacparse, data + i,
687 remaining, FALSE, NULL, &suspect_end);
688 if (header_ret == FRAME_HEADER_VALID) {
689 if (flacparse->check_frame_checksums || suspect_start || suspect_end) {
690 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
691 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
693 GST_LOG_OBJECT (flacparse,
694 "Found possible frame (%d, %d). Checking for CRC match",
695 suspect_start, suspect_end);
696 if (actual_crc != expected_crc) {
697 GST_DEBUG_OBJECT (flacparse,
698 "Checksum mismatch. Header CRC was '%d' but frame has '%d'",
699 expected_crc, actual_crc);
704 flacparse->block_size = block_size;
706 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
711 /* For the last frame output everything to the end */
712 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
713 if (flacparse->check_frame_checksums) {
714 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
715 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
717 if (actual_crc == expected_crc) {
719 flacparse->block_size = block_size;
724 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 (size + 4096, max);
747 gst_flac_parse_handle_frame (GstBaseParse * parse,
748 GstBaseParseFrame * frame, gint * skipsize)
750 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
751 GstBuffer *buffer = frame->buffer;
753 gboolean result = TRUE;
754 GstFlowReturn ret = GST_FLOW_OK;
757 gst_buffer_map (buffer, &map, GST_MAP_READ);
761 if (G_UNLIKELY (map.size < 4)) {
766 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
767 if (memcmp (map.data, "fLaC", 4) == 0) {
768 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
772 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
773 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
774 /* Minimal size of a frame header */
775 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
776 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
781 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
786 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
787 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
789 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
794 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
798 flacparse->offset = GST_BUFFER_OFFSET (buffer);
799 flacparse->blocking_strategy = 0;
800 flacparse->sample_number = 0;
802 GST_DEBUG_OBJECT (flacparse, "Found sync code");
803 ret = gst_flac_parse_frame_is_valid (flacparse, map.data, map.size, &next);
808 /* If we're at EOS and the frame was not valid, drop it! */
809 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
810 GST_WARNING_OBJECT (flacparse, "EOS");
816 } else if (next > map.size) {
817 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
819 gst_base_parse_set_min_frame_size (parse, next);
823 GST_ERROR_OBJECT (flacparse,
824 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
829 GstByteReader reader;
832 gst_byte_reader_init (&reader, map.data, map.size);
834 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
838 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
844 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
845 *skipsize = map.size - 3;
853 gst_buffer_unmap (buffer, &map);
858 if (result && framesize <= map.size) {
859 ret = gst_flac_parse_parse_frame (parse, frame, framesize);
860 if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
861 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
864 if (ret == GST_FLOW_OK)
865 ret = gst_base_parse_finish_frame (parse, frame, framesize);
872 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
877 gst_buffer_map (buffer, &map, GST_MAP_READ);
878 gst_bit_reader_init (&reader, map.data, map.size);
880 if (map.size != 4 + 34) {
881 GST_ERROR_OBJECT (flacparse,
882 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
886 /* Skip metadata block header */
887 if (!gst_bit_reader_skip (&reader, 32))
890 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
892 if (flacparse->min_blocksize < 16) {
893 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
894 flacparse->min_blocksize);
897 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
899 if (flacparse->max_blocksize < 16) {
900 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
901 flacparse->max_blocksize);
904 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
906 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
909 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
911 if (flacparse->samplerate == 0) {
912 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
916 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
918 flacparse->channels++;
919 if (flacparse->channels > 8) {
920 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
921 flacparse->channels);
925 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
929 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
931 if (flacparse->total_samples) {
932 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
933 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
936 gst_buffer_unmap (buffer, &map);
938 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
939 "\tmin/max blocksize: %u/%u,\n"
940 "\tmin/max framesize: %u/%u,\n"
941 "\tsamplerate: %u,\n"
943 "\tbits per sample: %u,\n"
944 "\ttotal samples: %" G_GUINT64_FORMAT,
945 flacparse->min_blocksize, flacparse->max_blocksize,
946 flacparse->min_framesize, flacparse->max_framesize,
947 flacparse->samplerate,
948 flacparse->channels, flacparse->bps, flacparse->total_samples);
953 GST_ERROR_OBJECT (flacparse, "Failed to read data");
955 gst_buffer_unmap (buffer, &map);
960 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
966 gst_buffer_map (buffer, &map, GST_MAP_READ);
969 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
970 gst_buffer_unmap (buffer, &map);
973 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
974 } else if (gst_tag_list_is_empty (tags)) {
975 gst_tag_list_unref (tags);
976 } else if (flacparse->tags == NULL) {
977 flacparse->tags = tags;
979 gst_tag_list_insert (flacparse->tags, tags, GST_TAG_MERGE_APPEND);
980 gst_tag_list_unref (tags);
987 gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
989 GstByteReader reader;
992 guint8 n_tracks, track_num, index;
999 GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
1001 gst_buffer_map (buffer, &map, GST_MAP_READ);
1002 gst_byte_reader_init (&reader, map.data, map.size);
1004 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1006 /* skip 4 bytes METADATA_BLOCK_HEADER */
1007 /* https://xiph.org/flac/format.html#metadata_block_header */
1008 if (!gst_byte_reader_skip (&reader, 4))
1011 /* skip 395 bytes from METADATA_BLOCK_CUESHEET */
1012 /* https://xiph.org/flac/format.html#metadata_block_cuesheet */
1013 if (!gst_byte_reader_skip (&reader, 395))
1016 if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
1019 /* CUESHEET_TRACK */
1020 /* https://xiph.org/flac/format.html#cuesheet_track */
1021 for (i = 0; i < n_tracks; i++) {
1022 if (!gst_byte_reader_get_uint64_be (&reader, &offset))
1024 if (!gst_byte_reader_get_uint8 (&reader, &track_num))
1027 if (gst_byte_reader_get_remaining (&reader) < 12)
1029 memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
1030 /* \0-terminate the string */
1032 if (!gst_byte_reader_skip (&reader, 12))
1035 /* skip 14 bytes from CUESHEET_TRACK */
1036 if (!gst_byte_reader_skip (&reader, 14))
1038 if (!gst_byte_reader_get_uint8 (&reader, &index))
1040 /* add tracks in TOC */
1041 /* lead-out tack has number 170 or 255 */
1042 if (track_num != 170 && track_num != 255) {
1043 prev_entry = cur_entry;
1044 /* previous track stop time = current track start time */
1045 if (prev_entry != NULL) {
1046 gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
1048 gst_util_uint64_scale_round (offset, GST_SECOND,
1049 flacparse->samplerate);
1050 gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
1052 id = g_strdup_printf ("%08x", track_num);
1053 cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
1056 gst_util_uint64_scale_round (offset, GST_SECOND,
1057 flacparse->samplerate);
1058 gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
1059 /* add ISRC as tag in track */
1060 if (strlen (isrc) != 0) {
1061 tags = gst_tag_list_new_empty ();
1062 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
1063 gst_toc_entry_set_tags (cur_entry, tags);
1065 gst_toc_append_entry (toc, cur_entry);
1066 /* CUESHEET_TRACK_INDEX */
1067 /* https://xiph.org/flac/format.html#cuesheet_track_index */
1068 for (j = 0; j < index; j++) {
1069 if (!gst_byte_reader_skip (&reader, 12))
1073 /* set stop time in last track */
1075 gst_util_uint64_scale_round (offset, GST_SECOND,
1076 flacparse->samplerate);
1077 gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
1081 /* send data as TOC */
1082 if (!flacparse->toc)
1083 flacparse->toc = toc;
1085 gst_buffer_unmap (buffer, &map);
1089 GST_ERROR_OBJECT (flacparse, "Error reading data");
1090 gst_buffer_unmap (buffer, &map);
1095 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
1097 GstByteReader reader;
1099 guint32 img_len = 0, img_type = 0;
1100 guint32 img_mimetype_len = 0, img_description_len = 0;
1102 gst_buffer_map (buffer, &map, GST_MAP_READ);
1103 gst_byte_reader_init (&reader, map.data, map.size);
1105 if (!gst_byte_reader_skip (&reader, 4))
1108 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1111 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1113 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1116 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1118 if (!gst_byte_reader_skip (&reader, img_description_len))
1121 if (!gst_byte_reader_skip (&reader, 4 * 4))
1124 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1127 if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1130 GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1133 if (flacparse->tags == NULL)
1134 flacparse->tags = gst_tag_list_new_empty ();
1136 gst_tag_list_add_id3_image (flacparse->tags,
1137 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1140 gst_buffer_unmap (buffer, &map);
1144 GST_ERROR_OBJECT (flacparse, "Error reading data");
1145 gst_buffer_unmap (buffer, &map);
1150 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1153 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1154 /* only store for now;
1155 * offset of the first frame is needed to get real info */
1156 if (flacparse->seektable)
1157 gst_buffer_unref (flacparse->seektable);
1158 flacparse->seektable = gst_buffer_ref (buffer);
1164 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1167 gint64 offset = 0, samples = 0;
1170 GST_DEBUG_OBJECT (flacparse,
1171 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1176 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1177 gst_byte_reader_init (&br, map.data, map.size);
1180 if (!gst_byte_reader_skip (&br, 4))
1184 while (gst_byte_reader_get_remaining (&br)) {
1185 if (!gst_byte_reader_get_int64_be (&br, &samples))
1187 if (!gst_byte_reader_get_int64_be (&br, &offset))
1189 if (!gst_byte_reader_skip (&br, 2))
1192 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1193 G_GINT64_FORMAT, samples, offset);
1196 if (G_LIKELY (offset > 0 && samples > 0)) {
1197 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1198 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1199 flacparse->samplerate), TRUE, FALSE);
1204 gst_buffer_unmap (flacparse->seektable, &map);
1206 gst_buffer_unref (flacparse->seektable);
1207 flacparse->seektable = NULL;
1211 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1213 GValue value = { 0, };
1215 g_value_init (&value, GST_TYPE_BUFFER);
1216 /* copy buffer to avoid problems with circular refcounts */
1217 buf = gst_buffer_copy (buf);
1218 /* again, for good measure */
1219 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1220 gst_value_set_buffer (&value, buf);
1221 gst_buffer_unref (buf);
1222 gst_value_array_append_value (array_val, &value);
1223 g_value_unset (&value);
1226 static GstFlowReturn
1227 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1229 GstBuffer *vorbiscomment = NULL;
1230 GstBuffer *streaminfo = NULL;
1231 GstBuffer *marker = NULL;
1232 GValue array = { 0, };
1235 GstFlowReturn res = GST_FLOW_OK;
1237 caps = gst_caps_new_simple ("audio/x-flac",
1238 "channels", G_TYPE_INT, flacparse->channels,
1239 "framed", G_TYPE_BOOLEAN, TRUE,
1240 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1242 if (!flacparse->headers)
1245 for (l = flacparse->headers; l; l = l->next) {
1246 GstBuffer *header = l->data;
1249 gst_buffer_map (header, &map, GST_MAP_READ);
1251 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1253 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1255 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1256 streaminfo = header;
1257 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1258 vorbiscomment = header;
1261 gst_buffer_unmap (header, &map);
1264 /* at least this one we can generate easily
1265 * to provide full headers downstream */
1266 if (vorbiscomment == NULL && streaminfo != NULL) {
1267 GST_DEBUG_OBJECT (flacparse,
1268 "missing vorbiscomment header; generating dummy");
1269 vorbiscomment = gst_flac_parse_generate_vorbiscomment (flacparse);
1270 flacparse->headers = g_list_insert (flacparse->headers, vorbiscomment,
1271 g_list_index (flacparse->headers, streaminfo) + 1);
1274 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1275 GST_WARNING_OBJECT (flacparse,
1276 "missing header %p %p %p, muxing into container "
1277 "formats may be broken", marker, streaminfo, vorbiscomment);
1281 g_value_init (&array, GST_TYPE_ARRAY);
1283 /* add marker including STREAMINFO header */
1287 GstMapInfo sinfomap, writemap;
1289 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1291 /* minus one for the marker that is merged with streaminfo here */
1292 num = g_list_length (flacparse->headers) - 1;
1294 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1295 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1297 writemap.data[0] = 0x7f;
1298 memcpy (writemap.data + 1, "FLAC", 4);
1299 writemap.data[5] = 0x01; /* mapping version major */
1300 writemap.data[6] = 0x00; /* mapping version minor */
1301 writemap.data[7] = (num & 0xFF00) >> 8;
1302 writemap.data[8] = (num & 0x00FF) >> 0;
1303 memcpy (writemap.data + 9, "fLaC", 4);
1304 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1305 _value_array_append_buffer (&array, buf);
1307 gst_buffer_unmap (streaminfo, &sinfomap);
1308 gst_buffer_unmap (buf, &writemap);
1309 gst_buffer_unref (buf);
1312 /* add VORBISCOMMENT header */
1313 _value_array_append_buffer (&array, vorbiscomment);
1315 /* add other headers, if there are any */
1316 for (l = flacparse->headers; l; l = l->next) {
1317 if (GST_BUFFER_CAST (l->data) != marker &&
1318 GST_BUFFER_CAST (l->data) != streaminfo &&
1319 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1320 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1324 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1325 "streamheader", &array);
1326 g_value_unset (&array);
1330 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1331 gst_caps_unref (caps);
1333 /* push header buffers; update caps, so when we push the first buffer the
1334 * negotiated caps will change to caps that include the streamheader field */
1335 while (flacparse->headers) {
1336 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1337 GstBaseParseFrame frame;
1339 flacparse->headers =
1340 g_list_delete_link (flacparse->headers, flacparse->headers);
1341 buf = gst_buffer_make_writable (buf);
1343 /* init, set and give away frame */
1344 gst_base_parse_frame_init (&frame);
1346 frame.overhead = -1;
1347 res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1348 gst_base_parse_frame_free (&frame);
1349 if (res != GST_FLOW_OK)
1352 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1353 g_list_free (flacparse->headers);
1354 flacparse->headers = NULL;
1359 /* empty vorbiscomment */
1361 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse)
1363 GstTagList *taglist = gst_tag_list_new_empty ();
1366 GstBuffer *vorbiscomment;
1369 header[0] = 0x84; /* is_last = 1; type = 4; */
1372 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1373 sizeof (header), NULL);
1374 gst_tag_list_unref (taglist);
1376 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1378 /* Get rid of framing bit */
1379 if (map.data[map.size - 1] == 1) {
1383 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1385 gst_buffer_unmap (vorbiscomment, &map);
1386 gst_buffer_unref (vorbiscomment);
1387 vorbiscomment = sub;
1388 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1391 size = map.size - 4;
1392 map.data[1] = ((size & 0xFF0000) >> 16);
1393 map.data[2] = ((size & 0x00FF00) >> 8);
1394 map.data[3] = (size & 0x0000FF);
1395 gst_buffer_unmap (vorbiscomment, &map);
1396 gst_flac_parse_reset_buffer_time_and_offset (vorbiscomment);
1398 return vorbiscomment;
1402 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1404 GstBuffer *marker, *streaminfo;
1407 marker = gst_buffer_new_and_alloc (4);
1408 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1409 memcpy (map.data, "fLaC", 4);
1410 gst_buffer_unmap (marker, &map);
1411 gst_flac_parse_reset_buffer_time_and_offset (marker);
1412 flacparse->headers = g_list_append (flacparse->headers, marker);
1414 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1415 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1416 memset (map.data, 0, 4 + 34);
1418 /* metadata block header */
1419 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1420 map.data[1] = 0x00; /* length = 34; */
1426 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1427 map.data[5] = (flacparse->block_size) & 0xff;
1428 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1429 map.data[7] = (flacparse->block_size) & 0xff;
1431 map.data[8] = 0x00; /* min framesize = 0; */
1433 map.data[10] = 0x00;
1434 map.data[11] = 0x00; /* max framesize = 0; */
1435 map.data[12] = 0x00;
1436 map.data[13] = 0x00;
1438 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1439 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1440 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1442 map.data[16] |= (flacparse->channels - 1) << 1;
1444 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1445 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1450 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1451 GST_FORMAT_TIME, &duration) && duration != -1) {
1452 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1454 map.data[17] |= (duration >> 32) & 0xff;
1455 map.data[18] |= (duration >> 24) & 0xff;
1456 map.data[19] |= (duration >> 16) & 0xff;
1457 map.data[20] |= (duration >> 8) & 0xff;
1458 map.data[21] |= (duration >> 0) & 0xff;
1463 gst_buffer_unmap (streaminfo, &map);
1464 gst_flac_parse_reset_buffer_time_and_offset (streaminfo);
1465 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1467 flacparse->headers = g_list_append (flacparse->headers,
1468 gst_flac_parse_generate_vorbiscomment (flacparse));
1474 gst_flac_parse_reset_buffer_time_and_offset (GstBuffer * buffer)
1476 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1477 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1478 GST_BUFFER_OFFSET (buffer) = 0;
1479 GST_BUFFER_OFFSET_END (buffer) = 0;
1482 /* Type 127 is invalid for a metadata block header & should
1483 * be discarded _before_ calling this function */
1485 gst_flac_parse_handle_block_type (GstFlacParse * flacparse, guint type,
1486 GstBuffer * sbuffer)
1488 gboolean ret = TRUE;
1491 case 0: /* STREAMINFO */
1492 GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1493 ret = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1495 case 3: /* SEEKTABLE */
1496 GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1497 ret = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1499 case 4: /* VORBIS_COMMENT */
1500 GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1501 ret = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1503 case 5: /* CUESHEET */
1504 GST_INFO_OBJECT (flacparse, "CUESHEET header");
1505 ret = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1507 case 6: /* PICTURE */
1508 GST_INFO_OBJECT (flacparse, "PICTURE header");
1509 ret = gst_flac_parse_handle_picture (flacparse, sbuffer);
1511 case 1: /* PADDING */
1512 GST_INFO_OBJECT (flacparse, "PADDING header");
1514 case 2: /* APPLICATION */
1515 GST_INFO_OBJECT (flacparse, "APPLICATION header");
1517 default: /* RESERVED */
1518 GST_INFO_OBJECT (flacparse, "Unhandled metadata header type '%u'", type);
1519 GST_FIXME_OBJECT (flacparse, "FLAC version might not be fully supported");
1526 static GstFlowReturn
1527 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1530 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1531 GstBuffer *buffer = frame->buffer, *sbuffer;
1533 GstFlowReturn res = GST_FLOW_ERROR;
1535 gst_buffer_map (buffer, &map, GST_MAP_READ);
1537 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1538 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1539 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1541 /* 32 bits metadata block */
1542 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1543 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1545 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1547 res = GST_BASE_PARSE_FLOW_DROPPED;
1548 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1549 gboolean is_last = map.data[0] >> 7;
1550 guint type = (map.data[0] & 0x7F);
1553 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type 127");
1554 res = GST_BASE_PARSE_FLOW_DROPPED;
1558 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1560 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1562 if (gst_flac_parse_handle_block_type (flacparse, type, sbuffer)) {
1563 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1564 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1566 GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1567 GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1569 gst_buffer_unref (sbuffer);
1571 /* error out unless we have a STREAMINFO header */
1572 if (flacparse->samplerate == 0 || flacparse->bps == 0)
1573 goto header_parsing_error;
1575 /* .. in which case just stop header parsing and try to find audio */
1580 res = gst_flac_parse_handle_headers (flacparse);
1582 /* Minimal size of a frame header */
1583 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1584 flacparse->min_framesize));
1585 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1587 if (res != GST_FLOW_OK)
1591 /* DROPPED because we pushed already or will push all headers manually */
1592 res = GST_BASE_PARSE_FLOW_DROPPED;
1594 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1595 FrameHeaderCheckReturn ret;
1597 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1599 gst_flac_parse_frame_header_is_valid (flacparse,
1600 map.data, map.size, TRUE, NULL, NULL);
1601 if (ret != FRAME_HEADER_VALID) {
1602 GST_ERROR_OBJECT (flacparse,
1603 "Baseclass didn't provide a complete frame");
1608 if (flacparse->block_size == 0) {
1609 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1613 if (flacparse->seektable)
1614 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1616 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1617 if (flacparse->blocking_strategy == 1) {
1618 GST_WARNING_OBJECT (flacparse,
1619 "Generating headers for variable blocksize streams not supported");
1621 res = gst_flac_parse_handle_headers (flacparse);
1623 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1625 if (!gst_flac_parse_generate_headers (flacparse))
1628 res = gst_flac_parse_handle_headers (flacparse);
1630 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1631 if (res != GST_FLOW_OK)
1635 /* also cater for oggmux metadata */
1636 if (flacparse->blocking_strategy == 0) {
1637 GST_BUFFER_PTS (buffer) =
1638 gst_util_uint64_scale (flacparse->sample_number,
1639 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1640 GST_BUFFER_OFFSET_END (buffer) =
1641 flacparse->sample_number * flacparse->block_size +
1642 flacparse->block_size;
1644 GST_BUFFER_PTS (buffer) =
1645 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1646 flacparse->samplerate);
1647 GST_BUFFER_OFFSET_END (buffer) =
1648 flacparse->sample_number + flacparse->block_size;
1651 GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
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_PTS (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 be 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);
1677 header_parsing_error:
1678 GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1679 ("Failed to parse headers"));
1683 static GstFlowReturn
1684 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1686 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1688 if (!flacparse->sent_codec_tag) {
1691 if (flacparse->tags == NULL)
1692 flacparse->tags = gst_tag_list_new_empty ();
1695 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1696 if (G_UNLIKELY (caps == NULL)) {
1697 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1698 GST_INFO_OBJECT (parse, "Src pad is flushing");
1699 return GST_FLOW_FLUSHING;
1701 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1702 return GST_FLOW_NOT_NEGOTIATED;
1704 gst_pb_utils_add_codec_description_to_tag_list (flacparse->tags,
1705 GST_TAG_AUDIO_CODEC, caps);
1706 gst_caps_unref (caps);
1708 /* Announce our pending tags */
1709 gst_base_parse_merge_tags (parse, flacparse->tags, GST_TAG_MERGE_REPLACE);
1711 /* also signals the end of first-frame processing */
1712 flacparse->sent_codec_tag = TRUE;
1716 if (flacparse->toc) {
1717 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1718 gst_event_new_toc (flacparse->toc, FALSE));
1721 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1727 gst_flac_parse_convert (GstBaseParse * parse,
1728 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1729 gint64 * dest_value)
1731 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1733 if (flacparse->samplerate > 0) {
1734 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1735 if (src_value != -1)
1737 gst_util_uint64_scale (src_value, GST_SECOND,
1738 flacparse->samplerate);
1742 } else if (src_format == GST_FORMAT_TIME &&
1743 dest_format == GST_FORMAT_DEFAULT) {
1744 if (src_value != -1)
1746 gst_util_uint64_scale (src_value, flacparse->samplerate,
1754 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1755 src_value, dest_format, dest_value);
1759 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1761 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1762 gboolean res = FALSE;
1764 switch (GST_EVENT_TYPE (event)) {
1765 case GST_EVENT_TOC_SELECT:
1767 GstTocEntry *entry = NULL;
1768 GstEvent *seek_event;
1773 /* FIXME: some locking would be good */
1775 toc = gst_toc_ref (flacparse->toc);
1778 gst_event_parse_toc_select (event, &uid);
1780 entry = gst_toc_find_entry (toc, uid);
1781 if (entry != NULL) {
1782 gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1784 /* FIXME: use segment rate here instead? */
1785 seek_event = gst_event_new_seek (1.0,
1787 GST_SEEK_FLAG_FLUSH,
1788 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1791 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1795 GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1799 gst_toc_unref (toc);
1801 GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1803 gst_event_unref (event);
1807 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1814 remove_fields (GstCaps * caps)
1818 n = gst_caps_get_size (caps);
1819 for (i = 0; i < n; i++) {
1820 GstStructure *s = gst_caps_get_structure (caps, i);
1822 gst_structure_remove_field (s, "framed");
1827 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1829 GstCaps *peercaps, *templ;
1832 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1834 GstCaps *fcopy = gst_caps_copy (filter);
1835 /* Remove the fields we convert */
1836 remove_fields (fcopy);
1837 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1838 gst_caps_unref (fcopy);
1840 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1843 /* Remove the framed field */
1844 peercaps = gst_caps_make_writable (peercaps);
1845 remove_fields (peercaps);
1847 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1848 gst_caps_unref (peercaps);
1849 gst_caps_unref (templ);
1855 GstCaps *intersection;
1858 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1859 gst_caps_unref (res);