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_details_simple (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)
383 GstBitReader reader = GST_BIT_READER_INIT (data, size);
384 guint8 blocking_strategy;
386 guint32 samplerate = 0;
387 guint64 sample_number;
388 guint8 channels, bps;
390 guint8 actual_crc, expected_crc = 0;
392 /* Skip 14 bit sync code */
393 gst_bit_reader_skip_unchecked (&reader, 14);
396 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
399 /* 0 == fixed block size, 1 == variable block size */
400 blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
401 if (flacparse->force_variable_block_size)
402 blocking_strategy = 1;
404 /* block size index, calculation of the real blocksize below */
405 block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
409 /* sample rate index, calculation of the real samplerate below */
410 samplerate = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
411 if (samplerate == 0x0f)
414 /* channel assignment */
415 channels = gst_bit_reader_get_bits_uint8_unchecked (&reader, 4);
418 } else if (channels <= 10) {
420 } else if (channels > 10) {
423 if (flacparse->channels && flacparse->channels != channels)
426 /* bits per sample */
427 bps = gst_bit_reader_get_bits_uint8_unchecked (&reader, 3);
428 if (bps == 0x03 || bps == 0x07) {
430 } else if (bps == 0 && flacparse->bps == 0) {
431 goto need_streaminfo;
433 bps = sample_size_table[bps];
434 if (flacparse->bps && bps != flacparse->bps)
437 /* reserved, must be 0 */
438 if (gst_bit_reader_get_bits_uint8_unchecked (&reader, 1) != 0)
441 /* read "utf8" encoded sample/frame number */
445 len = gst_bit_reader_get_bits_uint8_unchecked (&reader, 8);
447 /* This is slightly faster than a loop */
451 } else if ((len & 0xc0) && !(len & 0x20)) {
452 sample_number = len & 0x1f;
454 } else if ((len & 0xe0) && !(len & 0x10)) {
455 sample_number = len & 0x0f;
457 } else if ((len & 0xf0) && !(len & 0x08)) {
458 sample_number = len & 0x07;
460 } else if ((len & 0xf8) && !(len & 0x04)) {
461 sample_number = len & 0x03;
463 } else if ((len & 0xfc) && !(len & 0x02)) {
464 sample_number = len & 0x01;
466 } else if ((len & 0xfe) && !(len & 0x01)) {
467 sample_number = len & 0x0;
473 if ((blocking_strategy == 0 && len > 5) ||
474 (blocking_strategy == 1 && len > 6))
478 if (!gst_bit_reader_get_bits_uint8 (&reader, &tmp, 8))
481 if ((tmp & 0xc0) != 0x80)
485 sample_number |= (tmp & 0x3f);
490 /* calculate real blocksize from the blocksize index */
491 if (block_size == 0) {
493 } else if (block_size == 6) {
494 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 8))
497 } else if (block_size == 7) {
498 if (!gst_bit_reader_get_bits_uint16 (&reader, &block_size, 16))
502 block_size = blocksize_table[block_size];
505 /* calculate the real samplerate from the samplerate index */
506 if (samplerate == 0 && flacparse->samplerate == 0) {
507 goto need_streaminfo;
508 } else if (samplerate < 12) {
509 samplerate = sample_rate_table[samplerate];
510 } else if (samplerate == 12) {
511 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 8))
514 } else if (samplerate == 13) {
515 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
517 } else if (samplerate == 14) {
518 if (!gst_bit_reader_get_bits_uint32 (&reader, &samplerate, 16))
523 if (flacparse->samplerate && flacparse->samplerate != samplerate)
526 /* check crc-8 for the header */
527 if (!gst_bit_reader_get_bits_uint8 (&reader, &expected_crc, 8))
531 gst_flac_calculate_crc8 (data,
532 (gst_bit_reader_get_pos (&reader) / 8) - 1);
533 if (actual_crc != expected_crc)
536 /* Sanity check sample number against blocking strategy, as it seems
537 some files claim fixed block size but supply sample numbers,
538 rather than block numbers. */
539 if (blocking_strategy == 0 && flacparse->block_size != 0) {
540 if (!flacparse->strategy_checked) {
541 if (block_size == sample_number) {
542 GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
543 "but seems to be lying: assuming variable block size");
544 flacparse->force_variable_block_size = TRUE;
545 blocking_strategy = 1;
547 flacparse->strategy_checked = TRUE;
552 The FLAC format documentation says:
553 The "blocking strategy" bit determines how to calculate the sample number
554 of the first sample in the frame. If the bit is 0 (fixed-blocksize), the
555 frame header encodes the frame number as above, and the frame's starting
556 sample number will be the frame number times the blocksize. If it is 1
557 (variable-blocksize), the frame header encodes the frame's starting
558 sample number itself. (In the case of a fixed-blocksize stream, only the
559 last block may be shorter than the stream blocksize; its starting sample
560 number will be calculated as the frame number times the previous frame's
561 blocksize, or zero if it is the first frame).
563 Therefore, when in fixed block size mode, we only update the block size
564 the first time, then reuse that block size for subsequent calls.
565 This will also fix a timestamp problem with the last block's timestamp
566 being miscalculated by scaling the block number by a "wrong" block size.
568 if (blocking_strategy == 0) {
569 if (flacparse->block_size != 0) {
570 /* after first block */
571 if (flacparse->block_size != block_size) {
572 /* TODO: can we know we're on the last frame, to avoid warning ? */
573 GST_WARNING_OBJECT (flacparse, "Block size is not constant");
574 block_size = flacparse->block_size;
580 flacparse->block_size = block_size;
581 if (!flacparse->samplerate)
582 flacparse->samplerate = samplerate;
584 flacparse->bps = bps;
585 if (!flacparse->blocking_strategy)
586 flacparse->blocking_strategy = blocking_strategy;
587 if (!flacparse->channels)
588 flacparse->channels = channels;
589 if (!flacparse->sample_number)
590 flacparse->sample_number = sample_number;
592 GST_DEBUG_OBJECT (flacparse,
593 "Parsed frame at offset %" G_GUINT64_FORMAT ":\n" "Block size: %u\n"
594 "Sample/Frame number: %" G_GUINT64_FORMAT, flacparse->offset,
595 flacparse->block_size, flacparse->sample_number);
599 *block_size_ret = block_size;
601 return FRAME_HEADER_VALID;
604 GST_ERROR_OBJECT (flacparse, "Need STREAMINFO");
605 return FRAME_HEADER_INVALID;
607 return FRAME_HEADER_INVALID;
610 return FRAME_HEADER_MORE_DATA;
614 gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
615 GstBaseParseFrame * frame, guint * ret)
619 guint max, remaining;
620 guint i, search_start, search_end;
621 FrameHeaderCheckReturn header_ret;
623 gboolean result = FALSE;
625 buffer = frame->buffer;
626 gst_buffer_map (buffer, &map, GST_MAP_READ);
628 if (map.size < flacparse->min_framesize)
632 gst_flac_parse_frame_header_is_valid (flacparse, map.data, map.size, TRUE,
634 if (header_ret == FRAME_HEADER_INVALID) {
638 if (header_ret == FRAME_HEADER_MORE_DATA)
641 /* mind unknown framesize */
642 search_start = MAX (2, flacparse->min_framesize);
643 if (flacparse->max_framesize)
644 search_end = MIN (map.size, flacparse->max_framesize + 9 + 2);
646 search_end = map.size;
649 remaining = map.size;
651 for (i = search_start; i < search_end; i++, remaining--) {
652 if ((GST_READ_UINT16_BE (map.data + i) & 0xfffe) == 0xfff8) {
654 gst_flac_parse_frame_header_is_valid (flacparse, map.data + i,
655 remaining, FALSE, NULL);
656 if (header_ret == FRAME_HEADER_VALID) {
657 if (flacparse->check_frame_checksums) {
658 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, i - 2);
659 guint16 expected_crc = GST_READ_UINT16_BE (map.data + i - 2);
661 if (actual_crc != expected_crc)
665 flacparse->block_size = block_size;
668 } else if (header_ret == FRAME_HEADER_MORE_DATA) {
674 /* For the last frame output everything to the end */
675 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
676 if (flacparse->check_frame_checksums) {
677 guint16 actual_crc = gst_flac_calculate_crc16 (map.data, map.size - 2);
678 guint16 expected_crc = GST_READ_UINT16_BE (map.data + map.size - 2);
680 if (actual_crc == expected_crc) {
682 flacparse->block_size = block_size;
688 flacparse->block_size = block_size;
695 max = flacparse->max_framesize + 16;
698 *ret = MIN (map.size + 4096, max);
702 gst_buffer_unmap (buffer, &map);
707 gst_flac_parse_handle_frame (GstBaseParse * parse,
708 GstBaseParseFrame * frame, gint * skipsize)
710 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
711 GstBuffer *buffer = frame->buffer;
713 gboolean result = TRUE;
714 GstFlowReturn ret = GST_FLOW_OK;
717 gst_buffer_map (buffer, &map, GST_MAP_READ);
721 if (G_UNLIKELY (map.size < 4)) {
726 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
727 if (memcmp (map.data, "fLaC", 4) == 0) {
728 GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
732 if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
733 GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
734 /* Minimal size of a frame header */
735 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
736 flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
741 GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
746 if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
747 guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
749 GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
754 if ((GST_READ_UINT16_BE (map.data) & 0xfffe) == 0xfff8) {
758 flacparse->offset = GST_BUFFER_OFFSET (buffer);
759 flacparse->blocking_strategy = 0;
760 flacparse->sample_number = 0;
762 GST_DEBUG_OBJECT (flacparse, "Found sync code");
763 ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
768 /* If we're at EOS and the frame was not valid, drop it! */
769 if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
770 GST_WARNING_OBJECT (flacparse, "EOS");
776 } else if (next > map.size) {
777 GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
779 gst_base_parse_set_min_frame_size (parse, next);
783 GST_ERROR_OBJECT (flacparse,
784 "Giving up on invalid frame (%" G_GSIZE_FORMAT " bytes)", map.size);
790 GstByteReader reader;
793 gst_byte_reader_init (&reader, map.data, map.size);
795 gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
799 GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
804 GST_DEBUG_OBJECT (flacparse, "Sync code not found");
805 *skipsize = map.size - 3;
814 gst_buffer_unmap (buffer, &map);
819 if (result && framesize <= map.size) {
820 ret = gst_flac_parse_parse_frame (parse, frame, framesize);
821 if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
822 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
825 if (ret == GST_FLOW_OK)
826 ret = gst_base_parse_finish_frame (parse, frame, framesize);
833 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
838 gst_buffer_map (buffer, &map, GST_MAP_READ);
839 gst_bit_reader_init (&reader, map.data, map.size);
841 if (map.size != 4 + 34) {
842 GST_ERROR_OBJECT (flacparse,
843 "Invalid metablock size for STREAMINFO: %" G_GSIZE_FORMAT "", map.size);
847 /* Skip metadata block header */
848 gst_bit_reader_skip (&reader, 32);
850 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->min_blocksize, 16))
852 if (flacparse->min_blocksize < 16) {
853 GST_WARNING_OBJECT (flacparse, "Invalid minimum block size: %u",
854 flacparse->min_blocksize);
857 if (!gst_bit_reader_get_bits_uint16 (&reader, &flacparse->max_blocksize, 16))
859 if (flacparse->max_blocksize < 16) {
860 GST_WARNING_OBJECT (flacparse, "Invalid maximum block size: %u",
861 flacparse->max_blocksize);
864 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->min_framesize, 24))
866 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->max_framesize, 24))
869 if (!gst_bit_reader_get_bits_uint32 (&reader, &flacparse->samplerate, 20))
871 if (flacparse->samplerate == 0) {
872 GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
876 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
878 flacparse->channels++;
879 if (flacparse->channels > 8) {
880 GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
881 flacparse->channels);
885 if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
889 if (!gst_bit_reader_get_bits_uint64 (&reader, &flacparse->total_samples, 36))
891 if (flacparse->total_samples) {
892 gst_base_parse_set_duration (GST_BASE_PARSE (flacparse),
893 GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
896 gst_buffer_unmap (buffer, &map);
898 GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
899 "\tmin/max blocksize: %u/%u,\n"
900 "\tmin/max framesize: %u/%u,\n"
901 "\tsamplerate: %u,\n"
903 "\tbits per sample: %u,\n"
904 "\ttotal samples: %" G_GUINT64_FORMAT,
905 flacparse->min_blocksize, flacparse->max_blocksize,
906 flacparse->min_framesize, flacparse->max_framesize,
907 flacparse->samplerate,
908 flacparse->channels, flacparse->bps, flacparse->total_samples);
913 GST_ERROR_OBJECT (flacparse, "Failed to read data");
915 gst_buffer_unmap (buffer, &map);
920 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
925 gst_buffer_map (buffer, &map, GST_MAP_READ);
928 gst_tag_list_from_vorbiscomment (map.data, map.size, map.data, 4, NULL);
929 gst_buffer_unmap (buffer, &map);
931 if (flacparse->tags == NULL) {
932 GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
933 } else if (gst_tag_list_is_empty (flacparse->tags)) {
934 gst_tag_list_free (flacparse->tags);
935 flacparse->tags = NULL;
942 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
944 GstByteReader reader;
946 guint32 img_len = 0, img_type = 0;
947 guint32 img_mimetype_len = 0, img_description_len = 0;
949 gst_buffer_map (buffer, &map, GST_MAP_READ);
950 gst_byte_reader_init (&reader, map.data, map.size);
952 if (!gst_byte_reader_skip (&reader, 4))
955 if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
958 if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
960 if (!gst_byte_reader_skip (&reader, img_mimetype_len))
963 if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
965 if (!gst_byte_reader_skip (&reader, img_description_len))
968 if (!gst_byte_reader_skip (&reader, 4 * 4))
971 if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
974 if (!flacparse->tags)
975 flacparse->tags = gst_tag_list_new_empty ();
977 gst_tag_list_add_id3_image (flacparse->tags,
978 map.data + gst_byte_reader_get_pos (&reader), img_len, img_type);
980 if (gst_tag_list_is_empty (flacparse->tags)) {
981 gst_tag_list_free (flacparse->tags);
982 flacparse->tags = NULL;
985 gst_buffer_unmap (buffer, &map);
989 GST_ERROR_OBJECT (flacparse, "Error reading data");
990 gst_buffer_unmap (buffer, &map);
995 gst_flac_parse_handle_seektable (GstFlacParse * flacparse, GstBuffer * buffer)
998 GST_DEBUG_OBJECT (flacparse, "storing seektable");
999 /* only store for now;
1000 * offset of the first frame is needed to get real info */
1001 flacparse->seektable = gst_buffer_ref (buffer);
1007 gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
1010 gint64 offset = 0, samples = 0;
1013 GST_DEBUG_OBJECT (flacparse,
1014 "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
1019 gst_buffer_map (flacparse->seektable, &map, GST_MAP_READ);
1020 gst_byte_reader_init (&br, map.data, map.size);
1023 if (!gst_byte_reader_skip (&br, 4))
1027 while (gst_byte_reader_get_remaining (&br)) {
1028 if (!gst_byte_reader_get_int64_be (&br, &samples))
1030 if (!gst_byte_reader_get_int64_be (&br, &offset))
1032 if (!gst_byte_reader_skip (&br, 2))
1035 GST_LOG_OBJECT (flacparse, "samples %" G_GINT64_FORMAT " -> offset %"
1036 G_GINT64_FORMAT, samples, offset);
1039 if (G_LIKELY (offset > 0 && samples > 0)) {
1040 gst_base_parse_add_index_entry (GST_BASE_PARSE (flacparse),
1041 boffset + offset, gst_util_uint64_scale (samples, GST_SECOND,
1042 flacparse->samplerate), TRUE, FALSE);
1047 gst_buffer_unmap (flacparse->seektable, &map);
1049 gst_buffer_unref (flacparse->seektable);
1050 flacparse->seektable = NULL;
1054 _value_array_append_buffer (GValue * array_val, GstBuffer * buf)
1056 GValue value = { 0, };
1058 g_value_init (&value, GST_TYPE_BUFFER);
1059 /* copy buffer to avoid problems with circular refcounts */
1060 buf = gst_buffer_copy (buf);
1061 /* again, for good measure */
1062 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
1063 gst_value_set_buffer (&value, buf);
1064 gst_buffer_unref (buf);
1065 gst_value_array_append_value (array_val, &value);
1066 g_value_unset (&value);
1070 gst_flac_parse_handle_headers (GstFlacParse * flacparse)
1072 GstBuffer *vorbiscomment = NULL;
1073 GstBuffer *streaminfo = NULL;
1074 GstBuffer *marker = NULL;
1075 GValue array = { 0, };
1078 gboolean res = TRUE;
1080 caps = gst_caps_new_simple ("audio/x-flac",
1081 "channels", G_TYPE_INT, flacparse->channels,
1082 "framed", G_TYPE_BOOLEAN, TRUE,
1083 "rate", G_TYPE_INT, flacparse->samplerate, NULL);
1085 if (!flacparse->headers)
1088 for (l = flacparse->headers; l; l = l->next) {
1089 GstBuffer *header = l->data;
1092 gst_buffer_map (header, &map, GST_MAP_READ);
1094 GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_HEADER);
1096 if (map.size == 4 && memcmp (map.data, "fLaC", 4) == 0) {
1098 } else if (map.size > 1 && (map.data[0] & 0x7f) == 0) {
1099 streaminfo = header;
1100 } else if (map.size > 1 && (map.data[0] & 0x7f) == 4) {
1101 vorbiscomment = header;
1104 gst_buffer_unmap (header, &map);
1107 if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
1108 GST_WARNING_OBJECT (flacparse,
1109 "missing header %p %p %p, muxing into container "
1110 "formats may be broken", marker, streaminfo, vorbiscomment);
1114 g_value_init (&array, GST_TYPE_ARRAY);
1116 /* add marker including STREAMINFO header */
1120 GstMapInfo sinfomap, writemap;
1122 gst_buffer_map (streaminfo, &sinfomap, GST_MAP_READ);
1124 /* minus one for the marker that is merged with streaminfo here */
1125 num = g_list_length (flacparse->headers) - 1;
1127 buf = gst_buffer_new_and_alloc (13 + sinfomap.size);
1128 gst_buffer_map (buf, &writemap, GST_MAP_WRITE);
1130 writemap.data[0] = 0x7f;
1131 memcpy (writemap.data + 1, "FLAC", 4);
1132 writemap.data[5] = 0x01; /* mapping version major */
1133 writemap.data[6] = 0x00; /* mapping version minor */
1134 writemap.data[7] = (num & 0xFF00) >> 8;
1135 writemap.data[8] = (num & 0x00FF) >> 0;
1136 memcpy (writemap.data + 9, "fLaC", 4);
1137 memcpy (writemap.data + 13, sinfomap.data, sinfomap.size);
1138 _value_array_append_buffer (&array, buf);
1140 gst_buffer_unmap (streaminfo, &sinfomap);
1141 gst_buffer_unmap (buf, &writemap);
1142 gst_buffer_unref (buf);
1145 /* add VORBISCOMMENT header */
1146 _value_array_append_buffer (&array, vorbiscomment);
1148 /* add other headers, if there are any */
1149 for (l = flacparse->headers; l; l = l->next) {
1150 if (GST_BUFFER_CAST (l->data) != marker &&
1151 GST_BUFFER_CAST (l->data) != streaminfo &&
1152 GST_BUFFER_CAST (l->data) != vorbiscomment) {
1153 _value_array_append_buffer (&array, GST_BUFFER_CAST (l->data));
1157 gst_structure_set_value (gst_caps_get_structure (caps, 0),
1158 "streamheader", &array);
1159 g_value_unset (&array);
1163 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)), caps);
1164 gst_caps_unref (caps);
1166 /* push header buffers; update caps, so when we push the first buffer the
1167 * negotiated caps will change to caps that include the streamheader field */
1168 while (flacparse->headers) {
1169 GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
1171 GstBaseParseFrame frame;
1173 flacparse->headers =
1174 g_list_delete_link (flacparse->headers, flacparse->headers);
1175 buf = gst_buffer_make_writable (buf);
1177 /* init, set and give away frame */
1178 gst_base_parse_frame_init (&frame);
1180 frame.overhead = -1;
1181 ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame);
1182 if (ret != GST_FLOW_OK) {
1186 gst_base_parse_frame_free (&frame);
1188 g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
1189 g_list_free (flacparse->headers);
1190 flacparse->headers = NULL;
1196 gst_flac_parse_generate_headers (GstFlacParse * flacparse)
1198 GstBuffer *marker, *streaminfo, *vorbiscomment;
1201 marker = gst_buffer_new_and_alloc (4);
1202 gst_buffer_map (marker, &map, GST_MAP_WRITE);
1203 memcpy (map.data, "fLaC", 4);
1204 gst_buffer_unmap (marker, &map);
1205 GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
1206 GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
1207 GST_BUFFER_OFFSET (marker) = 0;
1208 GST_BUFFER_OFFSET_END (marker) = 0;
1209 flacparse->headers = g_list_append (flacparse->headers, marker);
1211 streaminfo = gst_buffer_new_and_alloc (4 + 34);
1212 gst_buffer_map (streaminfo, &map, GST_MAP_WRITE);
1213 memset (map.data, 0, 4 + 34);
1215 /* metadata block header */
1216 map.data[0] = 0x00; /* is_last = 0; type = 0; */
1217 map.data[1] = 0x00; /* length = 34; */
1223 map.data[4] = (flacparse->block_size >> 8) & 0xff; /* min blocksize = blocksize; */
1224 map.data[5] = (flacparse->block_size) & 0xff;
1225 map.data[6] = (flacparse->block_size >> 8) & 0xff; /* max blocksize = blocksize; */
1226 map.data[7] = (flacparse->block_size) & 0xff;
1228 map.data[8] = 0x00; /* min framesize = 0; */
1230 map.data[10] = 0x00;
1231 map.data[11] = 0x00; /* max framesize = 0; */
1232 map.data[12] = 0x00;
1233 map.data[13] = 0x00;
1235 map.data[14] = (flacparse->samplerate >> 12) & 0xff;
1236 map.data[15] = (flacparse->samplerate >> 4) & 0xff;
1237 map.data[16] = (flacparse->samplerate >> 0) & 0xf0;
1239 map.data[16] |= (flacparse->channels - 1) << 1;
1241 map.data[16] |= ((flacparse->bps - 1) >> 4) & 0x01;
1242 map.data[17] = (((flacparse->bps - 1)) & 0x0f) << 4;
1247 if (gst_pad_peer_query_duration (GST_BASE_PARSE_SINK_PAD (flacparse),
1248 GST_FORMAT_TIME, &duration)) {
1249 duration = GST_CLOCK_TIME_TO_FRAMES (duration, flacparse->samplerate);
1251 map.data[17] |= (duration >> 32) & 0xff;
1252 map.data[18] |= (duration >> 24) & 0xff;
1253 map.data[19] |= (duration >> 16) & 0xff;
1254 map.data[20] |= (duration >> 8) & 0xff;
1255 map.data[21] |= (duration >> 0) & 0xff;
1260 gst_buffer_unmap (streaminfo, &map);
1261 GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
1262 GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
1263 GST_BUFFER_OFFSET (streaminfo) = 0;
1264 GST_BUFFER_OFFSET_END (streaminfo) = 0;
1265 flacparse->headers = g_list_append (flacparse->headers, streaminfo);
1267 /* empty vorbiscomment */
1269 GstTagList *taglist = gst_tag_list_new_empty ();
1273 header[0] = 0x84; /* is_last = 1; type = 4; */
1276 gst_tag_list_to_vorbiscomment_buffer (taglist, header,
1277 sizeof (header), NULL);
1278 gst_tag_list_free (taglist);
1280 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1282 /* Get rid of framing bit */
1283 if (map.data[map.size - 1] == 1) {
1287 gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
1289 gst_buffer_unmap (vorbiscomment, &map);
1290 gst_buffer_unref (vorbiscomment);
1291 vorbiscomment = sub;
1292 gst_buffer_map (vorbiscomment, &map, GST_MAP_WRITE);
1295 size = map.size - 4;
1296 map.data[1] = ((size & 0xFF0000) >> 16);
1297 map.data[2] = ((size & 0x00FF00) >> 8);
1298 map.data[3] = (size & 0x0000FF);
1299 gst_buffer_unmap (vorbiscomment, &map);
1301 GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
1302 GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
1303 GST_BUFFER_OFFSET (vorbiscomment) = 0;
1304 GST_BUFFER_OFFSET_END (vorbiscomment) = 0;
1305 flacparse->headers = g_list_append (flacparse->headers, vorbiscomment);
1311 static GstFlowReturn
1312 gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
1315 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1316 GstBuffer *buffer = frame->buffer, *sbuffer;
1318 GstFlowReturn res = GST_FLOW_ERROR;
1320 gst_buffer_map (buffer, &map, GST_MAP_READ);
1322 if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
1323 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1324 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1325 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1326 GST_BUFFER_OFFSET (sbuffer) = 0;
1327 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1329 /* 32 bits metadata block */
1330 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
1331 flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
1333 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1335 res = GST_BASE_PARSE_FLOW_DROPPED;
1336 } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
1337 gboolean is_last = ((map.data[0] & 0x80) == 0x80);
1338 guint type = (map.data[0] & 0x7F);
1341 GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
1342 res = GST_BASE_PARSE_FLOW_DROPPED;
1346 GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
1348 sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
1351 case 0: /* STREAMINFO */
1352 if (!gst_flac_parse_handle_streaminfo (flacparse, sbuffer))
1355 case 3: /* SEEKTABLE */
1356 if (!gst_flac_parse_handle_seektable (flacparse, sbuffer))
1359 case 4: /* VORBIS_COMMENT */
1360 if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
1363 case 6: /* PICTURE */
1364 if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
1367 case 1: /* PADDING */
1368 case 2: /* APPLICATION */
1369 case 5: /* CUESHEET */
1370 default: /* RESERVED */
1374 GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
1375 GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
1376 GST_BUFFER_OFFSET (sbuffer) = 0;
1377 GST_BUFFER_OFFSET_END (sbuffer) = 0;
1379 flacparse->headers = g_list_append (flacparse->headers, sbuffer);
1382 if (!gst_flac_parse_handle_headers (flacparse))
1385 /* Minimal size of a frame header */
1386 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1387 flacparse->min_framesize));
1388 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1391 /* DROPPED because we pushed already or will push all headers manually */
1392 res = GST_BASE_PARSE_FLOW_DROPPED;
1394 if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
1395 FrameHeaderCheckReturn ret;
1397 flacparse->offset = GST_BUFFER_OFFSET (buffer);
1399 gst_flac_parse_frame_header_is_valid (flacparse,
1400 map.data, map.size, TRUE, NULL);
1401 if (ret != FRAME_HEADER_VALID) {
1402 GST_ERROR_OBJECT (flacparse,
1403 "Baseclass didn't provide a complete frame");
1408 if (flacparse->block_size == 0) {
1409 GST_ERROR_OBJECT (flacparse, "Unparsed frame");
1413 if (flacparse->seektable)
1414 gst_flac_parse_process_seektable (flacparse, GST_BUFFER_OFFSET (buffer));
1416 if (flacparse->state == GST_FLAC_PARSE_STATE_GENERATE_HEADERS) {
1417 if (flacparse->blocking_strategy == 1) {
1418 GST_WARNING_OBJECT (flacparse,
1419 "Generating headers for variable blocksize streams not supported");
1421 if (!gst_flac_parse_handle_headers (flacparse))
1424 GST_DEBUG_OBJECT (flacparse, "Generating headers");
1426 if (!gst_flac_parse_generate_headers (flacparse))
1429 if (!gst_flac_parse_handle_headers (flacparse))
1432 flacparse->state = GST_FLAC_PARSE_STATE_DATA;
1435 /* also cater for oggmux metadata */
1436 if (flacparse->blocking_strategy == 0) {
1437 GST_BUFFER_TIMESTAMP (buffer) =
1438 gst_util_uint64_scale (flacparse->sample_number,
1439 flacparse->block_size * GST_SECOND, flacparse->samplerate);
1440 GST_BUFFER_OFFSET_END (buffer) =
1441 flacparse->sample_number * flacparse->block_size +
1442 flacparse->block_size;
1444 GST_BUFFER_TIMESTAMP (buffer) =
1445 gst_util_uint64_scale (flacparse->sample_number, GST_SECOND,
1446 flacparse->samplerate);
1447 GST_BUFFER_OFFSET_END (buffer) =
1448 flacparse->sample_number + flacparse->block_size;
1450 GST_BUFFER_OFFSET (buffer) =
1451 gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND,
1452 flacparse->samplerate);
1453 GST_BUFFER_DURATION (buffer) =
1454 GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer);
1456 /* To simplify, we just assume that it's a fixed size header and ignore
1457 * subframe headers. The first could lead us to being off by 88 bits and
1458 * the second even less, so the total inaccuracy is negligible. */
1459 frame->overhead = 7;
1461 /* Minimal size of a frame header */
1462 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
1463 flacparse->min_framesize));
1465 flacparse->offset = -1;
1466 flacparse->blocking_strategy = 0;
1467 flacparse->sample_number = 0;
1472 gst_buffer_unmap (buffer, &map);
1477 static GstFlowReturn
1478 gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
1480 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1483 if (flacparse->tags) {
1484 gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (flacparse),
1485 gst_event_new_tag (flacparse->tags));
1486 flacparse->tags = NULL;
1489 frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1495 gst_flac_parse_convert (GstBaseParse * parse,
1496 GstFormat src_format, gint64 src_value, GstFormat dest_format,
1497 gint64 * dest_value)
1499 GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
1501 if (flacparse->samplerate > 0) {
1502 if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
1503 if (src_value != -1)
1505 gst_util_uint64_scale (src_value, GST_SECOND,
1506 flacparse->samplerate);
1510 } else if (src_format == GST_FORMAT_TIME &&
1511 dest_format == GST_FORMAT_DEFAULT) {
1512 if (src_value != -1)
1514 gst_util_uint64_scale (src_value, flacparse->samplerate,
1522 return GST_BASE_PARSE_CLASS (parent_class)->convert (parse, src_format,
1523 src_value, dest_format, dest_value);
1527 gst_flac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter)
1532 /* FIXME: handle filter caps */
1534 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1538 /* Remove the framed field */
1539 peercaps = gst_caps_make_writable (peercaps);
1540 n = gst_caps_get_size (peercaps);
1541 for (i = 0; i < n; i++) {
1542 GstStructure *s = gst_caps_get_structure (peercaps, i);
1544 gst_structure_remove_field (s, "framed");
1548 gst_caps_intersect_full (peercaps,
1549 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1550 GST_CAPS_INTERSECT_FIRST);
1551 gst_caps_unref (peercaps);
1554 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD