summaryrefslogtreecommitdiff
path: root/multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c
diff options
context:
space:
mode:
authorJoe Marcus Clarke <marcus@FreeBSD.org>2008-03-24 03:52:36 +0000
committerJoe Marcus Clarke <marcus@FreeBSD.org>2008-03-24 03:52:36 +0000
commit6f32add9a75efb180e462ffbdb0b080bc88088e3 (patch)
tree0fc7af36e22fc0dc7c1dc8aacabf6fe117e881da /multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c
parent- Add USE_XORG= x11 (diff)
The FreeBSD GNOME team is proud to annunce the release of GNOME 2.22.0 for
FreeBSD. The official GNOME 2.22 release notes can be found at http://library.gnome.org/misc/release-notes/2.22/ . On the FreeBSD front, this release features an updated hal port with support for video4linux devices, DRM (Direct Rendering), and better support of removable media. Work is also underway to tie webkit more closely into GNOME. As part of the GNOME 2.22 upgrade, GStreamer received a rather large upgrade as well. Be sure to consult UPDATING on the proper steps to upgrade all of your GNOME ports. This release would not have been possible without the contributions and testing efforts of the following people: Pawel Worach kan edwin Peter Ulrich Kruppa J. W. Ballantine Yasuda Keisuke Andriy Gapon
Diffstat (limited to 'multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c')
-rw-r--r--multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c733
1 files changed, 0 insertions, 733 deletions
diff --git a/multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c b/multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c
deleted file mode 100644
index 6c1d5b594cd0..000000000000
--- a/multimedia/gstreamer-plugins-ugly/files/patch-gst_mpegaudioparse_gstmpegaudioparse.c
+++ /dev/null
@@ -1,733 +0,0 @@
---- gst/mpegaudioparse/gstmpegaudioparse.c.orig 2007-12-17 00:16:51.000000000 -0500
-+++ gst/mpegaudioparse/gstmpegaudioparse.c 2007-12-17 00:17:13.000000000 -0500
-@@ -29,6 +29,7 @@
- GST_DEBUG_CATEGORY_STATIC (mp3parse_debug);
- #define GST_CAT_DEFAULT mp3parse_debug
-
-+
- /* elementfactory information */
- static GstElementDetails mp3parse_details = {
- "MPEG1 Audio Parser",
-@@ -71,8 +72,9 @@ enum
-
-
- static void gst_mp3parse_class_init (GstMPEGAudioParseClass * klass);
--static void gst_mp3parse_base_init (GstMPEGAudioParseClass * klass);
--static void gst_mp3parse_init (GstMPEGAudioParse * mp3parse);
-+static void gst_mp3parse_base_init (gpointer klass);
-+static void gst_mp3parse_init (GstMPEGAudioParse * mp3parse,
-+ GstMPEGAudioParseClass * klass);
-
- static gboolean gst_mp3parse_sink_event (GstPad * pad, GstEvent * event);
- static GstFlowReturn gst_mp3parse_chain (GstPad * pad, GstBuffer * buffer);
-@@ -95,35 +97,11 @@ static gboolean mp3parse_bytepos_to_time
- static gboolean
- mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total);
-
--static GstElementClass *parent_class = NULL;
--
- /*static guint gst_mp3parse_signals[LAST_SIGNAL] = { 0 }; */
-
--GType
--gst_mp3parse_get_type (void)
--{
-- static GType mp3parse_type = 0;
--
-- if (!mp3parse_type) {
-- static const GTypeInfo mp3parse_info = {
-- sizeof (GstMPEGAudioParseClass),
-- (GBaseInitFunc) gst_mp3parse_base_init,
-- NULL,
-- (GClassInitFunc) gst_mp3parse_class_init,
-- NULL,
-- NULL,
-- sizeof (GstMPEGAudioParse),
-- 0,
-- (GInstanceInitFunc) gst_mp3parse_init,
-- };
-+GST_BOILERPLATE (GstMPEGAudioParse, gst_mp3parse, GstElement, GST_TYPE_ELEMENT);
-
-- mp3parse_type = g_type_register_static (GST_TYPE_ELEMENT,
-- "GstMPEGAudioParse", &mp3parse_info, 0);
-- }
-- return mp3parse_type;
--}
--
--static guint mp3types_bitrates[2][3][16] = {
-+static const guint mp3types_bitrates[2][3][16] = {
- {
- {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
-@@ -136,7 +114,7 @@ static guint mp3types_bitrates[2][3][16]
- },
- };
-
--static guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
-+static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
- {22050, 24000, 16000},
- {11025, 12000, 8000}
- };
-@@ -218,13 +196,14 @@ mp3_caps_create (guint layer, guint chan
- new = gst_caps_new_simple ("audio/mpeg",
- "mpegversion", G_TYPE_INT, 1,
- "layer", G_TYPE_INT, layer,
-- "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL);
-+ "rate", G_TYPE_INT, samplerate,
-+ "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
-
- return new;
- }
-
- static void
--gst_mp3parse_base_init (GstMPEGAudioParseClass * klass)
-+gst_mp3parse_base_init (gpointer klass)
- {
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-@@ -265,8 +244,8 @@ gst_mp3parse_reset (GstMPEGAudioParse *
- {
- mp3parse->skip = 0;
- mp3parse->resyncing = TRUE;
-- mp3parse->cur_offset = -1;
- mp3parse->next_ts = GST_CLOCK_TIME_NONE;
-+ mp3parse->cur_offset = -1;
-
- mp3parse->tracked_offset = 0;
- mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
-@@ -276,6 +255,7 @@ gst_mp3parse_reset (GstMPEGAudioParse *
-
- mp3parse->rate = mp3parse->channels = mp3parse->layer = -1;
- mp3parse->version = 1;
-+ mp3parse->max_bitreservoir = GST_CLOCK_TIME_NONE;
-
- mp3parse->avg_bitrate = 0;
- mp3parse->bitrate_sum = 0;
-@@ -285,21 +265,42 @@ gst_mp3parse_reset (GstMPEGAudioParse *
-
- mp3parse->xing_flags = 0;
- mp3parse->xing_bitrate = 0;
-+
-+ if (mp3parse->seek_table) {
-+ g_list_foreach (mp3parse->seek_table, (GFunc) g_free, NULL);
-+ g_list_free (mp3parse->seek_table);
-+ mp3parse->seek_table = NULL;
-+ }
-+
-+ g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
-+ if (mp3parse->pending_accurate_seeks) {
-+ g_slist_foreach (mp3parse->pending_accurate_seeks, (GFunc) g_free, NULL);
-+ g_slist_free (mp3parse->pending_accurate_seeks);
-+ mp3parse->pending_accurate_seeks = NULL;
-+ }
-+ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
-+
-+ if (mp3parse->pending_segment) {
-+ GstEvent **eventp = &mp3parse->pending_segment;
-+
-+ gst_event_replace (eventp, NULL);
-+ }
-+
-+ mp3parse->exact_position = FALSE;
-+ gst_segment_init (&mp3parse->segment, GST_FORMAT_TIME);
- }
-
- static void
--gst_mp3parse_init (GstMPEGAudioParse * mp3parse)
-+gst_mp3parse_init (GstMPEGAudioParse * mp3parse, GstMPEGAudioParseClass * klass)
- {
- mp3parse->sinkpad =
-- gst_pad_new_from_template (gst_static_pad_template_get
-- (&mp3_sink_template), "sink");
-+ gst_pad_new_from_static_template (&mp3_sink_template, "sink");
- gst_pad_set_event_function (mp3parse->sinkpad, gst_mp3parse_sink_event);
- gst_pad_set_chain_function (mp3parse->sinkpad, gst_mp3parse_chain);
- gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->sinkpad);
-
- mp3parse->srcpad =
-- gst_pad_new_from_template (gst_static_pad_template_get
-- (&mp3_src_template), "src");
-+ gst_pad_new_from_static_template (&mp3_src_template, "src");
- gst_pad_use_fixed_caps (mp3parse->srcpad);
- gst_pad_set_event_function (mp3parse->srcpad, mp3parse_src_event);
- gst_pad_set_query_function (mp3parse->srcpad, mp3parse_src_query);
-@@ -307,6 +308,7 @@ gst_mp3parse_init (GstMPEGAudioParse * m
- gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->srcpad);
-
- mp3parse->adapter = gst_adapter_new ();
-+ mp3parse->pending_accurate_seeks_lock = g_mutex_new ();
-
- gst_mp3parse_reset (mp3parse);
- }
-@@ -316,10 +318,14 @@ gst_mp3parse_dispose (GObject * object)
- {
- GstMPEGAudioParse *mp3parse = GST_MP3PARSE (object);
-
-+ gst_mp3parse_reset (mp3parse);
-+
- if (mp3parse->adapter) {
- g_object_unref (mp3parse->adapter);
- mp3parse->adapter = NULL;
- }
-+ g_mutex_free (mp3parse->pending_accurate_seeks_lock);
-+ mp3parse->pending_accurate_seeks_lock = NULL;
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
- }
-@@ -329,6 +335,7 @@ gst_mp3parse_sink_event (GstPad * pad, G
- {
- gboolean res;
- GstMPEGAudioParse *mp3parse;
-+ GstEvent **eventp;
-
- mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
-
-@@ -343,6 +350,59 @@ gst_mp3parse_sink_event (GstPad * pad, G
- gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
- &format, &start, &stop, &pos);
-
-+ g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
-+ if (format == GST_FORMAT_BYTES && mp3parse->pending_accurate_seeks) {
-+ MPEGAudioPendingAccurateSeek *seek = NULL;
-+ GSList *node;
-+
-+ for (node = mp3parse->pending_accurate_seeks; node; node = node->next) {
-+ MPEGAudioPendingAccurateSeek *tmp = node->data;
-+
-+ if (tmp->upstream_start == pos) {
-+ seek = tmp;
-+ break;
-+ }
-+ }
-+ if (seek) {
-+ GstSegment *s = &seek->segment;
-+
-+ event =
-+ gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
-+ GST_FORMAT_TIME, s->start, s->stop, s->last_stop);
-+
-+ mp3parse->segment = seek->segment;
-+
-+ mp3parse->resyncing = FALSE;
-+ mp3parse->cur_offset = pos;
-+ mp3parse->next_ts = seek->timestamp_start;
-+ mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
-+ mp3parse->tracked_offset = 0;
-+
-+ gst_event_parse_new_segment_full (event, &update, &rate,
-+ &applied_rate, &format, &start, &stop, &pos);
-+
-+ GST_DEBUG_OBJECT (mp3parse,
-+ "Pushing accurate newseg rate %g, applied rate %g, "
-+ "format %d, start %lld, stop %lld, pos %lld\n", rate,
-+ applied_rate, format, start, stop, pos);
-+
-+ g_free (seek);
-+ mp3parse->pending_accurate_seeks =
-+ g_slist_delete_link (mp3parse->pending_accurate_seeks, node);
-+
-+ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
-+ res = gst_pad_push_event (mp3parse->srcpad, event);
-+
-+ return res;
-+ } else {
-+ GST_WARNING_OBJECT (mp3parse,
-+ "Accurate seek not possible, didn't get an appropiate upstream segment");
-+ }
-+ }
-+ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
-+
-+ mp3parse->exact_position = FALSE;
-+
- if (format == GST_FORMAT_BYTES) {
- GstClockTime seg_start, seg_stop, seg_pos;
-
-@@ -356,8 +416,9 @@ gst_mp3parse_sink_event (GstPad * pad, G
- GST_FORMAT_TIME, seg_start, seg_stop, seg_pos);
- format = GST_FORMAT_TIME;
- GST_DEBUG_OBJECT (mp3parse, "Converted incoming segment to TIME. "
-- "start = %" G_GINT64_FORMAT ", stop = %" G_GINT64_FORMAT
-- "pos = %" G_GINT64_FORMAT, seg_start, seg_stop, seg_pos);
-+ "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
-+ ", pos = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start),
-+ GST_TIME_ARGS (seg_stop), GST_TIME_ARGS (seg_pos));
- }
- }
-
-@@ -368,6 +429,7 @@ gst_mp3parse_sink_event (GstPad * pad, G
- event = gst_event_new_new_segment_full (update, rate, applied_rate,
- GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
- }
-+
- mp3parse->resyncing = TRUE;
- mp3parse->cur_offset = -1;
- mp3parse->next_ts = GST_CLOCK_TIME_NONE;
-@@ -379,12 +441,23 @@ gst_mp3parse_sink_event (GstPad * pad, G
- GST_DEBUG_OBJECT (mp3parse, "Pushing newseg rate %g, applied rate %g, "
- "format %d, start %lld, stop %lld, pos %lld\n",
- rate, applied_rate, format, start, stop, pos);
-- res = gst_pad_push_event (mp3parse->srcpad, event);
-+
-+ gst_segment_set_newsegment_full (&mp3parse->segment, update, rate,
-+ applied_rate, format, start, stop, pos);
-+
-+ /* save the segment for later, right before we push a new buffer so that
-+ * the caps are fixed and the next linked element can receive the segment. */
-+ eventp = &mp3parse->pending_segment;
-+ gst_event_replace (eventp, event);
-+ gst_event_unref (event);
-+ res = TRUE;
- break;
- }
- case GST_EVENT_FLUSH_STOP:
- /* Clear our adapter and set up for a new position */
- gst_adapter_clear (mp3parse->adapter);
-+ eventp = &mp3parse->pending_segment;
-+ gst_event_replace (eventp, NULL);
- res = gst_pad_push_event (mp3parse->srcpad, event);
- break;
- default:
-@@ -397,14 +470,26 @@ gst_mp3parse_sink_event (GstPad * pad, G
- return res;
- }
-
-+static MPEGAudioSeekEntry *
-+mp3parse_seek_table_last_entry (GstMPEGAudioParse * mp3parse)
-+{
-+ MPEGAudioSeekEntry *ret = NULL;
-+
-+ if (mp3parse->seek_table) {
-+ ret = mp3parse->seek_table->data;
-+ }
-+
-+ return ret;
-+}
-+
- /* Prepare a buffer of the indicated size, timestamp it and output */
- static GstFlowReturn
- gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size)
- {
- GstBuffer *outbuf;
- guint bitrate;
--
-- GST_DEBUG_OBJECT (mp3parse, "pushing buffer of %d bytes", size);
-+ GstFlowReturn ret = GST_FLOW_OK;
-+ GstClockTime push_start;
-
- outbuf = gst_adapter_take_buffer (mp3parse->adapter, size);
-
-@@ -456,6 +541,22 @@ gst_mp3parse_emit_frame (GstMPEGAudioPar
- }
- }
-
-+ if (GST_BUFFER_TIMESTAMP (outbuf) == 0)
-+ mp3parse->exact_position = TRUE;
-+
-+ if (mp3parse->exact_position && (!mp3parse->seek_table ||
-+ (mp3parse_seek_table_last_entry (mp3parse))->byte <
-+ GST_BUFFER_OFFSET (outbuf))) {
-+ MPEGAudioSeekEntry *entry = g_new0 (MPEGAudioSeekEntry, 1);
-+
-+ entry->byte = mp3parse->cur_offset;
-+ entry->timestamp = GST_BUFFER_TIMESTAMP (outbuf);
-+ mp3parse->seek_table = g_list_prepend (mp3parse->seek_table, entry);
-+ GST_DEBUG_OBJECT (mp3parse, "Adding index entry %" GST_TIME_FORMAT
-+ " @ offset 0x%08" G_GINT64_MODIFIER "x",
-+ GST_TIME_ARGS (entry->timestamp), entry->byte);
-+ }
-+
- /* Update our byte offset tracking */
- if (mp3parse->cur_offset != -1) {
- mp3parse->cur_offset += size;
-@@ -483,7 +584,53 @@ gst_mp3parse_emit_frame (GstMPEGAudioPar
- mp3parse->srcpad, taglist);
- }
-
-- return gst_pad_push (mp3parse->srcpad, outbuf);
-+ /* We start pushing 9 frames earlier (29 frames for MPEG2) than
-+ * segment start to be able to decode the first frame we want.
-+ * 9 (29) frames are the theoretical maximum of frames that contain
-+ * data for the current frame (bit reservoir).
-+ */
-+
-+ if (mp3parse->segment.start == 0) {
-+ push_start = 0;
-+ } else if (GST_CLOCK_TIME_IS_VALID (mp3parse->max_bitreservoir)) {
-+ if (mp3parse->segment.start > mp3parse->max_bitreservoir)
-+ push_start = mp3parse->segment.start - mp3parse->max_bitreservoir;
-+ else
-+ push_start = 0;
-+ } else {
-+ push_start = mp3parse->segment.start;
-+ }
-+
-+ if (G_UNLIKELY ((GST_CLOCK_TIME_IS_VALID (push_start) &&
-+ GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf)
-+ < push_start)
-+ || (GST_CLOCK_TIME_IS_VALID (mp3parse->segment.stop)
-+ && GST_BUFFER_TIMESTAMP (outbuf) >= mp3parse->segment.stop))) {
-+ GST_DEBUG_OBJECT (mp3parse,
-+ "Buffer outside of configured segment range %" GST_TIME_FORMAT
-+ " to %" GST_TIME_FORMAT ", dropping, timestamp %"
-+ GST_TIME_FORMAT ", offset 0x%08" G_GINT64_MODIFIER "x",
-+ GST_TIME_ARGS (push_start), GST_TIME_ARGS (mp3parse->segment.stop),
-+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
-+ GST_BUFFER_OFFSET (outbuf));
-+ gst_buffer_unref (outbuf);
-+ ret = GST_FLOW_OK;
-+ } else {
-+ GST_DEBUG_OBJECT (mp3parse,
-+ "pushing buffer of %d bytes, timestamp %" GST_TIME_FORMAT
-+ ", offset 0x%08" G_GINT64_MODIFIER "x", size,
-+ GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
-+ GST_BUFFER_OFFSET (outbuf));
-+ mp3parse->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuf);
-+ /* push any pending segment now */
-+ if (mp3parse->pending_segment) {
-+ gst_pad_push_event (mp3parse->srcpad, mp3parse->pending_segment);
-+ mp3parse->pending_segment = NULL;
-+ }
-+ ret = gst_pad_push (mp3parse->srcpad, outbuf);
-+ }
-+
-+ return ret;
- }
-
- #define XING_FRAMES_FLAG 0x0001
-@@ -610,14 +757,41 @@ gst_mp3parse_handle_first_frame (GstMPEG
- mp3parse->xing_bytes = 0;
-
- if (xing_flags & XING_TOC_FLAG) {
-- gint i;
-+ int i, percent = 0;
-+ guchar *table = mp3parse->xing_seek_table;
-+
-+ /* xing seek table: percent time -> 1/256 bytepos */
-+ memcpy (mp3parse->xing_seek_table, data, 100);
-
-- for (i = 0; i < 100; i++) {
-- mp3parse->xing_seek_table[i] = data[0];
-- data++;
-+ /* build inverse table: 1/256 bytepos -> 1/100 percent time */
-+ for (i = 0; i < 256; i++) {
-+ while (percent < 99 && table[percent + 1] <= i)
-+ percent++;
-+
-+ if (table[percent] == i) {
-+ mp3parse->xing_seek_table_inverse[i] = percent * 100;
-+ } else if (table[percent] < i && percent < 99) {
-+ gdouble fa, fb, fx;
-+ gint a = percent, b = percent + 1;
-+
-+ fa = table[a];
-+ fb = table[b];
-+ fx = (b - a) / (fb - fa) * (i - fa) + a;
-+ mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
-+ } else if (percent == 98 && table[percent + 1] <= i) {
-+ gdouble fa, fb, fx;
-+ gint a = percent + 1, b = 100;
-+
-+ fa = table[a];
-+ fb = 256.0;
-+ fx = (b - a) / (fb - fa) * (i - fa) + a;
-+ mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
-+ }
- }
-+ data += 100;
- } else {
- memset (mp3parse->xing_seek_table, 0, 100);
-+ memset (mp3parse->xing_seek_table_inverse, 0, 256);
- }
-
- if (xing_flags & XING_VBR_SCALE_FLAG) {
-@@ -777,6 +951,9 @@ gst_mp3parse_chain (GstPad * pad, GstBuf
- mp3parse->spf = 1152;
- }
-
-+ mp3parse->max_bitreservoir = gst_util_uint64_scale (GST_SECOND,
-+ ((version == 1) ? 10 : 30) * mp3parse->spf, mp3parse->rate);
-+
- /* Check the first frame for a Xing header to get our total length */
- if (mp3parse->frame_count == 0) {
- /* For the first frame in the file, look for a Xing frame after
-@@ -930,6 +1107,45 @@ gst_mp3parse_change_state (GstElement *
- return result;
- }
-
-+static gboolean
-+mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
-+{
-+ GstFormat fmt = GST_FORMAT_BYTES;
-+
-+ if (gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, total))
-+ return TRUE;
-+
-+ if (mp3parse->xing_flags & XING_BYTES_FLAG) {
-+ *total = mp3parse->xing_bytes;
-+ return TRUE;
-+ }
-+
-+ return FALSE;
-+}
-+
-+static gboolean
-+mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
-+{
-+ gint64 total_bytes;
-+
-+ *total = GST_CLOCK_TIME_NONE;
-+
-+ if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
-+ *total = mp3parse->xing_total_time;
-+ return TRUE;
-+ }
-+
-+ /* Calculate time from the measured bitrate */
-+ if (!mp3parse_total_bytes (mp3parse, &total_bytes))
-+ return FALSE;
-+
-+ if (total_bytes != -1
-+ && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total))
-+ return FALSE;
-+
-+ return TRUE;
-+}
-+
- /* Convert a timestamp to the file position required to start decoding that
- * timestamp. For now, this just uses the avg bitrate. Later, use an
- * incrementally accumulated seek table */
-@@ -937,12 +1153,38 @@ static gboolean
- mp3parse_time_to_bytepos (GstMPEGAudioParse * mp3parse, GstClockTime ts,
- gint64 * bytepos)
- {
-+ gint64 total_bytes;
-+ GstClockTime total_time;
-+
- /* -1 always maps to -1 */
- if (ts == -1) {
- *bytepos = -1;
- return TRUE;
- }
-
-+ /* If XING seek table exists use this for time->byte conversion */
-+ if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
-+ mp3parse_total_bytes (mp3parse, &total_bytes) &&
-+ mp3parse_total_time (mp3parse, &total_time)) {
-+ gdouble fa, fb, fx;
-+ gdouble percent =
-+ CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
-+ gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
-+ gint index = CLAMP (percent, 0, 99);
-+
-+ fa = mp3parse->xing_seek_table[index];
-+ if (index < 99)
-+ fb = mp3parse->xing_seek_table[index + 1];
-+ else
-+ fb = 256.0;
-+
-+ fx = fa + (fb - fa) * (percent - index);
-+
-+ *bytepos = (1.0 / 256.0) * fx * total_bytes;
-+
-+ return TRUE;
-+ }
-+
- if (mp3parse->avg_bitrate == 0)
- goto no_bitrate;
-
-@@ -958,6 +1200,9 @@ static gboolean
- mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
- gint64 bytepos, GstClockTime * ts)
- {
-+ gint64 total_bytes;
-+ GstClockTime total_time;
-+
- if (bytepos == -1) {
- *ts = GST_CLOCK_TIME_NONE;
- return TRUE;
-@@ -968,61 +1213,33 @@ mp3parse_bytepos_to_time (GstMPEGAudioPa
- return TRUE;
- }
-
-- /* Cannot convert anything except 0 if we don't have a bitrate yet */
-- if (mp3parse->avg_bitrate == 0)
-- return FALSE;
--
-- *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
-- mp3parse->avg_bitrate);
-- return TRUE;
--}
--
--static gboolean
--mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
--{
-- GstQuery *query;
-- GstPad *peer;
--
-- if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
-- query = gst_query_new_duration (GST_FORMAT_BYTES);
-- gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
--
-- if (gst_pad_query (peer, query)) {
-- gst_object_unref (peer);
-- gst_query_parse_duration (query, NULL, total);
-- return TRUE;
-- }
-- gst_object_unref (peer);
-- }
--
-- if (mp3parse->xing_flags & XING_BYTES_FLAG) {
-- *total = mp3parse->xing_bytes;
-- return TRUE;
-- }
--
-- return FALSE;
--}
-+ /* If XING seek table exists use this for byte->time conversion */
-+ if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
-+ mp3parse_total_bytes (mp3parse, &total_bytes) &&
-+ mp3parse_total_time (mp3parse, &total_time)) {
-+ gdouble fa, fb, fx;
-+ gdouble pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
-+ gint index = CLAMP (pos, 0, 255);
-+
-+ fa = mp3parse->xing_seek_table_inverse[index];
-+ if (index < 255)
-+ fb = mp3parse->xing_seek_table_inverse[index + 1];
-+ else
-+ fb = 10000.0;
-
--static gboolean
--mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
--{
-- gint64 total_bytes;
-+ fx = fa + (fb - fa) * (pos - index);
-
-- *total = GST_CLOCK_TIME_NONE;
-+ *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
-
-- if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
-- *total = mp3parse->xing_total_time;
- return TRUE;
- }
-
-- /* Calculate time from the measured bitrate */
-- if (!mp3parse_total_bytes (mp3parse, &total_bytes))
-- return FALSE;
--
-- if (total_bytes != -1
-- && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total))
-+ /* Cannot convert anything except 0 if we don't have a bitrate yet */
-+ if (mp3parse->avg_bitrate == 0)
- return FALSE;
-
-+ *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
-+ mp3parse->avg_bitrate);
- return TRUE;
- }
-
-@@ -1036,11 +1253,12 @@ mp3parse_handle_seek (GstMPEGAudioParse
- gint64 cur, stop;
- gint64 byte_cur, byte_stop;
-
-- /* FIXME: Use GstSegment for tracking our position */
--
- gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
- &stop_type, &stop);
-
-+ GST_DEBUG_OBJECT (mp3parse, "Performing seek to %" GST_TIME_FORMAT,
-+ GST_TIME_ARGS (cur));
-+
- /* For any format other than TIME, see if upstream handles
- * it directly or fail. For TIME, try upstream, but do it ourselves if
- * it fails upstream */
-@@ -1055,6 +1273,90 @@ mp3parse_handle_seek (GstMPEGAudioParse
-
- /* Handle TIME based seeks by converting to a BYTE position */
-
-+ /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames
-+ * before the one we want to seek to and push them all to the decoder.
-+ *
-+ * This is necessary because of the bit reservoir. See
-+ * http://www.mars.org/mailman/public/mad-dev/2002-May/000634.html
-+ *
-+ */
-+
-+ if (flags & GST_SEEK_FLAG_ACCURATE) {
-+ MPEGAudioPendingAccurateSeek *seek =
-+ g_new0 (MPEGAudioPendingAccurateSeek, 1);
-+ GstClockTime start;
-+
-+ seek->segment = mp3parse->segment;
-+
-+ gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME,
-+ flags, cur_type, cur, stop_type, stop, NULL);
-+
-+ if (!mp3parse->seek_table) {
-+ byte_cur = 0;
-+ byte_stop = -1;
-+ start = 0;
-+ } else {
-+ MPEGAudioSeekEntry *entry = NULL, *start_entry = NULL, *stop_entry = NULL;
-+ GList *start_node, *stop_node;
-+
-+ for (start_node = mp3parse->seek_table; start_node;
-+ start_node = start_node->next) {
-+ entry = start_node->data;
-+
-+ if (cur - mp3parse->max_bitreservoir >= entry->timestamp) {
-+ start_entry = entry;
-+ break;
-+ }
-+ }
-+
-+ if (!start_entry) {
-+ start_entry = mp3parse->seek_table->data;
-+ start = start_entry->timestamp;
-+ byte_cur = start_entry->byte;
-+ } else {
-+ start = start_entry->timestamp;
-+ byte_cur = start_entry->byte;
-+ }
-+
-+ for (stop_node = mp3parse->seek_table; stop_node;
-+ stop_node = stop_node->next) {
-+ entry = stop_node->data;
-+
-+ if (stop >= entry->timestamp) {
-+ stop_node = stop_node->prev;
-+ stop_entry = (stop_node) ? stop_node->data : NULL;
-+ break;
-+ }
-+ }
-+
-+ if (!stop_entry) {
-+ byte_stop = -1;
-+ } else {
-+ byte_stop = stop_entry->byte;
-+ }
-+
-+ }
-+ g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
-+ event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
-+ byte_cur, stop_type, byte_stop);
-+ if (gst_pad_push_event (mp3parse->sinkpad, event)) {
-+ mp3parse->exact_position = TRUE;
-+ seek->upstream_start = byte_cur;
-+ seek->timestamp_start = start;
-+ mp3parse->pending_accurate_seeks =
-+ g_slist_prepend (mp3parse->pending_accurate_seeks, seek);
-+ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
-+ return TRUE;
-+ } else {
-+ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
-+ mp3parse->exact_position = TRUE;
-+ g_free (seek);
-+ return TRUE;
-+ }
-+ }
-+
-+ mp3parse->exact_position = FALSE;
-+
- /* Convert the TIME to the appropriate BYTE position at which to resume
- * decoding. */
- if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) cur, &byte_cur))