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.
This commit is contained in:
Mark Nauwelaerts 2016-12-29 11:26:33 +01:00
parent 3362dceb25
commit 494f4beb40

View file

@ -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. */