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, framed = (boolean) false")
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);
202 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
203 GST_TYPE_BASE_PARSE);
206 gst_flac_parse_base_init (gpointer g_class)
208 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
210 gst_element_class_add_pad_template (element_class,
211 gst_static_pad_template_get (&src_factory));
212 gst_element_class_add_pad_template (element_class,
213 gst_static_pad_template_get (&sink_factory));
215 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
216 "Codec/Parser/Audio",
217 "Parses audio with the FLAC lossless audio codec",
218 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
220 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
221 "Flac parser element");
225 gst_flac_parse_class_init (GstFlacParseClass * klass)
227 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
228 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
230 gobject_class->finalize = gst_flac_parse_finalize;
231 gobject_class->set_property = gst_flac_parse_set_property;
232 gobject_class->get_property = gst_flac_parse_get_property;
234 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
235 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
236 "Check the overall checksums of every frame",
237 DEFAULT_CHECK_FRAME_CHECKSUMS,
238 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
240 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
241 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
242 baseparse_class->check_valid_frame =
243 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
244 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
245 baseparse_class->pre_push_frame =
246 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
250 gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
252 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
256 gst_flac_parse_set_property (GObject * object, guint prop_id,
257 const GValue * value, GParamSpec * pspec)
259 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
262 case PROP_CHECK_FRAME_CHECKSUMS:
263 flacparse->check_frame_checksums = g_value_get_boolean (value);
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
272 gst_flac_parse_get_property (GObject * object, guint prop_id,
273 GValue * value, GParamSpec * pspec)
275 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
278 case PROP_CHECK_FRAME_CHECKSUMS:
279 g_value_set_boolean (value, flacparse->check_frame_checksums);
282 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
288 gst_flac_parse_finalize (GObject * object)
290 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
292 if (flacparse->tags) {
293 gst_tag_list_free (flacparse->tags);
294 flacparse->tags = NULL;
297 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
298 g_list_free (flacparse->headers);
299 flacparse->headers = NULL;
301 G_OBJECT_CLASS (parent_class)->finalize (object);
305 gst_flac_parse_start (GstBaseParse * parse)
307 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
309 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
310 flacparse->min_blocksize = 0;
311 flacparse->max_blocksize = 0;
312 flacparse->min_framesize = 0;
313 flacparse->max_framesize = 0;
315 flacparse->upstream_length = -1;
317 flacparse->samplerate = 0;
318 flacparse->channels = 0;
320 flacparse->total_samples = 0;
322 flacparse->offset = GST_CLOCK_TIME_NONE;
323 flacparse->blocking_strategy = 0;
324 flacparse->block_size = 0;
325 flacparse->sample_number = 0;
328 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
330 /* inform baseclass we can come up with ts, based on counters in packets */
331 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
332 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
338 gst_flac_parse_stop (GstBaseParse * parse)
340 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
342 if (flacparse->tags) {
343 gst_tag_list_free (flacparse->tags);
344 flacparse->tags = NULL;
347 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
348 g_list_free (flacparse->headers);
349 flacparse->headers = NULL;
354 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
356 static const guint16 blocksize_table[16] = {
357 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
358 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
362 static const guint32 sample_rate_table[16] = {
364 88200, 176400, 192000,
365 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
372 FRAME_HEADER_INVALID,
373 FRAME_HEADER_MORE_DATA
374 } FrameHeaderCheckReturn;
376 static FrameHeaderCheckReturn
377 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
378 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
380 GstBitReader reader = GST_BIT_READER_INIT (data, size);
381 guint8 blocking_strategy;
383 guint32 samplerate = 0;
384 guint64 sample_number;
385 guint8 channels, bps;
387 guint8 actual_crc, expected_crc = 0;
389 /* Skip 14 bit sync code */
390 gst_bit_reader_skip_unchecked (&reader, 14);
393 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
396 /* 0 == fixed block size, 1 == variable block size */
397 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
399 /* block size index, calculation of the real blocksize below */
400 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
404 /* sample rate index, calculation of the real samplerate below */
405 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
406 if (samplerate == 0x0f)
409 /* channel assignment */
410 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
413 } else if (channels <= 10) {
415 } else if (channels > 10) {
418 if (flacparse->channels && flacparse->channels != channels)
421 /* bits per sample */
422 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
423 if (bps == 0x03 || bps == 0x07) {
425 } else if (bps == 0 && flacparse->bps == 0) {
426 goto need_streaminfo;
428 bps = sample_size_table[bps];
429 if (flacparse->bps && bps != flacparse->bps)
432 /* reserved, must be 0 */
433 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
436 /* read "utf8" encoded sample/frame number */
440 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
442 /* This is slightly faster than a loop */
446 } else if ((len & 0xc0) && !(len & 0x20)) {
447 sample_number = len & 0x1f;
449 } else if ((len & 0xe0) && !(len & 0x10)) {
450 sample_number = len & 0x0f;
452 } else if ((len & 0xf0) && !(len & 0x08)) {
453 sample_number = len & 0x07;
455 } else if ((len & 0xf8) && !(len & 0x04)) {
456 sample_number = len & 0x03;
458 } else if ((len & 0xfc) && !(len & 0x02)) {
459 sample_number = len & 0x01;
461 } else if ((len & 0xfe) && !(len & 0x01)) {
462 sample_number = len & 0x0;
468 if ((blocking_strategy == 0 && len > 5) ||
469 (blocking_strategy == 1 && len > 6))
473 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
476 if ((tmp & 0xc0) != 0x80)
480 sample_number |= (tmp & 0x3f);
485 /* calculate real blocksize from the blocksize index */
486 if (block_size == 0) {
488 } else if (block_size == 6) {
489 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
492 } else if (block_size == 7) {
493 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
497 block_size = blocksize_table[block_size];
500 /* calculate the real samplerate from the samplerate index */
501 if (samplerate == 0 && flacparse->samplerate == 0) {
502 goto need_streaminfo;
503 } else if (samplerate < 12) {
504 samplerate = sample_rate_table[samplerate];
505 } else if (samplerate == 12) {
506 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
509 } else if (samplerate == 13) {
510 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
512 } else if (samplerate == 14) {
513 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
518 if (flacparse->samplerate && flacparse->samplerate != samplerate)
521 /* check crc-8 for the header */
522 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
526 gst_flac_calculate_crc8 (data,
527 (gst_bit_reader_get_pos (&reader) / 8) - 1);
528 if (actual_crc != expected_crc)
532 flacparse->block_size = block_size;
533 if (!flacparse->samplerate)
534 flacparse->samplerate = samplerate;
536 flacparse->bps = bps;
537 if (!flacparse->blocking_strategy)
538 flacparse->blocking_strategy = blocking_strategy;
539 if (!flacparse->channels)
540 flacparse->channels = channels;
541 if (!flacparse->sample_number)
542 flacparse->sample_number = sample_number;
544 GST_DEBUG_OBJECT (flacparse,
545 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
546 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
547 flacparse->block_size, flacparse->sample_number);
551 *block_size_ret = block_size;
553 return FRAME_HEADER_VALID;
556 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
557 return FRAME_HEADER_INVALID;
559 return FRAME_HEADER_INVALID;
562 return FRAME_HEADER_MORE_DATA;
566 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
567 GstBaseParseFrame * frame, guint * ret)
571 guint max, size, remaining;
572 guint i, search_start, search_end;
573 FrameHeaderCheckReturn header_ret;
576 buffer = frame->buffer;
577 data = GST_BUFFER_DATA (buffer);
578 size = GST_BUFFER_SIZE (buffer);
580 if (size <= flacparse->min_framesize)
584 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
586 if (header_ret == FRAME_HEADER_INVALID) {
589 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
593 /* mind unknown framesize */
594 search_start = MAX (2, flacparse->min_framesize);
595 if (flacparse->max_framesize)
596 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
603 for (i = search_start; i < search_end; i++, remaining--) {
604 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
606 gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
608 if (header_ret == FRAME_HEADER_VALID) {
609 if (flacparse->check_frame_checksums) {
610 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
611 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
613 if (actual_crc != expected_crc)
617 flacparse->block_size = block_size;
619 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
625 /* For the last frame output everything to the end */
626 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
627 if (flacparse->check_frame_checksums) {
628 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
629 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
631 if (actual_crc == expected_crc) {
633 flacparse->block_size = block_size;
638 flacparse->block_size = block_size;
644 max = flacparse->max_framesize + 16;
647 *ret = MIN (size + 4096, max);
652 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
653 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
655 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
656 GstBuffer *buffer = frame->buffer;
657 const guint8 *data = GST_BUFFER_DATA (buffer);
659 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
662 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
663 if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
664 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
667 } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
668 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
669 /* Minimal size of a frame header */
670 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
671 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
675 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
678 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
679 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
681 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
685 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
689 flacparse->offset = GST_BUFFER_OFFSET (buffer);
690 flacparse->blocking_strategy = 0;
691 flacparse->block_size = 0;
692 flacparse->sample_number = 0;
694 GST_DEBUG_OBJECT (flacparse, "Found sync code");
695 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
700 /* If we're at EOS and the frame was not valid, drop it! */
701 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
702 GST_WARNING_OBJECT (flacparse, "EOS");
707 } else if (next > GST_BUFFER_SIZE (buffer)) {
708 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
710 gst_base_parse_set_min_frame_size (parse, next);
713 GST_ERROR_OBJECT (flacparse,
714 "Giving up on invalid frame (%d bytes)",
715 GST_BUFFER_SIZE (buffer));
720 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
724 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
725 0, GST_BUFFER_SIZE (buffer));
728 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
732 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
733 *skipsize = GST_BUFFER_SIZE (buffer) - 3;
743 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
745 GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
747 if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
748 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
749 GST_BUFFER_SIZE (buffer));
753 /* Skip metadata block header */
754 gst_bit_reader_skip (&reader, 32);
756 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
758 if (flacparse->min_blocksize < 16) {
759 GST_ERROR_OBJECT (flacparse, "Invalid minimum block size: %u",
760 flacparse->min_blocksize);
764 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
766 if (flacparse->max_blocksize < 16) {
767 GST_ERROR_OBJECT (flacparse, "Invalid maximum block size: %u",
768 flacparse->max_blocksize);
772 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
774 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
777 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
779 if (flacparse->samplerate == 0) {
780 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
784 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
786 flacparse->channels++;
787 if (flacparse->channels > 8) {
788 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
789 flacparse->channels);
793 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
797 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
799 if (flacparse->total_samples)
800 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse), GST_FORMAT_TIME,
801 GST_FRAMES_TO_CLOCK_TIME (flacparse->total_samples,
802 flacparse->samplerate), 0);
804 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
805 "\tmin/max blocksize: %u/%u,\n"
806 "\tmin/max framesize: %u/%u,\n"
807 "\tsamplerate: %u,\n"
809 "\tbits per sample: %u,\n"
810 "\ttotal samples: %" G_GUINT64_FORMAT,
811 flacparse->min_blocksize, flacparse->max_blocksize,
812 flacparse->min_framesize, flacparse->max_framesize,
813 flacparse->samplerate,
814 flacparse->channels, flacparse->bps, flacparse->total_samples);
819 GST_ERROR_OBJECT (flacparse, "Failed to read data");
824 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
827 flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
828 GST_BUFFER_DATA (buffer), 4, NULL);
830 if (flacparse->tags == NULL) {
831 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
832 } else if (gst_tag_list_is_empty (flacparse->tags)) {
833 gst_tag_list_free (flacparse->tags);
834 flacparse->tags = NULL;
841 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
843 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
844 const guint8 *data = GST_BUFFER_DATA (buffer);
845 guint32 img_len = 0, img_type = 0;
846 guint32 img_mimetype_len = 0, img_description_len = 0;
848 if (!gst_byte_reader_skip (&reader, 4))
851 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
854 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
856 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
859 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
861 if (!gst_byte_reader_skip (&reader, img_description_len))
864 if (!gst_byte_reader_skip (&reader, 4 * 4))
867 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
870 if (!flacparse->tags)
871 flacparse->tags = gst_tag_list_new ();
873 gst_tag_list_add_id3_image (flacparse->tags,
874 data + gst_byte_reader_get_pos (&reader), img_len, img_type);
876 if (gst_tag_list_is_empty (flacparse->tags)) {
877 gst_tag_list_free (flacparse->tags);
878 flacparse->tags = NULL;
884 GST_ERROR_OBJECT (flacparse, "Error reading data");
889 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
892 GST_DEBUG_OBJECT (flacparse, "storing seektable");
893 /* only store for now;
894 * offset of the first frame is needed to get real info */
895 flacparse->seektable = gst_buffer_ref (buffer);
901 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
904 gint64 offset = 0, samples = 0;
906 GST_DEBUG_OBJECT (flacparse,
907 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
912 gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
914 if (!gst_byte_reader_skip (&br, 4))
918 while (gst_byte_reader_get_remaining (&br)) {
919 if (!gst_byte_reader_get_int64_be (&br, &samples))
921 if (!gst_byte_reader_get_int64_be (&br, &offset))
923 if (!gst_byte_reader_skip (&br, 2))
926 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
927 G_GINT64_FORMAT, samples, offset);
930 if (G_LIKELY (offset > 0 && samples > 0)) {
931 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
932 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
933 flacparse->samplerate), TRUE, FALSE);
938 gst_buffer_unref (flacparse->seektable);
939 flacparse->seektable = NULL;
943 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
945 GValue value = { 0, };
947 g_value_init (&value, GST_TYPE_BUFFER);
948 /* copy buffer to avoid problems with circular refcounts */
949 buf = gst_buffer_copy (buf);
950 /* again, for good measure */
951 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
952 gst_value_set_buffer (&value, buf);
953 gst_buffer_unref (buf);
954 gst_value_array_append_value (array_val, &value);
955 g_value_unset (&value);
959 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
961 GstBuffer *vorbiscomment = NULL;
962 GstBuffer *streaminfo = NULL;
963 GstBuffer *marker = NULL;
964 GValue array = { 0, };
969 caps = gst_caps_new_simple ("audio/x-flac",
970 "channels", G_TYPE_INT, flacparse->channels,
971 "framed", G_TYPE_BOOLEAN, TRUE,
972 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
974 if (!flacparse->headers)
977 for (l = flacparse->headers; l; l = l->next) {
978 GstBuffer *header = l->data;
979 const guint8 *data = GST_BUFFER_DATA (header);
980 guint size = GST_BUFFER_SIZE (header);
982 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
984 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
986 } else if (size > 1 && (data[0] & 0x7f) == 0) {
988 } else if (size > 1 && (data[0] & 0x7f) == 4) {
989 vorbiscomment = header;
993 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
994 GST_WARNING_OBJECT (flacparse,
995 "missing header %p %p %p, muxing into container "
996 "formats may be broken", marker, streaminfo, vorbiscomment);
1000 g_value_init (&array, GST_TYPE_ARRAY);
1002 /* add marker including STREAMINFO header */
1007 /* minus one for the marker that is merged with streaminfo here */
1008 num = g_list_length (flacparse->headers) - 1;
1010 buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1011 GST_BUFFER_DATA (buf)[0] = 0x7f;
1012 memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1013 GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
1014 GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
1015 GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1016 GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1017 memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1018 memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1019 GST_BUFFER_SIZE (streaminfo));
1020 _value_array_append_buffer (&array, buf);
1021 gst_buffer_unref (buf);
1024 /* add VORBISCOMMENT header */
1025 _value_array_append_buffer (&array, vorbiscomment);
1027 /* add other headers, if there are any */
1028 for (l = flacparse->headers; l; l = l->next) {
1029 if (GST_BUFFER_CAST (l->data) != marker &&
1030 GST_BUFFER_CAST (l->data) != streaminfo &&
1031 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1032 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1036 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1037 "streamheader", &array);
1038 g_value_unset (&array);
1042 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1043 gst_caps_unref (caps);
1045 /* push header buffers; update caps, so when we push the first buffer the
1046 * negotiated caps will change to caps that include the streamheader field */
1047 while (flacparse->headers) {
1048 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1050 GstBaseParseFrame frame;
1052 flacparse->headers =
1053 g_list_delete_link (flacparse->headers, flacparse->headers);
1054 buf = gst_buffer_make_metadata_writable (buf);
1055 gst_buffer_set_caps (buf,
1056 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1058 /* init, set and give away frame */
1059 gst_base_parse_frame_init (&frame);
1061 frame.overhead = -1;
1062 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1063 if (ret != GST_FLOW_OK) {
1068 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1069 g_list_free (flacparse->headers);
1070 flacparse->headers = NULL;
1076 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1078 GstBuffer *marker, *streaminfo, *vorbiscomment;
1081 marker = gst_buffer_new_and_alloc (4);
1082 memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1083 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1084 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1085 GST_BUFFER_OFFSET (marker) = 0;
1086 GST_BUFFER_OFFSET_END (marker) = 0;
1087 flacparse->headers = g_list_append (flacparse->headers, marker);
1089 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1090 data = GST_BUFFER_DATA (streaminfo);
1091 memset (data, 0, 4 + 34);
1093 /* metadata block header */
1094 data[0] = 0x00; /* is_last = 0; type = 0; */
1095 data[1] = 0x00; /* length = 34; */
1101 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1102 data[5] = (flacparse->block_size) & 0xff;
1103 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1104 data[7] = (flacparse->block_size) & 0xff;
1106 data[8] = 0x00; /* min framesize = 0; */
1109 data[11] = 0x00; /* max framesize = 0; */
1113 data[14] = (flacparse->samplerate >> 12) & 0xff;
1114 data[15] = (flacparse->samplerate >> 4) & 0xff;
1115 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1117 data[16] |= (flacparse->channels - 1) << 1;
1119 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1120 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1124 GstFormat fmt = GST_FORMAT_TIME;
1126 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1127 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1128 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1130 data[17] |= (duration >> 32) & 0xff;
1131 data[18] |= (duration >> 24) & 0xff;
1132 data[19] |= (duration >> 16) & 0xff;
1133 data[20] |= (duration >> 8) & 0xff;
1134 data[21] |= (duration >> 0) & 0xff;
1139 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1140 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1141 GST_BUFFER_OFFSET (streaminfo) = 0;
1142 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1143 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1145 /* empty vorbiscomment */
1147 GstTagList *taglist = gst_tag_list_new ();
1151 header[0] = 0x84; /* is_last = 1; type = 4; */
1154 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1155 sizeof (header), NULL);
1156 gst_tag_list_free (taglist);
1158 /* Get rid of framing bit */
1159 if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1164 gst_buffer_create_sub (vorbiscomment, 0,
1165 GST_BUFFER_SIZE (vorbiscomment) - 1);
1166 gst_buffer_unref (vorbiscomment);
1167 vorbiscomment = sub;
1170 size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1171 GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1172 GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1173 GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1175 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1176 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1177 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1178 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1179 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1185 static GstFlowReturn
1186 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1188 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1189 GstBuffer *buffer = frame->buffer;
1190 const guint8 *data = GST_BUFFER_DATA (buffer);
1192 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1193 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1194 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1195 GST_BUFFER_OFFSET (buffer) = 0;
1196 GST_BUFFER_OFFSET_END (buffer) = 0;
1198 /* 32 bits metadata block */
1199 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1200 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1202 flacparse->headers =
1203 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1205 return GST_BASE_PARSE_FLOW_DROPPED;
1206 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1207 gboolean is_last = ((data[0] & 0x80) == 0x80);
1208 guint type = (data[0] & 0x7F);
1211 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1212 return GST_BASE_PARSE_FLOW_DROPPED;
1215 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1218 case 0: /* STREAMINFO */
1219 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1220 return GST_FLOW_ERROR;
1222 case 3: /* SEEKTABLE */
1223 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1224 return GST_FLOW_ERROR;
1226 case 4: /* VORBIS_COMMENT */
1227 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1228 return GST_FLOW_ERROR;
1230 case 6: /* PICTURE */
1231 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1232 return GST_FLOW_ERROR;
1234 case 1: /* PADDING */
1235 case 2: /* APPLICATION */
1236 case 5: /* CUESHEET */
1237 default: /* RESERVED */
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 flacparse->headers =
1247 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1250 if (!gst_flac_parse_handle_headers (flacparse))
1251 return GST_FLOW_ERROR;
1253 /* Minimal size of a frame header */
1254 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1255 flacparse->min_framesize));
1256 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1259 /* DROPPED because we pushed already or will push all headers manually */
1260 return GST_BASE_PARSE_FLOW_DROPPED;
1262 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1263 FrameHeaderCheckReturn ret;
1265 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1267 gst_flac_parse_frame_header_is_valid (flacparse,
1268 GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1269 if (ret != FRAME_HEADER_VALID) {
1270 GST_ERROR_OBJECT (flacparse,
1271 "Baseclass didn't provide a complete frame");
1272 return GST_FLOW_ERROR;
1276 if (flacparse->block_size == 0) {
1277 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1278 return GST_FLOW_ERROR;
1281 if (flacparse->seektable)
1282 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1284 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1285 if (flacparse->blocking_strategy == 1) {
1286 GST_WARNING_OBJECT (flacparse,
1287 "Generating headers for variable blocksize streams not supported");
1289 if (!gst_flac_parse_handle_headers (flacparse))
1290 return GST_FLOW_ERROR;
1292 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1294 if (!gst_flac_parse_generate_headers (flacparse))
1295 return GST_FLOW_ERROR;
1297 if (!gst_flac_parse_handle_headers (flacparse))
1298 return GST_FLOW_ERROR;
1300 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1303 /* also cater for oggmux metadata */
1304 if (flacparse->blocking_strategy == 0) {
1305 GST_BUFFER_TIMESTAMP (buffer) =
1306 gst_util_uint64_scale (flacparse->sample_number,
1307 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1308 GST_BUFFER_OFFSET_END (buffer) =
1309 flacparse->sample_number * flacparse->block_size +
1310 flacparse->block_size;
1312 GST_BUFFER_TIMESTAMP (buffer) =
1313 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1314 flacparse->samplerate);
1315 GST_BUFFER_OFFSET_END (buffer) =
1316 flacparse->sample_number + flacparse->block_size;
1318 GST_BUFFER_OFFSET (buffer) =
1319 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1320 flacparse->samplerate);
1321 GST_BUFFER_DURATION (buffer) =
1322 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1324 /* To simplify, we just assume that it's a fixed size header and ignore
1325 * subframe headers. The first could lead us to being off by 88 bits and
1326 * the second even less, so the total inaccuracy is negligible. */
1327 frame->overhead = 7;
1329 /* Minimal size of a frame header */
1330 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1331 flacparse->min_framesize));
1333 flacparse->offset = -1;
1334 flacparse->blocking_strategy = 0;
1335 flacparse->block_size = 0;
1336 flacparse->sample_number = 0;
1341 static GstFlowReturn
1342 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1344 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1347 if (flacparse->tags) {
1348 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1349 flacparse->tags = NULL;
1352 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;