From 494f4beb408411cf9341e06263d7fb5b3eaa3de0 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 29 Dec 2016 11:26:33 +0100 Subject: [PATCH] avidemux: tweak KEY_UNIT SNAP seek handling Previously, seeking to position y where y is (strictly) within a keyframe would seek to that keyframe both with SNAP_BEFORE and SNAP_AFTER, where the latter is now adjusted to really snap to the next keyframe. --- gst/avi/gstavidemux.c | 52 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/gst/avi/gstavidemux.c b/gst/avi/gstavidemux.c index 3964163..bd5ea72 100644 --- a/gst/avi/gstavidemux.c +++ b/gst/avi/gstavidemux.c @@ -72,8 +72,8 @@ static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", #ifndef GST_DISABLE_GST_DEBUG static const char *const snap_types[2][2] = { - {"any", "before"}, - {"after", "nearest"}, + {"any", "after"}, + {"before", "nearest"}, }; #endif @@ -2608,8 +2608,9 @@ gst_avi_demux_index_entry_search (GstAviIndexEntry * entry, guint64 * total) * @avi: Avi object * @stream: the stream * @time: a time position + * @next: whether to look for entry before or after @time * - * Finds the index entry which time is less or equal than the requested time. + * Finds the index entry which time is less/more or equal than the requested time. * Try to avoid binary search when we can convert the time to an index * position directly (for example for video frames with a fixed duration). * @@ -2617,7 +2618,7 @@ gst_avi_demux_index_entry_search (GstAviIndexEntry * entry, guint64 * total) */ static guint gst_avi_demux_index_for_time (GstAviDemux * avi, - GstAviStream * stream, guint64 time) + GstAviStream * stream, guint64 time, gboolean next) { guint index = -1; guint64 total; @@ -2638,6 +2639,14 @@ gst_avi_demux_index_for_time (GstAviDemux * avi, total = avi_stream_convert_time_to_frames_unchecked (stream, time); } else { index = avi_stream_convert_time_to_frames_unchecked (stream, time); + /* this entry typically undershoots the target time, + * so check a bit more if next needed */ + if (next) { + GstClockTime itime = + avi_stream_convert_frames_to_time_unchecked (stream, index); + if (itime < time && index + 1 < stream->idx_n) + index++; + } } } else if (stream->strh->type == GST_RIFF_FCC_auds) { /* constant rate stream */ @@ -2655,7 +2664,7 @@ gst_avi_demux_index_for_time (GstAviDemux * avi, entry = gst_util_array_binary_search (stream->index, stream->idx_n, sizeof (GstAviIndexEntry), (GCompareDataFunc) gst_avi_demux_index_entry_search, - GST_SEARCH_MODE_BEFORE, &total, NULL); + next ? GST_SEARCH_MODE_AFTER : GST_SEARCH_MODE_BEFORE, &total, NULL); if (entry == NULL) { GST_LOG_OBJECT (avi, "not found, assume index 0"); @@ -4447,6 +4456,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment, gboolean keyframe, before, after; guint i, index; GstAviStream *stream; + gboolean next; seek_time = segment->position; keyframe = ! !(flags & GST_SEEK_FLAG_KEY_UNIT); @@ -4461,20 +4471,18 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment, * which is mostly correct... */ stream = &avi->stream[avi->main_stream]; + next = after && !before; + if (segment->rate < 0) + next = !next; + /* get the entry index for the requested position */ - index = gst_avi_demux_index_for_time (avi, stream, seek_time); + index = gst_avi_demux_index_for_time (avi, stream, seek_time, next); GST_DEBUG_OBJECT (avi, "Got entry %u", index); if (index == -1) return FALSE; /* check if we are already on a keyframe */ if (!ENTRY_IS_KEYFRAME (&stream->index[index])) { - gboolean next; - - next = after && !before; - if (segment->rate < 0) - next = !next; - if (next) { GST_DEBUG_OBJECT (avi, "not keyframe, searching forward"); /* now go to the next keyframe, this is where we should start @@ -4518,7 +4526,7 @@ gst_avi_demux_do_seek (GstAviDemux * avi, GstSegment * segment, continue; /* get the entry index for the requested position */ - index = gst_avi_demux_index_for_time (avi, ostream, seek_time); + index = gst_avi_demux_index_for_time (avi, ostream, seek_time, FALSE); if (index == -1) continue; @@ -4686,7 +4694,7 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) GstSeekFlags flags; GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type; gint64 cur, stop; - gboolean keyframe, before, after; + gboolean keyframe, before, after, next; GstAviStream *stream; guint index; guint n, str_num; @@ -4746,8 +4754,12 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) str_num = avi->main_stream; stream = &avi->stream[str_num]; + next = after && !before; + if (seeksegment.rate < 0) + next = !next; + /* get the entry index for the requested position */ - index = gst_avi_demux_index_for_time (avi, stream, cur); + index = gst_avi_demux_index_for_time (avi, stream, cur, next); GST_DEBUG_OBJECT (avi, "str %u: Found entry %u for %" GST_TIME_FORMAT, str_num, index, GST_TIME_ARGS (cur)); if (index == -1) @@ -4755,12 +4767,6 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) /* check if we are already on a keyframe */ if (!ENTRY_IS_KEYFRAME (&stream->index[index])) { - gboolean next; - - next = after && !before; - if (seeksegment.rate < 0) - next = !next; - if (next) { GST_DEBUG_OBJECT (avi, "Entry is not a keyframe - searching forward"); /* now go to the next keyframe, this is where we should start @@ -4799,7 +4805,7 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) continue; /* get the entry index for the requested position */ - idx = gst_avi_demux_index_for_time (avi, str, cur); + idx = gst_avi_demux_index_for_time (avi, str, cur, FALSE); GST_DEBUG_OBJECT (avi, "str %u: Found entry %u for %" GST_TIME_FORMAT, n, idx, GST_TIME_ARGS (cur)); if (idx == -1) @@ -4807,7 +4813,7 @@ avi_demux_handle_seek_push (GstAviDemux * avi, GstPad * pad, GstEvent * event) /* check if we are already on a keyframe */ if (!ENTRY_IS_KEYFRAME (&str->index[idx])) { - if (after && !before) { + if (next) { GST_DEBUG_OBJECT (avi, "Entry is not a keyframe - searching forward"); /* now go to the next keyframe, this is where we should start * decoding from. */ -- 2.7.4