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., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, 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 -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>
62 #include <gst/base/gstbitreader.h>
63 #include <gst/base/gstbytereader.h>
65 GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
66 #define GST_CAT_DEFAULT flacparse_debug
68 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
69 static const guint8 crc8_table[256] = {
70 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
71 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
72 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
73 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
74 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
75 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
76 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
77 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
78 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
79 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
80 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
81 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
82 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
83 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
84 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
85 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
86 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
87 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
88 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
89 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
90 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
91 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
92 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
93 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
94 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
95 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
96 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
97 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
98 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
99 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
100 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
101 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
105 gst_flac_calculate_crc8 (const guint8 * data, guint length)
110 crc = crc8_table[crc ^ *data];
117 /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
118 static const guint16 crc16_table[256] = {
119 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
120 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
121 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
122 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
123 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
124 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
125 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
126 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
127 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
128 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
129 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
130 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
131 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
132 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
133 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
134 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
135 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
136 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
137 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
138 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
139 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
140 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
141 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
142 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
143 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
144 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
145 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
146 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
147 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
148 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
149 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
150 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
154 gst_flac_calculate_crc16 (const guint8 * data, guint length)
159 crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
169 PROP_CHECK_FRAME_CHECKSUMS
172 #define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
174 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
177 GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
178 "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
181 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
184 GST_STATIC_CAPS ("audio/x-flac")
187 static void gst_flac_parse_finalize (GObject * object);
188 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
189 const GValue * value, GParamSpec * pspec);
190 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
191 GValue * value, GParamSpec * pspec);
193 static gboolean gst_flac_parse_start (GstBaseParse * parse);
194 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
195 static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse,
196 GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
197 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
198 GstBaseParseFrame * frame);
199 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
200 GstBaseParseFrame * frame);
201 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
202 GstFormat src_format, gint64 src_value, GstFormat dest_format,
203 gint64 * dest_value);
204 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
207 #define gst_flac_parse_parent_class parent_class
208 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
211 gst_flac_parse_class_init (GstFlacParseClass * klass)
213 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
214 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
215 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
217 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
218 "Flac parser element");
220 gobject_class->finalize = gst_flac_parse_finalize;
221 gobject_class->set_property = gst_flac_parse_set_property;
222 gobject_class->get_property = gst_flac_parse_get_property;
224 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
225 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
226 "Check the overall checksums of every frame",
227 DEFAULT_CHECK_FRAME_CHECKSUMS,
228 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
230 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
231 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
232 baseparse_class->check_valid_frame =
233 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
234 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
235 baseparse_class->pre_push_frame =
236 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
237 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
238 baseparse_class->get_sink_caps =
239 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
241 gst_element_class_add_pad_template (element_class,
242 gst_static_pad_template_get (&src_factory));
243 gst_element_class_add_pad_template (element_class,
244 gst_static_pad_template_get (&sink_factory));
246 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
247 "Codec/Parser/Audio",
248 "Parses audio with the FLAC lossless audio codec",
249 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
253 gst_flac_parse_init (GstFlacParse * flacparse)
255 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
259 gst_flac_parse_set_property (GObject * object, guint prop_id,
260 const GValue * value, GParamSpec * pspec)
262 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
265 case PROP_CHECK_FRAME_CHECKSUMS:
266 flacparse->check_frame_checksums = g_value_get_boolean (value);
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
275 gst_flac_parse_get_property (GObject * object, guint prop_id,
276 GValue * value, GParamSpec * pspec)
278 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
281 case PROP_CHECK_FRAME_CHECKSUMS:
282 g_value_set_boolean (value, flacparse->check_frame_checksums);
285 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291 gst_flac_parse_finalize (GObject * object)
293 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
295 if (flacparse->tags) {
296 gst_tag_list_free (flacparse->tags);
297 flacparse->tags = NULL;
300 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
301 g_list_free (flacparse->headers);
302 flacparse->headers = NULL;
304 G_OBJECT_CLASS (parent_class)->finalize (object);
308 gst_flac_parse_start (GstBaseParse * parse)
310 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
312 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
313 flacparse->min_blocksize = 0;
314 flacparse->max_blocksize = 0;
315 flacparse->min_framesize = 0;
316 flacparse->max_framesize = 0;
318 flacparse->upstream_length = -1;
320 flacparse->samplerate = 0;
321 flacparse->channels = 0;
323 flacparse->total_samples = 0;
325 flacparse->offset = GST_CLOCK_TIME_NONE;
326 flacparse->blocking_strategy = 0;
327 flacparse->block_size = 0;
328 flacparse->sample_number = 0;
329 flacparse->strategy_checked = FALSE;
332 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
334 /* inform baseclass we can come up with ts, based on counters in packets */
335 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
336 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
342 gst_flac_parse_stop (GstBaseParse * parse)
344 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
346 if (flacparse->tags) {
347 gst_tag_list_free (flacparse->tags);
348 flacparse->tags = NULL;
351 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
352 g_list_free (flacparse->headers);
353 flacparse->headers = NULL;
358 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
360 static const guint16 blocksize_table[16] = {
361 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
362 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
366 static const guint32 sample_rate_table[16] = {
368 88200, 176400, 192000,
369 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
376 FRAME_HEADER_INVALID,
377 FRAME_HEADER_MORE_DATA
378 } FrameHeaderCheckReturn;
380 static FrameHeaderCheckReturn
381 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
382 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
384 GstBitReader reader = GST_BIT_READER_INIT (data, size);
385 guint8 blocking_strategy;
387 guint32 samplerate = 0;
388 guint64 sample_number;
389 guint8 channels, bps;
391 guint8 actual_crc, expected_crc = 0;
393 /* Skip 14 bit sync code */
394 gst_bit_reader_skip_unchecked (&reader, 14);
397 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
400 /* 0 == fixed block size, 1 == variable block size */
401 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
402 if (flacparse->force_variable_block_size)
403 blocking_strategy = 1;
405 /* block size index, calculation of the real blocksize below */
406 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
410 /* sample rate index, calculation of the real samplerate below */
411 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
412 if (samplerate == 0x0f)
415 /* channel assignment */
416 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
419 } else if (channels <= 10) {
421 } else if (channels > 10) {
424 if (flacparse->channels && flacparse->channels != channels)
427 /* bits per sample */
428 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
429 if (bps == 0x03 || bps == 0x07) {
431 } else if (bps == 0 && flacparse->bps == 0) {
432 goto need_streaminfo;
434 bps = sample_size_table[bps];
435 if (flacparse->bps && bps != flacparse->bps)
438 /* reserved, must be 0 */
439 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
442 /* read "utf8" encoded sample/frame number */
446 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
448 /* This is slightly faster than a loop */
452 } else if ((len & 0xc0) && !(len & 0x20)) {
453 sample_number = len & 0x1f;
455 } else if ((len & 0xe0) && !(len & 0x10)) {
456 sample_number = len & 0x0f;
458 } else if ((len & 0xf0) && !(len & 0x08)) {
459 sample_number = len & 0x07;
461 } else if ((len & 0xf8) && !(len & 0x04)) {
462 sample_number = len & 0x03;
464 } else if ((len & 0xfc) && !(len & 0x02)) {
465 sample_number = len & 0x01;
467 } else if ((len & 0xfe) && !(len & 0x01)) {
468 sample_number = len & 0x0;
474 if ((blocking_strategy == 0 && len > 5) ||
475 (blocking_strategy == 1 && len > 6))
479 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
482 if ((tmp & 0xc0) != 0x80)
486 sample_number |= (tmp & 0x3f);
491 /* calculate real blocksize from the blocksize index */
492 if (block_size == 0) {
494 } else if (block_size == 6) {
495 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
498 } else if (block_size == 7) {
499 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
503 block_size = blocksize_table[block_size];
506 /* calculate the real samplerate from the samplerate index */
507 if (samplerate == 0 && flacparse->samplerate == 0) {
508 goto need_streaminfo;
509 } else if (samplerate < 12) {
510 samplerate = sample_rate_table[samplerate];
511 } else if (samplerate == 12) {
512 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
515 } else if (samplerate == 13) {
516 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
518 } else if (samplerate == 14) {
519 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
524 if (flacparse->samplerate && flacparse->samplerate != samplerate)
527 /* check crc-8 for the header */
528 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
532 gst_flac_calculate_crc8 (data,
533 (gst_bit_reader_get_pos (&reader) / 8) - 1);
534 if (actual_crc != expected_crc)
537 /* Sanity check sample number against blocking strategy, as it seems
538 some files claim fixed block size but supply sample numbers,
539 rather than block numbers. */
540 if (blocking_strategy == 0 && flacparse->block_size != 0) {
541 if (!flacparse->strategy_checked) {
542 if (block_size == sample_number) {
543 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
544 "but seems to be lying: assuming variable block size");
545 flacparse->force_variable_block_size = TRUE;
546 blocking_strategy = 1;
548 flacparse->strategy_checked = TRUE;
553 The FLAC format documentation says:
554 The "blocking strategy" bit determines how to calculate the sample number
555 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
556 frame header encodes the frame number as above, and the frame's starting
557 sample number will be the frame number times the blocksize. If it is 1
558 (variable-blocksize), the frame header encodes the frame's starting
559 sample number itself. (In the case of a fixed-blocksize stream, only the
560 last block may be shorter than the stream blocksize; its starting sample
561 number will be calculated as the frame number times the previous frame's
562 blocksize, or zero if it is the first frame).
564 Therefore, when in fixed block size mode, we only update the block size
565 the first time, then reuse that block size for subsequent calls.
566 This will also fix a timestamp problem with the last block's timestamp
567 being miscalculated by scaling the block number by a "wrong" block size.
569 if (blocking_strategy == 0) {
570 if (flacparse->block_size != 0) {
571 /* after first block */
572 if (flacparse->block_size != block_size) {
573 /* TODO: can we know we're on the last frame, to avoid warning ? */
574 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
575 block_size = flacparse->block_size;
581 flacparse->block_size = block_size;
582 if (!flacparse->samplerate)
583 flacparse->samplerate = samplerate;
585 flacparse->bps = bps;
586 if (!flacparse->blocking_strategy)
587 flacparse->blocking_strategy = blocking_strategy;
588 if (!flacparse->channels)
589 flacparse->channels = channels;
590 if (!flacparse->sample_number)
591 flacparse->sample_number = sample_number;
593 GST_DEBUG_OBJECT (flacparse,
594 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
595 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
596 flacparse->block_size, flacparse->sample_number);
600 *block_size_ret = block_size;
602 return FRAME_HEADER_VALID;
605 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
606 return FRAME_HEADER_INVALID;
608 return FRAME_HEADER_INVALID;
611 return FRAME_HEADER_MORE_DATA;
615 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
616 GstBaseParseFrame * frame, guint * ret)
620 guint max, remaining;
621 guint i, search_start, search_end;
622 FrameHeaderCheckReturn header_ret;
624 gboolean result = FALSE;
626 buffer = frame->buffer;
627 gst_buffer_map (buffer, &map, GST_MAP_READ);
629 if (map.size < flacparse->min_framesize)
633 gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
635 if (header_ret == FRAME_HEADER_INVALID) {
639 if (header_ret == FRAME_HEADER_MORE_DATA)
642 /* mind unknown framesize */
643 search_start = MAX (2, flacparse->min_framesize);
644 if (flacparse->max_framesize)
645 search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
647 search_end = map.size;
650 remaining = map.size;
652 for (i = search_start; i < search_end; i++, remaining--) {
653 if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
655 gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
656 remaining, FALSE, NULL);
657 if (header_ret == FRAME_HEADER_VALID) {
658 if (flacparse->check_frame_checksums) {
659 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
660 guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
662 if (actual_crc != expected_crc)
666 flacparse->block_size = block_size;
669 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
675 /* For the last frame output everything to the end */
676 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
677 if (flacparse->check_frame_checksums) {
678 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
679 guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
681 if (actual_crc == expected_crc) {
683 flacparse->block_size = block_size;
689 flacparse->block_size = block_size;
696 max = flacparse->max_framesize + 16;
699 *ret = MIN (map.size + 4096, max);
703 gst_buffer_unmap (buffer, &map);
708 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
709 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
711 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
712 GstBuffer *buffer = frame->buffer;
714 gboolean result = TRUE;
716 gst_buffer_map (buffer, &map, GST_MAP_READ);
718 if (G_UNLIKELY (map.size < 4)) {
723 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
724 if (memcmp (map.data, "fLaC", 4) == 0) {
725 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
729 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
730 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
731 /* Minimal size of a frame header */
732 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
733 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
738 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
743 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
744 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
746 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
751 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
755 flacparse->offset = GST_BUFFER_OFFSET (buffer);
756 flacparse->blocking_strategy = 0;
757 flacparse->sample_number = 0;
759 GST_DEBUG_OBJECT (flacparse, "Found sync code");
760 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
765 /* If we're at EOS and the frame was not valid, drop it! */
766 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
767 GST_WARNING_OBJECT (flacparse, "EOS");
773 } else if (next > map.size) {
774 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
776 gst_base_parse_set_min_frame_size (parse, next);
780 GST_ERROR_OBJECT (flacparse,
781 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
787 GstByteReader reader;
790 gst_byte_reader_init (&reader, map.data, map.size);
792 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
796 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
801 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
802 *skipsize = map.size - 3;
811 gst_buffer_unmap (buffer, &map);
816 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
821 gst_buffer_map (buffer, &map, GST_MAP_READ);
822 gst_bit_reader_init (&reader, map.data, map.size);
824 if (map.size != 4 + 34) {
825 GST_ERROR_OBJECT (flacparse,
826 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
830 /* Skip metadata block header */
831 gst_bit_reader_skip (&reader, 32);
833 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
835 if (flacparse->min_blocksize < 16) {
836 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
837 flacparse->min_blocksize);
840 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
842 if (flacparse->max_blocksize < 16) {
843 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
844 flacparse->max_blocksize);
847 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
849 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
852 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
854 if (flacparse->samplerate == 0) {
855 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
859 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
861 flacparse->channels++;
862 if (flacparse->channels > 8) {
863 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
864 flacparse->channels);
868 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
872 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
874 if (flacparse->total_samples) {
875 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
876 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
879 gst_buffer_unmap (buffer, &map);
881 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
882 "\tmin/max blocksize: %u/%u,\n"
883 "\tmin/max framesize: %u/%u,\n"
884 "\tsamplerate: %u,\n"
886 "\tbits per sample: %u,\n"
887 "\ttotal samples: %" G_GUINT64_FORMAT,
888 flacparse->min_blocksize, flacparse->max_blocksize,
889 flacparse->min_framesize, flacparse->max_framesize,
890 flacparse->samplerate,
891 flacparse->channels, flacparse->bps, flacparse->total_samples);
896 GST_ERROR_OBJECT (flacparse, "Failed to read data");
898 gst_buffer_unmap (buffer, &map);
903 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
908 gst_buffer_map (buffer, &map, GST_MAP_READ);
911 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
912 gst_buffer_unmap (buffer, &map);
914 if (flacparse->tags == NULL) {
915 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
916 } else if (gst_tag_list_is_empty (flacparse->tags)) {
917 gst_tag_list_free (flacparse->tags);
918 flacparse->tags = NULL;
925 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
927 GstByteReader reader;
929 guint32 img_len = 0, img_type = 0;
930 guint32 img_mimetype_len = 0, img_description_len = 0;
932 gst_buffer_map (buffer, &map, GST_MAP_READ);
933 gst_byte_reader_init (&reader, map.data, map.size);
935 if (!gst_byte_reader_skip (&reader, 4))
938 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
941 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
943 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
946 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
948 if (!gst_byte_reader_skip (&reader, img_description_len))
951 if (!gst_byte_reader_skip (&reader, 4 * 4))
954 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
957 if (!flacparse->tags)
958 flacparse->tags = gst_tag_list_new_empty ();
960 gst_tag_list_add_id3_image (flacparse->tags,
961 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
963 if (gst_tag_list_is_empty (flacparse->tags)) {
964 gst_tag_list_free (flacparse->tags);
965 flacparse->tags = NULL;
968 gst_buffer_unmap (buffer, &map);
972 GST_ERROR_OBJECT (flacparse, "Error reading data");
973 gst_buffer_unmap (buffer, &map);
978 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
981 GST_DEBUG_OBJECT (flacparse, "storing seektable");
982 /* only store for now;
983 * offset of the first frame is needed to get real info */
984 flacparse->seektable = gst_buffer_ref (buffer);
990 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
993 gint64 offset = 0, samples = 0;
996 GST_DEBUG_OBJECT (flacparse,
997 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1002 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1003 gst_byte_reader_init (&br, map.data, map.size);
1006 if (!gst_byte_reader_skip (&br, 4))
1010 while (gst_byte_reader_get_remaining (&br)) {
1011 if (!gst_byte_reader_get_int64_be (&br, &samples))
1013 if (!gst_byte_reader_get_int64_be (&br, &offset))
1015 if (!gst_byte_reader_skip (&br, 2))
1018 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1019 G_GINT64_FORMAT, samples, offset);
1022 if (G_LIKELY (offset > 0 && samples > 0)) {
1023 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1024 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1025 flacparse->samplerate), TRUE, FALSE);
1030 gst_buffer_unmap (flacparse->seektable, &map);
1032 gst_buffer_unref (flacparse->seektable);
1033 flacparse->seektable = NULL;
1037 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1039 GValue value = { 0, };
1041 g_value_init (&value, GST_TYPE_BUFFER);
1042 /* copy buffer to avoid problems with circular refcounts */
1043 buf = gst_buffer_copy (buf);
1044 /* again, for good measure */
1045 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1046 gst_value_set_buffer (&value, buf);
1047 gst_buffer_unref (buf);
1048 gst_value_array_append_value (array_val, &value);
1049 g_value_unset (&value);
1053 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1055 GstBuffer *vorbiscomment = NULL;
1056 GstBuffer *streaminfo = NULL;
1057 GstBuffer *marker = NULL;
1058 GValue array = { 0, };
1061 gboolean res = TRUE;
1063 caps = gst_caps_new_simple ("audio/x-flac",
1064 "channels", G_TYPE_INT, flacparse->channels,
1065 "framed", G_TYPE_BOOLEAN, TRUE,
1066 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1068 if (!flacparse->headers)
1071 for (l = flacparse->headers; l; l = l->next) {
1072 GstBuffer *header = l->data;
1075 gst_buffer_map (header, &map, GST_MAP_READ);
1077 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1079 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1081 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1082 streaminfo = header;
1083 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1084 vorbiscomment = header;
1087 gst_buffer_unmap (header, &map);
1090 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1091 GST_WARNING_OBJECT (flacparse,
1092 "missing header %p %p %p, muxing into container "
1093 "formats may be broken", marker, streaminfo, vorbiscomment);
1097 g_value_init (&array, GST_TYPE_ARRAY);
1099 /* add marker including STREAMINFO header */
1103 GstMapInfo sinfomap, writemap;
1105 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1107 /* minus one for the marker that is merged with streaminfo here */
1108 num = g_list_length (flacparse->headers) - 1;
1110 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1111 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1113 writemap.data[0] = 0x7f;
1114 memcpy (writemap.data + 1, "FLAC", 4);
1115 writemap.data[5] = 0x01; /* mapping version major */
1116 writemap.data[6] = 0x00; /* mapping version minor */
1117 writemap.data[7] = (num & 0xFF00) >> 8;
1118 writemap.data[8] = (num & 0x00FF) >> 0;
1119 memcpy (writemap.data + 9, "fLaC", 4);
1120 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1121 _value_array_append_buffer (&array, buf);
1123 gst_buffer_unmap (streaminfo, &sinfomap);
1124 gst_buffer_unmap (buf, &writemap);
1125 gst_buffer_unref (buf);
1128 /* add VORBISCOMMENT header */
1129 _value_array_append_buffer (&array, vorbiscomment);
1131 /* add other headers, if there are any */
1132 for (l = flacparse->headers; l; l = l->next) {
1133 if (GST_BUFFER_CAST (l->data) != marker &&
1134 GST_BUFFER_CAST (l->data) != streaminfo &&
1135 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1136 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1140 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1141 "streamheader", &array);
1142 g_value_unset (&array);
1146 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1147 gst_caps_unref (caps);
1149 /* push header buffers; update caps, so when we push the first buffer the
1150 * negotiated caps will change to caps that include the streamheader field */
1151 while (flacparse->headers) {
1152 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1154 GstBaseParseFrame frame;
1156 flacparse->headers =
1157 g_list_delete_link (flacparse->headers, flacparse->headers);
1158 buf = gst_buffer_make_writable (buf);
1160 /* init, set and give away frame */
1161 gst_base_parse_frame_init (&frame);
1163 frame.overhead = -1;
1164 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1165 if (ret != GST_FLOW_OK) {
1170 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1171 g_list_free (flacparse->headers);
1172 flacparse->headers = NULL;
1178 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1180 GstBuffer *marker, *streaminfo, *vorbiscomment;
1183 marker = gst_buffer_new_and_alloc (4);
1184 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1185 memcpy (map.data, "fLaC", 4);
1186 gst_buffer_unmap (marker, &map);
1187 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1188 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1189 GST_BUFFER_OFFSET (marker) = 0;
1190 GST_BUFFER_OFFSET_END (marker) = 0;
1191 flacparse->headers = g_list_append (flacparse->headers, marker);
1193 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1194 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1195 memset (map.data, 0, 4 + 34);
1197 /* metadata block header */
1198 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1199 map.data[1] = 0x00; /* length = 34; */
1205 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1206 map.data[5] = (flacparse->block_size) & 0xff;
1207 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1208 map.data[7] = (flacparse->block_size) & 0xff;
1210 map.data[8] = 0x00; /* min framesize = 0; */
1212 map.data[10] = 0x00;
1213 map.data[11] = 0x00; /* max framesize = 0; */
1214 map.data[12] = 0x00;
1215 map.data[13] = 0x00;
1217 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1218 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1219 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1221 map.data[16] |= (flacparse->channels - 1) << 1;
1223 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1224 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1229 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1230 GST_FORMAT_TIME, &duration)) {
1231 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1233 map.data[17] |= (duration >> 32) & 0xff;
1234 map.data[18] |= (duration >> 24) & 0xff;
1235 map.data[19] |= (duration >> 16) & 0xff;
1236 map.data[20] |= (duration >> 8) & 0xff;
1237 map.data[21] |= (duration >> 0) & 0xff;
1242 gst_buffer_unmap (streaminfo, &map);
1243 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1244 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1245 GST_BUFFER_OFFSET (streaminfo) = 0;
1246 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1247 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1249 /* empty vorbiscomment */
1251 GstTagList *taglist = gst_tag_list_new_empty ();
1255 header[0] = 0x84; /* is_last = 1; type = 4; */
1258 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1259 sizeof (header), NULL);
1260 gst_tag_list_free (taglist);
1262 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1264 /* Get rid of framing bit */
1265 if (map.data[map.size - 1] == 1) {
1269 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1271 gst_buffer_unmap (vorbiscomment, &map);
1272 gst_buffer_unref (vorbiscomment);
1273 vorbiscomment = sub;
1274 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1277 size = map.size - 4;
1278 map.data[1] = ((size & 0xFF0000) >> 16);
1279 map.data[2] = ((size & 0x00FF00) >> 8);
1280 map.data[3] = (size & 0x0000FF);
1281 gst_buffer_unmap (vorbiscomment, &map);
1283 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1284 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1285 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1286 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1287 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1293 static GstFlowReturn
1294 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1296 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1297 GstBuffer *buffer = frame->buffer;
1299 GstFlowReturn res = GST_FLOW_ERROR;
1301 gst_buffer_map (buffer, &map, GST_MAP_READ);
1303 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1304 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1305 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1306 GST_BUFFER_OFFSET (buffer) = 0;
1307 GST_BUFFER_OFFSET_END (buffer) = 0;
1309 /* 32 bits metadata block */
1310 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1311 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1313 flacparse->headers =
1314 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1316 res = GST_BASE_PARSE_FLOW_DROPPED;
1317 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1318 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1319 guint type = (map.data[0] & 0x7F);
1322 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1323 res = GST_BASE_PARSE_FLOW_DROPPED;
1327 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1330 case 0: /* STREAMINFO */
1331 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1334 case 3: /* SEEKTABLE */
1335 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1338 case 4: /* VORBIS_COMMENT */
1339 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1342 case 6: /* PICTURE */
1343 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1346 case 1: /* PADDING */
1347 case 2: /* APPLICATION */
1348 case 5: /* CUESHEET */
1349 default: /* RESERVED */
1353 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1354 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1355 GST_BUFFER_OFFSET (buffer) = 0;
1356 GST_BUFFER_OFFSET_END (buffer) = 0;
1358 flacparse->headers =
1359 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1362 if (!gst_flac_parse_handle_headers (flacparse))
1365 /* Minimal size of a frame header */
1366 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1367 flacparse->min_framesize));
1368 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1371 /* DROPPED because we pushed already or will push all headers manually */
1372 res = GST_BASE_PARSE_FLOW_DROPPED;
1374 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1375 FrameHeaderCheckReturn ret;
1377 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1379 gst_flac_parse_frame_header_is_valid (flacparse,
1380 map.data, map.size, TRUE, NULL);
1381 if (ret != FRAME_HEADER_VALID) {
1382 GST_ERROR_OBJECT (flacparse,
1383 "Baseclass didn't provide a complete frame");
1388 if (flacparse->block_size == 0) {
1389 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1393 if (flacparse->seektable)
1394 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1396 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1397 if (flacparse->blocking_strategy == 1) {
1398 GST_WARNING_OBJECT (flacparse,
1399 "Generating headers for variable blocksize streams not supported");
1401 if (!gst_flac_parse_handle_headers (flacparse))
1404 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1406 if (!gst_flac_parse_generate_headers (flacparse))
1409 if (!gst_flac_parse_handle_headers (flacparse))
1412 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1415 /* also cater for oggmux metadata */
1416 if (flacparse->blocking_strategy == 0) {
1417 GST_BUFFER_TIMESTAMP (buffer) =
1418 gst_util_uint64_scale (flacparse->sample_number,
1419 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1420 GST_BUFFER_OFFSET_END (buffer) =
1421 flacparse->sample_number * flacparse->block_size +
1422 flacparse->block_size;
1424 GST_BUFFER_TIMESTAMP (buffer) =
1425 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1426 flacparse->samplerate);
1427 GST_BUFFER_OFFSET_END (buffer) =
1428 flacparse->sample_number + flacparse->block_size;
1430 GST_BUFFER_OFFSET (buffer) =
1431 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1432 flacparse->samplerate);
1433 GST_BUFFER_DURATION (buffer) =
1434 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1436 /* To simplify, we just assume that it's a fixed size header and ignore
1437 * subframe headers. The first could lead us to being off by 88 bits and
1438 * the second even less, so the total inaccuracy is negligible. */
1439 frame->overhead = 7;
1441 /* Minimal size of a frame header */
1442 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1443 flacparse->min_framesize));
1445 flacparse->offset = -1;
1446 flacparse->blocking_strategy = 0;
1447 flacparse->sample_number = 0;
1452 gst_buffer_unmap (buffer, &map);
1457 static GstFlowReturn
1458 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1460 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1463 if (flacparse->tags) {
1464 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1465 gst_event_new_tag (flacparse->tags));
1466 flacparse->tags = NULL;
1469 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1475 gst_flac_parse_convert (GstBaseParse * parse,
1476 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1477 gint64 * dest_value)
1479 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1481 if (flacparse->samplerate > 0) {
1482 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1483 if (src_value != -1)
1485 gst_util_uint64_scale (src_value, GST_SECOND,
1486 flacparse->samplerate);
1490 } else if (src_format == GST_FORMAT_TIME &&
1491 dest_format == GST_FORMAT_DEFAULT) {
1492 if (src_value != -1)
1494 gst_util_uint64_scale (src_value, flacparse->samplerate,
1502 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1503 src_value, dest_format, dest_value);
1507 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1512 /* FIXME: handle filter caps */
1514 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1518 /* Remove the framed field */
1519 peercaps = gst_caps_make_writable (peercaps);
1520 n = gst_caps_get_size (peercaps);
1521 for (i = 0; i < n; i++) {
1522 GstStructure *s = gst_caps_get_structure (peercaps, i);
1524 gst_structure_remove_field (s, "framed");
1528 gst_caps_intersect_full (peercaps,
1529 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1530 GST_CAPS_INTERSECT_FIRST);
1531 gst_caps_unref (peercaps);
1534 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD