matroska: implement forward snapping keyframe seeking

Requires an index.
This commit is contained in:
Vincent Penquerc'h 2012-04-26 12:47:27 +01:00
parent cfd0da4146
commit 93ce50f9b9
4 changed files with 26 additions and 15 deletions

View file

@ -1925,7 +1925,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
GstFormat format;
gboolean flush, keyunit;
gboolean flush, keyunit, before, after, snap_next;
gdouble rate;
gint64 cur, stop;
GstMatroskaTrackContext *track = NULL;
@ -1975,8 +1975,10 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
* would be determined again when parsing, but anyway ... */
seeksegment.duration = demux->common.segment.duration;
flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT);
flush = !!(flags & GST_SEEK_FLAG_FLUSH);
keyunit = !!(flags & GST_SEEK_FLAG_KEY_UNIT);
after = !!(flags & GST_SEEK_FLAG_SNAP_AFTER);
before = !!(flags & GST_SEEK_FLAG_SNAP_BEFORE);
GST_DEBUG_OBJECT (demux, "New segment %" GST_SEGMENT_FORMAT, &seeksegment);
@ -1989,11 +1991,14 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux,
}
/* check sanity before we start flushing and all that */
snap_next = after && !before;
if (seeksegment.rate < 0)
snap_next = !snap_next;
GST_OBJECT_LOCK (demux);
track = gst_matroska_read_common_get_seek_track (&demux->common, track);
if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, track,
seeksegment.position, &demux->seek_index, &demux->seek_entry)) ==
NULL) {
seeksegment.position, &demux->seek_index, &demux->seek_entry,
snap_next)) == NULL) {
/* pull mode without index can scan later on */
if (demux->streaming) {
GST_DEBUG_OBJECT (demux, "No matching seek entry in index");
@ -2053,8 +2058,9 @@ next:
}
if (keyunit) {
GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %"
GST_TIME_FORMAT, GST_TIME_ARGS (entry->time));
GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start from %"
GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (entry->time));
seeksegment.start = MAX (entry->time, demux->stream_start_time);
seeksegment.position = seeksegment.start;
seeksegment.time = seeksegment.start - demux->stream_start_time;

View file

@ -1364,8 +1364,8 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
/* check sanity before we start flushing and all that */
GST_OBJECT_LOCK (parse);
if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track,
seeksegment.position, &parse->seek_index, &parse->seek_entry)) ==
NULL) {
seeksegment.position, &parse->seek_index, &parse->seek_entry,
FALSE)) == NULL) {
/* pull mode without index can scan later on */
GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
GST_OBJECT_UNLOCK (parse);

View file

@ -365,7 +365,7 @@ gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
GstMatroskaIndex *
gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
GstMatroskaTrackContext * track, gint64 seek_pos, GArray ** _index,
gint * _entry_index)
gint * _entry_index, gboolean next)
{
GstMatroskaIndex *entry = NULL;
GArray *index;
@ -382,11 +382,16 @@ gst_matroska_read_common_do_index_seek (GstMatroskaReadCommon * common,
entry =
gst_util_array_binary_search (index->data, index->len,
sizeof (GstMatroskaIndex),
(GCompareDataFunc) gst_matroska_index_seek_find, GST_SEARCH_MODE_BEFORE,
&seek_pos, NULL);
(GCompareDataFunc) gst_matroska_index_seek_find,
next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &seek_pos, NULL);
if (entry == NULL)
entry = &g_array_index (index, GstMatroskaIndex, 0);
if (entry == NULL) {
if (next) {
return NULL;
} else {
entry = &g_array_index (index, GstMatroskaIndex, 0);
}
}
if (_index)
*_index = index;

View file

@ -106,7 +106,7 @@ gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
gpointer user_data);
GstMatroskaIndex * gst_matroska_read_common_do_index_seek (
GstMatroskaReadCommon * common, GstMatroskaTrackContext * track, gint64
seek_pos, GArray ** _index, gint * _entry_index);
seek_pos, GArray ** _index, gint * _entry_index, gboolean next);
void gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
GstElement * el, GstTagList * taglist);
gint64 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common);