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);
201 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
202 GstFormat src_format, gint64 src_value, GstFormat dest_format,
203 gint64 * dest_value);
205 #define gst_flac_parse_parent_class parent_class
206 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
209 gst_flac_parse_class_init (GstFlacParseClass * klass)
211 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
212 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
213 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
215 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
216 "Flac parser element");
218 gobject_class->finalize = gst_flac_parse_finalize;
219 gobject_class->set_property = gst_flac_parse_set_property;
220 gobject_class->get_property = gst_flac_parse_get_property;
222 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
223 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
224 "Check the overall checksums of every frame",
225 DEFAULT_CHECK_FRAME_CHECKSUMS,
226 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
228 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
229 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
230 baseparse_class->check_valid_frame =
231 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
232 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
233 baseparse_class->pre_push_frame =
234 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
235 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
237 gst_element_class_add_pad_template (element_class,
238 gst_static_pad_template_get (&src_factory));
239 gst_element_class_add_pad_template (element_class,
240 gst_static_pad_template_get (&sink_factory));
242 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
243 "Codec/Parser/Audio",
244 "Parses audio with the FLAC lossless audio codec",
245 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
249 gst_flac_parse_init (GstFlacParse * flacparse)
251 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
255 gst_flac_parse_set_property (GObject * object, guint prop_id,
256 const GValue * value, GParamSpec * pspec)
258 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
261 case PROP_CHECK_FRAME_CHECKSUMS:
262 flacparse->check_frame_checksums = g_value_get_boolean (value);
265 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
271 gst_flac_parse_get_property (GObject * object, guint prop_id,
272 GValue * value, GParamSpec * pspec)
274 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
277 case PROP_CHECK_FRAME_CHECKSUMS:
278 g_value_set_boolean (value, flacparse->check_frame_checksums);
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
287 gst_flac_parse_finalize (GObject * object)
289 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
291 if (flacparse->tags) {
292 gst_tag_list_free (flacparse->tags);
293 flacparse->tags = NULL;
296 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
297 g_list_free (flacparse->headers);
298 flacparse->headers = NULL;
300 G_OBJECT_CLASS (parent_class)->finalize (object);
304 gst_flac_parse_start (GstBaseParse * parse)
306 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
308 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
309 flacparse->min_blocksize = 0;
310 flacparse->max_blocksize = 0;
311 flacparse->min_framesize = 0;
312 flacparse->max_framesize = 0;
314 flacparse->upstream_length = -1;
316 flacparse->samplerate = 0;
317 flacparse->channels = 0;
319 flacparse->total_samples = 0;
321 flacparse->offset = GST_CLOCK_TIME_NONE;
322 flacparse->blocking_strategy = 0;
323 flacparse->block_size = 0;
324 flacparse->sample_number = 0;
327 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
329 /* inform baseclass we can come up with ts, based on counters in packets */
330 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
331 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
337 gst_flac_parse_stop (GstBaseParse * parse)
339 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
341 if (flacparse->tags) {
342 gst_tag_list_free (flacparse->tags);
343 flacparse->tags = NULL;
346 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
347 g_list_free (flacparse->headers);
348 flacparse->headers = NULL;
353 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
355 static const guint16 blocksize_table[16] = {
356 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
357 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
361 static const guint32 sample_rate_table[16] = {
363 88200, 176400, 192000,
364 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
371 FRAME_HEADER_INVALID,
372 FRAME_HEADER_MORE_DATA
373 } FrameHeaderCheckReturn;
375 static FrameHeaderCheckReturn
376 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
377 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
379 GstBitReader reader = GST_BIT_READER_INIT (data, size);
380 guint8 blocking_strategy;
382 guint32 samplerate = 0;
383 guint64 sample_number;
384 guint8 channels, bps;
386 guint8 actual_crc, expected_crc = 0;
388 /* Skip 14 bit sync code */
389 gst_bit_reader_skip_unchecked (&reader, 14);
392 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
395 /* 0 == fixed block size, 1 == variable block size */
396 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
398 /* block size index, calculation of the real blocksize below */
399 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
403 /* sample rate index, calculation of the real samplerate below */
404 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
405 if (samplerate == 0x0f)
408 /* channel assignment */
409 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
412 } else if (channels <= 10) {
414 } else if (channels > 10) {
417 if (flacparse->channels && flacparse->channels != channels)
420 /* bits per sample */
421 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
422 if (bps == 0x03 || bps == 0x07) {
424 } else if (bps == 0 && flacparse->bps == 0) {
425 goto need_streaminfo;
427 bps = sample_size_table[bps];
428 if (flacparse->bps && bps != flacparse->bps)
431 /* reserved, must be 0 */
432 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
435 /* read "utf8" encoded sample/frame number */
439 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
441 /* This is slightly faster than a loop */
445 } else if ((len & 0xc0) && !(len & 0x20)) {
446 sample_number = len & 0x1f;
448 } else if ((len & 0xe0) && !(len & 0x10)) {
449 sample_number = len & 0x0f;
451 } else if ((len & 0xf0) && !(len & 0x08)) {
452 sample_number = len & 0x07;
454 } else if ((len & 0xf8) && !(len & 0x04)) {
455 sample_number = len & 0x03;
457 } else if ((len & 0xfc) && !(len & 0x02)) {
458 sample_number = len & 0x01;
460 } else if ((len & 0xfe) && !(len & 0x01)) {
461 sample_number = len & 0x0;
467 if ((blocking_strategy == 0 && len > 5) ||
468 (blocking_strategy == 1 && len > 6))
472 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
475 if ((tmp & 0xc0) != 0x80)
479 sample_number |= (tmp & 0x3f);
484 /* calculate real blocksize from the blocksize index */
485 if (block_size == 0) {
487 } else if (block_size == 6) {
488 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
491 } else if (block_size == 7) {
492 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
496 block_size = blocksize_table[block_size];
499 /* calculate the real samplerate from the samplerate index */
500 if (samplerate == 0 && flacparse->samplerate == 0) {
501 goto need_streaminfo;
502 } else if (samplerate < 12) {
503 samplerate = sample_rate_table[samplerate];
504 } else if (samplerate == 12) {
505 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
508 } else if (samplerate == 13) {
509 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
511 } else if (samplerate == 14) {
512 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
517 if (flacparse->samplerate && flacparse->samplerate != samplerate)
520 /* check crc-8 for the header */
521 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
525 gst_flac_calculate_crc8 (data,
526 (gst_bit_reader_get_pos (&reader) / 8) - 1);
527 if (actual_crc != expected_crc)
531 flacparse->block_size = block_size;
532 if (!flacparse->samplerate)
533 flacparse->samplerate = samplerate;
535 flacparse->bps = bps;
536 if (!flacparse->blocking_strategy)
537 flacparse->blocking_strategy = blocking_strategy;
538 if (!flacparse->channels)
539 flacparse->channels = channels;
540 if (!flacparse->sample_number)
541 flacparse->sample_number = sample_number;
543 GST_DEBUG_OBJECT (flacparse,
544 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
545 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
546 flacparse->block_size, flacparse->sample_number);
550 *block_size_ret = block_size;
552 return FRAME_HEADER_VALID;
555 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
556 return FRAME_HEADER_INVALID;
558 return FRAME_HEADER_INVALID;
561 return FRAME_HEADER_MORE_DATA;
565 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
566 GstBaseParseFrame * frame, guint * ret)
571 guint max, remaining;
572 guint i, search_start, search_end;
573 FrameHeaderCheckReturn header_ret;
575 gboolean result = FALSE;
577 buffer = frame->buffer;
578 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
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) {
590 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;
620 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
626 /* For the last frame output everything to the end */
627 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
628 if (flacparse->check_frame_checksums) {
629 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
630 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
632 if (actual_crc == expected_crc) {
634 flacparse->block_size = block_size;
640 flacparse->block_size = block_size;
647 max = flacparse->max_framesize + 16;
650 *ret = MIN (size + 4096, max);
654 gst_buffer_unmap (buffer, data, size);
659 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
660 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
662 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
663 GstBuffer *buffer = frame->buffer;
666 gboolean result = TRUE;
668 data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
670 if (G_UNLIKELY (bufsize < 4)) {
675 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
676 if (memcmp (data, "fLaC", 4) == 0) {
677 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
681 if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
682 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
683 /* Minimal size of a frame header */
684 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
685 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
690 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
695 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
696 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
698 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
703 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
707 flacparse->offset = GST_BUFFER_OFFSET (buffer);
708 flacparse->blocking_strategy = 0;
709 flacparse->block_size = 0;
710 flacparse->sample_number = 0;
712 GST_DEBUG_OBJECT (flacparse, "Found sync code");
713 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
718 /* If we're at EOS and the frame was not valid, drop it! */
719 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
720 GST_WARNING_OBJECT (flacparse, "EOS");
726 } else if (next > bufsize) {
727 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
729 gst_base_parse_set_min_frame_size (parse, next);
733 GST_ERROR_OBJECT (flacparse,
734 "Giving up on invalid frame (%d bytes)", bufsize);
740 GstByteReader reader;
743 gst_byte_reader_init (&reader, data, bufsize);
745 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
749 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
754 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
755 *skipsize = bufsize - 3;
764 gst_buffer_unmap (buffer, data, bufsize);
769 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
775 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
776 gst_bit_reader_init (&reader, data, size);
778 if (size != 4 + 34) {
779 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
784 /* Skip metadata block header */
785 gst_bit_reader_skip (&reader, 32);
787 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
789 if (flacparse->min_blocksize < 16) {
790 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
791 flacparse->min_blocksize);
794 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
796 if (flacparse->max_blocksize < 16) {
797 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
798 flacparse->max_blocksize);
801 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
803 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
806 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
808 if (flacparse->samplerate == 0) {
809 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
813 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
815 flacparse->channels++;
816 if (flacparse->channels > 8) {
817 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
818 flacparse->channels);
822 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
826 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
828 if (flacparse->total_samples) {
829 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
830 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
833 gst_buffer_unmap (buffer, data, size);
835 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
836 "\tmin/max blocksize: %u/%u,\n"
837 "\tmin/max framesize: %u/%u,\n"
838 "\tsamplerate: %u,\n"
840 "\tbits per sample: %u,\n"
841 "\ttotal samples: %" G_GUINT64_FORMAT,
842 flacparse->min_blocksize, flacparse->max_blocksize,
843 flacparse->min_framesize, flacparse->max_framesize,
844 flacparse->samplerate,
845 flacparse->channels, flacparse->bps, flacparse->total_samples);
850 GST_ERROR_OBJECT (flacparse, "Failed to read data");
852 gst_buffer_unmap (buffer, data, size);
857 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
863 data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
865 flacparse->tags = gst_tag_list_from_vorbiscomment (data, size, data, 4, NULL);
866 gst_buffer_unmap (buffer, data, size);
868 if (flacparse->tags == NULL) {
869 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
870 } else if (gst_tag_list_is_empty (flacparse->tags)) {
871 gst_tag_list_free (flacparse->tags);
872 flacparse->tags = NULL;
879 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
881 GstByteReader reader;
884 guint32 img_len = 0, img_type = 0;
885 guint32 img_mimetype_len = 0, img_description_len = 0;
887 data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
888 gst_byte_reader_init (&reader, data, bufsize);
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;
923 gst_buffer_unmap (buffer, data, bufsize);
927 GST_ERROR_OBJECT (flacparse, "Error reading data");
928 gst_buffer_unmap (buffer, data, bufsize);
933 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
936 GST_DEBUG_OBJECT (flacparse, "storing seektable");
937 /* only store for now;
938 * offset of the first frame is needed to get real info */
939 flacparse->seektable = gst_buffer_ref (buffer);
945 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
948 gint64 offset = 0, samples = 0;
952 GST_DEBUG_OBJECT (flacparse,
953 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
958 data = gst_buffer_map (flacparse->seektable, &bufsize, NULL, GST_MAP_READ);
959 gst_byte_reader_init (&br, data, bufsize);
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_unmap (flacparse->seektable, data, bufsize);
988 gst_buffer_unref (flacparse->seektable);
989 flacparse->seektable = NULL;
993 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
995 GValue value = { 0, };
997 g_value_init (&value, GST_TYPE_BUFFER);
998 /* copy buffer to avoid problems with circular refcounts */
999 buf = gst_buffer_copy (buf);
1000 /* again, for good measure */
1001 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
1002 gst_value_set_buffer (&value, buf);
1003 gst_buffer_unref (buf);
1004 gst_value_array_append_value (array_val, &value);
1005 g_value_unset (&value);
1009 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1011 GstBuffer *vorbiscomment = NULL;
1012 GstBuffer *streaminfo = NULL;
1013 GstBuffer *marker = NULL;
1014 GValue array = { 0, };
1017 gboolean res = TRUE;
1019 caps = gst_caps_new_simple ("audio/x-flac",
1020 "channels", G_TYPE_INT, flacparse->channels,
1021 "framed", G_TYPE_BOOLEAN, TRUE,
1022 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1024 if (!flacparse->headers)
1027 for (l = flacparse->headers; l; l = l->next) {
1028 GstBuffer *header = l->data;
1032 data = gst_buffer_map (header, &size, NULL, GST_MAP_READ);
1034 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
1036 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
1038 } else if (size > 1 && (data[0] & 0x7f) == 0) {
1039 streaminfo = header;
1040 } else if (size > 1 && (data[0] & 0x7f) == 4) {
1041 vorbiscomment = header;
1044 gst_buffer_unmap (header, data, size);
1047 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1048 GST_WARNING_OBJECT (flacparse,
1049 "missing header %p %p %p, muxing into container "
1050 "formats may be broken", marker, streaminfo, vorbiscomment);
1054 g_value_init (&array, GST_TYPE_ARRAY);
1056 /* add marker including STREAMINFO header */
1060 guint8 *sinfodata, *writedata;
1061 gsize sinfosize, writesize;
1063 sinfodata = gst_buffer_map (streaminfo, &sinfosize, NULL, GST_MAP_READ);
1065 /* minus one for the marker that is merged with streaminfo here */
1066 num = g_list_length (flacparse->headers) - 1;
1068 buf = gst_buffer_new_and_alloc (13 + sinfosize);
1069 writedata = gst_buffer_map (buf, &writesize, NULL, GST_MAP_WRITE);
1071 writedata[0] = 0x7f;
1072 memcpy (writedata + 1, "FLAC", 4);
1073 writedata[5] = 0x01; /* mapping version major */
1074 writedata[6] = 0x00; /* mapping version minor */
1075 writedata[7] = (num & 0xFF00) >> 8;
1076 writedata[8] = (num & 0x00FF) >> 0;
1077 memcpy (writedata + 9, "fLaC", 4);
1078 memcpy (writedata + 13, sinfodata, sinfosize);
1079 _value_array_append_buffer (&array, buf);
1081 gst_buffer_unmap (streaminfo, sinfodata, sinfosize);
1082 gst_buffer_unmap (buf, writedata, writesize);
1083 gst_buffer_unref (buf);
1086 /* add VORBISCOMMENT header */
1087 _value_array_append_buffer (&array, vorbiscomment);
1089 /* add other headers, if there are any */
1090 for (l = flacparse->headers; l; l = l->next) {
1091 if (GST_BUFFER_CAST (l->data) != marker &&
1092 GST_BUFFER_CAST (l->data) != streaminfo &&
1093 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1094 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1098 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1099 "streamheader", &array);
1100 g_value_unset (&array);
1104 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1105 gst_caps_unref (caps);
1107 /* push header buffers; update caps, so when we push the first buffer the
1108 * negotiated caps will change to caps that include the streamheader field */
1109 while (flacparse->headers) {
1110 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1112 GstBaseParseFrame frame;
1114 flacparse->headers =
1115 g_list_delete_link (flacparse->headers, flacparse->headers);
1116 buf = gst_buffer_make_writable (buf);
1118 /* init, set and give away frame */
1119 gst_base_parse_frame_init (&frame);
1121 frame.overhead = -1;
1122 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1123 if (ret != GST_FLOW_OK) {
1128 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1129 g_list_free (flacparse->headers);
1130 flacparse->headers = NULL;
1136 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1138 GstBuffer *marker, *streaminfo, *vorbiscomment;
1142 marker = gst_buffer_new_and_alloc (4);
1143 data = gst_buffer_map (marker, &bufsize, NULL, GST_MAP_WRITE);
1144 memcpy (data, "fLaC", 4);
1145 gst_buffer_unmap (marker, data, bufsize);
1146 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1147 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1148 GST_BUFFER_OFFSET (marker) = 0;
1149 GST_BUFFER_OFFSET_END (marker) = 0;
1150 flacparse->headers = g_list_append (flacparse->headers, marker);
1152 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1153 data = gst_buffer_map (streaminfo, &bufsize, NULL, GST_MAP_WRITE);
1154 memset (data, 0, 4 + 34);
1156 /* metadata block header */
1157 data[0] = 0x00; /* is_last = 0; type = 0; */
1158 data[1] = 0x00; /* length = 34; */
1164 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1165 data[5] = (flacparse->block_size) & 0xff;
1166 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1167 data[7] = (flacparse->block_size) & 0xff;
1169 data[8] = 0x00; /* min framesize = 0; */
1172 data[11] = 0x00; /* max framesize = 0; */
1176 data[14] = (flacparse->samplerate >> 12) & 0xff;
1177 data[15] = (flacparse->samplerate >> 4) & 0xff;
1178 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1180 data[16] |= (flacparse->channels - 1) << 1;
1182 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1183 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1188 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1189 GST_FORMAT_TIME, &duration)) {
1190 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1192 data[17] |= (duration >> 32) & 0xff;
1193 data[18] |= (duration >> 24) & 0xff;
1194 data[19] |= (duration >> 16) & 0xff;
1195 data[20] |= (duration >> 8) & 0xff;
1196 data[21] |= (duration >> 0) & 0xff;
1201 gst_buffer_unmap (streaminfo, data, bufsize);
1202 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1203 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1204 GST_BUFFER_OFFSET (streaminfo) = 0;
1205 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1206 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1208 /* empty vorbiscomment */
1210 GstTagList *taglist = gst_tag_list_new ();
1214 header[0] = 0x84; /* is_last = 1; type = 4; */
1217 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1218 sizeof (header), NULL);
1219 gst_tag_list_free (taglist);
1221 data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
1223 /* Get rid of framing bit */
1224 if (data[bufsize - 1] == 1) {
1228 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1230 gst_buffer_unmap (vorbiscomment, data, bufsize);
1231 gst_buffer_unref (vorbiscomment);
1232 vorbiscomment = sub;
1233 data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
1237 data[1] = ((size & 0xFF0000) >> 16);
1238 data[2] = ((size & 0x00FF00) >> 8);
1239 data[3] = (size & 0x0000FF);
1241 gst_buffer_unmap (vorbiscomment, data, bufsize);
1242 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1243 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1244 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1245 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1246 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1252 static GstFlowReturn
1253 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1255 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1256 GstBuffer *buffer = frame->buffer;
1257 guint8 *data = NULL;
1259 GstFlowReturn res = GST_FLOW_ERROR;
1261 data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
1263 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1264 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1265 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1266 GST_BUFFER_OFFSET (buffer) = 0;
1267 GST_BUFFER_OFFSET_END (buffer) = 0;
1269 /* 32 bits metadata block */
1270 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1271 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1273 flacparse->headers =
1274 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1276 res = GST_BASE_PARSE_FLOW_DROPPED;
1277 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1278 gboolean is_last = ((data[0] & 0x80) == 0x80);
1279 guint type = (data[0] & 0x7F);
1282 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1283 res = GST_BASE_PARSE_FLOW_DROPPED;
1287 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1290 case 0: /* STREAMINFO */
1291 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1294 case 3: /* SEEKTABLE */
1295 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1298 case 4: /* VORBIS_COMMENT */
1299 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1302 case 6: /* PICTURE */
1303 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1306 case 1: /* PADDING */
1307 case 2: /* APPLICATION */
1308 case 5: /* CUESHEET */
1309 default: /* RESERVED */
1313 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1314 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1315 GST_BUFFER_OFFSET (buffer) = 0;
1316 GST_BUFFER_OFFSET_END (buffer) = 0;
1318 flacparse->headers =
1319 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1322 if (!gst_flac_parse_handle_headers (flacparse))
1325 /* Minimal size of a frame header */
1326 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1327 flacparse->min_framesize));
1328 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1331 /* DROPPED because we pushed already or will push all headers manually */
1332 res = GST_BASE_PARSE_FLOW_DROPPED;
1334 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1335 FrameHeaderCheckReturn ret;
1337 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1339 gst_flac_parse_frame_header_is_valid (flacparse,
1340 data, bufsize, TRUE, NULL);
1341 if (ret != FRAME_HEADER_VALID) {
1342 GST_ERROR_OBJECT (flacparse,
1343 "Baseclass didn't provide a complete frame");
1348 if (flacparse->block_size == 0) {
1349 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1353 if (flacparse->seektable)
1354 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1356 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1357 if (flacparse->blocking_strategy == 1) {
1358 GST_WARNING_OBJECT (flacparse,
1359 "Generating headers for variable blocksize streams not supported");
1361 if (!gst_flac_parse_handle_headers (flacparse))
1364 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1366 if (!gst_flac_parse_generate_headers (flacparse))
1369 if (!gst_flac_parse_handle_headers (flacparse))
1372 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1375 /* also cater for oggmux metadata */
1376 if (flacparse->blocking_strategy == 0) {
1377 GST_BUFFER_TIMESTAMP (buffer) =
1378 gst_util_uint64_scale (flacparse->sample_number,
1379 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1380 GST_BUFFER_OFFSET_END (buffer) =
1381 flacparse->sample_number * flacparse->block_size +
1382 flacparse->block_size;
1384 GST_BUFFER_TIMESTAMP (buffer) =
1385 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1386 flacparse->samplerate);
1387 GST_BUFFER_OFFSET_END (buffer) =
1388 flacparse->sample_number + flacparse->block_size;
1390 GST_BUFFER_OFFSET (buffer) =
1391 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1392 flacparse->samplerate);
1393 GST_BUFFER_DURATION (buffer) =
1394 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1396 /* To simplify, we just assume that it's a fixed size header and ignore
1397 * subframe headers. The first could lead us to being off by 88 bits and
1398 * the second even less, so the total inaccuracy is negligible. */
1399 frame->overhead = 7;
1401 /* Minimal size of a frame header */
1402 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1403 flacparse->min_framesize));
1405 flacparse->offset = -1;
1406 flacparse->blocking_strategy = 0;
1407 flacparse->block_size = 0;
1408 flacparse->sample_number = 0;
1414 gst_buffer_unmap (buffer, data, bufsize);
1419 static GstFlowReturn
1420 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1422 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1425 if (flacparse->tags) {
1426 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1427 flacparse->tags = NULL;
1430 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1436 gst_flac_parse_convert (GstBaseParse * parse,
1437 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1438 gint64 * dest_value)
1440 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1442 if (flacparse->samplerate > 0) {
1443 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1444 if (src_value != -1)
1446 gst_util_uint64_scale (src_value, GST_SECOND,
1447 flacparse->samplerate);
1451 } else if (src_format == GST_FORMAT_TIME &&
1452 dest_format == GST_FORMAT_DEFAULT) {
1453 if (src_value != -1)
1455 gst_util_uint64_scale (src_value, flacparse->samplerate,
1463 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1464 src_value, dest_format, dest_value);