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 GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
206 GST_TYPE_BASE_PARSE);
209 gst_flac_parse_base_init (gpointer g_class)
211 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
213 gst_element_class_add_pad_template (element_class,
214 gst_static_pad_template_get (&src_factory));
215 gst_element_class_add_pad_template (element_class,
216 gst_static_pad_template_get (&sink_factory));
218 gst_element_class_set_details_simple (element_class, "FLAC audio parser",
219 "Codec/Parser/Audio",
220 "Parses audio with the FLAC lossless audio codec",
221 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
223 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
224 "Flac parser element");
228 gst_flac_parse_class_init (GstFlacParseClass * klass)
230 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
231 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
233 gobject_class->finalize = gst_flac_parse_finalize;
234 gobject_class->set_property = gst_flac_parse_set_property;
235 gobject_class->get_property = gst_flac_parse_get_property;
237 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
238 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
239 "Check the overall checksums of every frame",
240 DEFAULT_CHECK_FRAME_CHECKSUMS,
241 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
243 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
244 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
245 baseparse_class->check_valid_frame =
246 GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
247 baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
248 baseparse_class->pre_push_frame =
249 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
250 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
254 gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
256 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
260 gst_flac_parse_set_property (GObject * object, guint prop_id,
261 const GValue * value, GParamSpec * pspec)
263 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
266 case PROP_CHECK_FRAME_CHECKSUMS:
267 flacparse->check_frame_checksums = g_value_get_boolean (value);
270 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
276 gst_flac_parse_get_property (GObject * object, guint prop_id,
277 GValue * value, GParamSpec * pspec)
279 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
282 case PROP_CHECK_FRAME_CHECKSUMS:
283 g_value_set_boolean (value, flacparse->check_frame_checksums);
286 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292 gst_flac_parse_finalize (GObject * object)
294 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
296 if (flacparse->tags) {
297 gst_tag_list_free (flacparse->tags);
298 flacparse->tags = NULL;
301 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
302 g_list_free (flacparse->headers);
303 flacparse->headers = NULL;
305 G_OBJECT_CLASS (parent_class)->finalize (object);
309 gst_flac_parse_start (GstBaseParse * parse)
311 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
313 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
314 flacparse->min_blocksize = 0;
315 flacparse->max_blocksize = 0;
316 flacparse->min_framesize = 0;
317 flacparse->max_framesize = 0;
319 flacparse->upstream_length = -1;
321 flacparse->samplerate = 0;
322 flacparse->channels = 0;
324 flacparse->total_samples = 0;
326 flacparse->offset = GST_CLOCK_TIME_NONE;
327 flacparse->blocking_strategy = 0;
328 flacparse->block_size = 0;
329 flacparse->sample_number = 0;
332 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
334 /* inform baseclass we can come up with ts, based on counters in packets */
335 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
336 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
342 gst_flac_parse_stop (GstBaseParse * parse)
344 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
346 if (flacparse->tags) {
347 gst_tag_list_free (flacparse->tags);
348 flacparse->tags = NULL;
351 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
352 g_list_free (flacparse->headers);
353 flacparse->headers = NULL;
358 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
360 static const guint16 blocksize_table[16] = {
361 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
362 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
366 static const guint32 sample_rate_table[16] = {
368 88200, 176400, 192000,
369 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
376 FRAME_HEADER_INVALID,
377 FRAME_HEADER_MORE_DATA
378 } FrameHeaderCheckReturn;
380 static FrameHeaderCheckReturn
381 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
382 const guint8 * data, guint size, gboolean set, guint16 * block_size_ret)
384 GstBitReader reader = GST_BIT_READER_INIT (data, size);
385 guint8 blocking_strategy;
387 guint32 samplerate = 0;
388 guint64 sample_number;
389 guint8 channels, bps;
391 guint8 actual_crc, expected_crc = 0;
393 /* Skip 14 bit sync code */
394 gst_bit_reader_skip_unchecked (&reader, 14);
397 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
400 /* 0 == fixed block size, 1 == variable block size */
401 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
403 /* block size index, calculation of the real blocksize below */
404 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
408 /* sample rate index, calculation of the real samplerate below */
409 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
410 if (samplerate == 0x0f)
413 /* channel assignment */
414 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
417 } else if (channels <= 10) {
419 } else if (channels > 10) {
422 if (flacparse->channels && flacparse->channels != channels)
425 /* bits per sample */
426 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
427 if (bps == 0x03 || bps == 0x07) {
429 } else if (bps == 0 && flacparse->bps == 0) {
430 goto need_streaminfo;
432 bps = sample_size_table[bps];
433 if (flacparse->bps && bps != flacparse->bps)
436 /* reserved, must be 0 */
437 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
440 /* read "utf8" encoded sample/frame number */
444 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
446 /* This is slightly faster than a loop */
450 } else if ((len & 0xc0) && !(len & 0x20)) {
451 sample_number = len & 0x1f;
453 } else if ((len & 0xe0) && !(len & 0x10)) {
454 sample_number = len & 0x0f;
456 } else if ((len & 0xf0) && !(len & 0x08)) {
457 sample_number = len & 0x07;
459 } else if ((len & 0xf8) && !(len & 0x04)) {
460 sample_number = len & 0x03;
462 } else if ((len & 0xfc) && !(len & 0x02)) {
463 sample_number = len & 0x01;
465 } else if ((len & 0xfe) && !(len & 0x01)) {
466 sample_number = len & 0x0;
472 if ((blocking_strategy == 0 && len > 5) ||
473 (blocking_strategy == 1 && len > 6))
477 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
480 if ((tmp & 0xc0) != 0x80)
484 sample_number |= (tmp & 0x3f);
489 /* calculate real blocksize from the blocksize index */
490 if (block_size == 0) {
492 } else if (block_size == 6) {
493 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
496 } else if (block_size == 7) {
497 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
501 block_size = blocksize_table[block_size];
504 /* calculate the real samplerate from the samplerate index */
505 if (samplerate == 0 && flacparse->samplerate == 0) {
506 goto need_streaminfo;
507 } else if (samplerate < 12) {
508 samplerate = sample_rate_table[samplerate];
509 } else if (samplerate == 12) {
510 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
513 } else if (samplerate == 13) {
514 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
516 } else if (samplerate == 14) {
517 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
522 if (flacparse->samplerate && flacparse->samplerate != samplerate)
525 /* check crc-8 for the header */
526 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
530 gst_flac_calculate_crc8 (data,
531 (gst_bit_reader_get_pos (&reader) / 8) - 1);
532 if (actual_crc != expected_crc)
536 flacparse->block_size = block_size;
537 if (!flacparse->samplerate)
538 flacparse->samplerate = samplerate;
540 flacparse->bps = bps;
541 if (!flacparse->blocking_strategy)
542 flacparse->blocking_strategy = blocking_strategy;
543 if (!flacparse->channels)
544 flacparse->channels = channels;
545 if (!flacparse->sample_number)
546 flacparse->sample_number = sample_number;
548 GST_DEBUG_OBJECT (flacparse,
549 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
550 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
551 flacparse->block_size, flacparse->sample_number);
555 *block_size_ret = block_size;
557 return FRAME_HEADER_VALID;
560 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
561 return FRAME_HEADER_INVALID;
563 return FRAME_HEADER_INVALID;
566 return FRAME_HEADER_MORE_DATA;
570 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
571 GstBaseParseFrame * frame, guint * ret)
575 guint max, size, remaining;
576 guint i, search_start, search_end;
577 FrameHeaderCheckReturn header_ret;
580 buffer = frame->buffer;
581 data = GST_BUFFER_DATA (buffer);
582 size = GST_BUFFER_SIZE (buffer);
584 if (size < flacparse->min_framesize)
588 gst_flac_parse_frame_header_is_valid (flacparse, data, size, TRUE,
590 if (header_ret == FRAME_HEADER_INVALID) {
593 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
597 /* mind unknown framesize */
598 search_start = MAX (2, flacparse->min_framesize);
599 if (flacparse->max_framesize)
600 search_end = MIN (size, flacparse->max_framesize + 9 + 2);
607 for (i = search_start; i < search_end; i++, remaining--) {
608 if ((GST_READ_UINT16_BE (data + i) & 0xfffe) == 0xfff8) {
610 gst_flac_parse_frame_header_is_valid (flacparse, data + i, remaining,
612 if (header_ret == FRAME_HEADER_VALID) {
613 if (flacparse->check_frame_checksums) {
614 guint16 actual_crc = gst_flac_calculate_crc16 (data, i - 2);
615 guint16 expected_crc = GST_READ_UINT16_BE (data + i - 2);
617 if (actual_crc != expected_crc)
621 flacparse->block_size = block_size;
623 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
629 /* For the last frame output everything to the end */
630 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
631 if (flacparse->check_frame_checksums) {
632 guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
633 guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
635 if (actual_crc == expected_crc) {
637 flacparse->block_size = block_size;
642 flacparse->block_size = block_size;
648 max = flacparse->max_framesize + 16;
651 *ret = MIN (size + 4096, max);
656 gst_flac_parse_check_valid_frame (GstBaseParse * parse,
657 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
659 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
660 GstBuffer *buffer = frame->buffer;
661 const guint8 *data = GST_BUFFER_DATA (buffer);
663 if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
666 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
667 if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
668 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
671 } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
672 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
673 /* Minimal size of a frame header */
674 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
675 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
679 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
682 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
683 guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
685 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
689 if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
693 flacparse->offset = GST_BUFFER_OFFSET (buffer);
694 flacparse->blocking_strategy = 0;
695 flacparse->block_size = 0;
696 flacparse->sample_number = 0;
698 GST_DEBUG_OBJECT (flacparse, "Found sync code");
699 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
704 /* If we're at EOS and the frame was not valid, drop it! */
705 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
706 GST_WARNING_OBJECT (flacparse, "EOS");
711 } else if (next > GST_BUFFER_SIZE (buffer)) {
712 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
714 gst_base_parse_set_min_frame_size (parse, next);
717 GST_ERROR_OBJECT (flacparse,
718 "Giving up on invalid frame (%d bytes)",
719 GST_BUFFER_SIZE (buffer));
724 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
728 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
729 0, GST_BUFFER_SIZE (buffer));
732 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
736 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
737 *skipsize = GST_BUFFER_SIZE (buffer) - 3;
747 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
749 GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
751 if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
752 GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
753 GST_BUFFER_SIZE (buffer));
757 /* Skip metadata block header */
758 gst_bit_reader_skip (&reader, 32);
760 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
762 if (flacparse->min_blocksize < 16) {
763 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
764 flacparse->min_blocksize);
767 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
769 if (flacparse->max_blocksize < 16) {
770 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
771 flacparse->max_blocksize);
774 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
776 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
779 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
781 if (flacparse->samplerate == 0) {
782 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
786 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
788 flacparse->channels++;
789 if (flacparse->channels > 8) {
790 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
791 flacparse->channels);
795 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
799 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
801 if (flacparse->total_samples) {
802 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
803 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
806 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
807 "\tmin/max blocksize: %u/%u,\n"
808 "\tmin/max framesize: %u/%u,\n"
809 "\tsamplerate: %u,\n"
811 "\tbits per sample: %u,\n"
812 "\ttotal samples: %" G_GUINT64_FORMAT,
813 flacparse->min_blocksize, flacparse->max_blocksize,
814 flacparse->min_framesize, flacparse->max_framesize,
815 flacparse->samplerate,
816 flacparse->channels, flacparse->bps, flacparse->total_samples);
821 GST_ERROR_OBJECT (flacparse, "Failed to read data");
826 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
829 flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
830 GST_BUFFER_DATA (buffer), 4, NULL);
832 if (flacparse->tags == NULL) {
833 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
834 } else if (gst_tag_list_is_empty (flacparse->tags)) {
835 gst_tag_list_free (flacparse->tags);
836 flacparse->tags = NULL;
843 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
845 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
846 const guint8 *data = GST_BUFFER_DATA (buffer);
847 guint32 img_len = 0, img_type = 0;
848 guint32 img_mimetype_len = 0, img_description_len = 0;
850 if (!gst_byte_reader_skip (&reader, 4))
853 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
856 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
858 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
861 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
863 if (!gst_byte_reader_skip (&reader, img_description_len))
866 if (!gst_byte_reader_skip (&reader, 4 * 4))
869 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
872 if (!flacparse->tags)
873 flacparse->tags = gst_tag_list_new ();
875 gst_tag_list_add_id3_image (flacparse->tags,
876 data + gst_byte_reader_get_pos (&reader), img_len, img_type);
878 if (gst_tag_list_is_empty (flacparse->tags)) {
879 gst_tag_list_free (flacparse->tags);
880 flacparse->tags = NULL;
886 GST_ERROR_OBJECT (flacparse, "Error reading data");
891 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
894 GST_DEBUG_OBJECT (flacparse, "storing seektable");
895 /* only store for now;
896 * offset of the first frame is needed to get real info */
897 flacparse->seektable = gst_buffer_ref (buffer);
903 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
906 gint64 offset = 0, samples = 0;
908 GST_DEBUG_OBJECT (flacparse,
909 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
914 gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
916 if (!gst_byte_reader_skip (&br, 4))
920 while (gst_byte_reader_get_remaining (&br)) {
921 if (!gst_byte_reader_get_int64_be (&br, &samples))
923 if (!gst_byte_reader_get_int64_be (&br, &offset))
925 if (!gst_byte_reader_skip (&br, 2))
928 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
929 G_GINT64_FORMAT, samples, offset);
932 if (G_LIKELY (offset > 0 && samples > 0)) {
933 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
934 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
935 flacparse->samplerate), TRUE, FALSE);
940 gst_buffer_unref (flacparse->seektable);
941 flacparse->seektable = NULL;
945 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
947 GValue value = { 0, };
949 g_value_init (&value, GST_TYPE_BUFFER);
950 /* copy buffer to avoid problems with circular refcounts */
951 buf = gst_buffer_copy (buf);
952 /* again, for good measure */
953 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
954 gst_value_set_buffer (&value, buf);
955 gst_buffer_unref (buf);
956 gst_value_array_append_value (array_val, &value);
957 g_value_unset (&value);
961 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
963 GstBuffer *vorbiscomment = NULL;
964 GstBuffer *streaminfo = NULL;
965 GstBuffer *marker = NULL;
966 GValue array = { 0, };
971 caps = gst_caps_new_simple ("audio/x-flac",
972 "channels", G_TYPE_INT, flacparse->channels,
973 "framed", G_TYPE_BOOLEAN, TRUE,
974 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
976 if (!flacparse->headers)
979 for (l = flacparse->headers; l; l = l->next) {
980 GstBuffer *header = l->data;
981 const guint8 *data = GST_BUFFER_DATA (header);
982 guint size = GST_BUFFER_SIZE (header);
984 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
986 if (size == 4 && memcmp (data, "fLaC", 4) == 0) {
988 } else if (size > 1 && (data[0] & 0x7f) == 0) {
990 } else if (size > 1 && (data[0] & 0x7f) == 4) {
991 vorbiscomment = header;
995 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
996 GST_WARNING_OBJECT (flacparse,
997 "missing header %p %p %p, muxing into container "
998 "formats may be broken", marker, streaminfo, vorbiscomment);
1002 g_value_init (&array, GST_TYPE_ARRAY);
1004 /* add marker including STREAMINFO header */
1009 /* minus one for the marker that is merged with streaminfo here */
1010 num = g_list_length (flacparse->headers) - 1;
1012 buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
1013 GST_BUFFER_DATA (buf)[0] = 0x7f;
1014 memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
1015 GST_BUFFER_DATA (buf)[5] = 0x01; /* mapping version major */
1016 GST_BUFFER_DATA (buf)[6] = 0x00; /* mapping version minor */
1017 GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
1018 GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
1019 memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
1020 memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
1021 GST_BUFFER_SIZE (streaminfo));
1022 _value_array_append_buffer (&array, buf);
1023 gst_buffer_unref (buf);
1026 /* add VORBISCOMMENT header */
1027 _value_array_append_buffer (&array, vorbiscomment);
1029 /* add other headers, if there are any */
1030 for (l = flacparse->headers; l; l = l->next) {
1031 if (GST_BUFFER_CAST (l->data) != marker &&
1032 GST_BUFFER_CAST (l->data) != streaminfo &&
1033 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1034 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1038 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1039 "streamheader", &array);
1040 g_value_unset (&array);
1044 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1045 gst_caps_unref (caps);
1047 /* push header buffers; update caps, so when we push the first buffer the
1048 * negotiated caps will change to caps that include the streamheader field */
1049 while (flacparse->headers) {
1050 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1052 GstBaseParseFrame frame;
1054 flacparse->headers =
1055 g_list_delete_link (flacparse->headers, flacparse->headers);
1056 buf = gst_buffer_make_metadata_writable (buf);
1057 gst_buffer_set_caps (buf,
1058 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
1060 /* init, set and give away frame */
1061 gst_base_parse_frame_init (&frame);
1063 frame.overhead = -1;
1064 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1065 if (ret != GST_FLOW_OK) {
1070 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1071 g_list_free (flacparse->headers);
1072 flacparse->headers = NULL;
1078 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1080 GstBuffer *marker, *streaminfo, *vorbiscomment;
1083 marker = gst_buffer_new_and_alloc (4);
1084 memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
1085 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1086 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1087 GST_BUFFER_OFFSET (marker) = 0;
1088 GST_BUFFER_OFFSET_END (marker) = 0;
1089 flacparse->headers = g_list_append (flacparse->headers, marker);
1091 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1092 data = GST_BUFFER_DATA (streaminfo);
1093 memset (data, 0, 4 + 34);
1095 /* metadata block header */
1096 data[0] = 0x00; /* is_last = 0; type = 0; */
1097 data[1] = 0x00; /* length = 34; */
1103 data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1104 data[5] = (flacparse->block_size) & 0xff;
1105 data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1106 data[7] = (flacparse->block_size) & 0xff;
1108 data[8] = 0x00; /* min framesize = 0; */
1111 data[11] = 0x00; /* max framesize = 0; */
1115 data[14] = (flacparse->samplerate >> 12) & 0xff;
1116 data[15] = (flacparse->samplerate >> 4) & 0xff;
1117 data[16] = (flacparse->samplerate >> 0) & 0xf0;
1119 data[16] |= (flacparse->channels - 1) << 1;
1121 data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1122 data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1126 GstFormat fmt = GST_FORMAT_TIME;
1128 if (gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
1129 (flacparse)), &fmt, &duration) && fmt == GST_FORMAT_TIME) {
1130 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1132 data[17] |= (duration >> 32) & 0xff;
1133 data[18] |= (duration >> 24) & 0xff;
1134 data[19] |= (duration >> 16) & 0xff;
1135 data[20] |= (duration >> 8) & 0xff;
1136 data[21] |= (duration >> 0) & 0xff;
1141 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1142 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1143 GST_BUFFER_OFFSET (streaminfo) = 0;
1144 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1145 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1147 /* empty vorbiscomment */
1149 GstTagList *taglist = gst_tag_list_new ();
1153 header[0] = 0x84; /* is_last = 1; type = 4; */
1156 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1157 sizeof (header), NULL);
1158 gst_tag_list_free (taglist);
1160 /* Get rid of framing bit */
1161 if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
1166 gst_buffer_create_sub (vorbiscomment, 0,
1167 GST_BUFFER_SIZE (vorbiscomment) - 1);
1168 gst_buffer_unref (vorbiscomment);
1169 vorbiscomment = sub;
1172 size = GST_BUFFER_SIZE (vorbiscomment) - 4;
1173 GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
1174 GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
1175 GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
1177 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1178 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1179 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1180 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1181 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1187 static GstFlowReturn
1188 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1190 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1191 GstBuffer *buffer = frame->buffer;
1192 const guint8 *data = GST_BUFFER_DATA (buffer);
1194 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1195 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1196 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1197 GST_BUFFER_OFFSET (buffer) = 0;
1198 GST_BUFFER_OFFSET_END (buffer) = 0;
1200 /* 32 bits metadata block */
1201 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1202 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1204 flacparse->headers =
1205 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1207 return GST_BASE_PARSE_FLOW_DROPPED;
1208 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1209 gboolean is_last = ((data[0] & 0x80) == 0x80);
1210 guint type = (data[0] & 0x7F);
1213 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1214 return GST_BASE_PARSE_FLOW_DROPPED;
1217 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1220 case 0: /* STREAMINFO */
1221 if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
1222 return GST_FLOW_ERROR;
1224 case 3: /* SEEKTABLE */
1225 if (!gst_flac_parse_handle_seektable (flacparse, buffer))
1226 return GST_FLOW_ERROR;
1228 case 4: /* VORBIS_COMMENT */
1229 if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
1230 return GST_FLOW_ERROR;
1232 case 6: /* PICTURE */
1233 if (!gst_flac_parse_handle_picture (flacparse, buffer))
1234 return GST_FLOW_ERROR;
1236 case 1: /* PADDING */
1237 case 2: /* APPLICATION */
1238 case 5: /* CUESHEET */
1239 default: /* RESERVED */
1243 GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
1244 GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
1245 GST_BUFFER_OFFSET (buffer) = 0;
1246 GST_BUFFER_OFFSET_END (buffer) = 0;
1248 flacparse->headers =
1249 g_list_append (flacparse->headers, gst_buffer_ref (buffer));
1252 if (!gst_flac_parse_handle_headers (flacparse))
1253 return GST_FLOW_ERROR;
1255 /* Minimal size of a frame header */
1256 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1257 flacparse->min_framesize));
1258 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1261 /* DROPPED because we pushed already or will push all headers manually */
1262 return GST_BASE_PARSE_FLOW_DROPPED;
1264 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1265 FrameHeaderCheckReturn ret;
1267 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1269 gst_flac_parse_frame_header_is_valid (flacparse,
1270 GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
1271 if (ret != FRAME_HEADER_VALID) {
1272 GST_ERROR_OBJECT (flacparse,
1273 "Baseclass didn't provide a complete frame");
1274 return GST_FLOW_ERROR;
1278 if (flacparse->block_size == 0) {
1279 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1280 return GST_FLOW_ERROR;
1283 if (flacparse->seektable)
1284 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1286 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1287 if (flacparse->blocking_strategy == 1) {
1288 GST_WARNING_OBJECT (flacparse,
1289 "Generating headers for variable blocksize streams not supported");
1291 if (!gst_flac_parse_handle_headers (flacparse))
1292 return GST_FLOW_ERROR;
1294 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1296 if (!gst_flac_parse_generate_headers (flacparse))
1297 return GST_FLOW_ERROR;
1299 if (!gst_flac_parse_handle_headers (flacparse))
1300 return GST_FLOW_ERROR;
1302 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1305 /* also cater for oggmux metadata */
1306 if (flacparse->blocking_strategy == 0) {
1307 GST_BUFFER_TIMESTAMP (buffer) =
1308 gst_util_uint64_scale (flacparse->sample_number,
1309 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1310 GST_BUFFER_OFFSET_END (buffer) =
1311 flacparse->sample_number * flacparse->block_size +
1312 flacparse->block_size;
1314 GST_BUFFER_TIMESTAMP (buffer) =
1315 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1316 flacparse->samplerate);
1317 GST_BUFFER_OFFSET_END (buffer) =
1318 flacparse->sample_number + flacparse->block_size;
1320 GST_BUFFER_OFFSET (buffer) =
1321 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1322 flacparse->samplerate);
1323 GST_BUFFER_DURATION (buffer) =
1324 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1326 /* To simplify, we just assume that it's a fixed size header and ignore
1327 * subframe headers. The first could lead us to being off by 88 bits and
1328 * the second even less, so the total inaccuracy is negligible. */
1329 frame->overhead = 7;
1331 /* Minimal size of a frame header */
1332 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1333 flacparse->min_framesize));
1335 flacparse->offset = -1;
1336 flacparse->blocking_strategy = 0;
1337 flacparse->block_size = 0;
1338 flacparse->sample_number = 0;
1343 static GstFlowReturn
1344 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1346 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1349 if (flacparse->tags) {
1350 gst_element_found_tags (GST_ELEMENT (flacparse), flacparse->tags);
1351 flacparse->tags = NULL;
1354 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1360 gst_flac_parse_convert (GstBaseParse * parse,
1361 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1362 gint64 * dest_value)
1364 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1366 if (flacparse->samplerate > 0) {
1367 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1368 if (src_value != -1)
1370 gst_util_uint64_scale (src_value, GST_SECOND,
1371 flacparse->samplerate);
1375 } else if (src_format == GST_FORMAT_TIME &&
1376 dest_format == GST_FORMAT_DEFAULT) {
1377 if (src_value != -1)
1379 gst_util_uint64_scale (src_value, flacparse->samplerate,
1387 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1388 src_value, dest_format, dest_value);