3 * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
4 * Copyright (C) 2009 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
5 * Copyright (C) 2009 Nokia Corporation. All rights reserved.
6 * Contact: Stefan Kost <stefan.kost@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * SECTION:element-flacparse
26 * @see_also: flacdec, oggdemux, vorbisparse
28 * The flacparse element will parse the header packets of the FLAC
29 * stream and put them as the streamheader in the caps. This is used in the
30 * multifdsink case where you want to stream live FLAC streams to multiple
31 * clients, each client has to receive the streamheaders first before they can
32 * consume the FLAC packets.
34 * This element also makes sure that the buffers that it pushes out are properly
35 * timestamped and that their offset and offset_end are set. The buffers that
36 * flacparse outputs have all of the metadata that oggmux expects to receive,
37 * which allows you to (for example) remux an ogg/flac or convert a native FLAC
38 * format file to an ogg bitstream.
41 * <title>Example pipelines</title>
43 * gst-launch -v filesrc location=sine.flac ! flacparse ! identity \
44 * ! oggmux ! filesink location=sine-remuxed.ogg
45 * ]| This pipeline converts a native FLAC format file to an ogg bitstream.
46 * It also illustrates that the streamheader is set in the caps, and that each
47 * buffer has the timestamp, duration, offset, and offset_end set.
56 #include "gstflacparse.h"
59 #include <gst/tag/tag.h>
60 #include <gst/audio/audio.h>
62 #include <gst/base/gstbitreader.h>
63 #include <gst/base/gstbytereader.h>
65 GST_DEBUG_CATEGORY_STATIC (flacparse_debug);
66 #define GST_CAT_DEFAULT flacparse_debug
68 /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
69 static const guint8 crc8_table[256] = {
70 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
71 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
72 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
73 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
74 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
75 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
76 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
77 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
78 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
79 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
80 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
81 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
82 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
83 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
84 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
85 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
86 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
87 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
88 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
89 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
90 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
91 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
92 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
93 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
94 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
95 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
96 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
97 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
98 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
99 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
100 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
101 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
105 gst_flac_calculate_crc8 (const guint8 * data, guint length)
110 crc = crc8_table[crc ^ *data];
117 /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
118 static const guint16 crc16_table[256] = {
119 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
120 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
121 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
122 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
123 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
124 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
125 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
126 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
127 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
128 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
129 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
130 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
131 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
132 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
133 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
134 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
135 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
136 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
137 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
138 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
139 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
140 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
141 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
142 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
143 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
144 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
145 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
146 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
147 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
148 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
149 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
150 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
154 gst_flac_calculate_crc16 (const guint8 * data, guint length)
159 crc = ((crc << 8) ^ crc16_table[(crc >> 8) ^ *data]) & 0xffff;
169 PROP_CHECK_FRAME_CHECKSUMS
172 #define DEFAULT_CHECK_FRAME_CHECKSUMS FALSE
174 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
177 GST_STATIC_CAPS ("audio/x-flac, framed = (boolean) true, "
178 "channels = (int) [ 1, 8 ], " "rate = (int) [ 1, 655350 ]")
181 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
184 GST_STATIC_CAPS ("audio/x-flac")
187 static void gst_flac_parse_finalize (GObject * object);
188 static void gst_flac_parse_set_property (GObject * object, guint prop_id,
189 const GValue * value, GParamSpec * pspec);
190 static void gst_flac_parse_get_property (GObject * object, guint prop_id,
191 GValue * value, GParamSpec * pspec);
193 static gboolean gst_flac_parse_start (GstBaseParse * parse);
194 static gboolean gst_flac_parse_stop (GstBaseParse * parse);
195 static GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
196 GstBaseParseFrame * frame, gint * skipsize);
197 static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
198 GstBaseParseFrame * frame, gint size);
199 static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
200 GstBaseParseFrame * frame);
201 static gboolean gst_flac_parse_convert (GstBaseParse * parse,
202 GstFormat src_format, gint64 src_value, GstFormat dest_format,
203 gint64 * dest_value);
204 static GstCaps *gst_flac_parse_get_sink_caps (GstBaseParse * parse,
207 #define gst_flac_parse_parent_class parent_class
208 G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
211 gst_flac_parse_class_init (GstFlacParseClass * klass)
213 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
214 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
215 GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
217 GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
218 "Flac parser element");
220 gobject_class->finalize = gst_flac_parse_finalize;
221 gobject_class->set_property = gst_flac_parse_set_property;
222 gobject_class->get_property = gst_flac_parse_get_property;
224 g_object_class_install_property (gobject_class, PROP_CHECK_FRAME_CHECKSUMS,
225 g_param_spec_boolean ("check-frame-checksums", "Check Frame Checksums",
226 "Check the overall checksums of every frame",
227 DEFAULT_CHECK_FRAME_CHECKSUMS,
228 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
230 baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
231 baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
232 baseparse_class->handle_frame =
233 GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
234 baseparse_class->pre_push_frame =
235 GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
236 baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
237 baseparse_class->get_sink_caps =
238 GST_DEBUG_FUNCPTR (gst_flac_parse_get_sink_caps);
240 gst_element_class_add_pad_template (element_class,
241 gst_static_pad_template_get (&src_factory));
242 gst_element_class_add_pad_template (element_class,
243 gst_static_pad_template_get (&sink_factory));
245 gst_element_class_set_static_metadata (element_class, "FLAC audio parser",
246 "Codec/Parser/Audio",
247 "Parses audio with the FLAC lossless audio codec",
248 "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
252 gst_flac_parse_init (GstFlacParse * flacparse)
254 flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
258 gst_flac_parse_set_property (GObject * object, guint prop_id,
259 const GValue * value, GParamSpec * pspec)
261 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
264 case PROP_CHECK_FRAME_CHECKSUMS:
265 flacparse->check_frame_checksums = g_value_get_boolean (value);
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
274 gst_flac_parse_get_property (GObject * object, guint prop_id,
275 GValue * value, GParamSpec * pspec)
277 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
280 case PROP_CHECK_FRAME_CHECKSUMS:
281 g_value_set_boolean (value, flacparse->check_frame_checksums);
284 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
290 gst_flac_parse_finalize (GObject * object)
292 GstFlacParse *flacparse = GST_FLAC_PARSE (object);
294 if (flacparse->tags) {
295 gst_tag_list_free (flacparse->tags);
296 flacparse->tags = NULL;
299 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
300 g_list_free (flacparse->headers);
301 flacparse->headers = NULL;
303 G_OBJECT_CLASS (parent_class)->finalize (object);
307 gst_flac_parse_start (GstBaseParse * parse)
309 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
311 flacparse->state = GST_FLAC_PARSE_STATE_INIT;
312 flacparse->min_blocksize = 0;
313 flacparse->max_blocksize = 0;
314 flacparse->min_framesize = 0;
315 flacparse->max_framesize = 0;
317 flacparse->upstream_length = -1;
319 flacparse->samplerate = 0;
320 flacparse->channels = 0;
322 flacparse->total_samples = 0;
324 flacparse->offset = GST_CLOCK_TIME_NONE;
325 flacparse->blocking_strategy = 0;
326 flacparse->block_size = 0;
327 flacparse->sample_number = 0;
328 flacparse->strategy_checked = FALSE;
331 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
333 /* inform baseclass we can come up with ts, based on counters in packets */
334 gst_base_parse_set_has_timing_info (GST_BASE_PARSE_CAST (flacparse), TRUE);
335 gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (flacparse), TRUE);
341 gst_flac_parse_stop (GstBaseParse * parse)
343 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
345 if (flacparse->tags) {
346 gst_tag_list_free (flacparse->tags);
347 flacparse->tags = NULL;
350 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
351 g_list_free (flacparse->headers);
352 flacparse->headers = NULL;
357 static const guint8 sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 };
359 static const guint16 blocksize_table[16] = {
360 0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
361 256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6,
365 static const guint32 sample_rate_table[16] = {
367 88200, 176400, 192000,
368 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
375 FRAME_HEADER_INVALID,
376 FRAME_HEADER_MORE_DATA
377 } FrameHeaderCheckReturn;
379 static FrameHeaderCheckReturn
380 gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
381 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);
402 if (flacparse->force_variable_block_size)
403 blocking_strategy = 1;
405 /* block size index, calculation of the real blocksize below */
406 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
410 /* sample rate index, calculation of the real samplerate below */
411 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
412 if (samplerate == 0x0f)
415 /* channel assignment */
416 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
419 } else if (channels <= 10) {
421 } else if (channels > 10) {
424 if (flacparse->channels && flacparse->channels != channels)
427 /* bits per sample */
428 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
429 if (bps == 0x03 || bps == 0x07) {
431 } else if (bps == 0 && flacparse->bps == 0) {
432 goto need_streaminfo;
434 bps = sample_size_table[bps];
435 if (flacparse->bps && bps != flacparse->bps)
438 /* reserved, must be 0 */
439 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
442 /* read "utf8" encoded sample/frame number */
446 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
448 /* This is slightly faster than a loop */
452 } else if ((len & 0xc0) && !(len & 0x20)) {
453 sample_number = len & 0x1f;
455 } else if ((len & 0xe0) && !(len & 0x10)) {
456 sample_number = len & 0x0f;
458 } else if ((len & 0xf0) && !(len & 0x08)) {
459 sample_number = len & 0x07;
461 } else if ((len & 0xf8) && !(len & 0x04)) {
462 sample_number = len & 0x03;
464 } else if ((len & 0xfc) && !(len & 0x02)) {
465 sample_number = len & 0x01;
467 } else if ((len & 0xfe) && !(len & 0x01)) {
468 sample_number = len & 0x0;
474 if ((blocking_strategy == 0 && len > 5) ||
475 (blocking_strategy == 1 && len > 6))
479 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
482 if ((tmp & 0xc0) != 0x80)
486 sample_number |= (tmp & 0x3f);
491 /* calculate real blocksize from the blocksize index */
492 if (block_size == 0) {
494 } else if (block_size == 6) {
495 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
498 } else if (block_size == 7) {
499 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
503 block_size = blocksize_table[block_size];
506 /* calculate the real samplerate from the samplerate index */
507 if (samplerate == 0 && flacparse->samplerate == 0) {
508 goto need_streaminfo;
509 } else if (samplerate < 12) {
510 samplerate = sample_rate_table[samplerate];
511 } else if (samplerate == 12) {
512 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
515 } else if (samplerate == 13) {
516 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
518 } else if (samplerate == 14) {
519 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
524 if (flacparse->samplerate && flacparse->samplerate != samplerate)
527 /* check crc-8 for the header */
528 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
532 gst_flac_calculate_crc8 (data,
533 (gst_bit_reader_get_pos (&reader) / 8) - 1);
534 if (actual_crc != expected_crc)
537 /* Sanity check sample number against blocking strategy, as it seems
538 some files claim fixed block size but supply sample numbers,
539 rather than block numbers. */
540 if (blocking_strategy == 0 && flacparse->block_size != 0) {
541 if (!flacparse->strategy_checked) {
542 if (block_size == sample_number) {
543 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
544 "but seems to be lying: assuming variable block size");
545 flacparse->force_variable_block_size = TRUE;
546 blocking_strategy = 1;
548 flacparse->strategy_checked = TRUE;
553 The FLAC format documentation says:
554 The "blocking strategy" bit determines how to calculate the sample number
555 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
556 frame header encodes the frame number as above, and the frame's starting
557 sample number will be the frame number times the blocksize. If it is 1
558 (variable-blocksize), the frame header encodes the frame's starting
559 sample number itself. (In the case of a fixed-blocksize stream, only the
560 last block may be shorter than the stream blocksize; its starting sample
561 number will be calculated as the frame number times the previous frame's
562 blocksize, or zero if it is the first frame).
564 Therefore, when in fixed block size mode, we only update the block size
565 the first time, then reuse that block size for subsequent calls.
566 This will also fix a timestamp problem with the last block's timestamp
567 being miscalculated by scaling the block number by a "wrong" block size.
569 if (blocking_strategy == 0) {
570 if (flacparse->block_size != 0) {
571 /* after first block */
572 if (flacparse->block_size != block_size) {
573 /* TODO: can we know we're on the last frame, to avoid warning ? */
574 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
575 block_size = flacparse->block_size;
583 flacparse->block_size = block_size;
584 if (!flacparse->samplerate)
585 flacparse->samplerate = samplerate;
587 flacparse->bps = bps;
588 if (!flacparse->blocking_strategy)
589 flacparse->blocking_strategy = blocking_strategy;
590 if (!flacparse->channels)
591 flacparse->channels = channels;
592 if (!flacparse->sample_number)
593 flacparse->sample_number = sample_number;
595 GST_DEBUG_OBJECT (flacparse,
596 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
597 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
598 flacparse->block_size, flacparse->sample_number);
602 *block_size_ret = block_size;
604 return FRAME_HEADER_VALID;
607 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
608 return FRAME_HEADER_INVALID;
610 return FRAME_HEADER_INVALID;
613 return FRAME_HEADER_MORE_DATA;
617 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
618 GstBaseParseFrame * frame, guint * ret)
622 guint max, remaining;
623 guint i, search_start, search_end;
624 FrameHeaderCheckReturn header_ret;
626 gboolean suspect_start = FALSE, suspect_end = FALSE;
627 gboolean result = FALSE;
629 buffer = frame->buffer;
630 gst_buffer_map (buffer, &map, GST_MAP_READ);
632 if (map.size < flacparse->min_framesize)
636 gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
637 &block_size, &suspect_start);
638 if (header_ret == FRAME_HEADER_INVALID) {
642 if (header_ret == FRAME_HEADER_MORE_DATA)
645 /* mind unknown framesize */
646 search_start = MAX (2, flacparse->min_framesize);
647 if (flacparse->max_framesize)
648 search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
650 search_end = map.size;
653 remaining = map.size;
655 for (i = search_start; i < search_end; i++, remaining--) {
656 if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
657 GST_LOG_OBJECT (flacparse, "possible frame end at offset %d", i);
660 gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
661 remaining, FALSE, NULL, &suspect_end);
662 if (header_ret == FRAME_HEADER_VALID) {
663 if (flacparse->check_frame_checksums) {
664 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
665 guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
667 GST_LOG_OBJECT (flacparse,
668 "checking checksum, frame suspect (%d, %d)",
669 suspect_start, suspect_end);
670 if (actual_crc != expected_crc) {
671 GST_DEBUG_OBJECT (flacparse, "checksum did not match");
676 flacparse->block_size = block_size;
679 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
685 /* For the last frame output everything to the end */
686 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
687 if (flacparse->check_frame_checksums) {
688 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
689 guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
691 if (actual_crc == expected_crc) {
693 flacparse->block_size = block_size;
699 flacparse->block_size = block_size;
705 /* so we searched to expected end and found nothing,
706 * give up on this frame (start) */
707 if (flacparse->max_framesize && i > 2 * flacparse->max_framesize) {
708 GST_LOG_OBJECT (flacparse,
709 "could not determine valid frame end, discarding frame (start)");
715 max = flacparse->max_framesize + 16;
718 *ret = MIN (map.size + 4096, max);
722 gst_buffer_unmap (buffer, &map);
727 gst_flac_parse_handle_frame (GstBaseParse * parse,
728 GstBaseParseFrame * frame, gint * skipsize)
730 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
731 GstBuffer *buffer = frame->buffer;
733 gboolean result = TRUE;
734 GstFlowReturn ret = GST_FLOW_OK;
737 gst_buffer_map (buffer, &map, GST_MAP_READ);
741 if (G_UNLIKELY (map.size < 4)) {
746 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
747 if (memcmp (map.data, "fLaC", 4) == 0) {
748 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
752 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
753 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
754 /* Minimal size of a frame header */
755 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
756 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
761 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
766 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
767 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
769 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
774 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
778 flacparse->offset = GST_BUFFER_OFFSET (buffer);
779 flacparse->blocking_strategy = 0;
780 flacparse->sample_number = 0;
782 GST_DEBUG_OBJECT (flacparse, "Found sync code");
783 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
788 /* If we're at EOS and the frame was not valid, drop it! */
789 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
790 GST_WARNING_OBJECT (flacparse, "EOS");
796 } else if (next > map.size) {
797 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
799 gst_base_parse_set_min_frame_size (parse, next);
803 GST_ERROR_OBJECT (flacparse,
804 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
810 GstByteReader reader;
813 gst_byte_reader_init (&reader, map.data, map.size);
815 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
819 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
824 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
825 *skipsize = map.size - 3;
834 gst_buffer_unmap (buffer, &map);
839 if (result && framesize <= map.size) {
840 ret = gst_flac_parse_parse_frame (parse, frame, framesize);
841 if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
842 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
845 if (ret == GST_FLOW_OK)
846 ret = gst_base_parse_finish_frame (parse, frame, framesize);
853 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
858 gst_buffer_map (buffer, &map, GST_MAP_READ);
859 gst_bit_reader_init (&reader, map.data, map.size);
861 if (map.size != 4 + 34) {
862 GST_ERROR_OBJECT (flacparse,
863 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
867 /* Skip metadata block header */
868 gst_bit_reader_skip (&reader, 32);
870 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
872 if (flacparse->min_blocksize < 16) {
873 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
874 flacparse->min_blocksize);
877 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
879 if (flacparse->max_blocksize < 16) {
880 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
881 flacparse->max_blocksize);
884 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
886 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
889 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
891 if (flacparse->samplerate == 0) {
892 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
896 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
898 flacparse->channels++;
899 if (flacparse->channels > 8) {
900 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
901 flacparse->channels);
905 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
909 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
911 if (flacparse->total_samples) {
912 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
913 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
916 gst_buffer_unmap (buffer, &map);
918 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
919 "\tmin/max blocksize: %u/%u,\n"
920 "\tmin/max framesize: %u/%u,\n"
921 "\tsamplerate: %u,\n"
923 "\tbits per sample: %u,\n"
924 "\ttotal samples: %" G_GUINT64_FORMAT,
925 flacparse->min_blocksize, flacparse->max_blocksize,
926 flacparse->min_framesize, flacparse->max_framesize,
927 flacparse->samplerate,
928 flacparse->channels, flacparse->bps, flacparse->total_samples);
933 GST_ERROR_OBJECT (flacparse, "Failed to read data");
935 gst_buffer_unmap (buffer, &map);
940 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
945 gst_buffer_map (buffer, &map, GST_MAP_READ);
948 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
949 gst_buffer_unmap (buffer, &map);
951 if (flacparse->tags == NULL) {
952 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
953 } else if (gst_tag_list_is_empty (flacparse->tags)) {
954 gst_tag_list_free (flacparse->tags);
955 flacparse->tags = NULL;
962 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
964 GstByteReader reader;
966 guint32 img_len = 0, img_type = 0;
967 guint32 img_mimetype_len = 0, img_description_len = 0;
969 gst_buffer_map (buffer, &map, GST_MAP_READ);
970 gst_byte_reader_init (&reader, map.data, map.size);
972 if (!gst_byte_reader_skip (&reader, 4))
975 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
978 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
980 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
983 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
985 if (!gst_byte_reader_skip (&reader, img_description_len))
988 if (!gst_byte_reader_skip (&reader, 4 * 4))
991 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
994 if (!flacparse->tags)
995 flacparse->tags = gst_tag_list_new_empty ();
997 gst_tag_list_add_id3_image (flacparse->tags,
998 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
1000 if (gst_tag_list_is_empty (flacparse->tags)) {
1001 gst_tag_list_free (flacparse->tags);
1002 flacparse->tags = NULL;
1005 gst_buffer_unmap (buffer, &map);
1009 GST_ERROR_OBJECT (flacparse, "Error reading data");
1010 gst_buffer_unmap (buffer, &map);
1015 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
1018 GST_DEBUG_OBJECT (flacparse, "storing seektable");
1019 /* only store for now;
1020 * offset of the first frame is needed to get real info */
1021 flacparse->seektable = gst_buffer_ref (buffer);
1027 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1030 gint64 offset = 0, samples = 0;
1033 GST_DEBUG_OBJECT (flacparse,
1034 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1039 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1040 gst_byte_reader_init (&br, map.data, map.size);
1043 if (!gst_byte_reader_skip (&br, 4))
1047 while (gst_byte_reader_get_remaining (&br)) {
1048 if (!gst_byte_reader_get_int64_be (&br, &samples))
1050 if (!gst_byte_reader_get_int64_be (&br, &offset))
1052 if (!gst_byte_reader_skip (&br, 2))
1055 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1056 G_GINT64_FORMAT, samples, offset);
1059 if (G_LIKELY (offset > 0 && samples > 0)) {
1060 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1061 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1062 flacparse->samplerate), TRUE, FALSE);
1067 gst_buffer_unmap (flacparse->seektable, &map);
1069 gst_buffer_unref (flacparse->seektable);
1070 flacparse->seektable = NULL;
1074 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1076 GValue value = { 0, };
1078 g_value_init (&value, GST_TYPE_BUFFER);
1079 /* copy buffer to avoid problems with circular refcounts */
1080 buf = gst_buffer_copy (buf);
1081 /* again, for good measure */
1082 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1083 gst_value_set_buffer (&value, buf);
1084 gst_buffer_unref (buf);
1085 gst_value_array_append_value (array_val, &value);
1086 g_value_unset (&value);
1090 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1092 GstBuffer *vorbiscomment = NULL;
1093 GstBuffer *streaminfo = NULL;
1094 GstBuffer *marker = NULL;
1095 GValue array = { 0, };
1098 gboolean res = TRUE;
1100 caps = gst_caps_new_simple ("audio/x-flac",
1101 "channels", G_TYPE_INT, flacparse->channels,
1102 "framed", G_TYPE_BOOLEAN, TRUE,
1103 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1105 if (!flacparse->headers)
1108 for (l = flacparse->headers; l; l = l->next) {
1109 GstBuffer *header = l->data;
1112 gst_buffer_map (header, &map, GST_MAP_READ);
1114 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1116 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1118 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1119 streaminfo = header;
1120 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1121 vorbiscomment = header;
1124 gst_buffer_unmap (header, &map);
1127 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1128 GST_WARNING_OBJECT (flacparse,
1129 "missing header %p %p %p, muxing into container "
1130 "formats may be broken", marker, streaminfo, vorbiscomment);
1134 g_value_init (&array, GST_TYPE_ARRAY);
1136 /* add marker including STREAMINFO header */
1140 GstMapInfo sinfomap, writemap;
1142 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1144 /* minus one for the marker that is merged with streaminfo here */
1145 num = g_list_length (flacparse->headers) - 1;
1147 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1148 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1150 writemap.data[0] = 0x7f;
1151 memcpy (writemap.data + 1, "FLAC", 4);
1152 writemap.data[5] = 0x01; /* mapping version major */
1153 writemap.data[6] = 0x00; /* mapping version minor */
1154 writemap.data[7] = (num & 0xFF00) >> 8;
1155 writemap.data[8] = (num & 0x00FF) >> 0;
1156 memcpy (writemap.data + 9, "fLaC", 4);
1157 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1158 _value_array_append_buffer (&array, buf);
1160 gst_buffer_unmap (streaminfo, &sinfomap);
1161 gst_buffer_unmap (buf, &writemap);
1162 gst_buffer_unref (buf);
1165 /* add VORBISCOMMENT header */
1166 _value_array_append_buffer (&array, vorbiscomment);
1168 /* add other headers, if there are any */
1169 for (l = flacparse->headers; l; l = l->next) {
1170 if (GST_BUFFER_CAST (l->data) != marker &&
1171 GST_BUFFER_CAST (l->data) != streaminfo &&
1172 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1173 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1177 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1178 "streamheader", &array);
1179 g_value_unset (&array);
1183 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1184 gst_caps_unref (caps);
1186 /* push header buffers; update caps, so when we push the first buffer the
1187 * negotiated caps will change to caps that include the streamheader field */
1188 while (flacparse->headers) {
1189 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1191 GstBaseParseFrame frame;
1193 flacparse->headers =
1194 g_list_delete_link (flacparse->headers, flacparse->headers);
1195 buf = gst_buffer_make_writable (buf);
1197 /* init, set and give away frame */
1198 gst_base_parse_frame_init (&frame);
1200 frame.overhead = -1;
1201 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1202 if (ret != GST_FLOW_OK) {
1206 gst_base_parse_frame_free (&frame);
1208 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1209 g_list_free (flacparse->headers);
1210 flacparse->headers = NULL;
1216 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1218 GstBuffer *marker, *streaminfo, *vorbiscomment;
1221 marker = gst_buffer_new_and_alloc (4);
1222 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1223 memcpy (map.data, "fLaC", 4);
1224 gst_buffer_unmap (marker, &map);
1225 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1226 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1227 GST_BUFFER_OFFSET (marker) = 0;
1228 GST_BUFFER_OFFSET_END (marker) = 0;
1229 flacparse->headers = g_list_append (flacparse->headers, marker);
1231 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1232 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1233 memset (map.data, 0, 4 + 34);
1235 /* metadata block header */
1236 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1237 map.data[1] = 0x00; /* length = 34; */
1243 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1244 map.data[5] = (flacparse->block_size) & 0xff;
1245 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1246 map.data[7] = (flacparse->block_size) & 0xff;
1248 map.data[8] = 0x00; /* min framesize = 0; */
1250 map.data[10] = 0x00;
1251 map.data[11] = 0x00; /* max framesize = 0; */
1252 map.data[12] = 0x00;
1253 map.data[13] = 0x00;
1255 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1256 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1257 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1259 map.data[16] |= (flacparse->channels - 1) << 1;
1261 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1262 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1267 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1268 GST_FORMAT_TIME, &duration)) {
1269 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1271 map.data[17] |= (duration >> 32) & 0xff;
1272 map.data[18] |= (duration >> 24) & 0xff;
1273 map.data[19] |= (duration >> 16) & 0xff;
1274 map.data[20] |= (duration >> 8) & 0xff;
1275 map.data[21] |= (duration >> 0) & 0xff;
1280 gst_buffer_unmap (streaminfo, &map);
1281 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1282 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1283 GST_BUFFER_OFFSET (streaminfo) = 0;
1284 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1285 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1287 /* empty vorbiscomment */
1289 GstTagList *taglist = gst_tag_list_new_empty ();
1293 header[0] = 0x84; /* is_last = 1; type = 4; */
1296 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1297 sizeof (header), NULL);
1298 gst_tag_list_free (taglist);
1300 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1302 /* Get rid of framing bit */
1303 if (map.data[map.size - 1] == 1) {
1307 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1309 gst_buffer_unmap (vorbiscomment, &map);
1310 gst_buffer_unref (vorbiscomment);
1311 vorbiscomment = sub;
1312 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1315 size = map.size - 4;
1316 map.data[1] = ((size & 0xFF0000) >> 16);
1317 map.data[2] = ((size & 0x00FF00) >> 8);
1318 map.data[3] = (size & 0x0000FF);
1319 gst_buffer_unmap (vorbiscomment, &map);
1321 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1322 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1323 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1324 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1325 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1331 static GstFlowReturn
1332 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1335 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1336 GstBuffer *buffer = frame->buffer, *sbuffer;
1338 GstFlowReturn res = GST_FLOW_ERROR;
1340 gst_buffer_map (buffer, &map, GST_MAP_READ);
1342 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1343 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1344 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1345 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1346 GST_BUFFER_OFFSET (sbuffer) = 0;
1347 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1349 /* 32 bits metadata block */
1350 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1351 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1353 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1355 res = GST_BASE_PARSE_FLOW_DROPPED;
1356 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1357 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1358 guint type = (map.data[0] & 0x7F);
1361 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1362 res = GST_BASE_PARSE_FLOW_DROPPED;
1366 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1368 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1371 case 0: /* STREAMINFO */
1372 if (!gst_flac_parse_handle_streaminfo (flacparse, sbuffer))
1375 case 3: /* SEEKTABLE */
1376 if (!gst_flac_parse_handle_seektable (flacparse, sbuffer))
1379 case 4: /* VORBIS_COMMENT */
1380 if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
1383 case 6: /* PICTURE */
1384 if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
1387 case 1: /* PADDING */
1388 case 2: /* APPLICATION */
1389 case 5: /* CUESHEET */
1390 default: /* RESERVED */
1394 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1395 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1396 GST_BUFFER_OFFSET (sbuffer) = 0;
1397 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1399 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1402 if (!gst_flac_parse_handle_headers (flacparse))
1405 /* Minimal size of a frame header */
1406 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1407 flacparse->min_framesize));
1408 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1411 /* DROPPED because we pushed already or will push all headers manually */
1412 res = GST_BASE_PARSE_FLOW_DROPPED;
1414 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1415 FrameHeaderCheckReturn ret;
1417 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1419 gst_flac_parse_frame_header_is_valid (flacparse,
1420 map.data, map.size, TRUE, NULL, NULL);
1421 if (ret != FRAME_HEADER_VALID) {
1422 GST_ERROR_OBJECT (flacparse,
1423 "Baseclass didn't provide a complete frame");
1428 if (flacparse->block_size == 0) {
1429 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1433 if (flacparse->seektable)
1434 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1436 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1437 if (flacparse->blocking_strategy == 1) {
1438 GST_WARNING_OBJECT (flacparse,
1439 "Generating headers for variable blocksize streams not supported");
1441 if (!gst_flac_parse_handle_headers (flacparse))
1444 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1446 if (!gst_flac_parse_generate_headers (flacparse))
1449 if (!gst_flac_parse_handle_headers (flacparse))
1452 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1455 /* also cater for oggmux metadata */
1456 if (flacparse->blocking_strategy == 0) {
1457 GST_BUFFER_TIMESTAMP (buffer) =
1458 gst_util_uint64_scale (flacparse->sample_number,
1459 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1460 GST_BUFFER_OFFSET_END (buffer) =
1461 flacparse->sample_number * flacparse->block_size +
1462 flacparse->block_size;
1464 GST_BUFFER_TIMESTAMP (buffer) =
1465 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1466 flacparse->samplerate);
1467 GST_BUFFER_OFFSET_END (buffer) =
1468 flacparse->sample_number + flacparse->block_size;
1470 GST_BUFFER_OFFSET (buffer) =
1471 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1472 flacparse->samplerate);
1473 GST_BUFFER_DURATION (buffer) =
1474 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1476 /* To simplify, we just assume that it's a fixed size header and ignore
1477 * subframe headers. The first could lead us to being off by 88 bits and
1478 * the second even less, so the total inaccuracy is negligible. */
1479 frame->overhead = 7;
1481 /* Minimal size of a frame header */
1482 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1483 flacparse->min_framesize));
1485 flacparse->offset = -1;
1486 flacparse->blocking_strategy = 0;
1487 flacparse->sample_number = 0;
1492 gst_buffer_unmap (buffer, &map);
1497 static GstFlowReturn
1498 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1500 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1503 if (flacparse->tags) {
1504 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1505 gst_event_new_tag (flacparse->tags));
1506 flacparse->tags = NULL;
1509 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1515 gst_flac_parse_convert (GstBaseParse * parse,
1516 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1517 gint64 * dest_value)
1519 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1521 if (flacparse->samplerate > 0) {
1522 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1523 if (src_value != -1)
1525 gst_util_uint64_scale (src_value, GST_SECOND,
1526 flacparse->samplerate);
1530 } else if (src_format == GST_FORMAT_TIME &&
1531 dest_format == GST_FORMAT_DEFAULT) {
1532 if (src_value != -1)
1534 gst_util_uint64_scale (src_value, flacparse->samplerate,
1542 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1543 src_value, dest_format, dest_value);
1547 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1549 GstCaps *peercaps, *templ;
1552 /* FIXME: handle filter caps */
1553 templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
1555 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1559 /* Remove the framed field */
1560 peercaps = gst_caps_make_writable (peercaps);
1561 n = gst_caps_get_size (peercaps);
1562 for (i = 0; i < n; i++) {
1563 GstStructure *s = gst_caps_get_structure (peercaps, i);
1565 gst_structure_remove_field (s, "framed");
1568 res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
1569 gst_caps_unref (peercaps);
1570 gst_caps_unref (templ);