2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2006-2007> Jan Schmidt <thaytan@mad.scientist.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * SECTION:element-mp3parse
24 * Parses and frames mpeg1 audio streams. Provides seeking.
27 * <title>Example launch line</title>
29 * gst-launch filesrc location=test.mp3 ! mp3parse ! mad ! autoaudiosink
41 #include "gstmpegaudioparse.h"
43 #include <gst/glib-compat-private.h>
45 GST_DEBUG_CATEGORY_STATIC (mp3parse_debug);
46 #define GST_CAT_DEFAULT mp3parse_debug
48 #define MP3_CHANNEL_MODE_UNKNOWN -1
49 #define MP3_CHANNEL_MODE_STEREO 0
50 #define MP3_CHANNEL_MODE_JOINT_STEREO 1
51 #define MP3_CHANNEL_MODE_DUAL_CHANNEL 2
52 #define MP3_CHANNEL_MODE_MONO 3
54 #define CRC_UNKNOWN -1
55 #define CRC_PROTECTED 0
56 #define CRC_NOT_PROTECTED 1
58 #define XING_FRAMES_FLAG 0x0001
59 #define XING_BYTES_FLAG 0x0002
60 #define XING_TOC_FLAG 0x0004
61 #define XING_VBR_SCALE_FLAG 0x0008
63 #ifndef GST_READ_UINT24_BE
64 #define GST_READ_UINT24_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16))
67 /* Minimum number of consecutive, valid-looking frames to consider
69 #define MIN_RESYNC_FRAMES 3
71 static inline MPEGAudioSeekEntry *
72 mpeg_audio_seek_entry_new (void)
74 return g_slice_new (MPEGAudioSeekEntry);
78 mpeg_audio_seek_entry_free (MPEGAudioSeekEntry * entry)
80 g_slice_free (MPEGAudioSeekEntry, entry);
83 static GstStaticPadTemplate mp3_src_template = GST_STATIC_PAD_TEMPLATE ("src",
86 GST_STATIC_CAPS ("audio/mpeg, "
87 "mpegversion = (int) 1, "
88 "layer = (int) [ 1, 3 ], "
89 "rate = (int) [ 8000, 48000 ], channels = (int) [ 1, 2 ],"
90 "parsed=(boolean) true")
93 static GstStaticPadTemplate mp3_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
96 GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) 1, parsed=(boolean)false")
99 /* GstMPEGAudioParse signals and args */
115 static gboolean gst_mp3parse_sink_event (GstPad * pad, GstEvent * event);
116 static GstFlowReturn gst_mp3parse_chain (GstPad * pad, GstBuffer * buffer);
117 static gboolean mp3parse_src_query (GstPad * pad, GstQuery * query);
118 static const GstQueryType *mp3parse_get_query_types (GstPad * pad);
119 static gboolean mp3parse_src_event (GstPad * pad, GstEvent * event);
121 static int head_check (GstMPEGAudioParse * mp3parse, unsigned long head);
123 static void gst_mp3parse_dispose (GObject * object);
124 static void gst_mp3parse_set_property (GObject * object, guint prop_id,
125 const GValue * value, GParamSpec * pspec);
126 static void gst_mp3parse_get_property (GObject * object, guint prop_id,
127 GValue * value, GParamSpec * pspec);
128 static GstStateChangeReturn gst_mp3parse_change_state (GstElement * element,
129 GstStateChange transition);
131 gst_mp3parse_handle_data (GstMPEGAudioParse * mp3parse, gboolean at_eos);
133 static gboolean mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
134 gint64 bytepos, GstClockTime * ts, gboolean from_total_time);
136 mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total);
138 mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total);
140 GST_BOILERPLATE (GstMPEGAudioParse, gst_mp3parse, GstElement, GST_TYPE_ELEMENT);
142 #define GST_TYPE_MP3_CHANNEL_MODE (gst_mp3_channel_mode_get_type())
144 static const GEnumValue mp3_channel_mode[] = {
145 {MP3_CHANNEL_MODE_UNKNOWN, "Unknown", "unknown"},
146 {MP3_CHANNEL_MODE_MONO, "Mono", "mono"},
147 {MP3_CHANNEL_MODE_DUAL_CHANNEL, "Dual Channel", "dual-channel"},
148 {MP3_CHANNEL_MODE_JOINT_STEREO, "Joint Stereo", "joint-stereo"},
149 {MP3_CHANNEL_MODE_STEREO, "Stereo", "stereo"},
154 gst_mp3_channel_mode_get_type (void)
156 static GType mp3_channel_mode_type = 0;
158 if (!mp3_channel_mode_type) {
159 mp3_channel_mode_type =
160 g_enum_register_static ("GstMp3ChannelMode", mp3_channel_mode);
162 return mp3_channel_mode_type;
166 gst_mp3_channel_mode_get_nick (gint mode)
169 for (i = 0; i < G_N_ELEMENTS (mp3_channel_mode); i++) {
170 if (mp3_channel_mode[i].value == mode)
171 return mp3_channel_mode[i].value_nick;
176 static const guint mp3types_bitrates[2][3][16] = {
178 {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
179 {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
180 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
183 {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
184 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
185 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
189 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
190 {22050, 24000, 16000},
195 mp3_type_frame_length_from_header (GstMPEGAudioParse * mp3parse, guint32 header,
196 guint * put_version, guint * put_layer, guint * put_channels,
197 guint * put_bitrate, guint * put_samplerate, guint * put_mode,
201 gulong mode, samplerate, bitrate, layer, channels, padding, crc;
205 if (header & (1 << 20)) {
206 lsf = (header & (1 << 19)) ? 0 : 1;
213 version = 1 + lsf + mpg25;
215 layer = 4 - ((header >> 17) & 0x3);
217 crc = (header >> 16) & 0x1;
219 bitrate = (header >> 12) & 0xF;
220 bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
221 /* The caller has ensured we have a valid header, so bitrate can't be
223 g_assert (bitrate != 0);
225 samplerate = (header >> 10) & 0x3;
226 samplerate = mp3types_freqs[lsf + mpg25][samplerate];
228 padding = (header >> 9) & 0x1;
230 mode = (header >> 6) & 0x3;
231 channels = (mode == 3) ? 1 : 2;
235 length = 4 * ((bitrate * 12) / samplerate + padding);
238 length = (bitrate * 144) / samplerate + padding;
242 length = (bitrate * 144) / (samplerate << lsf) + padding;
246 GST_DEBUG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes",
248 GST_DEBUG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
249 "layer = %lu, channels = %lu, mode = %s", samplerate, bitrate, version,
250 layer, channels, gst_mp3_channel_mode_get_nick (mode));
253 *put_version = version;
257 *put_channels = channels;
259 *put_bitrate = bitrate;
261 *put_samplerate = samplerate;
271 mp3_caps_create (guint version, guint layer, guint channels, guint samplerate)
277 g_assert (samplerate);
280 new = gst_caps_new_simple ("audio/mpeg",
281 "mpegversion", G_TYPE_INT, 1,
282 "mpegaudioversion", G_TYPE_INT, version,
283 "layer", G_TYPE_INT, layer,
284 "rate", G_TYPE_INT, samplerate,
285 "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
291 gst_mp3parse_base_init (gpointer klass)
293 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
295 gst_element_class_add_static_pad_template (element_class,
297 gst_element_class_add_static_pad_template (element_class,
300 GST_DEBUG_CATEGORY_INIT (mp3parse_debug, "mp3parse", 0, "MPEG Audio Parser");
302 gst_element_class_set_details_simple (element_class, "MPEG1 Audio Parser",
303 "Codec/Parser/Audio",
304 "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
305 "Jan Schmidt <thaytan@mad.scientist.com>,"
306 "Erik Walthinsen <omega@cse.ogi.edu>");
310 gst_mp3parse_class_init (GstMPEGAudioParseClass * klass)
312 GObjectClass *gobject_class;
313 GstElementClass *gstelement_class;
315 gobject_class = (GObjectClass *) klass;
316 gstelement_class = (GstElementClass *) klass;
318 parent_class = g_type_class_peek_parent (klass);
320 gobject_class->set_property = gst_mp3parse_set_property;
321 gobject_class->get_property = gst_mp3parse_get_property;
322 gobject_class->dispose = gst_mp3parse_dispose;
324 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SKIP,
325 g_param_spec_int ("skip", "skip", "skip",
326 G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
327 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BIT_RATE,
328 g_param_spec_int ("bitrate", "Bitrate", "Bit Rate",
329 G_MININT, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
331 gstelement_class->change_state = gst_mp3parse_change_state;
334 #define GST_TAG_CRC "has-crc"
335 #define GST_TAG_MODE "channel-mode"
337 gst_tag_register (GST_TAG_CRC, GST_TAG_FLAG_META, G_TYPE_BOOLEAN,
338 "has crc", "Using CRC", NULL);
339 gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
340 "channel mode", "MPEG audio channel mode", NULL);
342 g_type_class_ref (GST_TYPE_MP3_CHANNEL_MODE);
346 gst_mp3parse_reset (GstMPEGAudioParse * mp3parse)
349 mp3parse->resyncing = TRUE;
350 mp3parse->next_ts = GST_CLOCK_TIME_NONE;
351 mp3parse->cur_offset = -1;
353 mp3parse->sync_offset = 0;
354 mp3parse->tracked_offset = 0;
355 mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
356 mp3parse->pending_offset = -1;
358 gst_adapter_clear (mp3parse->adapter);
360 mp3parse->rate = mp3parse->channels = mp3parse->layer = -1;
361 mp3parse->version = 1;
362 mp3parse->max_bitreservoir = GST_CLOCK_TIME_NONE;
364 mp3parse->avg_bitrate = 0;
365 mp3parse->bitrate_sum = 0;
366 mp3parse->last_posted_bitrate = 0;
367 mp3parse->frame_count = 0;
368 mp3parse->sent_codec_tag = FALSE;
370 mp3parse->last_posted_crc = CRC_UNKNOWN;
371 mp3parse->last_posted_channel_mode = MP3_CHANNEL_MODE_UNKNOWN;
373 mp3parse->xing_flags = 0;
374 mp3parse->xing_bitrate = 0;
375 mp3parse->xing_frames = 0;
376 mp3parse->xing_total_time = 0;
377 mp3parse->xing_bytes = 0;
378 mp3parse->xing_vbr_scale = 0;
379 memset (mp3parse->xing_seek_table, 0, 100);
380 memset (mp3parse->xing_seek_table_inverse, 0, 256);
382 mp3parse->vbri_bitrate = 0;
383 mp3parse->vbri_frames = 0;
384 mp3parse->vbri_total_time = 0;
385 mp3parse->vbri_bytes = 0;
386 mp3parse->vbri_seek_points = 0;
387 g_free (mp3parse->vbri_seek_table);
388 mp3parse->vbri_seek_table = NULL;
390 if (mp3parse->seek_table) {
391 g_list_foreach (mp3parse->seek_table, (GFunc) mpeg_audio_seek_entry_free,
393 g_list_free (mp3parse->seek_table);
394 mp3parse->seek_table = NULL;
397 g_mutex_lock (mp3parse->pending_seeks_lock);
398 if (mp3parse->pending_accurate_seeks) {
399 g_slist_foreach (mp3parse->pending_accurate_seeks, (GFunc) g_free, NULL);
400 g_slist_free (mp3parse->pending_accurate_seeks);
401 mp3parse->pending_accurate_seeks = NULL;
403 if (mp3parse->pending_nonaccurate_seeks) {
404 g_slist_foreach (mp3parse->pending_nonaccurate_seeks, (GFunc) g_free, NULL);
405 g_slist_free (mp3parse->pending_nonaccurate_seeks);
406 mp3parse->pending_nonaccurate_seeks = NULL;
408 g_mutex_unlock (mp3parse->pending_seeks_lock);
410 if (mp3parse->pending_segment) {
411 GstEvent **eventp = &mp3parse->pending_segment;
413 gst_event_replace (eventp, NULL);
416 mp3parse->exact_position = FALSE;
417 gst_segment_init (&mp3parse->segment, GST_FORMAT_TIME);
421 gst_mp3parse_init (GstMPEGAudioParse * mp3parse, GstMPEGAudioParseClass * klass)
424 gst_pad_new_from_static_template (&mp3_sink_template, "sink");
425 gst_pad_set_event_function (mp3parse->sinkpad, gst_mp3parse_sink_event);
426 gst_pad_set_chain_function (mp3parse->sinkpad, gst_mp3parse_chain);
427 gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->sinkpad);
430 gst_pad_new_from_static_template (&mp3_src_template, "src");
431 gst_pad_use_fixed_caps (mp3parse->srcpad);
432 gst_pad_set_event_function (mp3parse->srcpad, mp3parse_src_event);
433 gst_pad_set_query_function (mp3parse->srcpad, mp3parse_src_query);
434 gst_pad_set_query_type_function (mp3parse->srcpad, mp3parse_get_query_types);
435 gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->srcpad);
437 mp3parse->adapter = gst_adapter_new ();
438 mp3parse->pending_seeks_lock = g_mutex_new ();
440 gst_mp3parse_reset (mp3parse);
444 gst_mp3parse_dispose (GObject * object)
446 GstMPEGAudioParse *mp3parse = GST_MP3PARSE (object);
448 gst_mp3parse_reset (mp3parse);
450 if (mp3parse->adapter) {
451 g_object_unref (mp3parse->adapter);
452 mp3parse->adapter = NULL;
454 g_mutex_free (mp3parse->pending_seeks_lock);
455 mp3parse->pending_seeks_lock = NULL;
457 g_list_foreach (mp3parse->pending_events, (GFunc) gst_mini_object_unref,
459 g_list_free (mp3parse->pending_events);
460 mp3parse->pending_events = NULL;
462 G_OBJECT_CLASS (parent_class)->dispose (object);
466 gst_mp3parse_sink_event (GstPad * pad, GstEvent * event)
469 GstMPEGAudioParse *mp3parse;
472 mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
474 switch (GST_EVENT_TYPE (event)) {
475 case GST_EVENT_NEWSEGMENT:
477 gdouble rate, applied_rate;
479 gint64 start, stop, pos;
481 MPEGAudioPendingAccurateSeek *seek = NULL;
484 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
485 &format, &start, &stop, &pos);
487 g_mutex_lock (mp3parse->pending_seeks_lock);
488 if (format == GST_FORMAT_BYTES && mp3parse->pending_accurate_seeks) {
490 for (node = mp3parse->pending_accurate_seeks; node; node = node->next) {
491 MPEGAudioPendingAccurateSeek *tmp = node->data;
493 if (tmp->upstream_start == pos) {
499 GstSegment *s = &seek->segment;
502 gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
503 GST_FORMAT_TIME, s->start, s->stop, s->last_stop);
505 mp3parse->segment = seek->segment;
507 mp3parse->resyncing = FALSE;
508 mp3parse->cur_offset = pos;
509 mp3parse->next_ts = seek->timestamp_start;
510 mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
511 mp3parse->tracked_offset = 0;
512 mp3parse->sync_offset = 0;
514 gst_event_parse_new_segment_full (event, &update, &rate,
515 &applied_rate, &format, &start, &stop, &pos);
517 GST_DEBUG_OBJECT (mp3parse,
518 "Pushing accurate newseg rate %g, applied rate %g, "
519 "format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT
520 ", pos %" G_GINT64_FORMAT, rate, applied_rate, format, start,
524 mp3parse->pending_accurate_seeks =
525 g_slist_delete_link (mp3parse->pending_accurate_seeks, node);
527 g_mutex_unlock (mp3parse->pending_seeks_lock);
528 res = gst_pad_push_event (mp3parse->srcpad, event);
532 GST_WARNING_OBJECT (mp3parse,
533 "Accurate seek not possible, didn't get an appropiate upstream segment");
536 g_mutex_unlock (mp3parse->pending_seeks_lock);
538 mp3parse->exact_position = FALSE;
540 if (format == GST_FORMAT_BYTES) {
541 GstClockTime seg_start, seg_stop, seg_pos;
543 /* stop time is allowed to be open-ended, but not start & pos */
544 if (!mp3parse_bytepos_to_time (mp3parse, stop, &seg_stop, FALSE))
545 seg_stop = GST_CLOCK_TIME_NONE;
546 if (mp3parse_bytepos_to_time (mp3parse, start, &seg_start, FALSE) &&
547 mp3parse_bytepos_to_time (mp3parse, pos, &seg_pos, FALSE)) {
548 gst_event_unref (event);
550 /* search the pending nonaccurate seeks */
551 g_mutex_lock (mp3parse->pending_seeks_lock);
553 for (node = mp3parse->pending_nonaccurate_seeks; node;
555 MPEGAudioPendingAccurateSeek *tmp = node->data;
557 if (tmp->upstream_start == pos) {
564 if (seek->segment.stop == -1) {
565 /* corrent the segment end, because non-accurate seeks might make
566 * our streaming end earlier (see bug #603695) */
570 mp3parse->pending_nonaccurate_seeks =
571 g_slist_delete_link (mp3parse->pending_nonaccurate_seeks, node);
573 g_mutex_unlock (mp3parse->pending_seeks_lock);
575 event = gst_event_new_new_segment_full (update, rate, applied_rate,
576 GST_FORMAT_TIME, seg_start, seg_stop, seg_pos);
577 format = GST_FORMAT_TIME;
578 GST_DEBUG_OBJECT (mp3parse, "Converted incoming segment to TIME. "
579 "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
580 ", pos = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start),
581 GST_TIME_ARGS (seg_stop), GST_TIME_ARGS (seg_pos));
585 if (format != GST_FORMAT_TIME) {
586 /* Unknown incoming segment format. Output a default open-ended
588 gst_event_unref (event);
589 event = gst_event_new_new_segment_full (update, rate, applied_rate,
590 GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
593 mp3parse->resyncing = TRUE;
594 mp3parse->cur_offset = -1;
595 mp3parse->next_ts = GST_CLOCK_TIME_NONE;
596 mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
597 mp3parse->tracked_offset = 0;
598 mp3parse->sync_offset = 0;
599 /* also clear leftover data if clearing so much state */
600 gst_adapter_clear (mp3parse->adapter);
602 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
603 &format, &start, &stop, &pos);
604 GST_DEBUG_OBJECT (mp3parse, "Pushing newseg rate %g, applied rate %g, "
605 "format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT
606 ", pos %" G_GINT64_FORMAT, rate, applied_rate, format, start, stop,
609 gst_segment_set_newsegment_full (&mp3parse->segment, update, rate,
610 applied_rate, format, start, stop, pos);
612 /* save the segment for later, right before we push a new buffer so that
613 * the caps are fixed and the next linked element can receive the segment. */
614 eventp = &mp3parse->pending_segment;
615 gst_event_replace (eventp, event);
616 gst_event_unref (event);
620 case GST_EVENT_FLUSH_STOP:
621 /* Clear our adapter and set up for a new position */
622 gst_adapter_clear (mp3parse->adapter);
623 eventp = &mp3parse->pending_segment;
624 gst_event_replace (eventp, NULL);
625 res = gst_pad_push_event (mp3parse->srcpad, event);
628 /* If we haven't processed any frames yet, then make sure we process
629 at least whatever's in our adapter */
630 if (mp3parse->frame_count == 0) {
631 gst_mp3parse_handle_data (mp3parse, TRUE);
633 /* If we STILL have zero frames processed, fire an error */
634 if (mp3parse->frame_count == 0) {
635 GST_ELEMENT_ERROR (mp3parse, STREAM, WRONG_TYPE,
636 ("No valid frames found before end of stream"), (NULL));
641 if (mp3parse->pending_segment &&
642 (GST_EVENT_TYPE (event) != GST_EVENT_EOS) &&
643 (GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START)) {
644 /* Cache all events except EOS and the ones above if we have
645 * a pending segment */
646 mp3parse->pending_events =
647 g_list_append (mp3parse->pending_events, event);
649 res = gst_pad_push_event (mp3parse->srcpad, event);
654 gst_object_unref (mp3parse);
660 gst_mp3parse_add_index_entry (GstMPEGAudioParse * mp3parse, guint64 offset,
663 MPEGAudioSeekEntry *entry, *last;
665 if (G_LIKELY (mp3parse->seek_table != NULL)) {
666 last = mp3parse->seek_table->data;
668 if (last->byte >= offset)
671 if (GST_CLOCK_DIFF (last->timestamp, ts) < mp3parse->idx_interval)
675 entry = mpeg_audio_seek_entry_new ();
676 entry->byte = offset;
677 entry->timestamp = ts;
678 mp3parse->seek_table = g_list_prepend (mp3parse->seek_table, entry);
680 GST_LOG_OBJECT (mp3parse, "Adding index entry %" GST_TIME_FORMAT " @ offset "
681 "0x%08" G_GINT64_MODIFIER "x", GST_TIME_ARGS (ts), offset);
684 /* Prepare a buffer of the indicated size, timestamp it and output */
686 gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size,
687 guint mode, guint crc)
691 GstFlowReturn ret = GST_FLOW_OK;
692 GstClockTime push_start;
695 outbuf = gst_adapter_take_buffer (mp3parse->adapter, size);
697 GST_BUFFER_DURATION (outbuf) =
698 gst_util_uint64_scale (GST_SECOND, mp3parse->spf, mp3parse->rate);
700 GST_BUFFER_OFFSET (outbuf) = mp3parse->cur_offset;
702 /* Check if we have a pending timestamp from an incoming buffer to apply
704 if (GST_CLOCK_TIME_IS_VALID (mp3parse->pending_ts)) {
705 if (mp3parse->tracked_offset >= mp3parse->pending_offset) {
706 /* If the incoming timestamp differs from our expected by more than
707 * half a frame, then take it instead of our calculated timestamp.
708 * This avoids creating imperfect streams just because of
709 * quantization in the container timestamping */
710 GstClockTimeDiff diff = mp3parse->next_ts - mp3parse->pending_ts;
711 GstClockTimeDiff thresh = GST_BUFFER_DURATION (outbuf) / 2;
713 if (diff < -thresh || diff > thresh) {
714 GST_DEBUG_OBJECT (mp3parse, "Updating next_ts from %" GST_TIME_FORMAT
715 " to pending ts %" GST_TIME_FORMAT
716 " at offset %" G_GINT64_FORMAT " (pending offset was %"
717 G_GINT64_FORMAT ")", GST_TIME_ARGS (mp3parse->next_ts),
718 GST_TIME_ARGS (mp3parse->pending_ts), mp3parse->tracked_offset,
719 mp3parse->pending_offset);
720 mp3parse->next_ts = mp3parse->pending_ts;
722 mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
726 /* Decide what timestamp we're going to apply */
727 if (GST_CLOCK_TIME_IS_VALID (mp3parse->next_ts)) {
728 GST_BUFFER_TIMESTAMP (outbuf) = mp3parse->next_ts;
732 /* No timestamp yet, convert our offset to a timestamp if we can, or
734 if (mp3parse_bytepos_to_time (mp3parse, mp3parse->cur_offset, &ts, FALSE) &&
735 GST_CLOCK_TIME_IS_VALID (ts))
736 GST_BUFFER_TIMESTAMP (outbuf) = ts;
738 GST_BUFFER_TIMESTAMP (outbuf) = 0;
742 if (GST_BUFFER_TIMESTAMP (outbuf) == 0)
743 mp3parse->exact_position = TRUE;
745 if (mp3parse->seekable &&
746 mp3parse->exact_position && GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
747 mp3parse->cur_offset != GST_BUFFER_OFFSET_NONE) {
748 gst_mp3parse_add_index_entry (mp3parse, mp3parse->cur_offset,
749 GST_BUFFER_TIMESTAMP (outbuf));
752 /* Update our byte offset tracking */
753 if (mp3parse->cur_offset != -1) {
754 mp3parse->cur_offset += size;
756 mp3parse->tracked_offset += size;
758 if (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf))
760 GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
762 gst_buffer_set_caps (outbuf, GST_PAD_CAPS (mp3parse->srcpad));
764 /* Post a bitrate tag if we need to before pushing the buffer */
765 if (mp3parse->xing_bitrate != 0)
766 bitrate = mp3parse->xing_bitrate;
767 else if (mp3parse->vbri_bitrate != 0)
768 bitrate = mp3parse->vbri_bitrate;
770 bitrate = mp3parse->avg_bitrate;
772 /* we will create a taglist (if any of the parameters has changed)
773 * to add the tags that changed */
775 if ((mp3parse->last_posted_bitrate / 10000) != (bitrate / 10000)) {
776 taglist = gst_tag_list_new ();
777 mp3parse->last_posted_bitrate = bitrate;
778 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
779 mp3parse->last_posted_bitrate, NULL);
781 /* Post a new duration message if the average bitrate changes that much
782 * so applications can update their cached values
784 if ((mp3parse->xing_flags & XING_TOC_FLAG) == 0
785 && mp3parse->vbri_total_time == 0) {
786 gst_element_post_message (GST_ELEMENT (mp3parse),
787 gst_message_new_duration (GST_OBJECT (mp3parse), GST_FORMAT_TIME,
792 if (mp3parse->last_posted_crc != crc) {
796 taglist = gst_tag_list_new ();
798 mp3parse->last_posted_crc = crc;
799 if (mp3parse->last_posted_crc == CRC_PROTECTED) {
804 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_CRC,
808 if (mp3parse->last_posted_channel_mode != mode) {
810 taglist = gst_tag_list_new ();
812 mp3parse->last_posted_channel_mode = mode;
814 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MODE,
815 gst_mp3_channel_mode_get_nick (mode), NULL);
818 /* if the taglist exists, we need to send it */
820 gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
821 mp3parse->srcpad, taglist);
824 /* We start pushing 9 frames earlier (29 frames for MPEG2) than
825 * segment start to be able to decode the first frame we want.
826 * 9 (29) frames are the theoretical maximum of frames that contain
827 * data for the current frame (bit reservoir).
829 if (mp3parse->segment.start == 0) {
831 } else if (GST_CLOCK_TIME_IS_VALID (mp3parse->max_bitreservoir)) {
832 if (GST_CLOCK_TIME_IS_VALID (mp3parse->segment.start) &&
833 mp3parse->segment.start > mp3parse->max_bitreservoir)
834 push_start = mp3parse->segment.start - mp3parse->max_bitreservoir;
838 push_start = mp3parse->segment.start;
841 if (G_UNLIKELY ((GST_CLOCK_TIME_IS_VALID (push_start) &&
842 GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
843 GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf)
845 GST_DEBUG_OBJECT (mp3parse,
846 "Buffer before configured segment range %" GST_TIME_FORMAT
847 " to %" GST_TIME_FORMAT ", dropping, timestamp %"
848 GST_TIME_FORMAT " duration %" GST_TIME_FORMAT
849 ", offset 0x%08" G_GINT64_MODIFIER "x", GST_TIME_ARGS (push_start),
850 GST_TIME_ARGS (mp3parse->segment.stop),
851 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
852 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
853 GST_BUFFER_OFFSET (outbuf));
855 gst_buffer_unref (outbuf);
857 } else if (G_UNLIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (outbuf) &&
858 GST_CLOCK_TIME_IS_VALID (mp3parse->segment.stop) &&
859 GST_BUFFER_TIMESTAMP (outbuf) >=
860 mp3parse->segment.stop + GST_BUFFER_DURATION (outbuf))) {
861 /* Some mp3 streams have an offset in the timestamps, for which we have to
862 * push the frame *after* the end position in order for the decoder to be
863 * able to decode everything up until the segment.stop position.
864 * That is the reason of the calculated offset */
865 GST_DEBUG_OBJECT (mp3parse,
866 "Buffer after configured segment range %" GST_TIME_FORMAT " to %"
867 GST_TIME_FORMAT ", returning GST_FLOW_UNEXPECTED, timestamp %"
868 GST_TIME_FORMAT " duration %" GST_TIME_FORMAT ", offset 0x%08"
869 G_GINT64_MODIFIER "x", GST_TIME_ARGS (push_start),
870 GST_TIME_ARGS (mp3parse->segment.stop),
871 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
872 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
873 GST_BUFFER_OFFSET (outbuf));
875 gst_buffer_unref (outbuf);
876 ret = GST_FLOW_UNEXPECTED;
878 GST_DEBUG_OBJECT (mp3parse,
879 "pushing buffer of %d bytes, timestamp %" GST_TIME_FORMAT
880 ", offset 0x%08" G_GINT64_MODIFIER "x", size,
881 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
882 GST_BUFFER_OFFSET (outbuf));
883 mp3parse->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuf);
884 /* push any pending segment now */
885 if (mp3parse->pending_segment) {
886 gst_pad_push_event (mp3parse->srcpad, mp3parse->pending_segment);
887 mp3parse->pending_segment = NULL;
889 if (mp3parse->pending_events) {
892 for (l = mp3parse->pending_events; l != NULL; l = l->next) {
893 gst_pad_push_event (mp3parse->srcpad, GST_EVENT (l->data));
895 g_list_free (mp3parse->pending_events);
896 mp3parse->pending_events = NULL;
899 /* set discont if needed */
900 if (mp3parse->discont) {
901 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
902 mp3parse->discont = FALSE;
905 ret = gst_pad_push (mp3parse->srcpad, outbuf);
912 gst_mp3parse_handle_first_frame (GstMPEGAudioParse * mp3parse)
916 const guint32 xing_id = 0x58696e67; /* 'Xing' in hex */
917 const guint32 info_id = 0x496e666f; /* 'Info' in hex - found in LAME CBR files */
918 const guint32 vbri_id = 0x56425249; /* 'VBRI' in hex */
923 gint64 upstream_total_bytes = 0;
927 /* Output codec tag */
928 if (!mp3parse->sent_codec_tag) {
929 if (mp3parse->layer == 3) {
930 codec = g_strdup_printf ("MPEG %d Audio, Layer %d (MP3)",
931 mp3parse->version, mp3parse->layer);
933 codec = g_strdup_printf ("MPEG %d Audio, Layer %d",
934 mp3parse->version, mp3parse->layer);
937 taglist = gst_tag_list_new ();
938 gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
939 GST_TAG_AUDIO_CODEC, codec, NULL);
940 gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
941 mp3parse->srcpad, taglist);
944 mp3parse->sent_codec_tag = TRUE;
946 /* end setting the tag */
948 /* Check first frame for Xing info */
949 if (mp3parse->version == 1) { /* MPEG-1 file */
950 if (mp3parse->channels == 1)
954 } else { /* MPEG-2 header */
955 if (mp3parse->channels == 1)
960 /* Skip the 4 bytes of the MP3 header too */
963 /* Check if we have enough data to read the Xing header */
964 avail = gst_adapter_available (mp3parse->adapter);
966 if (avail < offset + 8)
969 data = gst_adapter_peek (mp3parse->adapter, offset + 8);
972 /* The header starts at the provided offset */
975 /* obtain real upstream total bytes */
976 mp3parse_total_bytes (mp3parse, &upstream_total_bytes);
978 read_id = GST_READ_UINT32_BE (data);
979 if (read_id == xing_id || read_id == info_id) {
981 guint bytes_needed = offset + 8;
983 GstClockTime total_time;
985 GST_DEBUG_OBJECT (mp3parse, "Found Xing header marker 0x%x", xing_id);
987 /* Read 4 base bytes of flags, big-endian */
988 xing_flags = GST_READ_UINT32_BE (data + 4);
989 if (xing_flags & XING_FRAMES_FLAG)
991 if (xing_flags & XING_BYTES_FLAG)
993 if (xing_flags & XING_TOC_FLAG)
995 if (xing_flags & XING_VBR_SCALE_FLAG)
997 if (avail < bytes_needed) {
998 GST_DEBUG_OBJECT (mp3parse,
999 "Not enough data to read Xing header (need %d)", bytes_needed);
1003 GST_DEBUG_OBJECT (mp3parse, "Reading Xing header");
1004 mp3parse->xing_flags = xing_flags;
1005 data = gst_adapter_peek (mp3parse->adapter, bytes_needed);
1008 if (xing_flags & XING_FRAMES_FLAG) {
1009 mp3parse->xing_frames = GST_READ_UINT32_BE (data);
1010 if (mp3parse->xing_frames == 0) {
1011 GST_WARNING_OBJECT (mp3parse,
1012 "Invalid number of frames in Xing header");
1013 mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
1015 mp3parse->xing_total_time = gst_util_uint64_scale (GST_SECOND,
1016 (guint64) (mp3parse->xing_frames) * (mp3parse->spf),
1022 mp3parse->xing_frames = 0;
1023 mp3parse->xing_total_time = 0;
1026 if (xing_flags & XING_BYTES_FLAG) {
1027 mp3parse->xing_bytes = GST_READ_UINT32_BE (data);
1028 if (mp3parse->xing_bytes == 0) {
1029 GST_WARNING_OBJECT (mp3parse, "Invalid number of bytes in Xing header");
1030 mp3parse->xing_flags &= ~XING_BYTES_FLAG;
1035 mp3parse->xing_bytes = 0;
1038 /* If we know the upstream size and duration, compute the
1039 * total bitrate, rounded up to the nearest kbit/sec */
1040 if ((total_time = mp3parse->xing_total_time) &&
1041 (total_bytes = mp3parse->xing_bytes)) {
1042 mp3parse->xing_bitrate = gst_util_uint64_scale (total_bytes,
1043 8 * GST_SECOND, total_time);
1044 mp3parse->xing_bitrate += 500;
1045 mp3parse->xing_bitrate -= mp3parse->xing_bitrate % 1000;
1048 if (xing_flags & XING_TOC_FLAG) {
1050 guchar *table = mp3parse->xing_seek_table;
1051 guchar old = 0, new;
1055 GST_DEBUG_OBJECT (mp3parse,
1056 "Subtracting initial offset of %d bytes from Xing TOC", first);
1058 /* xing seek table: percent time -> 1/256 bytepos */
1059 for (i = 0; i < 100; i++) {
1060 new = data[i] - first;
1062 GST_WARNING_OBJECT (mp3parse, "Skipping broken Xing TOC");
1063 mp3parse->xing_flags &= ~XING_TOC_FLAG;
1066 mp3parse->xing_seek_table[i] = old = new;
1069 /* build inverse table: 1/256 bytepos -> 1/100 percent time */
1070 for (i = 0; i < 256; i++) {
1071 while (percent < 99 && table[percent + 1] <= i)
1074 if (table[percent] == i) {
1075 mp3parse->xing_seek_table_inverse[i] = percent * 100;
1076 } else if (table[percent] < i && percent < 99) {
1078 gint a = percent, b = percent + 1;
1082 fx = (b - a) / (fb - fa) * (i - fa) + a;
1083 mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
1084 } else if (percent == 99) {
1086 gint a = percent, b = 100;
1090 fx = (b - a) / (fb - fa) * (i - fa) + a;
1091 mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
1097 memset (mp3parse->xing_seek_table, 0, 100);
1098 memset (mp3parse->xing_seek_table_inverse, 0, 256);
1101 if (xing_flags & XING_VBR_SCALE_FLAG) {
1102 mp3parse->xing_vbr_scale = GST_READ_UINT32_BE (data);
1104 mp3parse->xing_vbr_scale = 0;
1106 GST_DEBUG_OBJECT (mp3parse, "Xing header reported %u frames, time %"
1107 GST_TIME_FORMAT ", %u bytes, vbr scale %u", mp3parse->xing_frames,
1108 GST_TIME_ARGS (mp3parse->xing_total_time), mp3parse->xing_bytes,
1109 mp3parse->xing_vbr_scale);
1111 /* check for truncated file */
1112 if (upstream_total_bytes && mp3parse->xing_bytes &&
1113 mp3parse->xing_bytes * 0.8 > upstream_total_bytes) {
1114 GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
1115 "invalidating Xing header duration and size");
1116 mp3parse->xing_flags &= ~XING_BYTES_FLAG;
1117 mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
1119 } else if (read_id == vbri_id) {
1120 gint64 total_bytes, total_frames;
1121 GstClockTime total_time;
1122 guint16 nseek_points;
1124 GST_DEBUG_OBJECT (mp3parse, "Found VBRI header marker 0x%x", vbri_id);
1125 if (avail < offset + 26) {
1126 GST_DEBUG_OBJECT (mp3parse,
1127 "Not enough data to read VBRI header (need %d)", offset + 26);
1131 GST_DEBUG_OBJECT (mp3parse, "Reading VBRI header");
1132 data = gst_adapter_peek (mp3parse->adapter, offset + 26);
1135 if (GST_READ_UINT16_BE (data) != 0x0001) {
1136 GST_WARNING_OBJECT (mp3parse,
1137 "Unsupported VBRI version 0x%x", GST_READ_UINT16_BE (data));
1142 /* Skip encoder delay */
1148 total_bytes = GST_READ_UINT32_BE (data);
1149 if (total_bytes != 0)
1150 mp3parse->vbri_bytes = total_bytes;
1153 total_frames = GST_READ_UINT32_BE (data);
1154 if (total_frames != 0) {
1155 mp3parse->vbri_frames = total_frames;
1156 mp3parse->vbri_total_time = gst_util_uint64_scale (GST_SECOND,
1157 (guint64) (mp3parse->vbri_frames) * (mp3parse->spf), mp3parse->rate);
1161 /* If we know the upstream size and duration, compute the
1162 * total bitrate, rounded up to the nearest kbit/sec */
1163 if ((total_time = mp3parse->vbri_total_time) &&
1164 (total_bytes = mp3parse->vbri_bytes)) {
1165 mp3parse->vbri_bitrate = gst_util_uint64_scale (total_bytes,
1166 8 * GST_SECOND, total_time);
1167 mp3parse->vbri_bitrate += 500;
1168 mp3parse->vbri_bitrate -= mp3parse->vbri_bitrate % 1000;
1171 nseek_points = GST_READ_UINT16_BE (data);
1174 if (nseek_points > 0) {
1175 guint scale, seek_bytes, seek_frames;
1178 mp3parse->vbri_seek_points = nseek_points;
1180 scale = GST_READ_UINT16_BE (data);
1183 seek_bytes = GST_READ_UINT16_BE (data);
1186 seek_frames = GST_READ_UINT16_BE (data);
1188 if (scale == 0 || seek_bytes == 0 || seek_bytes > 4 || seek_frames == 0) {
1189 GST_WARNING_OBJECT (mp3parse, "Unsupported VBRI seek table");
1193 if (avail < offset + 26 + nseek_points * seek_bytes) {
1194 GST_WARNING_OBJECT (mp3parse,
1195 "Not enough data to read VBRI seek table (need %d)",
1196 offset + 26 + nseek_points * seek_bytes);
1200 if (seek_frames * nseek_points < total_frames - seek_frames ||
1201 seek_frames * nseek_points > total_frames + seek_frames) {
1202 GST_WARNING_OBJECT (mp3parse,
1203 "VBRI seek table doesn't cover the complete file");
1208 gst_adapter_peek (mp3parse->adapter,
1209 offset + 26 + nseek_points * seek_bytes);
1210 data += offset + 26;
1213 /* VBRI seek table: frame/seek_frames -> byte */
1214 mp3parse->vbri_seek_table = g_new (guint32, nseek_points);
1215 if (seek_bytes == 4)
1216 for (i = 0; i < nseek_points; i++) {
1217 mp3parse->vbri_seek_table[i] = GST_READ_UINT32_BE (data) * scale;
1219 } else if (seek_bytes == 3)
1220 for (i = 0; i < nseek_points; i++) {
1221 mp3parse->vbri_seek_table[i] = GST_READ_UINT24_BE (data) * scale;
1223 } else if (seek_bytes == 2)
1224 for (i = 0; i < nseek_points; i++) {
1225 mp3parse->vbri_seek_table[i] = GST_READ_UINT16_BE (data) * scale;
1227 } else /* seek_bytes == 1 */
1228 for (i = 0; i < nseek_points; i++) {
1229 mp3parse->vbri_seek_table[i] = GST_READ_UINT8 (data) * scale;
1235 GST_DEBUG_OBJECT (mp3parse, "VBRI header reported %u frames, time %"
1236 GST_TIME_FORMAT ", bytes %u", mp3parse->vbri_frames,
1237 GST_TIME_ARGS (mp3parse->vbri_total_time), mp3parse->vbri_bytes);
1239 /* check for truncated file */
1240 if (upstream_total_bytes && mp3parse->vbri_bytes &&
1241 mp3parse->vbri_bytes * 0.8 > upstream_total_bytes) {
1242 GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
1243 "invalidating VBRI header duration and size");
1244 mp3parse->vbri_valid = FALSE;
1246 mp3parse->vbri_valid = TRUE;
1249 GST_DEBUG_OBJECT (mp3parse,
1250 "Xing, LAME or VBRI header not found in first frame");
1255 gst_mp3parse_check_seekability (GstMPEGAudioParse * mp3parse)
1258 gboolean seekable = FALSE;
1259 gint64 start = -1, stop = -1;
1260 guint idx_interval = 0;
1262 query = gst_query_new_seeking (GST_FORMAT_BYTES);
1263 if (!gst_pad_peer_query (mp3parse->sinkpad, query)) {
1264 GST_DEBUG_OBJECT (mp3parse, "seeking query failed");
1268 gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
1270 /* try harder to query upstream size if we didn't get it the first time */
1271 if (seekable && stop == -1) {
1272 GstFormat fmt = GST_FORMAT_BYTES;
1274 GST_DEBUG_OBJECT (mp3parse, "doing duration query to fix up unset stop");
1275 gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, &stop);
1278 /* if upstream doesn't know the size, it's likely that it's not seekable in
1279 * practice even if it technically may be seekable */
1280 if (seekable && (start != 0 || stop <= start)) {
1281 GST_DEBUG_OBJECT (mp3parse, "seekable but unknown start/stop -> disable");
1285 /* let's not put every single frame into our index */
1287 if (stop < 10 * 1024 * 1024)
1289 else if (stop < 100 * 1024 * 1024)
1292 idx_interval = 1000;
1297 GST_INFO_OBJECT (mp3parse, "seekable: %d (%" G_GUINT64_FORMAT " - %"
1298 G_GUINT64_FORMAT ")", seekable, start, stop);
1299 mp3parse->seekable = seekable;
1301 GST_INFO_OBJECT (mp3parse, "idx_interval: %ums", idx_interval);
1302 mp3parse->idx_interval = idx_interval * GST_MSECOND;
1304 gst_query_unref (query);
1307 /* Flush some number of bytes and update tracked offsets */
1309 gst_mp3parse_flush_bytes (GstMPEGAudioParse * mp3parse, int bytes)
1311 gst_adapter_flush (mp3parse->adapter, bytes);
1312 if (mp3parse->cur_offset != -1)
1313 mp3parse->cur_offset += bytes;
1314 mp3parse->tracked_offset += bytes;
1317 /* Perform extended validation to check that subsequent headers match
1318 the first header given here in important characteristics, to avoid
1319 false sync. We look for a minimum of MIN_RESYNC_FRAMES consecutive
1320 frames to match their major characteristics.
1322 If at_eos is set to TRUE, we just check that we don't find any invalid
1323 frames in whatever data is available, rather than requiring a full
1324 MIN_RESYNC_FRAMES of data.
1326 Returns TRUE if we've seen enough data to validate or reject the frame.
1327 If TRUE is returned, then *valid contains TRUE if it validated, or false
1328 if we decided it was false sync.
1331 gst_mp3parse_validate_extended (GstMPEGAudioParse * mp3parse, guint32 header,
1332 int bpf, gboolean at_eos, gboolean * valid)
1334 guint32 next_header;
1337 int frames_found = 1;
1340 while (frames_found < MIN_RESYNC_FRAMES) {
1341 /* Check if we have enough data for all these frames, plus the next
1343 available = gst_adapter_available (mp3parse->adapter);
1344 if (available < offset + 4) {
1346 /* Running out of data at EOS is fine; just accept it */
1354 data = gst_adapter_peek (mp3parse->adapter, offset + 4);
1355 next_header = GST_READ_UINT32_BE (data + offset);
1356 GST_DEBUG_OBJECT (mp3parse, "At %d: header=%08X, header2=%08X, bpf=%d",
1357 offset, (unsigned int) header, (unsigned int) next_header, bpf);
1359 /* mask the bits which are allowed to differ between frames */
1360 #define HDRMASK ~((0xF << 12) /* bitrate */ | \
1361 (0x1 << 9) /* padding */ | \
1362 (0xf << 4) /* mode|mode extension */ | \
1363 (0xf)) /* copyright|emphasis */
1365 if ((next_header & HDRMASK) != (header & HDRMASK)) {
1366 /* If any of the unmasked bits don't match, then it's not valid */
1367 GST_DEBUG_OBJECT (mp3parse, "next header doesn't match "
1368 "(header=%08X (%08X), header2=%08X (%08X), bpf=%d)",
1369 (guint) header, (guint) header & HDRMASK, (guint) next_header,
1370 (guint) next_header & HDRMASK, bpf);
1373 } else if ((((next_header >> 12) & 0xf) == 0) ||
1374 (((next_header >> 12) & 0xf) == 0xf)) {
1375 /* The essential parts were the same, but the bitrate held an
1376 invalid value - also reject */
1377 GST_DEBUG_OBJECT (mp3parse, "next header invalid (bitrate)");
1382 bpf = mp3_type_frame_length_from_header (mp3parse, next_header,
1383 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1393 static GstFlowReturn
1394 gst_mp3parse_handle_data (GstMPEGAudioParse * mp3parse, gboolean at_eos)
1396 GstFlowReturn flow = GST_FLOW_OK;
1401 guint bitrate, layer, rate, channels, version, mode, crc;
1402 gboolean caps_change;
1404 /* while we still have at least 4 bytes (for the header) available */
1405 while (gst_adapter_available (mp3parse->adapter) >= 4) {
1406 /* Get the header bytes, check if they're potentially valid */
1407 data = gst_adapter_peek (mp3parse->adapter, 4);
1408 header = GST_READ_UINT32_BE (data);
1410 if (!head_check (mp3parse, header)) {
1411 /* Not a valid MP3 header; we start looking forward byte-by-byte trying to
1412 find a place to resync */
1413 if (!mp3parse->resyncing)
1414 mp3parse->sync_offset = mp3parse->tracked_offset;
1415 mp3parse->resyncing = TRUE;
1416 gst_mp3parse_flush_bytes (mp3parse, 1);
1417 GST_DEBUG_OBJECT (mp3parse, "wrong header, skipping byte");
1421 /* We have a potentially valid header.
1422 If this is just a normal 'next frame', we go ahead and output it.
1424 However, sometimes, we do additional validation to ensure we haven't
1425 got false sync (common with mp3 due to the short sync word).
1426 The additional validation requires that we find several consecutive mp3
1427 frames with the same major parameters, or reach EOS with a smaller
1428 number of valid-looking frames.
1431 - This is the very first frame we've processed
1432 - We're resyncing after a non-accurate seek, or after losing sync
1433 due to invalid data.
1434 - The format of the stream changes in a major way (number of channels,
1435 sample rate, layer, or mpeg version).
1437 available = gst_adapter_available (mp3parse->adapter);
1439 if (G_UNLIKELY (mp3parse->resyncing &&
1440 mp3parse->tracked_offset - mp3parse->sync_offset > 2 * 1024 * 1024))
1443 bpf = mp3_type_frame_length_from_header (mp3parse, header,
1444 &version, &layer, &channels, &bitrate, &rate, &mode, &crc);
1445 g_assert (bpf != 0);
1447 if (channels != mp3parse->channels ||
1448 rate != mp3parse->rate || layer != mp3parse->layer ||
1449 version != mp3parse->version)
1452 caps_change = FALSE;
1454 if (mp3parse->resyncing || caps_change) {
1456 if (!gst_mp3parse_validate_extended (mp3parse, header, bpf, at_eos,
1458 /* Not enough data to validate; wait for more */
1463 /* Extended validation failed; we probably got false sync.
1464 Continue searching from the next byte in the stream */
1465 if (!mp3parse->resyncing)
1466 mp3parse->sync_offset = mp3parse->tracked_offset;
1467 mp3parse->resyncing = TRUE;
1468 gst_mp3parse_flush_bytes (mp3parse, 1);
1473 /* if we don't have the whole frame... */
1474 if (available < bpf) {
1475 GST_DEBUG_OBJECT (mp3parse, "insufficient data available, need "
1476 "%d bytes, have %d", bpf, available);
1483 caps = mp3_caps_create (version, layer, channels, rate);
1484 gst_pad_set_caps (mp3parse->srcpad, caps);
1485 gst_caps_unref (caps);
1487 mp3parse->channels = channels;
1488 mp3parse->rate = rate;
1490 mp3parse->layer = layer;
1491 mp3parse->version = version;
1493 /* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
1494 if (mp3parse->layer == 1)
1495 mp3parse->spf = 384;
1496 else if (mp3parse->layer == 2)
1497 mp3parse->spf = 1152;
1498 else if (mp3parse->version == 1) {
1499 mp3parse->spf = 1152;
1501 /* MPEG-2 or "2.5" */
1502 mp3parse->spf = 576;
1505 mp3parse->max_bitreservoir = gst_util_uint64_scale (GST_SECOND,
1506 ((version == 1) ? 10 : 30) * mp3parse->spf, mp3parse->rate);
1509 mp3parse->bit_rate = bitrate;
1511 /* Check the first frame for a Xing header to get our total length */
1512 if (mp3parse->frame_count == 0) {
1513 /* For the first frame in the file, look for a Xing frame after
1514 * the header, and output a codec tag */
1515 gst_mp3parse_handle_first_frame (mp3parse);
1517 /* Check if we're seekable */
1518 gst_mp3parse_check_seekability (mp3parse);
1521 /* Update VBR stats */
1522 mp3parse->bitrate_sum += mp3parse->bit_rate;
1523 mp3parse->frame_count++;
1524 /* Compute the average bitrate, rounded up to the nearest 1000 bits */
1525 mp3parse->avg_bitrate =
1526 (mp3parse->bitrate_sum / mp3parse->frame_count + 500);
1527 mp3parse->avg_bitrate -= mp3parse->avg_bitrate % 1000;
1529 if (!mp3parse->skip) {
1530 mp3parse->resyncing = FALSE;
1531 flow = gst_mp3parse_emit_frame (mp3parse, bpf, mode, crc);
1532 if (flow != GST_FLOW_OK)
1535 GST_DEBUG_OBJECT (mp3parse, "skipping buffer of %d bytes", bpf);
1536 gst_mp3parse_flush_bytes (mp3parse, bpf);
1546 GST_ELEMENT_ERROR (mp3parse, STREAM, DECODE,
1547 ("Failed to parse stream"), (NULL));
1548 return GST_FLOW_ERROR;
1552 static GstFlowReturn
1553 gst_mp3parse_chain (GstPad * pad, GstBuffer * buf)
1555 GstMPEGAudioParse *mp3parse;
1556 GstClockTime timestamp;
1558 mp3parse = GST_MP3PARSE (GST_PAD_PARENT (pad));
1560 GST_LOG_OBJECT (mp3parse, "buffer of %d bytes", GST_BUFFER_SIZE (buf));
1562 timestamp = GST_BUFFER_TIMESTAMP (buf);
1564 mp3parse->discont |= GST_BUFFER_IS_DISCONT (buf);
1566 /* If we don't yet have a next timestamp, save it and the incoming offset
1567 * so we can apply it to the right outgoing buffer */
1568 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1569 gint64 avail = gst_adapter_available (mp3parse->adapter);
1571 mp3parse->pending_ts = timestamp;
1572 mp3parse->pending_offset = mp3parse->tracked_offset + avail;
1574 /* If we have no data pending and the next timestamp is
1575 * invalid we can use the upstream timestamp for the next frame.
1577 * This will give us a timestamp if we're resyncing and upstream
1578 * gave us -1 as offset. */
1579 if (avail == 0 && !GST_CLOCK_TIME_IS_VALID (mp3parse->next_ts))
1580 mp3parse->next_ts = timestamp;
1582 GST_LOG_OBJECT (mp3parse, "Have pending ts %" GST_TIME_FORMAT
1583 " to apply in %" G_GINT64_FORMAT " bytes (@ off %" G_GINT64_FORMAT ")",
1584 GST_TIME_ARGS (mp3parse->pending_ts), avail, mp3parse->pending_offset);
1587 /* Update the cur_offset we'll apply to outgoing buffers */
1588 if (mp3parse->cur_offset == -1 && GST_BUFFER_OFFSET (buf) != -1)
1589 mp3parse->cur_offset = GST_BUFFER_OFFSET (buf);
1591 /* And add the data to the pool */
1592 gst_adapter_push (mp3parse->adapter, buf);
1594 return gst_mp3parse_handle_data (mp3parse, FALSE);
1598 head_check (GstMPEGAudioParse * mp3parse, unsigned long head)
1600 GST_DEBUG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
1601 /* if it's not a valid sync */
1602 if ((head & 0xffe00000) != 0xffe00000) {
1603 GST_WARNING_OBJECT (mp3parse, "invalid sync");
1606 /* if it's an invalid MPEG version */
1607 if (((head >> 19) & 3) == 0x1) {
1608 GST_WARNING_OBJECT (mp3parse, "invalid MPEG version: 0x%lx",
1612 /* if it's an invalid layer */
1613 if (!((head >> 17) & 3)) {
1614 GST_WARNING_OBJECT (mp3parse, "invalid layer: 0x%lx", (head >> 17) & 3);
1617 /* if it's an invalid bitrate */
1618 if (((head >> 12) & 0xf) == 0x0) {
1619 GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx."
1620 "Free format files are not supported yet", (head >> 12) & 0xf);
1623 if (((head >> 12) & 0xf) == 0xf) {
1624 GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx", (head >> 12) & 0xf);
1627 /* if it's an invalid samplerate */
1628 if (((head >> 10) & 0x3) == 0x3) {
1629 GST_WARNING_OBJECT (mp3parse, "invalid samplerate: 0x%lx",
1630 (head >> 10) & 0x3);
1634 if ((head & 0x3) == 0x2) {
1635 /* Ignore this as there are some files with emphasis 0x2 that can
1636 * be played fine. See BGO #537235 */
1637 GST_WARNING_OBJECT (mp3parse, "invalid emphasis: 0x%lx", head & 0x3);
1644 gst_mp3parse_set_property (GObject * object, guint prop_id,
1645 const GValue * value, GParamSpec * pspec)
1647 GstMPEGAudioParse *src;
1649 src = GST_MP3PARSE (object);
1653 src->skip = g_value_get_int (value);
1661 gst_mp3parse_get_property (GObject * object, guint prop_id, GValue * value,
1664 GstMPEGAudioParse *src;
1666 src = GST_MP3PARSE (object);
1670 g_value_set_int (value, src->skip);
1673 g_value_set_int (value, src->bit_rate * 1000);
1676 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1681 static GstStateChangeReturn
1682 gst_mp3parse_change_state (GstElement * element, GstStateChange transition)
1684 GstMPEGAudioParse *mp3parse;
1685 GstStateChangeReturn result;
1687 mp3parse = GST_MP3PARSE (element);
1689 result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1691 switch (transition) {
1692 case GST_STATE_CHANGE_PAUSED_TO_READY:
1693 gst_mp3parse_reset (mp3parse);
1703 mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
1705 GstFormat fmt = GST_FORMAT_BYTES;
1707 if (gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, total))
1710 if (mp3parse->xing_flags & XING_BYTES_FLAG) {
1711 *total = mp3parse->xing_bytes;
1715 if (mp3parse->vbri_bytes != 0 && mp3parse->vbri_valid) {
1716 *total = mp3parse->vbri_bytes;
1724 mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
1728 *total = GST_CLOCK_TIME_NONE;
1730 if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
1731 *total = mp3parse->xing_total_time;
1735 if (mp3parse->vbri_total_time != 0 && mp3parse->vbri_valid) {
1736 *total = mp3parse->vbri_total_time;
1740 /* Calculate time from the measured bitrate */
1741 if (!mp3parse_total_bytes (mp3parse, &total_bytes))
1744 if (total_bytes != -1
1745 && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total, TRUE))
1751 /* Convert a timestamp to the file position required to start decoding that
1752 * timestamp. For now, this just uses the avg bitrate. Later, use an
1753 * incrementally accumulated seek table */
1755 mp3parse_time_to_bytepos (GstMPEGAudioParse * mp3parse, GstClockTime ts,
1759 GstClockTime total_time;
1761 /* -1 always maps to -1 */
1767 /* If XING seek table exists use this for time->byte conversion */
1768 if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
1769 (total_bytes = mp3parse->xing_bytes) &&
1770 (total_time = mp3parse->xing_total_time)) {
1773 CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
1774 gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
1775 gint index = CLAMP (percent, 0, 99);
1777 fa = mp3parse->xing_seek_table[index];
1779 fb = mp3parse->xing_seek_table[index + 1];
1783 fx = fa + (fb - fa) * (percent - index);
1785 *bytepos = (1.0 / 256.0) * fx * total_bytes;
1790 if (mp3parse->vbri_seek_table && (total_bytes = mp3parse->vbri_bytes) &&
1791 (total_time = mp3parse->vbri_total_time)) {
1793 gdouble a, b, fa, fb;
1795 i = gst_util_uint64_scale (ts, mp3parse->vbri_seek_points - 1, total_time);
1796 i = CLAMP (i, 0, mp3parse->vbri_seek_points - 1);
1798 a = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
1799 mp3parse->vbri_seek_points));
1801 for (j = i; j >= 0; j--)
1802 fa += mp3parse->vbri_seek_table[j];
1804 if (i + 1 < mp3parse->vbri_seek_points) {
1805 b = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
1806 mp3parse->vbri_seek_points));
1807 fb = fa + mp3parse->vbri_seek_table[i + 1];
1809 b = gst_guint64_to_gdouble (total_time);
1813 *bytepos = fa + ((fb - fa) / (b - a)) * (gst_guint64_to_gdouble (ts) - a);
1818 if (mp3parse->avg_bitrate == 0)
1822 gst_util_uint64_scale (ts, mp3parse->avg_bitrate, (8 * GST_SECOND));
1825 GST_DEBUG_OBJECT (mp3parse, "Cannot seek yet - no average bitrate");
1830 mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
1831 gint64 bytepos, GstClockTime * ts, gboolean from_total_time)
1834 GstClockTime total_time;
1836 if (bytepos == -1) {
1837 *ts = GST_CLOCK_TIME_NONE;
1846 /* If XING seek table exists use this for byte->time conversion */
1847 if (!from_total_time && (mp3parse->xing_flags & XING_TOC_FLAG) &&
1848 (total_bytes = mp3parse->xing_bytes) &&
1849 (total_time = mp3parse->xing_total_time)) {
1854 pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
1855 index = CLAMP (pos, 0, 255);
1856 fa = mp3parse->xing_seek_table_inverse[index];
1858 fb = mp3parse->xing_seek_table_inverse[index + 1];
1862 fx = fa + (fb - fa) * (pos - index);
1864 *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
1869 if (!from_total_time && mp3parse->vbri_seek_table &&
1870 (total_bytes = mp3parse->vbri_bytes) &&
1871 (total_time = mp3parse->vbri_total_time)) {
1874 gdouble a, b, fa, fb;
1877 sum += mp3parse->vbri_seek_table[i];
1879 } while (i + 1 < mp3parse->vbri_seek_points
1880 && sum + mp3parse->vbri_seek_table[i] < bytepos);
1883 a = gst_guint64_to_gdouble (sum);
1884 fa = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
1885 mp3parse->vbri_seek_points));
1887 if (i + 1 < mp3parse->vbri_seek_points) {
1888 b = a + mp3parse->vbri_seek_table[i + 1];
1889 fb = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
1890 mp3parse->vbri_seek_points));
1893 fb = gst_guint64_to_gdouble (total_time);
1896 *ts = gst_gdouble_to_guint64 (fa + ((fb - fa) / (b - a)) * (bytepos - a));
1901 /* Cannot convert anything except 0 if we don't have a bitrate yet */
1902 if (mp3parse->avg_bitrate == 0)
1905 *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
1906 mp3parse->avg_bitrate);
1911 mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event)
1916 GstSeekType cur_type, stop_type;
1918 gint64 byte_cur, byte_stop;
1919 MPEGAudioPendingAccurateSeek *seek;
1922 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
1925 GST_DEBUG_OBJECT (mp3parse, "Performing seek to %" GST_TIME_FORMAT,
1926 GST_TIME_ARGS (cur));
1928 /* For any format other than TIME, see if upstream handles
1929 * it directly or fail. For TIME, try upstream, but do it ourselves if
1930 * it fails upstream */
1931 if (format != GST_FORMAT_TIME) {
1932 gst_event_ref (event);
1933 return gst_pad_push_event (mp3parse->sinkpad, event);
1935 gst_event_ref (event);
1936 if (gst_pad_push_event (mp3parse->sinkpad, event))
1940 seek = g_new0 (MPEGAudioPendingAccurateSeek, 1);
1942 seek->segment = mp3parse->segment;
1944 gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME,
1945 flags, cur_type, cur, stop_type, stop, NULL);
1947 /* Handle TIME based seeks by converting to a BYTE position */
1949 /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames
1950 * before the one we want to seek to and push them all to the decoder.
1952 * This is necessary because of the bit reservoir. See
1953 * http://www.mars.org/mailman/public/mad-dev/2002-May/000634.html
1957 if (flags & GST_SEEK_FLAG_ACCURATE) {
1958 if (!mp3parse->seek_table) {
1963 MPEGAudioSeekEntry *entry = NULL, *start_entry = NULL, *stop_entry = NULL;
1964 GList *start_node, *stop_node;
1965 gint64 seek_ts = (cur > mp3parse->max_bitreservoir) ?
1966 (cur - mp3parse->max_bitreservoir) : 0;
1968 for (start_node = mp3parse->seek_table; start_node;
1969 start_node = start_node->next) {
1970 entry = start_node->data;
1972 if (seek_ts >= entry->timestamp) {
1973 start_entry = entry;
1979 start_entry = mp3parse->seek_table->data;
1980 start = start_entry->timestamp;
1981 byte_cur = start_entry->byte;
1983 start = start_entry->timestamp;
1984 byte_cur = start_entry->byte;
1987 for (stop_node = mp3parse->seek_table; stop_node;
1988 stop_node = stop_node->next) {
1989 entry = stop_node->data;
1991 if (stop >= entry->timestamp) {
1992 stop_node = stop_node->prev;
1993 stop_entry = (stop_node) ? stop_node->data : NULL;
2001 byte_stop = stop_entry->byte;
2005 event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
2006 byte_cur, stop_type, byte_stop);
2007 g_mutex_lock (mp3parse->pending_seeks_lock);
2008 seek->upstream_start = byte_cur;
2009 seek->timestamp_start = start;
2010 mp3parse->pending_accurate_seeks =
2011 g_slist_prepend (mp3parse->pending_accurate_seeks, seek);
2012 g_mutex_unlock (mp3parse->pending_seeks_lock);
2013 if (gst_pad_push_event (mp3parse->sinkpad, event)) {
2014 mp3parse->exact_position = TRUE;
2017 mp3parse->exact_position = TRUE;
2018 g_mutex_lock (mp3parse->pending_seeks_lock);
2019 mp3parse->pending_accurate_seeks =
2020 g_slist_remove (mp3parse->pending_accurate_seeks, seek);
2021 g_mutex_unlock (mp3parse->pending_seeks_lock);
2027 mp3parse->exact_position = FALSE;
2029 /* Convert the TIME to the appropriate BYTE position at which to resume
2031 if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) cur, &byte_cur))
2033 if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) stop, &byte_stop))
2036 GST_DEBUG_OBJECT (mp3parse, "Seeking to byte range %" G_GINT64_FORMAT
2037 " to %" G_GINT64_FORMAT, byte_cur, byte_stop);
2039 /* Send BYTE based seek upstream */
2040 event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
2041 byte_cur, stop_type, byte_stop);
2043 GST_LOG_OBJECT (mp3parse, "Storing pending seek");
2044 g_mutex_lock (mp3parse->pending_seeks_lock);
2045 seek->upstream_start = byte_cur;
2046 seek->timestamp_start = cur;
2047 mp3parse->pending_nonaccurate_seeks =
2048 g_slist_prepend (mp3parse->pending_nonaccurate_seeks, seek);
2049 g_mutex_unlock (mp3parse->pending_seeks_lock);
2050 if (gst_pad_push_event (mp3parse->sinkpad, event)) {
2053 g_mutex_lock (mp3parse->pending_seeks_lock);
2054 mp3parse->pending_nonaccurate_seeks =
2055 g_slist_remove (mp3parse->pending_nonaccurate_seeks, seek);
2056 g_mutex_unlock (mp3parse->pending_seeks_lock);
2062 GST_DEBUG_OBJECT (mp3parse,
2063 "Could not determine byte position for desired time");
2068 mp3parse_src_event (GstPad * pad, GstEvent * event)
2070 GstMPEGAudioParse *mp3parse;
2071 gboolean res = FALSE;
2073 mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
2075 switch (GST_EVENT_TYPE (event)) {
2076 case GST_EVENT_SEEK:
2077 res = mp3parse_handle_seek (mp3parse, event);
2078 gst_event_unref (event);
2081 res = gst_pad_event_default (pad, event);
2085 gst_object_unref (mp3parse);
2090 mp3parse_src_query (GstPad * pad, GstQuery * query)
2094 GstMPEGAudioParse *mp3parse;
2095 gboolean res = FALSE;
2098 mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
2100 GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
2102 switch (GST_QUERY_TYPE (query)) {
2103 case GST_QUERY_POSITION:
2104 gst_query_parse_position (query, &format, NULL);
2106 if (format == GST_FORMAT_BYTES || format == GST_FORMAT_DEFAULT) {
2107 if (mp3parse->cur_offset != -1) {
2108 gst_query_set_position (query, GST_FORMAT_BYTES,
2109 mp3parse->cur_offset);
2112 } else if (format == GST_FORMAT_TIME) {
2113 if (mp3parse->next_ts == GST_CLOCK_TIME_NONE)
2115 gst_query_set_position (query, GST_FORMAT_TIME, mp3parse->next_ts);
2119 /* If no answer above, see if upstream knows */
2121 if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
2122 res = gst_pad_query (peer, query);
2123 gst_object_unref (peer);
2129 case GST_QUERY_DURATION:
2130 gst_query_parse_duration (query, &format, NULL);
2132 /* First, see if upstream knows */
2133 if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
2134 res = gst_pad_query (peer, query);
2135 gst_object_unref (peer);
2140 if (format == GST_FORMAT_TIME) {
2141 if (!mp3parse_total_time (mp3parse, &total) || total == -1)
2143 gst_query_set_duration (query, format, total);
2147 case GST_QUERY_SEEKING:
2148 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
2150 /* does upstream handle ? */
2151 if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
2152 res = gst_pad_query (peer, query);
2153 gst_object_unref (peer);
2155 /* we may be able to help if in TIME */
2156 if (format == GST_FORMAT_TIME) {
2159 gst_query_parse_seeking (query, &format, &seekable, NULL, NULL);
2160 /* already OK if upstream takes care */
2161 if (!(res && seekable)) {
2165 if (!mp3parse_total_time (mp3parse, &total) || total == -1) {
2167 } else if (!mp3parse_time_to_bytepos (mp3parse, 0, &pos)) {
2172 q = gst_query_new_seeking (GST_FORMAT_BYTES);
2173 if (!gst_pad_peer_query (mp3parse->sinkpad, q)) {
2176 gst_query_parse_seeking (q, &format, &seekable, NULL, NULL);
2178 gst_query_unref (q);
2180 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, total);
2186 res = gst_pad_query_default (pad, query);
2191 gst_object_unref (mp3parse);
2195 static const GstQueryType *
2196 mp3parse_get_query_types (GstPad * pad G_GNUC_UNUSED)
2198 static const GstQueryType query_types[] = {