diff options
author | Thiago Santos <thiago.sousa.santos@collabora.co.uk> | 2009-12-08 19:55:04 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.co.uk> | 2010-01-04 10:01:44 -0300 |
commit | 5e3f07b6a1b259cd3c73fa7fe6e3a3110ae3e3ce (patch) | |
tree | 76e084092976430bc38f1303cbbda2b63990b5aa | |
parent | 6c05222326525c59b81831cce8a11d9dd179bb62 (diff) |
mp3parse: conserve stop time for non-accurate seek
Use the same strategy as accurate seeks to store
pending non-accurate seeks to avoid overwriting non-definite
stop times. When doing non-accurate seeks our position
reporting might drift off by some secs and the stream can
end up before it should.
Fixes #603695
-rw-r--r-- | gst/mpegaudioparse/gstmpegaudioparse.c | 96 | ||||
-rw-r--r-- | gst/mpegaudioparse/gstmpegaudioparse.h | 4 |
2 files changed, 75 insertions, 25 deletions
diff --git a/gst/mpegaudioparse/gstmpegaudioparse.c b/gst/mpegaudioparse/gstmpegaudioparse.c index b5602f17..8f5996e3 100644 --- a/gst/mpegaudioparse/gstmpegaudioparse.c +++ b/gst/mpegaudioparse/gstmpegaudioparse.c @@ -388,13 +388,18 @@ gst_mp3parse_reset (GstMPEGAudioParse * mp3parse) mp3parse->seek_table = NULL; } - g_mutex_lock (mp3parse->pending_accurate_seeks_lock); + g_mutex_lock (mp3parse->pending_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_nonaccurate_seeks) { + g_slist_foreach (mp3parse->pending_nonaccurate_seeks, (GFunc) g_free, NULL); + g_slist_free (mp3parse->pending_nonaccurate_seeks); + mp3parse->pending_nonaccurate_seeks = NULL; + } + g_mutex_unlock (mp3parse->pending_seeks_lock); if (mp3parse->pending_segment) { GstEvent **eventp = &mp3parse->pending_segment; @@ -424,7 +429,7 @@ gst_mp3parse_init (GstMPEGAudioParse * mp3parse, GstMPEGAudioParseClass * klass) gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->srcpad); mp3parse->adapter = gst_adapter_new (); - mp3parse->pending_accurate_seeks_lock = g_mutex_new (); + mp3parse->pending_seeks_lock = g_mutex_new (); gst_mp3parse_reset (mp3parse); } @@ -440,8 +445,8 @@ gst_mp3parse_dispose (GObject * object) g_object_unref (mp3parse->adapter); mp3parse->adapter = NULL; } - g_mutex_free (mp3parse->pending_accurate_seeks_lock); - mp3parse->pending_accurate_seeks_lock = NULL; + g_mutex_free (mp3parse->pending_seeks_lock); + mp3parse->pending_seeks_lock = NULL; g_list_foreach (mp3parse->pending_events, (GFunc) gst_mini_object_unref, NULL); @@ -467,14 +472,14 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event) GstFormat format; gint64 start, stop, pos; gboolean update; + MPEGAudioPendingAccurateSeek *seek = NULL; + GSList *node; gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &format, &start, &stop, &pos); - g_mutex_lock (mp3parse->pending_accurate_seeks_lock); + g_mutex_lock (mp3parse->pending_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; @@ -513,7 +518,7 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event) mp3parse->pending_accurate_seeks = g_slist_delete_link (mp3parse->pending_accurate_seeks, node); - g_mutex_unlock (mp3parse->pending_accurate_seeks_lock); + g_mutex_unlock (mp3parse->pending_seeks_lock); res = gst_pad_push_event (mp3parse->srcpad, event); return res; @@ -522,7 +527,7 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event) "Accurate seek not possible, didn't get an appropiate upstream segment"); } } - g_mutex_unlock (mp3parse->pending_accurate_seeks_lock); + g_mutex_unlock (mp3parse->pending_seeks_lock); mp3parse->exact_position = FALSE; @@ -535,6 +540,32 @@ gst_mp3parse_sink_event (GstPad * pad, GstEvent * event) if (mp3parse_bytepos_to_time (mp3parse, start, &seg_start, FALSE) && mp3parse_bytepos_to_time (mp3parse, pos, &seg_pos, FALSE)) { gst_event_unref (event); + + /* search the pending nonaccurate seeks */ + g_mutex_lock (mp3parse->pending_seeks_lock); + seek = NULL; + for (node = mp3parse->pending_nonaccurate_seeks; node; + node = node->next) { + MPEGAudioPendingAccurateSeek *tmp = node->data; + + if (tmp->upstream_start == pos) { + seek = tmp; + break; + } + } + + if (seek) { + if (seek->segment.stop == -1) { + /* corrent the segment end, because non-accurate seeks might make + * our streaming end earlier (see bug #603695) */ + seg_stop = -1; + } + g_free (seek); + mp3parse->pending_nonaccurate_seeks = + g_slist_delete_link (mp3parse->pending_nonaccurate_seeks, node); + } + g_mutex_unlock (mp3parse->pending_seeks_lock); + event = gst_event_new_new_segment_full (update, rate, applied_rate, GST_FORMAT_TIME, seg_start, seg_stop, seg_pos); format = GST_FORMAT_TIME; @@ -1869,6 +1900,8 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event) GstSeekType cur_type, stop_type; gint64 cur, stop; gint64 byte_cur, byte_stop; + MPEGAudioPendingAccurateSeek *seek; + GstClockTime start; gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); @@ -1888,6 +1921,13 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event) return TRUE; } + seek = g_new0 (MPEGAudioPendingAccurateSeek, 1); + + seek->segment = mp3parse->segment; + + gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME, + flags, cur_type, cur, stop_type, stop, NULL); + /* Handle TIME based seeks by converting to a BYTE position */ /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames @@ -1899,15 +1939,6 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event) */ 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; @@ -1957,21 +1988,21 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event) } event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur, stop_type, byte_stop); - g_mutex_lock (mp3parse->pending_accurate_seeks_lock); + g_mutex_lock (mp3parse->pending_seeks_lock); 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); + g_mutex_unlock (mp3parse->pending_seeks_lock); if (gst_pad_push_event (mp3parse->sinkpad, event)) { mp3parse->exact_position = TRUE; return TRUE; } else { mp3parse->exact_position = TRUE; - g_mutex_lock (mp3parse->pending_accurate_seeks_lock); + g_mutex_lock (mp3parse->pending_seeks_lock); mp3parse->pending_accurate_seeks = g_slist_remove (mp3parse->pending_accurate_seeks, seek); - g_mutex_unlock (mp3parse->pending_accurate_seeks_lock); + g_mutex_unlock (mp3parse->pending_seeks_lock); g_free (seek); return FALSE; } @@ -1993,7 +2024,24 @@ mp3parse_handle_seek (GstMPEGAudioParse * mp3parse, GstEvent * event) event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur, stop_type, byte_stop); - return gst_pad_push_event (mp3parse->sinkpad, event); + GST_LOG_OBJECT (mp3parse, "Storing pending seek"); + g_mutex_lock (mp3parse->pending_seeks_lock); + seek->upstream_start = byte_cur; + seek->timestamp_start = cur; + mp3parse->pending_nonaccurate_seeks = + g_slist_prepend (mp3parse->pending_nonaccurate_seeks, seek); + g_mutex_unlock (mp3parse->pending_seeks_lock); + if (gst_pad_push_event (mp3parse->sinkpad, event)) { + return TRUE; + } else { + g_mutex_lock (mp3parse->pending_seeks_lock); + mp3parse->pending_nonaccurate_seeks = + g_slist_remove (mp3parse->pending_nonaccurate_seeks, seek); + g_mutex_unlock (mp3parse->pending_seeks_lock); + g_free (seek); + return FALSE; + } + no_pos: GST_DEBUG_OBJECT (mp3parse, "Could not determine byte position for desired time"); diff --git a/gst/mpegaudioparse/gstmpegaudioparse.h b/gst/mpegaudioparse/gstmpegaudioparse.h index c5e48cdc..abadf724 100644 --- a/gst/mpegaudioparse/gstmpegaudioparse.h +++ b/gst/mpegaudioparse/gstmpegaudioparse.h @@ -118,10 +118,12 @@ struct _GstMPEGAudioParse { /* Accurate seeking */ GList *seek_table; - GMutex *pending_accurate_seeks_lock; + GMutex *pending_seeks_lock; GSList *pending_accurate_seeks; gboolean exact_position; + GSList *pending_nonaccurate_seeks; + /* Track whether we're seekable (in BYTES format, if upstream operates in * TIME format, we don't care about seekability and assume upstream handles * it). The seek table for accurate seeking is not maintained if we're not |