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_static_pad_template (element_class, &src_factory);
215 gst_element_class_add_static_pad_template (element_class, &sink_factory);
217 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
218 "Codec/Parser/Audio",
219 "Parses audio with the FLAC lossless audio codec",
220 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
222 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
223 "Flac parser element");
227 gst_flac_parse_class_init (GstFlacParseClass * klass)
229 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
230 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
232 gobject_class->finalize = gst_flac_parse_finalize;
233 gobject_class->set_property = gst_flac_parse_set_property;
234 gobject_class->get_property = gst_flac_parse_get_property;
236 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
237 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
238 "Check the overall checksums of every frame",
239 DEFAULT_CHECK_FRAME_CHECKSUMS,
240 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
242 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
243 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
244 baseparse_class->check_valid_frame =
245 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
246 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
247 baseparse_class->pre_push_frame =
248 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
249 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
250 baseparse_class->get_sink_caps =
251 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
255 gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
257 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
261 gst_flac_parse_set_property (GObject * object, guint prop_id,
262 const GValue * value, GParamSpec * pspec)
264 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
267 case PROP_CHECK_FRAME_CHECKSUMS:
268 flacparse->check_frame_checksums = g_value_get_boolean (value);
271 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
277 gst_flac_parse_get_property (GObject * object, guint prop_id,
278 GValue * value, GParamSpec * pspec)
280 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
283 case PROP_CHECK_FRAME_CHECKSUMS:
284 g_value_set_boolean (value, flacparse->check_frame_checksums);
287 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
293 gst_flac_parse_finalize (GObject * object)
295 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
297 if (flacparse->tags) {
298 gst_tag_list_free (flacparse->tags);
299 flacparse->tags = NULL;
302 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
303 g_list_free (flacparse->headers);
304 flacparse->headers = NULL;
306 G_OBJECT_CLASS (parent_class)->finalize (object);
310 gst_flac_parse_start (GstBaseParse * parse)
312 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
314 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
315 flacparse->min_blocksize = 0;
316 flacparse->max_blocksize = 0;
317 flacparse->min_framesize = 0;
318 flacparse->max_framesize = 0;
320 flacparse->upstream_length = -1;
322 flacparse->samplerate = 0;
323 flacparse->channels = 0;
325 flacparse->total_samples = 0;
327 flacparse->offset = GST_CLOCK_TIME_NONE;
328 flacparse->blocking_strategy = 0;
329 flacparse->block_size = 0;
330 flacparse->sample_number = 0;
331 flacparse->strategy_checked = FALSE;
334 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
336 /* inform baseclass we can come up with ts, based on counters in packets */
337 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
338 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
344 gst_flac_parse_stop (GstBaseParse * parse)
346 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
348 if (flacparse->tags) {
349 gst_tag_list_free (flacparse->tags);
350 flacparse->tags = NULL;
353 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
354 g_list_free (flacparse->headers);
355 flacparse->headers = NULL;
360 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
362 static const guint16 blocksize_table[16] = {
363 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
364 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
368 static const guint32 sample_rate_table[16] = {
370 88200, 176400, 192000,
371 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
378 FRAME_HEADER_INVALID,
379 FRAME_HEADER_MORE_DATA
380 } FrameHeaderCheckReturn;
382 static FrameHeaderCheckReturn
383 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
384 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
386 GstBitReader reader = GST_BIT_READER_INIT (data, size);
387 guint8 blocking_strategy;
389 guint32 samplerate = 0;
390 guint64 sample_number;
391 guint8 channels, bps;
393 guint8 actual_crc, expected_crc = 0;
395 /* Skip 14 bit sync code */
396 gst_bit_reader_skip_unchecked (&reader, 14);
399 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
402 /* 0 == fixed block size, 1 == variable block size */
403 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
404 if (flacparse->force_variable_block_size)
405 blocking_strategy = 1;
407 /* block size index, calculation of the real blocksize below */
408 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
412 /* sample rate index, calculation of the real samplerate below */
413 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
414 if (samplerate == 0x0f)
417 /* channel assignment */
418 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
421 } else if (channels <= 10) {
423 } else if (channels > 10) {
426 if (flacparse->channels && flacparse->channels != channels)
429 /* bits per sample */
430 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
431 if (bps == 0x03 || bps == 0x07) {
433 } else if (bps == 0 && flacparse->bps == 0) {
434 goto need_streaminfo;
436 bps = sample_size_table[bps];
437 if (flacparse->bps && bps != flacparse->bps)
440 /* reserved, must be 0 */
441 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
444 /* read "utf8" encoded sample/frame number */
448 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
450 /* This is slightly faster than a loop */
454 } else if ((len & 0xc0) && !(len & 0x20)) {
455 sample_number = len & 0x1f;
457 } else if ((len & 0xe0) && !(len & 0x10)) {
458 sample_number = len & 0x0f;
460 } else if ((len & 0xf0) && !(len & 0x08)) {
461 sample_number = len & 0x07;
463 } else if ((len & 0xf8) && !(len & 0x04)) {
464 sample_number = len & 0x03;
466 } else if ((len & 0xfc) && !(len & 0x02)) {
467 sample_number = len & 0x01;
469 } else if ((len & 0xfe) && !(len & 0x01)) {
470 sample_number = len & 0x0;
476 if ((blocking_strategy == 0 && len > 5) ||
477 (blocking_strategy == 1 && len > 6))
481 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
484 if ((tmp & 0xc0) != 0x80)
488 sample_number |= (tmp & 0x3f);
493 /* calculate real blocksize from the blocksize index */
494 if (block_size == 0) {
496 } else if (block_size == 6) {
497 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
500 } else if (block_size == 7) {
501 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
505 block_size = blocksize_table[block_size];
508 /* calculate the real samplerate from the samplerate index */
509 if (samplerate == 0 && flacparse->samplerate == 0) {
510 goto need_streaminfo;
511 } else if (samplerate < 12) {
512 samplerate = sample_rate_table[samplerate];
513 } else if (samplerate == 12) {
514 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
517 } else if (samplerate == 13) {
518 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
520 } else if (samplerate == 14) {
521 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
526 if (flacparse->samplerate && flacparse->samplerate != samplerate)
529 /* check crc-8 for the header */
530 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
534 gst_flac_calculate_crc8 (data,
535 (gst_bit_reader_get_pos (&reader) / 8) - 1);
536 if (actual_crc != expected_crc)
539 /* Sanity check sample number against blocking strategy, as it seems
540 some files claim fixed block size but supply sample numbers,
541 rather than block numbers. */
542 if (blocking_strategy == 0 && flacparse->block_size != 0) {
543 if (!flacparse->strategy_checked) {
544 if (block_size == sample_number) {
545 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
546 "but seems to be lying: assuming variable block size");
547 flacparse->force_variable_block_size = TRUE;
548 blocking_strategy = 1;
550 flacparse->strategy_checked = TRUE;
555 The FLAC format documentation says:
556 The "blocking strategy" bit determines how to calculate the sample number
557 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
558 frame header encodes the frame number as above, and the frame's starting
559 sample number will be the frame number times the blocksize. If it is 1
560 (variable-blocksize), the frame header encodes the frame's starting
561 sample number itself. (In the case of a fixed-blocksize stream, only the
562 last block may be shorter than the stream blocksize; its starting sample
563 number will be calculated as the frame number times the previous frame's
564 blocksize, or zero if it is the first frame).
566 Therefore, when in fixed block size mode, we only update the block size
567 the first time, then reuse that block size for subsequent calls.
568 This will also fix a timestamp problem with the last block's timestamp
569 being miscalculated by scaling the block number by a "wrong" block size.
571 if (blocking_strategy == 0) {
572 if (flacparse->block_size != 0) {
573 /* after first block */
574 if (flacparse->block_size != block_size) {
575 /* TODO: can we know we're on the last frame, to avoid warning ? */
576 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
577 block_size = flacparse->block_size;
583 flacparse->block_size = block_size;
584 if (!flacparse->samplerate)
585 flacparse->samplerate = samplerate;
587 flacparse->bps = bps;
588 if (!flacparse->blocking_strategy)
589 flacparse->blocking_strategy = blocking_strategy;
590 if (!flacparse->channels)
591 flacparse->channels = channels;
592 if (!flacparse->sample_number)
593 flacparse->sample_number = sample_number;
595 GST_DEBUG_OBJECT (flacparse,
596 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
597 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
598 flacparse->block_size, flacparse->sample_number);
602 *block_size_ret = block_size;
604 return FRAME_HEADER_VALID;
607 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
608 return FRAME_HEADER_INVALID;
610 return FRAME_HEADER_INVALID;
613 return FRAME_HEADER_MORE_DATA;
617 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
618 GstBaseParseFrame * frame, guint * ret)
622 guint max, size, remaining;
623 guint i, search_start, search_end;
624 FrameHeaderCheckReturn header_ret;
627 buffer = frame->buffer;
628 data = GST_BUFFER_DATA (buffer);
629 size = GST_BUFFER_SIZE (buffer);
631 if (size < flacparse->min_framesize)
635 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
637 if (header_ret == FRAME_HEADER_INVALID) {
640 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
644 /* mind unknown framesize */
645 search_start = MAX (2, flacparse->min_framesize);
646 if (flacparse->max_framesize)
647 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
654 for (i = search_start; i < search_end; i++, remaining--) {
655 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
657 gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
659 if (header_ret == FRAME_HEADER_VALID) {
660 if (flacparse->check_frame_checksums) {
661 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
662 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
664 if (actual_crc != expected_crc)
668 flacparse->block_size = block_size;
670 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
676 /* For the last frame output everything to the end */
677 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
678 if (flacparse->check_frame_checksums) {
679 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
680 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
682 if (actual_crc == expected_crc) {
684 flacparse->block_size = block_size;
689 flacparse->block_size = block_size;
695 max = flacparse->max_framesize + 16;
698 *ret = MIN (size + 4096, max);
703 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
704 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
706 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
707 GstBuffer *buffer = frame->buffer;
708 const guint8 *data = GST_BUFFER_DATA (buffer);
710 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
713 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
714 if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
715 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
718 } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
719 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
720 /* Minimal size of a frame header */
721 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
722 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
726 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
729 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
730 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
732 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
736 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
740 flacparse->offset = GST_BUFFER_OFFSET (buffer);
741 flacparse->blocking_strategy = 0;
742 flacparse->sample_number = 0;
744 GST_DEBUG_OBJECT (flacparse, "Found sync code");
745 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
750 /* If we're at EOS and the frame was not valid, drop it! */
751 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
752 GST_WARNING_OBJECT (flacparse, "EOS");
757 } else if (next > GST_BUFFER_SIZE (buffer)) {
758 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
760 gst_base_parse_set_min_frame_size (parse, next);
763 GST_ERROR_OBJECT (flacparse,
764 "Giving up on invalid frame (%d bytes)",
765 GST_BUFFER_SIZE (buffer));
770 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
774 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
775 0, GST_BUFFER_SIZE (buffer));
778 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
782 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
783 *skipsize = GST_BUFFER_SIZE (buffer) - 3;
793 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
795 GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
797 if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
798 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
799 GST_BUFFER_SIZE (buffer));
803 /* Skip metadata block header */
804 gst_bit_reader_skip (&reader, 32);
806 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
808 if (flacparse->min_blocksize < 16) {
809 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
810 flacparse->min_blocksize);
813 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
815 if (flacparse->max_blocksize < 16) {
816 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
817 flacparse->max_blocksize);
820 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
822 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
825 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
827 if (flacparse->samplerate == 0) {
828 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
832 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
834 flacparse->channels++;
835 if (flacparse->channels > 8) {
836 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
837 flacparse->channels);
841 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
845 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
847 if (flacparse->total_samples) {
848 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
849 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
852 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
853 "\tmin/max blocksize: %u/%u,\n"
854 "\tmin/max framesize: %u/%u,\n"
855 "\tsamplerate: %u,\n"
857 "\tbits per sample: %u,\n"
858 "\ttotal samples: %" G_GUINT64_FORMAT,
859 flacparse->min_blocksize, flacparse->max_blocksize,
860 flacparse->min_framesize, flacparse->max_framesize,
861 flacparse->samplerate,
862 flacparse->channels, flacparse->bps, flacparse->total_samples);
867 GST_ERROR_OBJECT (flacparse, "Failed to read data");
872 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
875 flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
876 GST_BUFFER_DATA (buffer), 4, NULL);
878 if (flacparse->tags == NULL) {
879 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
880 } else if (gst_tag_list_is_empty (flacparse->tags)) {
881 gst_tag_list_free (flacparse->tags);
882 flacparse->tags = NULL;
889 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
891 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
892 const guint8 *data = GST_BUFFER_DATA (buffer);
893 guint32 img_len = 0, img_type = 0;
894 guint32 img_mimetype_len = 0, img_description_len = 0;
896 if (!gst_byte_reader_skip (&reader, 4))
899 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
902 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
904 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
907 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
909 if (!gst_byte_reader_skip (&reader, img_description_len))
912 if (!gst_byte_reader_skip (&reader, 4 * 4))
915 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
918 if (!flacparse->tags)
919 flacparse->tags = gst_tag_list_new ();
921 gst_tag_list_add_id3_image (flacparse->tags,
922 data + gst_byte_reader_get_pos (&reader), img_len, img_type);
924 if (gst_tag_list_is_empty (flacparse->tags)) {
925 gst_tag_list_free (flacparse->tags);
926 flacparse->tags = NULL;
932 GST_ERROR_OBJECT (flacparse, "Error reading data");
937 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
940 GST_DEBUG_OBJECT (flacparse, "storing seektable");
941 /* only store for now;
942 * offset of the first frame is needed to get real info */
943 flacparse->seektable = gst_buffer_ref (buffer);
949 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
952 gint64 offset = 0, samples = 0;
954 GST_DEBUG_OBJECT (flacparse,
955 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
960 gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
962 if (!gst_byte_reader_skip (&br, 4))
966 while (gst_byte_reader_get_remaining (&br)) {
967 if (!gst_byte_reader_get_int64_be (&br, &samples))
969 if (!gst_byte_reader_get_int64_be (&br, &offset))
971 if (!gst_byte_reader_skip (&br, 2))
974 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
975 G_GINT64_FORMAT, samples, offset);
978 if (G_LIKELY (offset > 0 && samples > 0)) {
979 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
980 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
981 flacparse->samplerate), TRUE, FALSE);
986 gst_buffer_unref (flacparse->seektable);
987 flacparse->seektable = NULL;
991 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
993 GValue value = { 0, };
995 g_value_init (&value, GST_TYPE_BUFFER);
996 /* copy buffer to avoid problems with circular refcounts */
997 buf = gst_buffer_copy (buf);
998 /* again, for good measure */
999 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
1000 gst_value_set_buffer (&value, buf);
1001 gst_buffer_unref (buf);
1002 gst_value_array_append_value (array_val, &value);
1003 g_value_unset (&value);
1007 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1009 GstBuffer *vorbiscomment = NULL;
1010 GstBuffer *streaminfo = NULL;
1011 GstBuffer *marker = NULL;
1012 GValue array = { 0, };
1015 gboolean res = TRUE;
1017 caps = gst_caps_new_simple ("audio/x-flac",
1018 "channels", G_TYPE_INT, flacparse->channels,
1019 "framed", G_TYPE_BOOLEAN, TRUE,
1020 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1022 if (!flacparse->headers)
1025 for (l = flacparse->headers; l; l = l->next) {
1026 GstBuffer *header = l->data;
1027 const guint8 *data = GST_BUFFER_DATA (header);
1028 guint size = GST_BUFFER_SIZE (header);
1030 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
1032 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
1034 } else if (size > 1 && (data[0] & 0x7f) == 0) {
1035 streaminfo = header;
1036 } else if (size > 1 && (data[0] & 0x7f) == 4) {
1037 vorbiscomment = header;
1041 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1042 GST_WARNING_OBJECT (flacparse,
1043 "missing header %p %p %p, muxing into container "
1044 "formats may be broken", marker, streaminfo, vorbiscomment);
1048 g_value_init (&array, GST_TYPE_ARRAY);
1050 /* add marker including STREAMINFO header */
1055 /* minus one for the marker that is merged with streaminfo here */
1056 num = g_list_length (flacparse->headers) - 1;
1058 buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1059 GST_BUFFER_DATA (buf)[0] = 0x7f;
1060 memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1061 GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
1062 GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
1063 GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1064 GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1065 memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1066 memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1067 GST_BUFFER_SIZE (streaminfo));
1068 _value_array_append_buffer (&array, buf);
1069 gst_buffer_unref (buf);
1072 /* add VORBISCOMMENT header */
1073 _value_array_append_buffer (&array, vorbiscomment);
1075 /* add other headers, if there are any */
1076 for (l = flacparse->headers; l; l = l->next) {
1077 if (GST_BUFFER_CAST (l->data) != marker &&
1078 GST_BUFFER_CAST (l->data) != streaminfo &&
1079 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1080 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1084 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1085 "streamheader", &array);
1086 g_value_unset (&array);
1090 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1091 gst_caps_unref (caps);
1093 /* push header buffers; update caps, so when we push the first buffer the
1094 * negotiated caps will change to caps that include the streamheader field */
1095 while (flacparse->headers) {
1096 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1098 GstBaseParseFrame frame;
1100 flacparse->headers =
1101 g_list_delete_link (flacparse->headers, flacparse->headers);
1102 buf = gst_buffer_make_metadata_writable (buf);
1103 gst_buffer_set_caps (buf,
1104 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1106 /* init, set and give away frame */
1107 gst_base_parse_frame_init (&frame);
1109 frame.overhead = -1;
1110 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1111 if (ret != GST_FLOW_OK) {
1116 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1117 g_list_free (flacparse->headers);
1118 flacparse->headers = NULL;
1124 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1126 GstBuffer *marker, *streaminfo, *vorbiscomment;
1129 marker = gst_buffer_new_and_alloc (4);
1130 memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1131 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1132 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1133 GST_BUFFER_OFFSET (marker) = 0;
1134 GST_BUFFER_OFFSET_END (marker) = 0;
1135 flacparse->headers = g_list_append (flacparse->headers, marker);
1137 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1138 data = GST_BUFFER_DATA (streaminfo);
1139 memset (data, 0, 4 + 34);
1141 /* metadata block header */
1142 data[0] = 0x00; /* is_last = 0; type = 0; */
1143 data[1] = 0x00; /* length = 34; */
1149 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1150 data[5] = (flacparse->block_size) & 0xff;
1151 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1152 data[7] = (flacparse->block_size) & 0xff;
1154 data[8] = 0x00; /* min framesize = 0; */
1157 data[11] = 0x00; /* max framesize = 0; */
1161 data[14] = (flacparse->samplerate >> 12) & 0xff;
1162 data[15] = (flacparse->samplerate >> 4) & 0xff;
1163 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1165 data[16] |= (flacparse->channels - 1) << 1;
1167 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1168 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1172 GstFormat fmt = GST_FORMAT_TIME;
1174 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1175 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1176 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1178 data[17] |= (duration >> 32) & 0xff;
1179 data[18] |= (duration >> 24) & 0xff;
1180 data[19] |= (duration >> 16) & 0xff;
1181 data[20] |= (duration >> 8) & 0xff;
1182 data[21] |= (duration >> 0) & 0xff;
1187 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1188 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1189 GST_BUFFER_OFFSET (streaminfo) = 0;
1190 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1191 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1193 /* empty vorbiscomment */
1195 GstTagList *taglist = gst_tag_list_new ();
1199 header[0] = 0x84; /* is_last = 1; type = 4; */
1202 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1203 sizeof (header), NULL);
1204 gst_tag_list_free (taglist);
1206 /* Get rid of framing bit */
1207 if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1212 gst_buffer_create_sub (vorbiscomment, 0,
1213 GST_BUFFER_SIZE (vorbiscomment) - 1);
1214 gst_buffer_unref (vorbiscomment);
1215 vorbiscomment = sub;
1218 size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1219 GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1220 GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1221 GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1223 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1224 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1225 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1226 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1227 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1233 static GstFlowReturn
1234 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1236 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1237 GstBuffer *buffer = frame->buffer;
1238 const guint8 *data = GST_BUFFER_DATA (buffer);
1240 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1241 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1242 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1243 GST_BUFFER_OFFSET (buffer) = 0;
1244 GST_BUFFER_OFFSET_END (buffer) = 0;
1246 /* 32 bits metadata block */
1247 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1248 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1250 flacparse->headers =
1251 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1253 return GST_BASE_PARSE_FLOW_DROPPED;
1254 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1255 gboolean is_last = ((data[0] & 0x80) == 0x80);
1256 guint type = (data[0] & 0x7F);
1259 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1260 return GST_BASE_PARSE_FLOW_DROPPED;
1263 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1266 case 0: /* STREAMINFO */
1267 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1268 return GST_FLOW_ERROR;
1270 case 3: /* SEEKTABLE */
1271 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1272 return GST_FLOW_ERROR;
1274 case 4: /* VORBIS_COMMENT */
1275 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1276 return GST_FLOW_ERROR;
1278 case 6: /* PICTURE */
1279 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1280 return GST_FLOW_ERROR;
1282 case 1: /* PADDING */
1283 case 2: /* APPLICATION */
1284 case 5: /* CUESHEET */
1285 default: /* RESERVED */
1289 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1290 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1291 GST_BUFFER_OFFSET (buffer) = 0;
1292 GST_BUFFER_OFFSET_END (buffer) = 0;
1294 flacparse->headers =
1295 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1298 if (!gst_flac_parse_handle_headers (flacparse))
1299 return GST_FLOW_ERROR;
1301 /* Minimal size of a frame header */
1302 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1303 flacparse->min_framesize));
1304 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1307 /* DROPPED because we pushed already or will push all headers manually */
1308 return GST_BASE_PARSE_FLOW_DROPPED;
1310 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1311 FrameHeaderCheckReturn ret;
1313 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1315 gst_flac_parse_frame_header_is_valid (flacparse,
1316 GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1317 if (ret != FRAME_HEADER_VALID) {
1318 GST_ERROR_OBJECT (flacparse,
1319 "Baseclass didn't provide a complete frame");
1320 return GST_FLOW_ERROR;
1324 if (flacparse->block_size == 0) {
1325 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1326 return GST_FLOW_ERROR;
1329 if (flacparse->seektable)
1330 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1332 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1333 if (flacparse->blocking_strategy == 1) {
1334 GST_WARNING_OBJECT (flacparse,
1335 "Generating headers for variable blocksize streams not supported");
1337 if (!gst_flac_parse_handle_headers (flacparse))
1338 return GST_FLOW_ERROR;
1340 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1342 if (!gst_flac_parse_generate_headers (flacparse))
1343 return GST_FLOW_ERROR;
1345 if (!gst_flac_parse_handle_headers (flacparse))
1346 return GST_FLOW_ERROR;
1348 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1351 /* also cater for oggmux metadata */
1352 if (flacparse->blocking_strategy == 0) {
1353 GST_BUFFER_TIMESTAMP (buffer) =
1354 gst_util_uint64_scale (flacparse->sample_number,
1355 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1356 GST_BUFFER_OFFSET_END (buffer) =
1357 flacparse->sample_number * flacparse->block_size +
1358 flacparse->block_size;
1360 GST_BUFFER_TIMESTAMP (buffer) =
1361 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1362 flacparse->samplerate);
1363 GST_BUFFER_OFFSET_END (buffer) =
1364 flacparse->sample_number + flacparse->block_size;
1366 GST_BUFFER_OFFSET (buffer) =
1367 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1368 flacparse->samplerate);
1369 GST_BUFFER_DURATION (buffer) =
1370 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1372 /* To simplify, we just assume that it's a fixed size header and ignore
1373 * subframe headers. The first could lead us to being off by 88 bits and
1374 * the second even less, so the total inaccuracy is negligible. */
1375 frame->overhead = 7;
1377 /* Minimal size of a frame header */
1378 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1379 flacparse->min_framesize));
1381 flacparse->offset = -1;
1382 flacparse->blocking_strategy = 0;
1383 flacparse->sample_number = 0;
1388 static GstFlowReturn
1389 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1391 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1394 if (flacparse->tags) {
1395 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1396 flacparse->tags = NULL;
1399 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1405 gst_flac_parse_convert (GstBaseParse * parse,
1406 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1407 gint64 * dest_value)
1409 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1411 if (flacparse->samplerate > 0) {
1412 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1413 if (src_value != -1)
1415 gst_util_uint64_scale (src_value, GST_SECOND,
1416 flacparse->samplerate);
1420 } else if (src_format == GST_FORMAT_TIME &&
1421 dest_format == GST_FORMAT_DEFAULT) {
1422 if (src_value != -1)
1424 gst_util_uint64_scale (src_value, flacparse->samplerate,
1432 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1433 src_value, dest_format, dest_value);
1437 gst_flac_parse_get_sink_caps (GstBaseParse * parse)
1442 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1446 /* Remove the framed field */
1447 peercaps = gst_caps_make_writable (peercaps);
1448 n = gst_caps_get_size (peercaps);
1449 for (i = 0; i < n; i++) {
1450 GstStructure *s = gst_caps_get_structure (peercaps, i);
1452 gst_structure_remove_field (s, "framed");
1456 gst_caps_intersect_full (peercaps,
1457 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1458 GST_CAPS_INTERSECT_FIRST);
1459 gst_caps_unref (peercaps);
1462 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD