* [gentoo-commits] gentoo-x86 commit in media-libs/gst-plugins-ugly/files: gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch digest-gst-plugins-ugly-0.10.6-r1
@ 2007-11-18 20:19 Samuli Suominen (drac)
0 siblings, 0 replies; only message in thread
From: Samuli Suominen (drac) @ 2007-11-18 20:19 UTC (permalink / raw
To: gentoo-commits
drac 07/11/18 20:19:26
Added:
gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
digest-gst-plugins-ugly-0.10.6-r1
Log:
Update mpegaudioparse to CVS 20071117 to work with current core.
(Portage version: 2.1.3.19)
Revision Changes Path
1.1 media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch?rev=1.1&content-type=text/plain
Index: gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
===================================================================
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 {
1.1 media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1
file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1?rev=1.1&content-type=text/plain
Index: digest-gst-plugins-ugly-0.10.6-r1
===================================================================
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
--
gentoo-commits@gentoo.org mailing list
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-11-18 20:19 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-18 20:19 [gentoo-commits] gentoo-x86 commit in media-libs/gst-plugins-ugly/files: gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch digest-gst-plugins-ugly-0.10.6-r1 Samuli Suominen (drac)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox