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;
333 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
335 /* inform baseclass we can come up with ts, based on counters in packets */
336 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
337 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
343 gst_flac_parse_stop (GstBaseParse * parse)
345 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
347 if (flacparse->tags) {
348 gst_tag_list_free (flacparse->tags);
349 flacparse->tags = NULL;
352 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
353 g_list_free (flacparse->headers);
354 flacparse->headers = NULL;
359 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
361 static const guint16 blocksize_table[16] = {
362 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
363 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
367 static const guint32 sample_rate_table[16] = {
369 88200, 176400, 192000,
370 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
377 FRAME_HEADER_INVALID,
378 FRAME_HEADER_MORE_DATA
379 } FrameHeaderCheckReturn;
381 static FrameHeaderCheckReturn
382 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
383 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
385 GstBitReader reader = GST_BIT_READER_INIT (data, size);
386 guint8 blocking_strategy;
388 guint32 samplerate = 0;
389 guint64 sample_number;
390 guint8 channels, bps;
392 guint8 actual_crc, expected_crc = 0;
394 /* Skip 14 bit sync code */
395 gst_bit_reader_skip_unchecked (&reader, 14);
398 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
401 /* 0 == fixed block size, 1 == variable block size */
402 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
403 if (flacparse->force_variable_block_size)
404 blocking_strategy = 1;
406 /* block size index, calculation of the real blocksize below */
407 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
411 /* sample rate index, calculation of the real samplerate below */
412 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
413 if (samplerate == 0x0f)
416 /* channel assignment */
417 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
420 } else if (channels <= 10) {
422 } else if (channels > 10) {
425 if (flacparse->channels && flacparse->channels != channels)
428 /* bits per sample */
429 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
430 if (bps == 0x03 || bps == 0x07) {
432 } else if (bps == 0 && flacparse->bps == 0) {
433 goto need_streaminfo;
435 bps = sample_size_table[bps];
436 if (flacparse->bps && bps != flacparse->bps)
439 /* reserved, must be 0 */
440 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
443 /* read "utf8" encoded sample/frame number */
447 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
449 /* This is slightly faster than a loop */
453 } else if ((len & 0xc0) && !(len & 0x20)) {
454 sample_number = len & 0x1f;
456 } else if ((len & 0xe0) && !(len & 0x10)) {
457 sample_number = len & 0x0f;
459 } else if ((len & 0xf0) && !(len & 0x08)) {
460 sample_number = len & 0x07;
462 } else if ((len & 0xf8) && !(len & 0x04)) {
463 sample_number = len & 0x03;
465 } else if ((len & 0xfc) && !(len & 0x02)) {
466 sample_number = len & 0x01;
468 } else if ((len & 0xfe) && !(len & 0x01)) {
469 sample_number = len & 0x0;
475 if ((blocking_strategy == 0 && len > 5) ||
476 (blocking_strategy == 1 && len > 6))
480 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
483 if ((tmp & 0xc0) != 0x80)
487 sample_number |= (tmp & 0x3f);
492 /* calculate real blocksize from the blocksize index */
493 if (block_size == 0) {
495 } else if (block_size == 6) {
496 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
499 } else if (block_size == 7) {
500 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
504 block_size = blocksize_table[block_size];
507 /* calculate the real samplerate from the samplerate index */
508 if (samplerate == 0 && flacparse->samplerate == 0) {
509 goto need_streaminfo;
510 } else if (samplerate < 12) {
511 samplerate = sample_rate_table[samplerate];
512 } else if (samplerate == 12) {
513 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
516 } else if (samplerate == 13) {
517 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
519 } else if (samplerate == 14) {
520 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
525 if (flacparse->samplerate && flacparse->samplerate != samplerate)
528 /* check crc-8 for the header */
529 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
533 gst_flac_calculate_crc8 (data,
534 (gst_bit_reader_get_pos (&reader) / 8) - 1);
535 if (actual_crc != expected_crc)
538 /* Sanity check sample number against blocking strategy, as it seems
539 some files claim fixed block size but supply sample numbers,
540 rather than block numbers. */
541 if (set && blocking_strategy == 0 && block_size == sample_number) {
542 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
543 "but seems to be lying: assuming variable block size");
544 flacparse->force_variable_block_size = TRUE;
545 blocking_strategy = 1;
549 The FLAC format documentation says:
550 The "blocking strategy" bit determines how to calculate the sample number
551 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
552 frame header encodes the frame number as above, and the frame's starting
553 sample number will be the frame number times the blocksize. If it is 1
554 (variable-blocksize), the frame header encodes the frame's starting
555 sample number itself. (In the case of a fixed-blocksize stream, only the
556 last block may be shorter than the stream blocksize; its starting sample
557 number will be calculated as the frame number times the previous frame's
558 blocksize, or zero if it is the first frame).
560 Therefore, when in fixed block size mode, we only update the block size
561 the first time, then reuse that block size for subsequent calls.
562 This will also fix a timestamp problem with the last block's timestamp
563 being miscalculated by scaling the block number by a "wrong" block size.
565 if (blocking_strategy == 0) {
566 if (flacparse->block_size != 0) {
567 /* after first block */
568 if (flacparse->block_size != block_size) {
569 /* TODO: can we know we're on the last frame, to avoid warning ? */
570 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
571 block_size = flacparse->block_size;
577 flacparse->block_size = block_size;
578 if (!flacparse->samplerate)
579 flacparse->samplerate = samplerate;
581 flacparse->bps = bps;
582 if (!flacparse->blocking_strategy)
583 flacparse->blocking_strategy = blocking_strategy;
584 if (!flacparse->channels)
585 flacparse->channels = channels;
586 if (!flacparse->sample_number)
587 flacparse->sample_number = sample_number;
589 GST_DEBUG_OBJECT (flacparse,
590 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
591 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
592 flacparse->block_size, flacparse->sample_number);
596 *block_size_ret = block_size;
598 return FRAME_HEADER_VALID;
601 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
602 return FRAME_HEADER_INVALID;
604 return FRAME_HEADER_INVALID;
607 return FRAME_HEADER_MORE_DATA;
611 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
612 GstBaseParseFrame * frame, guint * ret)
616 guint max, size, remaining;
617 guint i, search_start, search_end;
618 FrameHeaderCheckReturn header_ret;
621 buffer = frame->buffer;
622 data = GST_BUFFER_DATA (buffer);
623 size = GST_BUFFER_SIZE (buffer);
625 if (size < flacparse->min_framesize)
629 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
631 if (header_ret == FRAME_HEADER_INVALID) {
634 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
638 /* mind unknown framesize */
639 search_start = MAX (2, flacparse->min_framesize);
640 if (flacparse->max_framesize)
641 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
648 for (i = search_start; i < search_end; i++, remaining--) {
649 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
651 gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
653 if (header_ret == FRAME_HEADER_VALID) {
654 if (flacparse->check_frame_checksums) {
655 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
656 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
658 if (actual_crc != expected_crc)
662 flacparse->block_size = block_size;
664 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
670 /* For the last frame output everything to the end */
671 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
672 if (flacparse->check_frame_checksums) {
673 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
674 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
676 if (actual_crc == expected_crc) {
678 flacparse->block_size = block_size;
683 flacparse->block_size = block_size;
689 max = flacparse->max_framesize + 16;
692 *ret = MIN (size + 4096, max);
697 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
698 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
700 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
701 GstBuffer *buffer = frame->buffer;
702 const guint8 *data = GST_BUFFER_DATA (buffer);
704 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
707 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
708 if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
709 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
712 } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
713 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
714 /* Minimal size of a frame header */
715 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
716 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
720 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
723 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
724 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
726 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
730 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
734 flacparse->offset = GST_BUFFER_OFFSET (buffer);
735 flacparse->blocking_strategy = 0;
736 flacparse->sample_number = 0;
738 GST_DEBUG_OBJECT (flacparse, "Found sync code");
739 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
744 /* If we're at EOS and the frame was not valid, drop it! */
745 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
746 GST_WARNING_OBJECT (flacparse, "EOS");
751 } else if (next > GST_BUFFER_SIZE (buffer)) {
752 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
754 gst_base_parse_set_min_frame_size (parse, next);
757 GST_ERROR_OBJECT (flacparse,
758 "Giving up on invalid frame (%d bytes)",
759 GST_BUFFER_SIZE (buffer));
764 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
768 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
769 0, GST_BUFFER_SIZE (buffer));
772 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
776 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
777 *skipsize = GST_BUFFER_SIZE (buffer) - 3;
787 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
789 GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
791 if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
792 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
793 GST_BUFFER_SIZE (buffer));
797 /* Skip metadata block header */
798 gst_bit_reader_skip (&reader, 32);
800 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
802 if (flacparse->min_blocksize < 16) {
803 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
804 flacparse->min_blocksize);
807 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
809 if (flacparse->max_blocksize < 16) {
810 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
811 flacparse->max_blocksize);
814 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
816 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
819 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
821 if (flacparse->samplerate == 0) {
822 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
826 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
828 flacparse->channels++;
829 if (flacparse->channels > 8) {
830 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
831 flacparse->channels);
835 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
839 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
841 if (flacparse->total_samples) {
842 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
843 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
846 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
847 "\tmin/max blocksize: %u/%u,\n"
848 "\tmin/max framesize: %u/%u,\n"
849 "\tsamplerate: %u,\n"
851 "\tbits per sample: %u,\n"
852 "\ttotal samples: %" G_GUINT64_FORMAT,
853 flacparse->min_blocksize, flacparse->max_blocksize,
854 flacparse->min_framesize, flacparse->max_framesize,
855 flacparse->samplerate,
856 flacparse->channels, flacparse->bps, flacparse->total_samples);
861 GST_ERROR_OBJECT (flacparse, "Failed to read data");
866 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
869 flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
870 GST_BUFFER_DATA (buffer), 4, NULL);
872 if (flacparse->tags == NULL) {
873 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
874 } else if (gst_tag_list_is_empty (flacparse->tags)) {
875 gst_tag_list_free (flacparse->tags);
876 flacparse->tags = NULL;
883 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
885 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
886 const guint8 *data = GST_BUFFER_DATA (buffer);
887 guint32 img_len = 0, img_type = 0;
888 guint32 img_mimetype_len = 0, img_description_len = 0;
890 if (!gst_byte_reader_skip (&reader, 4))
893 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
896 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
898 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
901 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
903 if (!gst_byte_reader_skip (&reader, img_description_len))
906 if (!gst_byte_reader_skip (&reader, 4 * 4))
909 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
912 if (!flacparse->tags)
913 flacparse->tags = gst_tag_list_new ();
915 gst_tag_list_add_id3_image (flacparse->tags,
916 data + gst_byte_reader_get_pos (&reader), img_len, img_type);
918 if (gst_tag_list_is_empty (flacparse->tags)) {
919 gst_tag_list_free (flacparse->tags);
920 flacparse->tags = NULL;
926 GST_ERROR_OBJECT (flacparse, "Error reading data");
931 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
934 GST_DEBUG_OBJECT (flacparse, "storing seektable");
935 /* only store for now;
936 * offset of the first frame is needed to get real info */
937 flacparse->seektable = gst_buffer_ref (buffer);
943 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
946 gint64 offset = 0, samples = 0;
948 GST_DEBUG_OBJECT (flacparse,
949 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
954 gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
956 if (!gst_byte_reader_skip (&br, 4))
960 while (gst_byte_reader_get_remaining (&br)) {
961 if (!gst_byte_reader_get_int64_be (&br, &samples))
963 if (!gst_byte_reader_get_int64_be (&br, &offset))
965 if (!gst_byte_reader_skip (&br, 2))
968 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
969 G_GINT64_FORMAT, samples, offset);
972 if (G_LIKELY (offset > 0 && samples > 0)) {
973 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
974 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
975 flacparse->samplerate), TRUE, FALSE);
980 gst_buffer_unref (flacparse->seektable);
981 flacparse->seektable = NULL;
985 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
987 GValue value = { 0, };
989 g_value_init (&value, GST_TYPE_BUFFER);
990 /* copy buffer to avoid problems with circular refcounts */
991 buf = gst_buffer_copy (buf);
992 /* again, for good measure */
993 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
994 gst_value_set_buffer (&value, buf);
995 gst_buffer_unref (buf);
996 gst_value_array_append_value (array_val, &value);
997 g_value_unset (&value);
1001 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1003 GstBuffer *vorbiscomment = NULL;
1004 GstBuffer *streaminfo = NULL;
1005 GstBuffer *marker = NULL;
1006 GValue array = { 0, };
1009 gboolean res = TRUE;
1011 caps = gst_caps_new_simple ("audio/x-flac",
1012 "channels", G_TYPE_INT, flacparse->channels,
1013 "framed", G_TYPE_BOOLEAN, TRUE,
1014 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1016 if (!flacparse->headers)
1019 for (l = flacparse->headers; l; l = l->next) {
1020 GstBuffer *header = l->data;
1021 const guint8 *data = GST_BUFFER_DATA (header);
1022 guint size = GST_BUFFER_SIZE (header);
1024 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
1026 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
1028 } else if (size > 1 && (data[0] & 0x7f) == 0) {
1029 streaminfo = header;
1030 } else if (size > 1 && (data[0] & 0x7f) == 4) {
1031 vorbiscomment = header;
1035 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1036 GST_WARNING_OBJECT (flacparse,
1037 "missing header %p %p %p, muxing into container "
1038 "formats may be broken", marker, streaminfo, vorbiscomment);
1042 g_value_init (&array, GST_TYPE_ARRAY);
1044 /* add marker including STREAMINFO header */
1049 /* minus one for the marker that is merged with streaminfo here */
1050 num = g_list_length (flacparse->headers) - 1;
1052 buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1053 GST_BUFFER_DATA (buf)[0] = 0x7f;
1054 memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1055 GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
1056 GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
1057 GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1058 GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1059 memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1060 memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1061 GST_BUFFER_SIZE (streaminfo));
1062 _value_array_append_buffer (&array, buf);
1063 gst_buffer_unref (buf);
1066 /* add VORBISCOMMENT header */
1067 _value_array_append_buffer (&array, vorbiscomment);
1069 /* add other headers, if there are any */
1070 for (l = flacparse->headers; l; l = l->next) {
1071 if (GST_BUFFER_CAST (l->data) != marker &&
1072 GST_BUFFER_CAST (l->data) != streaminfo &&
1073 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1074 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1078 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1079 "streamheader", &array);
1080 g_value_unset (&array);
1084 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1085 gst_caps_unref (caps);
1087 /* push header buffers; update caps, so when we push the first buffer the
1088 * negotiated caps will change to caps that include the streamheader field */
1089 while (flacparse->headers) {
1090 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1092 GstBaseParseFrame frame;
1094 flacparse->headers =
1095 g_list_delete_link (flacparse->headers, flacparse->headers);
1096 buf = gst_buffer_make_metadata_writable (buf);
1097 gst_buffer_set_caps (buf,
1098 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1100 /* init, set and give away frame */
1101 gst_base_parse_frame_init (&frame);
1103 frame.overhead = -1;
1104 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1105 if (ret != GST_FLOW_OK) {
1110 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1111 g_list_free (flacparse->headers);
1112 flacparse->headers = NULL;
1118 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1120 GstBuffer *marker, *streaminfo, *vorbiscomment;
1123 marker = gst_buffer_new_and_alloc (4);
1124 memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1125 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1126 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1127 GST_BUFFER_OFFSET (marker) = 0;
1128 GST_BUFFER_OFFSET_END (marker) = 0;
1129 flacparse->headers = g_list_append (flacparse->headers, marker);
1131 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1132 data = GST_BUFFER_DATA (streaminfo);
1133 memset (data, 0, 4 + 34);
1135 /* metadata block header */
1136 data[0] = 0x00; /* is_last = 0; type = 0; */
1137 data[1] = 0x00; /* length = 34; */
1143 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1144 data[5] = (flacparse->block_size) & 0xff;
1145 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1146 data[7] = (flacparse->block_size) & 0xff;
1148 data[8] = 0x00; /* min framesize = 0; */
1151 data[11] = 0x00; /* max framesize = 0; */
1155 data[14] = (flacparse->samplerate >> 12) & 0xff;
1156 data[15] = (flacparse->samplerate >> 4) & 0xff;
1157 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1159 data[16] |= (flacparse->channels - 1) << 1;
1161 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1162 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1166 GstFormat fmt = GST_FORMAT_TIME;
1168 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1169 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1170 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1172 data[17] |= (duration >> 32) & 0xff;
1173 data[18] |= (duration >> 24) & 0xff;
1174 data[19] |= (duration >> 16) & 0xff;
1175 data[20] |= (duration >> 8) & 0xff;
1176 data[21] |= (duration >> 0) & 0xff;
1181 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1182 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1183 GST_BUFFER_OFFSET (streaminfo) = 0;
1184 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1185 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1187 /* empty vorbiscomment */
1189 GstTagList *taglist = gst_tag_list_new ();
1193 header[0] = 0x84; /* is_last = 1; type = 4; */
1196 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1197 sizeof (header), NULL);
1198 gst_tag_list_free (taglist);
1200 /* Get rid of framing bit */
1201 if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1206 gst_buffer_create_sub (vorbiscomment, 0,
1207 GST_BUFFER_SIZE (vorbiscomment) - 1);
1208 gst_buffer_unref (vorbiscomment);
1209 vorbiscomment = sub;
1212 size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1213 GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1214 GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1215 GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1217 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1218 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1219 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1220 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1221 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1227 static GstFlowReturn
1228 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1230 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1231 GstBuffer *buffer = frame->buffer;
1232 const guint8 *data = GST_BUFFER_DATA (buffer);
1234 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1235 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1236 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1237 GST_BUFFER_OFFSET (buffer) = 0;
1238 GST_BUFFER_OFFSET_END (buffer) = 0;
1240 /* 32 bits metadata block */
1241 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1242 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1244 flacparse->headers =
1245 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1247 return GST_BASE_PARSE_FLOW_DROPPED;
1248 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1249 gboolean is_last = ((data[0] & 0x80) == 0x80);
1250 guint type = (data[0] & 0x7F);
1253 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1254 return GST_BASE_PARSE_FLOW_DROPPED;
1257 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1260 case 0: /* STREAMINFO */
1261 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1262 return GST_FLOW_ERROR;
1264 case 3: /* SEEKTABLE */
1265 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1266 return GST_FLOW_ERROR;
1268 case 4: /* VORBIS_COMMENT */
1269 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1270 return GST_FLOW_ERROR;
1272 case 6: /* PICTURE */
1273 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1274 return GST_FLOW_ERROR;
1276 case 1: /* PADDING */
1277 case 2: /* APPLICATION */
1278 case 5: /* CUESHEET */
1279 default: /* RESERVED */
1283 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1284 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1285 GST_BUFFER_OFFSET (buffer) = 0;
1286 GST_BUFFER_OFFSET_END (buffer) = 0;
1288 flacparse->headers =
1289 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1292 if (!gst_flac_parse_handle_headers (flacparse))
1293 return GST_FLOW_ERROR;
1295 /* Minimal size of a frame header */
1296 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1297 flacparse->min_framesize));
1298 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1301 /* DROPPED because we pushed already or will push all headers manually */
1302 return GST_BASE_PARSE_FLOW_DROPPED;
1304 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1305 FrameHeaderCheckReturn ret;
1307 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1309 gst_flac_parse_frame_header_is_valid (flacparse,
1310 GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1311 if (ret != FRAME_HEADER_VALID) {
1312 GST_ERROR_OBJECT (flacparse,
1313 "Baseclass didn't provide a complete frame");
1314 return GST_FLOW_ERROR;
1318 if (flacparse->block_size == 0) {
1319 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1320 return GST_FLOW_ERROR;
1323 if (flacparse->seektable)
1324 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1326 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1327 if (flacparse->blocking_strategy == 1) {
1328 GST_WARNING_OBJECT (flacparse,
1329 "Generating headers for variable blocksize streams not supported");
1331 if (!gst_flac_parse_handle_headers (flacparse))
1332 return GST_FLOW_ERROR;
1334 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1336 if (!gst_flac_parse_generate_headers (flacparse))
1337 return GST_FLOW_ERROR;
1339 if (!gst_flac_parse_handle_headers (flacparse))
1340 return GST_FLOW_ERROR;
1342 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1345 /* also cater for oggmux metadata */
1346 if (flacparse->blocking_strategy == 0) {
1347 GST_BUFFER_TIMESTAMP (buffer) =
1348 gst_util_uint64_scale (flacparse->sample_number,
1349 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1350 GST_BUFFER_OFFSET_END (buffer) =
1351 flacparse->sample_number * flacparse->block_size +
1352 flacparse->block_size;
1354 GST_BUFFER_TIMESTAMP (buffer) =
1355 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1356 flacparse->samplerate);
1357 GST_BUFFER_OFFSET_END (buffer) =
1358 flacparse->sample_number + flacparse->block_size;
1360 GST_BUFFER_OFFSET (buffer) =
1361 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1362 flacparse->samplerate);
1363 GST_BUFFER_DURATION (buffer) =
1364 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1366 /* To simplify, we just assume that it's a fixed size header and ignore
1367 * subframe headers. The first could lead us to being off by 88 bits and
1368 * the second even less, so the total inaccuracy is negligible. */
1369 frame->overhead = 7;
1371 /* Minimal size of a frame header */
1372 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1373 flacparse->min_framesize));
1375 flacparse->offset = -1;
1376 flacparse->blocking_strategy = 0;
1377 flacparse->sample_number = 0;
1382 static GstFlowReturn
1383 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1385 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1388 if (flacparse->tags) {
1389 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1390 flacparse->tags = NULL;
1393 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1399 gst_flac_parse_convert (GstBaseParse * parse,
1400 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1401 gint64 * dest_value)
1403 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1405 if (flacparse->samplerate > 0) {
1406 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1407 if (src_value != -1)
1409 gst_util_uint64_scale (src_value, GST_SECOND,
1410 flacparse->samplerate);
1414 } else if (src_format == GST_FORMAT_TIME &&
1415 dest_format == GST_FORMAT_DEFAULT) {
1416 if (src_value != -1)
1418 gst_util_uint64_scale (src_value, flacparse->samplerate,
1426 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1427 src_value, dest_format, dest_value);
1431 gst_flac_parse_get_sink_caps (GstBaseParse * parse)
1436 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1440 /* Remove the framed field */
1441 peercaps = gst_caps_make_writable (peercaps);
1442 n = gst_caps_get_size (peercaps);
1443 for (i = 0; i < n; i++) {
1444 GstStructure *s = gst_caps_get_structure (peercaps, i);
1446 gst_structure_remove_field (s, "framed");
1450 gst_caps_intersect_full (peercaps,
1451 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1452 GST_CAPS_INTERSECT_FIRST);
1453 gst_caps_unref (peercaps);
1456 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD