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_pad_template (element_class,
251 gst_static_pad_template_get (&src_factory));
252 gst_element_class_add_pad_template (element_class,
253 gst_static_pad_template_get (&sink_factory));
255 gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
256 "Codec/Parser/Audio",
257 "Parses audio with the FLAC lossless audio codec",
258 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
262 gst_flac_parse_init (GstFlacParse * flacparse)
264 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
265 GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (flacparse));
266 GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (flacparse));
270 gst_flac_parse_set_property (GObject * object, guint prop_id,
271 const GValue * value, GParamSpec * pspec)
273 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
276 case PROP_CHECK_FRAME_CHECKSUMS:
277 flacparse->check_frame_checksums = g_value_get_boolean (value);
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
286 gst_flac_parse_get_property (GObject * object, guint prop_id,
287 GValue * value, GParamSpec * pspec)
289 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
292 case PROP_CHECK_FRAME_CHECKSUMS:
293 g_value_set_boolean (value, flacparse->check_frame_checksums);
296 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
302 gst_flac_parse_reset (GstFlacParse * parser)
305 gst_tag_list_unref (parser->tags);
309 gst_toc_unref (parser->toc);
312 if (parser->seektable) {
313 gst_buffer_unref (parser->seektable);
314 parser->seektable = NULL;
317 g_list_foreach (parser->headers, (GFunc) gst_mini_object_unref, NULL);
318 g_list_free (parser->headers);
319 parser->headers = NULL;
323 gst_flac_parse_finalize (GObject * object)
325 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
327 gst_flac_parse_reset (flacparse);
328 G_OBJECT_CLASS (parent_class)->finalize (object);
332 gst_flac_parse_start (GstBaseParse * parse)
334 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
336 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
337 flacparse->min_blocksize = 0;
338 flacparse->max_blocksize = 0;
339 flacparse->min_framesize = 0;
340 flacparse->max_framesize = 0;
342 flacparse->upstream_length = -1;
344 flacparse->samplerate = 0;
345 flacparse->channels = 0;
347 flacparse->total_samples = 0;
349 flacparse->offset = GST_CLOCK_TIME_NONE;
350 flacparse->blocking_strategy = 0;
351 flacparse->block_size = 0;
352 flacparse->sample_number = 0;
353 flacparse->strategy_checked = FALSE;
355 flacparse->sent_codec_tag = FALSE;
358 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
360 /* inform baseclass we can come up with ts, based on counters in packets */
361 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
362 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
368 gst_flac_parse_stop (GstBaseParse * parse)
370 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
372 gst_flac_parse_reset (flacparse);
376 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
378 static const guint16 blocksize_table[16] = {
379 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
380 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
384 static const guint32 sample_rate_table[16] = {
386 88200, 176400, 192000,
387 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
394 FRAME_HEADER_INVALID,
395 FRAME_HEADER_MORE_DATA
396 } FrameHeaderCheckReturn;
398 static FrameHeaderCheckReturn
399 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
400 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret,
403 GstBitReader reader = GST_BIT_READER_INIT (data, size);
404 guint8 blocking_strategy;
406 guint32 samplerate = 0;
407 guint64 sample_number;
408 guint8 channels, bps;
410 guint8 actual_crc, expected_crc = 0;
412 /* Skip 14 bit sync code */
413 gst_bit_reader_skip_unchecked (&reader, 14);
416 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
419 /* 0 == fixed block size, 1 == variable block size */
420 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
421 if (flacparse->force_variable_block_size)
422 blocking_strategy = 1;
424 /* block size index, calculation of the real blocksize below */
425 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
429 /* sample rate index, calculation of the real samplerate below */
430 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
431 if (samplerate == 0x0f)
434 /* channel assignment */
435 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
438 } else if (channels <= 10) {
440 } else if (channels > 10) {
443 if (flacparse->channels && flacparse->channels != channels)
446 /* bits per sample */
447 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
448 if (bps == 0x03 || bps == 0x07) {
450 } else if (bps == 0 && flacparse->bps == 0) {
451 goto need_streaminfo;
453 bps = sample_size_table[bps];
454 if (flacparse->bps && bps != flacparse->bps)
457 /* reserved, must be 0 */
458 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
461 /* read "utf8" encoded sample/frame number */
465 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
467 /* This is slightly faster than a loop */
471 } else if ((len & 0xc0) && !(len & 0x20)) {
472 sample_number = len & 0x1f;
474 } else if ((len & 0xe0) && !(len & 0x10)) {
475 sample_number = len & 0x0f;
477 } else if ((len & 0xf0) && !(len & 0x08)) {
478 sample_number = len & 0x07;
480 } else if ((len & 0xf8) && !(len & 0x04)) {
481 sample_number = len & 0x03;
483 } else if ((len & 0xfc) && !(len & 0x02)) {
484 sample_number = len & 0x01;
486 } else if ((len & 0xfe) && !(len & 0x01)) {
487 sample_number = len & 0x0;
493 if ((blocking_strategy == 0 && len > 5) ||
494 (blocking_strategy == 1 && len > 6))
498 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
501 if ((tmp & 0xc0) != 0x80)
505 sample_number |= (tmp & 0x3f);
510 /* calculate real blocksize from the blocksize index */
511 if (block_size == 6) {
512 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
515 } else if (block_size == 7) {
516 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
520 block_size = blocksize_table[block_size];
523 /* calculate the real samplerate from the samplerate index */
524 if (samplerate == 0 && flacparse->samplerate == 0) {
525 goto need_streaminfo;
526 } else if (samplerate < 12) {
527 samplerate = sample_rate_table[samplerate];
528 } else if (samplerate == 12) {
529 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
532 } else if (samplerate == 13) {
533 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
535 } else if (samplerate == 14) {
536 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
541 if (flacparse->samplerate && flacparse->samplerate != samplerate)
544 /* check crc-8 for the header */
545 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
549 gst_flac_calculate_crc8 (data,
550 (gst_bit_reader_get_pos (&reader) / 8) - 1);
551 if (actual_crc != expected_crc)
554 /* Sanity check sample number against blocking strategy, as it seems
555 some files claim fixed block size but supply sample numbers,
556 rather than block numbers. */
557 if (blocking_strategy == 0 && flacparse->block_size != 0) {
558 if (!flacparse->strategy_checked) {
559 if (block_size == sample_number) {
560 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
561 "but seems to be lying: assuming variable block size");
562 flacparse->force_variable_block_size = TRUE;
563 blocking_strategy = 1;
565 flacparse->strategy_checked = TRUE;
569 /* documentation says:
570 * The "blocking strategy" bit must be the same throughout the entire stream. */
571 if (flacparse->blocking_strategy != blocking_strategy) {
572 if (flacparse->block_size != 0) {
573 GST_WARNING_OBJECT (flacparse, "blocking strategy is not constant");
580 The FLAC format documentation says:
581 The "blocking strategy" bit determines how to calculate the sample number
582 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
583 frame header encodes the frame number as above, and the frame's starting
584 sample number will be the frame number times the blocksize. If it is 1
585 (variable-blocksize), the frame header encodes the frame's starting
586 sample number itself. (In the case of a fixed-blocksize stream, only the
587 last block may be shorter than the stream blocksize; its starting sample
588 number will be calculated as the frame number times the previous frame's
589 blocksize, or zero if it is the first frame).
591 Therefore, when in fixed block size mode, we only update the block size
592 the first time, then reuse that block size for subsequent calls.
593 This will also fix a timestamp problem with the last block's timestamp
594 being miscalculated by scaling the block number by a "wrong" block size.
596 if (blocking_strategy == 0) {
597 if (flacparse->block_size != 0) {
598 /* after first block */
599 if (flacparse->block_size != block_size) {
600 /* TODO: can we know we're on the last frame, to avoid warning ? */
601 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
602 block_size = flacparse->block_size;
610 flacparse->block_size = block_size;
611 if (!flacparse->samplerate)
612 flacparse->samplerate = samplerate;
614 flacparse->bps = bps;
615 if (!flacparse->blocking_strategy)
616 flacparse->blocking_strategy = blocking_strategy;
617 if (!flacparse->channels)
618 flacparse->channels = channels;
619 if (!flacparse->sample_number)
620 flacparse->sample_number = sample_number;
622 GST_DEBUG_OBJECT (flacparse,
623 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
624 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
625 flacparse->block_size, flacparse->sample_number);
629 *block_size_ret = block_size;
631 return FRAME_HEADER_VALID;
634 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO metadata. Bits per sample "
635 "or sample rate not in frame header");
637 return FRAME_HEADER_INVALID;
640 return FRAME_HEADER_MORE_DATA;
644 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
645 GstBaseParseFrame * frame, 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;
654 gboolean result = FALSE;
656 buffer = frame->buffer;
657 gst_buffer_map (buffer, &map, GST_MAP_READ);
659 if (map.size < flacparse->min_framesize)
663 gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
664 &block_size, &suspect_start);
665 if (header_ret == FRAME_HEADER_INVALID) {
669 if (header_ret == FRAME_HEADER_MORE_DATA)
672 /* mind unknown framesize */
673 search_start = MAX (2, flacparse->min_framesize);
674 if (flacparse->max_framesize)
675 search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
677 search_end = map.size;
680 remaining = map.size;
682 for (i = search_start; i < search_end; i++, remaining--) {
684 if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) != 0xfff8)
687 GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
690 gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
691 remaining, FALSE, NULL, &suspect_end);
692 if (header_ret == FRAME_HEADER_VALID) {
693 if (flacparse->check_frame_checksums || suspect_start || suspect_end) {
694 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
695 guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
697 GST_LOG_OBJECT (flacparse,
698 "checking checksum, frame suspect (%d, %d)",
699 suspect_start, suspect_end);
700 if (actual_crc != expected_crc) {
701 GST_DEBUG_OBJECT (flacparse, "checksum did not match");
706 flacparse->block_size = block_size;
709 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
714 /* For the last frame output everything to the end */
715 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
716 if (flacparse->check_frame_checksums) {
717 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
718 guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
720 if (actual_crc == expected_crc) {
722 flacparse->block_size = block_size;
728 flacparse->block_size = block_size;
734 /* so we searched to expected end and found nothing,
735 * give up on this frame (start) */
736 if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
737 GST_LOG_OBJECT (flacparse,
738 "could not determine valid frame end, discarding frame (start)");
744 max = flacparse->max_framesize + 16;
747 *ret = MIN (map.size + 4096, max);
751 gst_buffer_unmap (buffer, &map);
756 gst_flac_parse_handle_frame (GstBaseParse * parse,
757 GstBaseParseFrame * frame, gint * skipsize)
759 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
760 GstBuffer *buffer = frame->buffer;
762 gboolean result = TRUE;
763 GstFlowReturn ret = GST_FLOW_OK;
766 gst_buffer_map (buffer, &map, GST_MAP_READ);
770 if (G_UNLIKELY (map.size < 4)) {
775 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
776 if (memcmp (map.data, "fLaC", 4) == 0) {
777 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
781 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
782 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
783 /* Minimal size of a frame header */
784 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
785 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
790 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
795 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
796 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
798 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
803 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
807 flacparse->offset = GST_BUFFER_OFFSET (buffer);
808 flacparse->blocking_strategy = 0;
809 flacparse->sample_number = 0;
811 GST_DEBUG_OBJECT (flacparse, "Found sync code");
812 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
817 /* If we're at EOS and the frame was not valid, drop it! */
818 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
819 GST_WARNING_OBJECT (flacparse, "EOS");
825 } else if (next > map.size) {
826 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
828 gst_base_parse_set_min_frame_size (parse, next);
832 GST_ERROR_OBJECT (flacparse,
833 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
839 GstByteReader reader;
842 gst_byte_reader_init (&reader, map.data, map.size);
844 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
848 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
853 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
854 *skipsize = map.size - 3;
863 gst_buffer_unmap (buffer, &map);
868 if (result && framesize <= map.size) {
869 ret = gst_flac_parse_parse_frame (parse, frame, framesize);
870 if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
871 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
874 if (ret == GST_FLOW_OK)
875 ret = gst_base_parse_finish_frame (parse, frame, framesize);
882 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
887 gst_buffer_map (buffer, &map, GST_MAP_READ);
888 gst_bit_reader_init (&reader, map.data, map.size);
890 if (map.size != 4 + 34) {
891 GST_ERROR_OBJECT (flacparse,
892 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
896 /* Skip metadata block header */
897 if (!gst_bit_reader_skip (&reader, 32))
900 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
902 if (flacparse->min_blocksize < 16) {
903 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
904 flacparse->min_blocksize);
907 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
909 if (flacparse->max_blocksize < 16) {
910 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
911 flacparse->max_blocksize);
914 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
916 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
919 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
921 if (flacparse->samplerate == 0) {
922 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
926 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
928 flacparse->channels++;
929 if (flacparse->channels > 8) {
930 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
931 flacparse->channels);
935 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
939 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
941 if (flacparse->total_samples) {
942 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
943 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
946 gst_buffer_unmap (buffer, &map);
948 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
949 "\tmin/max blocksize: %u/%u,\n"
950 "\tmin/max framesize: %u/%u,\n"
951 "\tsamplerate: %u,\n"
953 "\tbits per sample: %u,\n"
954 "\ttotal samples: %" G_GUINT64_FORMAT,
955 flacparse->min_blocksize, flacparse->max_blocksize,
956 flacparse->min_framesize, flacparse->max_framesize,
957 flacparse->samplerate,
958 flacparse->channels, flacparse->bps, flacparse->total_samples);
963 GST_ERROR_OBJECT (flacparse, "Failed to read data");
965 gst_buffer_unmap (buffer, &map);
970 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
976 gst_buffer_map (buffer, &map, GST_MAP_READ);
979 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
980 gst_buffer_unmap (buffer, &map);
983 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
984 } else if (gst_tag_list_is_empty (tags)) {
985 gst_tag_list_unref (tags);
986 } else if (flacparse->tags == NULL) {
987 flacparse->tags = tags;
989 gst_tag_list_insert (flacparse->tags, tags, GST_TAG_MERGE_APPEND);
990 gst_tag_list_unref (tags);
997 gst_flac_parse_handle_cuesheet (GstFlacParse * flacparse, GstBuffer * buffer)
999 GstByteReader reader;
1002 guint8 n_tracks, track_num, index;
1009 GstTocEntry *cur_entry = NULL, *prev_entry = NULL;
1011 gst_buffer_map (buffer, &map, GST_MAP_READ);
1012 gst_byte_reader_init (&reader, map.data, map.size);
1014 toc = gst_toc_new (GST_TOC_SCOPE_GLOBAL);
1016 /* skip 4 bytes METADATA_BLOCK_HEADER */
1017 /* http://flac.sourceforge.net/format.html#metadata_block_header */
1018 if (!gst_byte_reader_skip (&reader, 4))
1021 /* skip 395 bytes from METADATA_BLOCK_CUESHEET */
1022 /* http://flac.sourceforge.net/format.html#metadata_block_cuesheet */
1023 if (!gst_byte_reader_skip (&reader, 395))
1026 if (!gst_byte_reader_get_uint8 (&reader, &n_tracks))
1029 /* CUESHEET_TRACK */
1030 /* http://flac.sourceforge.net/format.html#cuesheet_track */
1031 for (i = 0; i < n_tracks; i++) {
1032 if (!gst_byte_reader_get_uint64_be (&reader, &offset))
1034 if (!gst_byte_reader_get_uint8 (&reader, &track_num))
1037 if (gst_byte_reader_get_remaining (&reader) < 12)
1039 memcpy (isrc, map.data + gst_byte_reader_get_pos (&reader), 12);
1040 /* \0-terminate the string */
1042 if (!gst_byte_reader_skip (&reader, 12))
1045 /* skip 14 bytes from CUESHEET_TRACK */
1046 if (!gst_byte_reader_skip (&reader, 14))
1048 if (!gst_byte_reader_get_uint8 (&reader, &index))
1050 /* add tracks in TOC */
1051 /* lead-out tack has number 170 or 255 */
1052 if (track_num != 170 && track_num != 255) {
1053 prev_entry = cur_entry;
1054 /* previous track stop time = current track start time */
1055 if (prev_entry != NULL) {
1056 gst_toc_entry_get_start_stop_times (prev_entry, &start, NULL);
1058 gst_util_uint64_scale_round (offset, GST_SECOND,
1059 flacparse->samplerate);
1060 gst_toc_entry_set_start_stop_times (prev_entry, start, stop);
1062 id = g_strdup_printf ("%08x", track_num);
1063 cur_entry = gst_toc_entry_new (GST_TOC_ENTRY_TYPE_TRACK, id);
1066 gst_util_uint64_scale_round (offset, GST_SECOND,
1067 flacparse->samplerate);
1068 gst_toc_entry_set_start_stop_times (cur_entry, start, -1);
1069 /* add ISRC as tag in track */
1070 if (strlen (isrc) != 0) {
1071 tags = gst_tag_list_new_empty ();
1072 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_ISRC, isrc, NULL);
1073 gst_toc_entry_set_tags (cur_entry, tags);
1075 gst_toc_append_entry (toc, cur_entry);
1076 /* CUESHEET_TRACK_INDEX */
1077 /* http://flac.sourceforge.net/format.html#cuesheet_track_index */
1078 for (j = 0; j < index; j++) {
1079 if (!gst_byte_reader_skip (&reader, 12))
1083 /* set stop time in last track */
1085 gst_util_uint64_scale_round (offset, GST_SECOND,
1086 flacparse->samplerate);
1087 gst_toc_entry_set_start_stop_times (cur_entry, start, stop);
1091 /* send data as TOC */
1092 if (!flacparse->toc)
1093 flacparse->toc = toc;
1095 gst_buffer_unmap (buffer, &map);
1099 GST_ERROR_OBJECT (flacparse, "Error reading data");
1100 gst_buffer_unmap (buffer, &map);
1105 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
1107 GstByteReader reader;
1109 guint32 img_len = 0, img_type = 0;
1110 guint32 img_mimetype_len = 0, img_description_len = 0;
1112 gst_buffer_map (buffer, &map, GST_MAP_READ);
1113 gst_byte_reader_init (&reader, map.data, map.size);
1115 if (!gst_byte_reader_skip (&reader, 4))
1118 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
1121 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
1123 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
1126 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
1128 if (!gst_byte_reader_skip (&reader, img_description_len))
1131 if (!gst_byte_reader_skip (&reader, 4 * 4))
1134 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
1137 if (gst_byte_reader_get_pos (&reader) + img_len > map.size)
1140 GST_INFO_OBJECT (flacparse, "Got image of %d bytes", img_len);
1143 if (flacparse->tags == NULL)
1144 flacparse->tags = gst_tag_list_new_empty ();
1146 gst_tag_list_add_id3_image (flacparse->tags,
1147 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1150 gst_buffer_unmap (buffer, &map);
1154 GST_ERROR_OBJECT (flacparse, "Error reading data");
1155 gst_buffer_unmap (buffer, &map);
1160 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1163 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1164 /* only store for now;
1165 * offset of the first frame is needed to get real info */
1166 if (flacparse->seektable)
1167 gst_buffer_unref (flacparse->seektable);
1168 flacparse->seektable = gst_buffer_ref (buffer);
1174 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1177 gint64 offset = 0, samples = 0;
1180 GST_DEBUG_OBJECT (flacparse,
1181 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1186 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1187 gst_byte_reader_init (&br, map.data, map.size);
1190 if (!gst_byte_reader_skip (&br, 4))
1194 while (gst_byte_reader_get_remaining (&br)) {
1195 if (!gst_byte_reader_get_int64_be (&br, &samples))
1197 if (!gst_byte_reader_get_int64_be (&br, &offset))
1199 if (!gst_byte_reader_skip (&br, 2))
1202 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1203 G_GINT64_FORMAT, samples, offset);
1206 if (G_LIKELY (offset > 0 && samples > 0)) {
1207 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1208 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1209 flacparse->samplerate), TRUE, FALSE);
1214 gst_buffer_unmap (flacparse->seektable, &map);
1216 gst_buffer_unref (flacparse->seektable);
1217 flacparse->seektable = NULL;
1221 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1223 GValue value = { 0, };
1225 g_value_init (&value, GST_TYPE_BUFFER);
1226 /* copy buffer to avoid problems with circular refcounts */
1227 buf = gst_buffer_copy (buf);
1228 /* again, for good measure */
1229 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1230 gst_value_set_buffer (&value, buf);
1231 gst_buffer_unref (buf);
1232 gst_value_array_append_value (array_val, &value);
1233 g_value_unset (&value);
1236 static GstFlowReturn
1237 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1239 GstBuffer *vorbiscomment = NULL;
1240 GstBuffer *streaminfo = NULL;
1241 GstBuffer *marker = NULL;
1242 GValue array = { 0, };
1245 GstFlowReturn res = GST_FLOW_OK;
1247 caps = gst_caps_new_simple ("audio/x-flac",
1248 "channels", G_TYPE_INT, flacparse->channels,
1249 "framed", G_TYPE_BOOLEAN, TRUE,
1250 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1252 if (!flacparse->headers)
1255 for (l = flacparse->headers; l; l = l->next) {
1256 GstBuffer *header = l->data;
1259 gst_buffer_map (header, &map, GST_MAP_READ);
1261 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1263 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1265 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1266 streaminfo = header;
1267 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1268 vorbiscomment = header;
1271 gst_buffer_unmap (header, &map);
1274 /* at least this one we can generate easily
1275 * to provide full headers downstream */
1276 if (vorbiscomment == NULL && streaminfo != NULL) {
1277 GST_DEBUG_OBJECT (flacparse,
1278 "missing vorbiscomment header; generating dummy");
1279 vorbiscomment = gst_flac_parse_generate_vorbiscomment (flacparse);
1280 flacparse->headers = g_list_insert (flacparse->headers, vorbiscomment,
1281 g_list_index (flacparse->headers, streaminfo) + 1);
1284 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1285 GST_WARNING_OBJECT (flacparse,
1286 "missing header %p %p %p, muxing into container "
1287 "formats may be broken", marker, streaminfo, vorbiscomment);
1291 g_value_init (&array, GST_TYPE_ARRAY);
1293 /* add marker including STREAMINFO header */
1297 GstMapInfo sinfomap, writemap;
1299 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1301 /* minus one for the marker that is merged with streaminfo here */
1302 num = g_list_length (flacparse->headers) - 1;
1304 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1305 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1307 writemap.data[0] = 0x7f;
1308 memcpy (writemap.data + 1, "FLAC", 4);
1309 writemap.data[5] = 0x01; /* mapping version major */
1310 writemap.data[6] = 0x00; /* mapping version minor */
1311 writemap.data[7] = (num & 0xFF00) >> 8;
1312 writemap.data[8] = (num & 0x00FF) >> 0;
1313 memcpy (writemap.data + 9, "fLaC", 4);
1314 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1315 _value_array_append_buffer (&array, buf);
1317 gst_buffer_unmap (streaminfo, &sinfomap);
1318 gst_buffer_unmap (buf, &writemap);
1319 gst_buffer_unref (buf);
1322 /* add VORBISCOMMENT header */
1323 _value_array_append_buffer (&array, vorbiscomment);
1325 /* add other headers, if there are any */
1326 for (l = flacparse->headers; l; l = l->next) {
1327 if (GST_BUFFER_CAST (l->data) != marker &&
1328 GST_BUFFER_CAST (l->data) != streaminfo &&
1329 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1330 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1334 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1335 "streamheader", &array);
1336 g_value_unset (&array);
1340 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1341 gst_caps_unref (caps);
1343 /* push header buffers; update caps, so when we push the first buffer the
1344 * negotiated caps will change to caps that include the streamheader field */
1345 while (flacparse->headers) {
1346 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1347 GstBaseParseFrame frame;
1349 flacparse->headers =
1350 g_list_delete_link (flacparse->headers, flacparse->headers);
1351 buf = gst_buffer_make_writable (buf);
1353 /* init, set and give away frame */
1354 gst_base_parse_frame_init (&frame);
1356 frame.overhead = -1;
1357 res = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1358 gst_base_parse_frame_free (&frame);
1359 if (res != GST_FLOW_OK)
1362 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1363 g_list_free (flacparse->headers);
1364 flacparse->headers = NULL;
1369 /* empty vorbiscomment */
1371 gst_flac_parse_generate_vorbiscomment (GstFlacParse * flacparse)
1373 GstTagList *taglist = gst_tag_list_new_empty ();
1376 GstBuffer *vorbiscomment;
1379 header[0] = 0x84; /* is_last = 1; type = 4; */
1382 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1383 sizeof (header), NULL);
1384 gst_tag_list_unref (taglist);
1386 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1388 /* Get rid of framing bit */
1389 if (map.data[map.size - 1] == 1) {
1393 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1395 gst_buffer_unmap (vorbiscomment, &map);
1396 gst_buffer_unref (vorbiscomment);
1397 vorbiscomment = sub;
1398 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1401 size = map.size - 4;
1402 map.data[1] = ((size & 0xFF0000) >> 16);
1403 map.data[2] = ((size & 0x00FF00) >> 8);
1404 map.data[3] = (size & 0x0000FF);
1405 gst_buffer_unmap (vorbiscomment, &map);
1406 gst_flac_parse_reset_buffer_time_and_offset (vorbiscomment);
1408 return vorbiscomment;
1412 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1414 GstBuffer *marker, *streaminfo;
1417 marker = gst_buffer_new_and_alloc (4);
1418 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1419 memcpy (map.data, "fLaC", 4);
1420 gst_buffer_unmap (marker, &map);
1421 gst_flac_parse_reset_buffer_time_and_offset (marker);
1422 flacparse->headers = g_list_append (flacparse->headers, marker);
1424 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1425 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1426 memset (map.data, 0, 4 + 34);
1428 /* metadata block header */
1429 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1430 map.data[1] = 0x00; /* length = 34; */
1436 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1437 map.data[5] = (flacparse->block_size) & 0xff;
1438 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1439 map.data[7] = (flacparse->block_size) & 0xff;
1441 map.data[8] = 0x00; /* min framesize = 0; */
1443 map.data[10] = 0x00;
1444 map.data[11] = 0x00; /* max framesize = 0; */
1445 map.data[12] = 0x00;
1446 map.data[13] = 0x00;
1448 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1449 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1450 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1452 map.data[16] |= (flacparse->channels - 1) << 1;
1454 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1455 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1460 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1461 GST_FORMAT_TIME, &duration) && duration != -1) {
1462 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1464 map.data[17] |= (duration >> 32) & 0xff;
1465 map.data[18] |= (duration >> 24) & 0xff;
1466 map.data[19] |= (duration >> 16) & 0xff;
1467 map.data[20] |= (duration >> 8) & 0xff;
1468 map.data[21] |= (duration >> 0) & 0xff;
1473 gst_buffer_unmap (streaminfo, &map);
1474 gst_flac_parse_reset_buffer_time_and_offset (streaminfo);
1475 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1477 flacparse->headers = g_list_append (flacparse->headers,
1478 gst_flac_parse_generate_vorbiscomment (flacparse));
1484 gst_flac_parse_reset_buffer_time_and_offset (GstBuffer * buffer)
1486 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1487 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1488 GST_BUFFER_OFFSET (buffer) = 0;
1489 GST_BUFFER_OFFSET_END (buffer) = 0;
1493 gst_flac_parse_handle_block_type (GstFlacParse * flacparse, guint type,
1494 GstBuffer * sbuffer)
1496 gboolean ret = TRUE;
1499 case 0: /* STREAMINFO */
1500 GST_INFO_OBJECT (flacparse, "STREAMINFO header");
1501 ret = gst_flac_parse_handle_streaminfo (flacparse, sbuffer);
1503 case 3: /* SEEKTABLE */
1504 GST_INFO_OBJECT (flacparse, "SEEKTABLE header");
1505 ret = gst_flac_parse_handle_seektable (flacparse, sbuffer);
1507 case 4: /* VORBIS_COMMENT */
1508 GST_INFO_OBJECT (flacparse, "VORBISCOMMENT header");
1509 ret = gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer);
1511 case 5: /* CUESHEET */
1512 GST_INFO_OBJECT (flacparse, "CUESHEET header");
1513 ret = gst_flac_parse_handle_cuesheet (flacparse, sbuffer);
1515 case 6: /* PICTURE */
1516 GST_INFO_OBJECT (flacparse, "PICTURE header");
1517 ret = gst_flac_parse_handle_picture (flacparse, sbuffer);
1519 case 1: /* PADDING */
1520 GST_INFO_OBJECT (flacparse, "PADDING header");
1522 case 2: /* APPLICATION */
1523 GST_INFO_OBJECT (flacparse, "APPLICATION header");
1525 default: /* RESERVED */
1526 GST_INFO_OBJECT (flacparse, "unhandled header of type %u", type);
1533 static GstFlowReturn
1534 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1537 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1538 GstBuffer *buffer = frame->buffer, *sbuffer;
1540 GstFlowReturn res = GST_FLOW_ERROR;
1542 gst_buffer_map (buffer, &map, GST_MAP_READ);
1544 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1545 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1546 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1548 /* 32 bits metadata block */
1549 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1550 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1552 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1554 res = GST_BASE_PARSE_FLOW_DROPPED;
1555 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1556 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1557 guint type = (map.data[0] & 0x7F);
1560 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1561 res = GST_BASE_PARSE_FLOW_DROPPED;
1565 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1567 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1569 if (gst_flac_parse_handle_block_type (flacparse, type, sbuffer)) {
1570 gst_flac_parse_reset_buffer_time_and_offset (sbuffer);
1571 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1573 GST_WARNING_OBJECT (parse, "failed to parse header of type %u", type);
1574 GST_MEMDUMP_OBJECT (parse, "bad header data", map.data, size);
1576 gst_buffer_unref (sbuffer);
1578 /* error out unless we have a STREAMINFO header */
1579 if (flacparse->samplerate == 0 || flacparse->bps == 0)
1580 goto header_parsing_error;
1582 /* .. in which case just stop header parsing and try to find audio */
1587 res = gst_flac_parse_handle_headers (flacparse);
1589 /* Minimal size of a frame header */
1590 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1591 flacparse->min_framesize));
1592 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1594 if (res != GST_FLOW_OK)
1598 /* DROPPED because we pushed already or will push all headers manually */
1599 res = GST_BASE_PARSE_FLOW_DROPPED;
1601 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1602 FrameHeaderCheckReturn ret;
1604 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1606 gst_flac_parse_frame_header_is_valid (flacparse,
1607 map.data, map.size, TRUE, NULL, NULL);
1608 if (ret != FRAME_HEADER_VALID) {
1609 GST_ERROR_OBJECT (flacparse,
1610 "Baseclass didn't provide a complete frame");
1615 if (flacparse->block_size == 0) {
1616 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1620 if (flacparse->seektable)
1621 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1623 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1624 if (flacparse->blocking_strategy == 1) {
1625 GST_WARNING_OBJECT (flacparse,
1626 "Generating headers for variable blocksize streams not supported");
1628 res = gst_flac_parse_handle_headers (flacparse);
1630 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1632 if (!gst_flac_parse_generate_headers (flacparse))
1635 res = gst_flac_parse_handle_headers (flacparse);
1637 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1638 if (res != GST_FLOW_OK)
1642 /* also cater for oggmux metadata */
1643 if (flacparse->blocking_strategy == 0) {
1644 GST_BUFFER_PTS (buffer) =
1645 gst_util_uint64_scale (flacparse->sample_number,
1646 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1647 GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
1648 GST_BUFFER_OFFSET_END (buffer) =
1649 flacparse->sample_number * flacparse->block_size +
1650 flacparse->block_size;
1652 GST_BUFFER_PTS (buffer) =
1653 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1654 flacparse->samplerate);
1655 GST_BUFFER_DTS (buffer) = GST_BUFFER_PTS (buffer);
1656 GST_BUFFER_OFFSET_END (buffer) =
1657 flacparse->sample_number + flacparse->block_size;
1659 GST_BUFFER_OFFSET (buffer) =
1660 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1661 flacparse->samplerate);
1662 GST_BUFFER_DURATION (buffer) =
1663 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_PTS (buffer);
1665 /* To simplify, we just assume that it's a fixed size header and ignore
1666 * subframe headers. The first could lead us to being off by 88 bits and
1667 * the second even less, so the total inaccuracy is negligible. */
1668 frame->overhead = 7;
1670 /* Minimal size of a frame header */
1671 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1672 flacparse->min_framesize));
1674 flacparse->offset = -1;
1675 flacparse->blocking_strategy = 0;
1676 flacparse->sample_number = 0;
1681 gst_buffer_unmap (buffer, &map);
1686 header_parsing_error:
1688 GST_ELEMENT_ERROR (flacparse, STREAM, DECODE, (NULL),
1689 ("Failed to parse headers"));
1694 static GstFlowReturn
1695 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1697 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1699 if (!flacparse->sent_codec_tag) {
1702 if (flacparse->tags == NULL)
1703 flacparse->tags = gst_tag_list_new_empty ();
1706 caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse));
1707 if (G_UNLIKELY (caps == NULL)) {
1708 if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) {
1709 GST_INFO_OBJECT (parse, "Src pad is flushing");
1710 return GST_FLOW_FLUSHING;
1712 GST_INFO_OBJECT (parse, "Src pad is not negotiated!");
1713 return GST_FLOW_NOT_NEGOTIATED;
1716 gst_pb_utils_add_codec_description_to_tag_list (flacparse->tags,
1717 GST_TAG_AUDIO_CODEC, caps);
1718 gst_caps_unref (caps);
1720 /* Announce our pending tags */
1721 gst_base_parse_merge_tags (parse, flacparse->tags, GST_TAG_MERGE_REPLACE);
1723 /* also signals the end of first-frame processing */
1724 flacparse->sent_codec_tag = TRUE;
1728 if (flacparse->toc) {
1729 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1730 gst_event_new_toc (flacparse->toc, FALSE));
1733 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1739 gst_flac_parse_convert (GstBaseParse * parse,
1740 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1741 gint64 * dest_value)
1743 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1745 if (flacparse->samplerate > 0) {
1746 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1747 if (src_value != -1)
1749 gst_util_uint64_scale (src_value, GST_SECOND,
1750 flacparse->samplerate);
1754 } else if (src_format == GST_FORMAT_TIME &&
1755 dest_format == GST_FORMAT_DEFAULT) {
1756 if (src_value != -1)
1758 gst_util_uint64_scale (src_value, flacparse->samplerate,
1766 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1767 src_value, dest_format, dest_value);
1771 gst_flac_parse_src_event (GstBaseParse * parse, GstEvent * event)
1773 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1774 gboolean res = FALSE;
1776 switch (GST_EVENT_TYPE (event)) {
1777 case GST_EVENT_TOC_SELECT:
1779 GstTocEntry *entry = NULL;
1780 GstEvent *seek_event;
1785 /* FIXME: some locking would be good */
1787 toc = gst_toc_ref (flacparse->toc);
1790 gst_event_parse_toc_select (event, &uid);
1792 entry = gst_toc_find_entry (toc, uid);
1793 if (entry != NULL) {
1794 gst_toc_entry_get_start_stop_times (entry, &start_pos, NULL);
1796 /* FIXME: use segment rate here instead? */
1797 seek_event = gst_event_new_seek (1.0,
1799 GST_SEEK_FLAG_FLUSH,
1800 GST_SEEK_TYPE_SET, start_pos, GST_SEEK_TYPE_NONE, -1);
1803 GST_BASE_PARSE_CLASS (parent_class)->src_event (parse,
1807 GST_WARNING_OBJECT (parse, "no TOC entry with given UID: %s", uid);
1811 gst_toc_unref (toc);
1813 GST_DEBUG_OBJECT (flacparse, "no TOC to select");
1815 gst_event_unref (event);
1819 res = GST_BASE_PARSE_CLASS (parent_class)->src_event (parse, event);
1826 remove_fields (GstCaps * caps)
1830 n = gst_caps_get_size (caps);
1831 for (i = 0; i < n; i++) {
1832 GstStructure *s = gst_caps_get_structure (caps, i);
1834 gst_structure_remove_field (s, "framed");
1839 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1841 GstCaps *peercaps, *templ;
1844 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1846 GstCaps *fcopy = gst_caps_copy (filter);
1847 /* Remove the fields we convert */
1848 remove_fields (fcopy);
1849 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
1850 gst_caps_unref (fcopy);
1852 peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
1855 /* Remove the framed field */
1856 peercaps = gst_caps_make_writable (peercaps);
1857 remove_fields (peercaps);
1859 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1860 gst_caps_unref (peercaps);
1861 gst_caps_unref (templ);
1867 GstCaps *intersection;
1870 gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
1871 gst_caps_unref (res);