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);
206 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
207 GST_TYPE_BASE_PARSE);
210 gst_flac_parse_base_init (gpointer g_class)
212 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
214 gst_element_class_add_pad_template (element_class,
215 gst_static_pad_template_get (&src_factory));
216 gst_element_class_add_pad_template (element_class,
217 gst_static_pad_template_get (&sink_factory));
219 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
220 "Codec/Parser/Audio",
221 "Parses audio with the FLAC lossless audio codec",
222 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
224 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
225 "Flac parser element");
229 gst_flac_parse_class_init (GstFlacParseClass * klass)
231 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
232 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
234 gobject_class->finalize = gst_flac_parse_finalize;
235 gobject_class->set_property = gst_flac_parse_set_property;
236 gobject_class->get_property = gst_flac_parse_get_property;
238 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
239 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
240 "Check the overall checksums of every frame",
241 DEFAULT_CHECK_FRAME_CHECKSUMS,
242 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
244 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
245 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
246 baseparse_class->check_valid_frame =
247 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
248 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
249 baseparse_class->pre_push_frame =
250 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
251 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
252 baseparse_class->get_sink_caps =
253 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
257 gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
259 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
263 gst_flac_parse_set_property (GObject * object, guint prop_id,
264 const GValue * value, GParamSpec * pspec)
266 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
269 case PROP_CHECK_FRAME_CHECKSUMS:
270 flacparse->check_frame_checksums = g_value_get_boolean (value);
273 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279 gst_flac_parse_get_property (GObject * object, guint prop_id,
280 GValue * value, GParamSpec * pspec)
282 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
285 case PROP_CHECK_FRAME_CHECKSUMS:
286 g_value_set_boolean (value, flacparse->check_frame_checksums);
289 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
295 gst_flac_parse_finalize (GObject * object)
297 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
299 if (flacparse->tags) {
300 gst_tag_list_free (flacparse->tags);
301 flacparse->tags = NULL;
304 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
305 g_list_free (flacparse->headers);
306 flacparse->headers = NULL;
308 G_OBJECT_CLASS (parent_class)->finalize (object);
312 gst_flac_parse_start (GstBaseParse * parse)
314 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
316 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
317 flacparse->min_blocksize = 0;
318 flacparse->max_blocksize = 0;
319 flacparse->min_framesize = 0;
320 flacparse->max_framesize = 0;
322 flacparse->upstream_length = -1;
324 flacparse->samplerate = 0;
325 flacparse->channels = 0;
327 flacparse->total_samples = 0;
329 flacparse->offset = GST_CLOCK_TIME_NONE;
330 flacparse->blocking_strategy = 0;
331 flacparse->block_size = 0;
332 flacparse->sample_number = 0;
335 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
337 /* inform baseclass we can come up with ts, based on counters in packets */
338 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
339 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
345 gst_flac_parse_stop (GstBaseParse * parse)
347 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
349 if (flacparse->tags) {
350 gst_tag_list_free (flacparse->tags);
351 flacparse->tags = NULL;
354 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
355 g_list_free (flacparse->headers);
356 flacparse->headers = NULL;
361 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
363 static const guint16 blocksize_table[16] = {
364 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
365 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
369 static const guint32 sample_rate_table[16] = {
371 88200, 176400, 192000,
372 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
379 FRAME_HEADER_INVALID,
380 FRAME_HEADER_MORE_DATA
381 } FrameHeaderCheckReturn;
383 static FrameHeaderCheckReturn
384 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
385 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
387 GstBitReader reader = GST_BIT_READER_INIT (data, size);
388 guint8 blocking_strategy;
390 guint32 samplerate = 0;
391 guint64 sample_number;
392 guint8 channels, bps;
394 guint8 actual_crc, expected_crc = 0;
396 /* Skip 14 bit sync code */
397 gst_bit_reader_skip_unchecked (&reader, 14);
400 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
403 /* 0 == fixed block size, 1 == variable block size */
404 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
405 if (flacparse->force_variable_block_size)
406 blocking_strategy = 1;
408 /* block size index, calculation of the real blocksize below */
409 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
413 /* sample rate index, calculation of the real samplerate below */
414 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
415 if (samplerate == 0x0f)
418 /* channel assignment */
419 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
422 } else if (channels <= 10) {
424 } else if (channels > 10) {
427 if (flacparse->channels && flacparse->channels != channels)
430 /* bits per sample */
431 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
432 if (bps == 0x03 || bps == 0x07) {
434 } else if (bps == 0 && flacparse->bps == 0) {
435 goto need_streaminfo;
437 bps = sample_size_table[bps];
438 if (flacparse->bps && bps != flacparse->bps)
441 /* reserved, must be 0 */
442 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
445 /* read "utf8" encoded sample/frame number */
449 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
451 /* This is slightly faster than a loop */
455 } else if ((len & 0xc0) && !(len & 0x20)) {
456 sample_number = len & 0x1f;
458 } else if ((len & 0xe0) && !(len & 0x10)) {
459 sample_number = len & 0x0f;
461 } else if ((len & 0xf0) && !(len & 0x08)) {
462 sample_number = len & 0x07;
464 } else if ((len & 0xf8) && !(len & 0x04)) {
465 sample_number = len & 0x03;
467 } else if ((len & 0xfc) && !(len & 0x02)) {
468 sample_number = len & 0x01;
470 } else if ((len & 0xfe) && !(len & 0x01)) {
471 sample_number = len & 0x0;
477 if ((blocking_strategy == 0 && len > 5) ||
478 (blocking_strategy == 1 && len > 6))
482 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
485 if ((tmp & 0xc0) != 0x80)
489 sample_number |= (tmp & 0x3f);
494 /* calculate real blocksize from the blocksize index */
495 if (block_size == 0) {
497 } else if (block_size == 6) {
498 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
501 } else if (block_size == 7) {
502 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
506 block_size = blocksize_table[block_size];
509 /* calculate the real samplerate from the samplerate index */
510 if (samplerate == 0 && flacparse->samplerate == 0) {
511 goto need_streaminfo;
512 } else if (samplerate < 12) {
513 samplerate = sample_rate_table[samplerate];
514 } else if (samplerate == 12) {
515 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
518 } else if (samplerate == 13) {
519 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
521 } else if (samplerate == 14) {
522 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
527 if (flacparse->samplerate && flacparse->samplerate != samplerate)
530 /* check crc-8 for the header */
531 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
535 gst_flac_calculate_crc8 (data,
536 (gst_bit_reader_get_pos (&reader) / 8) - 1);
537 if (actual_crc != expected_crc)
540 /* Sanity check sample number against blocking strategy, as it seems
541 some files claim fixed block size but supply sample numbers,
542 rather than block numbers. */
543 if (set && blocking_strategy == 0 && block_size == sample_number) {
544 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
545 "but seems to be lying: assuming variable block size");
546 flacparse->force_variable_block_size = TRUE;
547 blocking_strategy = 1;
551 The FLAC format documentation says:
552 The "blocking strategy" bit determines how to calculate the sample number
553 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
554 frame header encodes the frame number as above, and the frame's starting
555 sample number will be the frame number times the blocksize. If it is 1
556 (variable-blocksize), the frame header encodes the frame's starting
557 sample number itself. (In the case of a fixed-blocksize stream, only the
558 last block may be shorter than the stream blocksize; its starting sample
559 number will be calculated as the frame number times the previous frame's
560 blocksize, or zero if it is the first frame).
562 Therefore, when in fixed block size mode, we only update the block size
563 the first time, then reuse that block size for subsequent calls.
564 This will also fix a timestamp problem with the last block's timestamp
565 being miscalculated by scaling the block number by a "wrong" block size.
567 if (blocking_strategy == 0) {
568 if (flacparse->block_size != 0) {
569 /* after first block */
570 if (flacparse->block_size != block_size) {
571 /* TODO: can we know we're on the last frame, to avoid warning ? */
572 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
573 block_size = flacparse->block_size;
579 flacparse->block_size = block_size;
580 if (!flacparse->samplerate)
581 flacparse->samplerate = samplerate;
583 flacparse->bps = bps;
584 if (!flacparse->blocking_strategy)
585 flacparse->blocking_strategy = blocking_strategy;
586 if (!flacparse->channels)
587 flacparse->channels = channels;
588 if (!flacparse->sample_number)
589 flacparse->sample_number = sample_number;
591 GST_DEBUG_OBJECT (flacparse,
592 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
593 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
594 flacparse->block_size, flacparse->sample_number);
598 *block_size_ret = block_size;
600 return FRAME_HEADER_VALID;
603 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
604 return FRAME_HEADER_INVALID;
606 return FRAME_HEADER_INVALID;
609 return FRAME_HEADER_MORE_DATA;
613 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
614 GstBaseParseFrame * frame, guint * ret)
618 guint max, size, remaining;
619 guint i, search_start, search_end;
620 FrameHeaderCheckReturn header_ret;
623 buffer = frame->buffer;
624 data = GST_BUFFER_DATA (buffer);
625 size = GST_BUFFER_SIZE (buffer);
627 if (size < flacparse->min_framesize)
631 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
633 if (header_ret == FRAME_HEADER_INVALID) {
636 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
640 /* mind unknown framesize */
641 search_start = MAX (2, flacparse->min_framesize);
642 if (flacparse->max_framesize)
643 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
650 for (i = search_start; i < search_end; i++, remaining--) {
651 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
653 gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
655 if (header_ret == FRAME_HEADER_VALID) {
656 if (flacparse->check_frame_checksums) {
657 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
658 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
660 if (actual_crc != expected_crc)
664 flacparse->block_size = block_size;
666 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
672 /* For the last frame output everything to the end */
673 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
674 if (flacparse->check_frame_checksums) {
675 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
676 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
678 if (actual_crc == expected_crc) {
680 flacparse->block_size = block_size;
685 flacparse->block_size = block_size;
691 max = flacparse->max_framesize + 16;
694 *ret = MIN (size + 4096, max);
699 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
700 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
702 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
703 GstBuffer *buffer = frame->buffer;
704 const guint8 *data = GST_BUFFER_DATA (buffer);
706 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
709 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
710 if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
711 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
714 } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
715 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
716 /* Minimal size of a frame header */
717 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
718 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
722 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
725 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
726 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
728 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
732 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
736 flacparse->offset = GST_BUFFER_OFFSET (buffer);
737 flacparse->blocking_strategy = 0;
738 flacparse->sample_number = 0;
740 GST_DEBUG_OBJECT (flacparse, "Found sync code");
741 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
746 /* If we're at EOS and the frame was not valid, drop it! */
747 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
748 GST_WARNING_OBJECT (flacparse, "EOS");
753 } else if (next > GST_BUFFER_SIZE (buffer)) {
754 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
756 gst_base_parse_set_min_frame_size (parse, next);
759 GST_ERROR_OBJECT (flacparse,
760 "Giving up on invalid frame (%d bytes)",
761 GST_BUFFER_SIZE (buffer));
766 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
770 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
771 0, GST_BUFFER_SIZE (buffer));
774 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
778 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
779 *skipsize = GST_BUFFER_SIZE (buffer) - 3;
789 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
791 GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
793 if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
794 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
795 GST_BUFFER_SIZE (buffer));
799 /* Skip metadata block header */
800 gst_bit_reader_skip (&reader, 32);
802 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
804 if (flacparse->min_blocksize < 16) {
805 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
806 flacparse->min_blocksize);
809 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
811 if (flacparse->max_blocksize < 16) {
812 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
813 flacparse->max_blocksize);
816 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
818 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
821 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
823 if (flacparse->samplerate == 0) {
824 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
828 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
830 flacparse->channels++;
831 if (flacparse->channels > 8) {
832 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
833 flacparse->channels);
837 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
841 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
843 if (flacparse->total_samples) {
844 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
845 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
848 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
849 "\tmin/max blocksize: %u/%u,\n"
850 "\tmin/max framesize: %u/%u,\n"
851 "\tsamplerate: %u,\n"
853 "\tbits per sample: %u,\n"
854 "\ttotal samples: %" G_GUINT64_FORMAT,
855 flacparse->min_blocksize, flacparse->max_blocksize,
856 flacparse->min_framesize, flacparse->max_framesize,
857 flacparse->samplerate,
858 flacparse->channels, flacparse->bps, flacparse->total_samples);
863 GST_ERROR_OBJECT (flacparse, "Failed to read data");
868 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
871 flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
872 GST_BUFFER_DATA (buffer), 4, NULL);
874 if (flacparse->tags == NULL) {
875 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
876 } else if (gst_tag_list_is_empty (flacparse->tags)) {
877 gst_tag_list_free (flacparse->tags);
878 flacparse->tags = NULL;
885 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
887 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
888 const guint8 *data = GST_BUFFER_DATA (buffer);
889 guint32 img_len = 0, img_type = 0;
890 guint32 img_mimetype_len = 0, img_description_len = 0;
892 if (!gst_byte_reader_skip (&reader, 4))
895 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
898 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
900 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
903 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
905 if (!gst_byte_reader_skip (&reader, img_description_len))
908 if (!gst_byte_reader_skip (&reader, 4 * 4))
911 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
914 if (!flacparse->tags)
915 flacparse->tags = gst_tag_list_new ();
917 gst_tag_list_add_id3_image (flacparse->tags,
918 data + gst_byte_reader_get_pos (&reader), img_len, img_type);
920 if (gst_tag_list_is_empty (flacparse->tags)) {
921 gst_tag_list_free (flacparse->tags);
922 flacparse->tags = NULL;
928 GST_ERROR_OBJECT (flacparse, "Error reading data");
933 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
936 GST_DEBUG_OBJECT (flacparse, "storing seektable");
937 /* only store for now;
938 * offset of the first frame is needed to get real info */
939 flacparse->seektable = gst_buffer_ref (buffer);
945 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
948 gint64 offset = 0, samples = 0;
950 GST_DEBUG_OBJECT (flacparse,
951 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
956 gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
958 if (!gst_byte_reader_skip (&br, 4))
962 while (gst_byte_reader_get_remaining (&br)) {
963 if (!gst_byte_reader_get_int64_be (&br, &samples))
965 if (!gst_byte_reader_get_int64_be (&br, &offset))
967 if (!gst_byte_reader_skip (&br, 2))
970 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
971 G_GINT64_FORMAT, samples, offset);
974 if (G_LIKELY (offset > 0 && samples > 0)) {
975 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
976 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
977 flacparse->samplerate), TRUE, FALSE);
982 gst_buffer_unref (flacparse->seektable);
983 flacparse->seektable = NULL;
987 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
989 GValue value = { 0, };
991 g_value_init (&value, GST_TYPE_BUFFER);
992 /* copy buffer to avoid problems with circular refcounts */
993 buf = gst_buffer_copy (buf);
994 /* again, for good measure */
995 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
996 gst_value_set_buffer (&value, buf);
997 gst_buffer_unref (buf);
998 gst_value_array_append_value (array_val, &value);
999 g_value_unset (&value);
1003 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1005 GstBuffer *vorbiscomment = NULL;
1006 GstBuffer *streaminfo = NULL;
1007 GstBuffer *marker = NULL;
1008 GValue array = { 0, };
1011 gboolean res = TRUE;
1013 caps = gst_caps_new_simple ("audio/x-flac",
1014 "channels", G_TYPE_INT, flacparse->channels,
1015 "framed", G_TYPE_BOOLEAN, TRUE,
1016 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1018 if (!flacparse->headers)
1021 for (l = flacparse->headers; l; l = l->next) {
1022 GstBuffer *header = l->data;
1023 const guint8 *data = GST_BUFFER_DATA (header);
1024 guint size = GST_BUFFER_SIZE (header);
1026 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
1028 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
1030 } else if (size > 1 && (data[0] & 0x7f) == 0) {
1031 streaminfo = header;
1032 } else if (size > 1 && (data[0] & 0x7f) == 4) {
1033 vorbiscomment = header;
1037 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1038 GST_WARNING_OBJECT (flacparse,
1039 "missing header %p %p %p, muxing into container "
1040 "formats may be broken", marker, streaminfo, vorbiscomment);
1044 g_value_init (&array, GST_TYPE_ARRAY);
1046 /* add marker including STREAMINFO header */
1051 /* minus one for the marker that is merged with streaminfo here */
1052 num = g_list_length (flacparse->headers) - 1;
1054 buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1055 GST_BUFFER_DATA (buf)[0] = 0x7f;
1056 memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1057 GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
1058 GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
1059 GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1060 GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1061 memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1062 memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1063 GST_BUFFER_SIZE (streaminfo));
1064 _value_array_append_buffer (&array, buf);
1065 gst_buffer_unref (buf);
1068 /* add VORBISCOMMENT header */
1069 _value_array_append_buffer (&array, vorbiscomment);
1071 /* add other headers, if there are any */
1072 for (l = flacparse->headers; l; l = l->next) {
1073 if (GST_BUFFER_CAST (l->data) != marker &&
1074 GST_BUFFER_CAST (l->data) != streaminfo &&
1075 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1076 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1080 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1081 "streamheader", &array);
1082 g_value_unset (&array);
1086 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1087 gst_caps_unref (caps);
1089 /* push header buffers; update caps, so when we push the first buffer the
1090 * negotiated caps will change to caps that include the streamheader field */
1091 while (flacparse->headers) {
1092 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1094 GstBaseParseFrame frame;
1096 flacparse->headers =
1097 g_list_delete_link (flacparse->headers, flacparse->headers);
1098 buf = gst_buffer_make_metadata_writable (buf);
1099 gst_buffer_set_caps (buf,
1100 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1102 /* init, set and give away frame */
1103 gst_base_parse_frame_init (&frame);
1105 frame.overhead = -1;
1106 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1107 if (ret != GST_FLOW_OK) {
1112 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1113 g_list_free (flacparse->headers);
1114 flacparse->headers = NULL;
1120 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1122 GstBuffer *marker, *streaminfo, *vorbiscomment;
1125 marker = gst_buffer_new_and_alloc (4);
1126 memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1127 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1128 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1129 GST_BUFFER_OFFSET (marker) = 0;
1130 GST_BUFFER_OFFSET_END (marker) = 0;
1131 flacparse->headers = g_list_append (flacparse->headers, marker);
1133 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1134 data = GST_BUFFER_DATA (streaminfo);
1135 memset (data, 0, 4 + 34);
1137 /* metadata block header */
1138 data[0] = 0x00; /* is_last = 0; type = 0; */
1139 data[1] = 0x00; /* length = 34; */
1145 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1146 data[5] = (flacparse->block_size) & 0xff;
1147 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1148 data[7] = (flacparse->block_size) & 0xff;
1150 data[8] = 0x00; /* min framesize = 0; */
1153 data[11] = 0x00; /* max framesize = 0; */
1157 data[14] = (flacparse->samplerate >> 12) & 0xff;
1158 data[15] = (flacparse->samplerate >> 4) & 0xff;
1159 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1161 data[16] |= (flacparse->channels - 1) << 1;
1163 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1164 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1168 GstFormat fmt = GST_FORMAT_TIME;
1170 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1171 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1172 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1174 data[17] |= (duration >> 32) & 0xff;
1175 data[18] |= (duration >> 24) & 0xff;
1176 data[19] |= (duration >> 16) & 0xff;
1177 data[20] |= (duration >> 8) & 0xff;
1178 data[21] |= (duration >> 0) & 0xff;
1183 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1184 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1185 GST_BUFFER_OFFSET (streaminfo) = 0;
1186 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1187 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1189 /* empty vorbiscomment */
1191 GstTagList *taglist = gst_tag_list_new ();
1195 header[0] = 0x84; /* is_last = 1; type = 4; */
1198 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1199 sizeof (header), NULL);
1200 gst_tag_list_free (taglist);
1202 /* Get rid of framing bit */
1203 if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1208 gst_buffer_create_sub (vorbiscomment, 0,
1209 GST_BUFFER_SIZE (vorbiscomment) - 1);
1210 gst_buffer_unref (vorbiscomment);
1211 vorbiscomment = sub;
1214 size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1215 GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1216 GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1217 GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1219 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1220 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1221 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1222 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1223 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1229 static GstFlowReturn
1230 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1232 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1233 GstBuffer *buffer = frame->buffer;
1234 const guint8 *data = GST_BUFFER_DATA (buffer);
1236 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1237 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1238 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1239 GST_BUFFER_OFFSET (buffer) = 0;
1240 GST_BUFFER_OFFSET_END (buffer) = 0;
1242 /* 32 bits metadata block */
1243 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1244 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1246 flacparse->headers =
1247 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1249 return GST_BASE_PARSE_FLOW_DROPPED;
1250 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1251 gboolean is_last = ((data[0] & 0x80) == 0x80);
1252 guint type = (data[0] & 0x7F);
1255 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1256 return GST_BASE_PARSE_FLOW_DROPPED;
1259 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1262 case 0: /* STREAMINFO */
1263 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1264 return GST_FLOW_ERROR;
1266 case 3: /* SEEKTABLE */
1267 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1268 return GST_FLOW_ERROR;
1270 case 4: /* VORBIS_COMMENT */
1271 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1272 return GST_FLOW_ERROR;
1274 case 6: /* PICTURE */
1275 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1276 return GST_FLOW_ERROR;
1278 case 1: /* PADDING */
1279 case 2: /* APPLICATION */
1280 case 5: /* CUESHEET */
1281 default: /* RESERVED */
1285 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1286 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1287 GST_BUFFER_OFFSET (buffer) = 0;
1288 GST_BUFFER_OFFSET_END (buffer) = 0;
1290 flacparse->headers =
1291 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1294 if (!gst_flac_parse_handle_headers (flacparse))
1295 return GST_FLOW_ERROR;
1297 /* Minimal size of a frame header */
1298 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1299 flacparse->min_framesize));
1300 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1303 /* DROPPED because we pushed already or will push all headers manually */
1304 return GST_BASE_PARSE_FLOW_DROPPED;
1306 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1307 FrameHeaderCheckReturn ret;
1309 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1311 gst_flac_parse_frame_header_is_valid (flacparse,
1312 GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1313 if (ret != FRAME_HEADER_VALID) {
1314 GST_ERROR_OBJECT (flacparse,
1315 "Baseclass didn't provide a complete frame");
1316 return GST_FLOW_ERROR;
1320 if (flacparse->block_size == 0) {
1321 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1322 return GST_FLOW_ERROR;
1325 if (flacparse->seektable)
1326 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1328 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1329 if (flacparse->blocking_strategy == 1) {
1330 GST_WARNING_OBJECT (flacparse,
1331 "Generating headers for variable blocksize streams not supported");
1333 if (!gst_flac_parse_handle_headers (flacparse))
1334 return GST_FLOW_ERROR;
1336 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1338 if (!gst_flac_parse_generate_headers (flacparse))
1339 return GST_FLOW_ERROR;
1341 if (!gst_flac_parse_handle_headers (flacparse))
1342 return GST_FLOW_ERROR;
1344 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1347 /* also cater for oggmux metadata */
1348 if (flacparse->blocking_strategy == 0) {
1349 GST_BUFFER_TIMESTAMP (buffer) =
1350 gst_util_uint64_scale (flacparse->sample_number,
1351 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1352 GST_BUFFER_OFFSET_END (buffer) =
1353 flacparse->sample_number * flacparse->block_size +
1354 flacparse->block_size;
1356 GST_BUFFER_TIMESTAMP (buffer) =
1357 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1358 flacparse->samplerate);
1359 GST_BUFFER_OFFSET_END (buffer) =
1360 flacparse->sample_number + flacparse->block_size;
1362 GST_BUFFER_OFFSET (buffer) =
1363 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1364 flacparse->samplerate);
1365 GST_BUFFER_DURATION (buffer) =
1366 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1368 /* To simplify, we just assume that it's a fixed size header and ignore
1369 * subframe headers. The first could lead us to being off by 88 bits and
1370 * the second even less, so the total inaccuracy is negligible. */
1371 frame->overhead = 7;
1373 /* Minimal size of a frame header */
1374 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1375 flacparse->min_framesize));
1377 flacparse->offset = -1;
1378 flacparse->blocking_strategy = 0;
1379 flacparse->sample_number = 0;
1384 static GstFlowReturn
1385 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1387 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1390 if (flacparse->tags) {
1391 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1392 flacparse->tags = NULL;
1395 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1401 gst_flac_parse_convert (GstBaseParse * parse,
1402 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1403 gint64 * dest_value)
1405 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1407 if (flacparse->samplerate > 0) {
1408 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1409 if (src_value != -1)
1411 gst_util_uint64_scale (src_value, GST_SECOND,
1412 flacparse->samplerate);
1416 } else if (src_format == GST_FORMAT_TIME &&
1417 dest_format == GST_FORMAT_DEFAULT) {
1418 if (src_value != -1)
1420 gst_util_uint64_scale (src_value, flacparse->samplerate,
1428 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1429 src_value, dest_format, dest_value);
1433 gst_flac_parse_get_sink_caps (GstBaseParse * parse)
1438 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1442 /* Remove the framed field */
1443 peercaps = gst_caps_make_writable (peercaps);
1444 n = gst_caps_get_size (peercaps);
1445 for (i = 0; i < n; i++) {
1446 GstStructure *s = gst_caps_get_structure (peercaps, i);
1448 gst_structure_remove_field (s, "framed");
1452 gst_caps_intersect_full (peercaps,
1453 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1454 GST_CAPS_INTERSECT_FIRST);
1455 gst_caps_unref (peercaps);
1458 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD