summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuli Suominen <drac@gentoo.org>2007-11-18 20:19:26 +0000
committerSamuli Suominen <drac@gentoo.org>2007-11-18 20:19:26 +0000
commite4a48835ee6e39d17d37ce33ebb23c8409a9adb4 (patch)
tree8500b373da1949ceb7206b5bd882cdc2c61d04e7 /media-libs
parentadd a check for flac cxx use flag, FLAC++ is needed here (diff)
downloadgentoo-2-e4a48835ee6e39d17d37ce33ebb23c8409a9adb4.tar.gz
gentoo-2-e4a48835ee6e39d17d37ce33ebb23c8409a9adb4.tar.bz2
gentoo-2-e4a48835ee6e39d17d37ce33ebb23c8409a9adb4.zip
Update mpegaudioparse to CVS 20071117 to work with current core.
(Portage version: 2.1.3.19)
Diffstat (limited to 'media-libs')
-rw-r--r--media-libs/gst-plugins-ugly/ChangeLog9
-rw-r--r--media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r13
-rw-r--r--media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch794
-rw-r--r--media-libs/gst-plugins-ugly/gst-plugins-ugly-0.10.6-r1.ebuild64
4 files changed, 869 insertions, 1 deletions
diff --git a/media-libs/gst-plugins-ugly/ChangeLog b/media-libs/gst-plugins-ugly/ChangeLog
index b07c00f43647..63a0877bc720 100644
--- a/media-libs/gst-plugins-ugly/ChangeLog
+++ b/media-libs/gst-plugins-ugly/ChangeLog
@@ -1,6 +1,13 @@
# ChangeLog for media-libs/gst-plugins-ugly
# Copyright 1999-2007 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/media-libs/gst-plugins-ugly/ChangeLog,v 1.30 2007/10/11 14:54:34 corsair Exp $
+# $Header: /var/cvsroot/gentoo-x86/media-libs/gst-plugins-ugly/ChangeLog,v 1.31 2007/11/18 20:19:25 drac Exp $
+
+*gst-plugins-ugly-0.10.6-r1 (18 Nov 2007)
+
+ 18 Nov 2007; Samuli Suominen <drac@gentoo.org>
+ +files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch,
+ +gst-plugins-ugly-0.10.6-r1.ebuild:
+ Update mpegaudioparse to CVS 20071117 to work with current core.
11 Oct 2007; Markus Rothe <corsair@gentoo.org>
gst-plugins-ugly-0.10.6.ebuild:
diff --git a/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1 b/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1
new file mode 100644
index 000000000000..24b61c3cde29
--- /dev/null
+++ b/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1
@@ -0,0 +1,3 @@
+MD5 f1016148ecbfba968c0ef1773066988b gst-plugins-ugly-0.10.6.tar.bz2 773777
+RMD160 6f2ce61800e1013f8695b8e09a3f03beee1c9af8 gst-plugins-ugly-0.10.6.tar.bz2 773777
+SHA256 9c514d4002fb2a2efc5c60e009c330be2ee05c28649d73de3aa45530161c2c62 gst-plugins-ugly-0.10.6.tar.bz2 773777
diff --git a/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch b/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
new file mode 100644
index 000000000000..28077b22298b
--- /dev/null
+++ b/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
@@ -0,0 +1,794 @@
+Index: gst/mpegaudioparse/gstmpegaudioparse.c
+===================================================================
+RCS file: /cvs/gstreamer/gst-plugins-ugly/gst/mpegaudioparse/gstmpegaudioparse.c,v
+retrieving revision 1.62
+retrieving revision 1.74
+diff -u -r1.62 -r1.74
+--- gst/mpegaudioparse/gstmpegaudioparse.c 8 Jun 2007 08:39:43 -0000 1.62
++++ gst/mpegaudioparse/gstmpegaudioparse.c 30 Oct 2007 12:27:32 -0000 1.74
+@@ -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 @@
+
+
+ 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,33 +97,9 @@
+ 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,
+- };
+-
+- mp3parse_type = g_type_register_static (GST_TYPE_ELEMENT,
+- "GstMPEGAudioParse", &mp3parse_info, 0);
+- }
+- return mp3parse_type;
+-}
++GST_BOILERPLATE (GstMPEGAudioParse, gst_mp3parse, GstElement, GST_TYPE_ELEMENT);
+
+ static guint mp3types_bitrates[2][3][16] = {
+ {
+@@ -218,13 +196,14 @@
+ 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 @@
+ {
+ 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 @@
+
+ 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,34 @@
+
+ mp3parse->xing_flags = 0;
+ mp3parse->xing_bitrate = 0;
++
++ if (mp3parse->seek_table) {
++ g_list_foreach (mp3parse->seek_table, (GFunc) g_free, NULL);
++ 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);
++ mp3parse->pending_accurate_seeks = NULL;
++ }
++ g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
++
++ 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 +300,7 @@
+ 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 +310,14 @@
+ {
+ 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 +327,7 @@
+ {
+ gboolean res;
+ GstMPEGAudioParse *mp3parse;
++ GstEvent **eventp;
+
+ mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
+
+@@ -343,6 +342,64 @@
+ 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);
++ if (s->flags & GST_SEEK_FLAG_SEGMENT) {
++ gst_element_post_message (GST_ELEMENT_CAST (mp3parse),
++ gst_message_new_segment_start (GST_OBJECT_CAST (mp3parse),
++ s->format, s->last_stop));
++ }
++ 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 +413,9 @@
+ 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));
+ }
+ }
+
+@@ -379,12 +437,22 @@
+ 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);
++ 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 +465,26 @@
+ 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 +536,22 @@
+ }
+ }
+
++ 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 +579,52 @@
+ 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 +751,41 @@
+ 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 +945,9 @@
+ 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 +1101,45 @@
+ 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 +1147,38 @@
+ 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 +1194,9 @@
+ 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 +1207,33 @@
+ 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 +1247,12 @@
+ 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 +1267,90 @@
+
+ /* 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))
+@@ -1069,6 +1365,11 @@
+ event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
+ byte_cur, stop_type, byte_stop);
+
++ if (flags & GST_SEEK_FLAG_SEGMENT) {
++ gst_element_post_message (GST_ELEMENT_CAST (mp3parse),
++ gst_message_new_segment_start (GST_OBJECT_CAST (mp3parse),
++ GST_FORMAT_TIME, cur));
++ }
+ return gst_pad_push_event (mp3parse->sinkpad, event);
+ no_pos:
+ GST_DEBUG_OBJECT (mp3parse,
+Index: gst/mpegaudioparse/gstmpegaudioparse.h
+===================================================================
+RCS file: /cvs/gstreamer/gst-plugins-ugly/gst/mpegaudioparse/gstmpegaudioparse.h,v
+retrieving revision 1.16
+retrieving revision 1.20
+diff -u -r1.16 -r1.20
+--- gst/mpegaudioparse/gstmpegaudioparse.h 8 Jun 2007 08:39:43 -0000 1.16
++++ gst/mpegaudioparse/gstmpegaudioparse.h 16 Aug 2007 11:52:57 -0000 1.20
+@@ -40,13 +40,29 @@
+
+ typedef struct _GstMPEGAudioParse GstMPEGAudioParse;
+ typedef struct _GstMPEGAudioParseClass GstMPEGAudioParseClass;
++typedef struct _MPEGAudioSeekEntry MPEGAudioSeekEntry;
++typedef struct _MPEGAudioPendingAccurateSeek MPEGAudioPendingAccurateSeek;
++
++
++struct _MPEGAudioSeekEntry {
++ gint64 byte;
++ GstClockTime timestamp;
++};
++
++struct _MPEGAudioPendingAccurateSeek {
++ GstSegment segment;
++ gint64 upstream_start;
++ GstClockTime timestamp_start;
++};
+
+ struct _GstMPEGAudioParse {
+ GstElement element;
+
+ GstPad *sinkpad, *srcpad;
+
++ GstSegment segment;
+ GstClockTime next_ts;
++
+ /* Offset as supplied by incoming buffers */
+ gint64 cur_offset;
+
+@@ -62,6 +78,7 @@
+ guint skip; /* number of frames to skip */
+ guint bit_rate; /* in kbps */
+ gint channels, rate, layer, version;
++ GstClockTime max_bitreservoir;
+ gint spf; /* Samples per frame */
+
+ gboolean resyncing; /* True when attempting to resync (stricter checks are
+@@ -79,9 +96,21 @@
+ guint32 xing_frames;
+ GstClockTime xing_total_time;
+ guint32 xing_bytes;
++ /* percent -> filepos mapping */
+ guchar xing_seek_table[100];
++ /* filepos -> percent mapping */
++ guint16 xing_seek_table_inverse[256];
+ guint32 xing_vbr_scale;
+ guint xing_bitrate;
++
++ /* Accurate seeking */
++ GList *seek_table;
++ GMutex *pending_accurate_seeks_lock;
++ GSList *pending_accurate_seeks;
++ gboolean exact_position;
++
++ /* pending segment */
++ GstEvent *pending_segment;
+ };
+
+ struct _GstMPEGAudioParseClass {
diff --git a/media-libs/gst-plugins-ugly/gst-plugins-ugly-0.10.6-r1.ebuild b/media-libs/gst-plugins-ugly/gst-plugins-ugly-0.10.6-r1.ebuild
new file mode 100644
index 000000000000..f934289b3ee6
--- /dev/null
+++ b/media-libs/gst-plugins-ugly/gst-plugins-ugly-0.10.6-r1.ebuild
@@ -0,0 +1,64 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/media-libs/gst-plugins-ugly/gst-plugins-ugly-0.10.6-r1.ebuild,v 1.1 2007/11/18 20:19:25 drac Exp $
+
+# order is important, gnome2 after gst-plugins
+inherit gst-plugins-ugly gst-plugins10 gnome2 eutils flag-o-matic libtool
+
+DESCRIPTION="Basepack of plugins for gstreamer"
+HOMEPAGE="http://gstreamer.sourceforge.net"
+SRC_URI="http://gstreamer.freedesktop.org/src/${PN}/${P}.tar.bz2"
+
+LICENSE="GPL-2"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+RDEPEND=">=media-libs/gst-plugins-base-0.10.15
+ >=media-libs/gstreamer-0.10.15
+ >=dev-libs/liboil-0.3
+ >=dev-libs/glib-2.6"
+DEPEND="${RDEPEND}
+ >=sys-devel/gettext-0.11.5
+ >=dev-util/pkgconfig-0.9"
+
+GST_PLUGINS_BUILD=""
+
+src_unpack() {
+ unpack ${A}
+ cd "${S}"
+ epatch "${FILESDIR}"/${P}-mpegaudioparse-cvs20071117.patch
+}
+
+src_compile() {
+ elibtoolize
+
+ # gst doesnt handle optimisations well
+ strip-flags
+ replace-flags "-O3" "-O2"
+ filter-flags "-fprefetch-loop-arrays" # see bug 22249
+
+ gst-plugins-ugly_src_configure
+
+ emake || die "emake failed."
+}
+
+# override eclass
+src_install() {
+ gnome2_src_install
+}
+
+DOCS="AUTHORS README RELEASE"
+
+pkg_postinst () {
+ gnome2_pkg_postinst
+
+ elog "The Gstreamer plugins setup has changed quite a bit on Gentoo,"
+ elog "applications now should provide the basic plugins needed."
+ elog ""
+ elog "The new seperate plugins are all named 'gst-plugins-<plugin>'."
+ elog "To get a listing of currently available plugins execute 'emerge -s gst-plugins-'."
+ elog "In most cases it shouldn't be needed though to emerge extra plugins."
+}
+
+pkg_postrm() {
+ gnome2_pkg_postrm
+}