summaryrefslogtreecommitdiff
path: root/libavformat/subtitles.c
diff options
context:
space:
mode:
authorClément Bœsch <u@pkh.me>2013-09-08 12:36:57 +0200
committerClément Bœsch <u@pkh.me>2013-09-08 12:54:49 +0200
commitb1319e14e3b068045a9147244f3edd5863abe6fd (patch)
treeaca5067aadae758a07d4b4b086cc826cee035208 /libavformat/subtitles.c
parent1ca4bf930bab681a79fb591330043675c7cfd798 (diff)
avformat/subtitles: binary search seeking.
Diffstat (limited to 'libavformat/subtitles.c')
-rw-r--r--libavformat/subtitles.c50
1 files changed, 36 insertions, 14 deletions
diff --git a/libavformat/subtitles.c b/libavformat/subtitles.c
index b796f4062c..d4607970ac 100644
--- a/libavformat/subtitles.c
+++ b/libavformat/subtitles.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Clément Bœsch
+ * Copyright (c) 2012-2013 Clément Bœsch <u pkh me>
*
* This file is part of FFmpeg.
*
@@ -94,6 +94,28 @@ int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt)
return 0;
}
+static int search_sub_ts(const FFDemuxSubtitlesQueue *q, int64_t ts)
+{
+ int s1 = 0, s2 = q->nb_subs - 1;
+
+ if (s2 < s1)
+ return AVERROR(ERANGE);
+
+ for (;;) {
+ int mid;
+
+ if (s1 == s2)
+ return s1;
+ if (s1 == s2 - 1)
+ return q->subs[s1].pts <= q->subs[s2].pts ? s1 : s2;
+ mid = (s1 + s2) / 2;
+ if (q->subs[mid].pts <= ts)
+ s1 = mid;
+ else
+ s2 = mid;
+ }
+}
+
int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int stream_index,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{
@@ -104,23 +126,23 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st
return AVERROR(ERANGE);
q->current_sub_idx = ts;
} else {
- int i, idx = -1;
- int64_t min_ts_diff = INT64_MAX;
+ int i, idx = search_sub_ts(q, ts);
int64_t ts_selected;
- /* TODO: q->subs[] is sorted by pts so we could do a binary search */
- for (i = 0; i < q->nb_subs; i++) {
- int64_t pts = q->subs[i].pts;
- uint64_t ts_diff = FFABS(pts - ts);
- if ((stream_index == -1 || q->subs[i].stream_index == stream_index) &&
- pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) {
- min_ts_diff = ts_diff;
- idx = i;
- }
- }
+
if (idx < 0)
+ return idx;
+ for (i = idx; i < q->nb_subs && q->subs[i].pts < min_ts; i++)
+ if (stream_index == -1 || q->subs[i].stream_index == stream_index)
+ idx = i;
+ for (i = idx; i > 0 && q->subs[i].pts > max_ts; i--)
+ if (stream_index == -1 || q->subs[i].stream_index == stream_index)
+ idx = i;
+
+ ts_selected = q->subs[idx].pts;
+ if (ts_selected < min_ts || ts_selected > max_ts)
return AVERROR(ERANGE);
+
/* look back in the latest subtitles for overlapping subtitles */
- ts_selected = q->subs[idx].pts;
for (i = idx - 1; i >= 0; i--) {
int64_t pts = q->subs[i].pts;
if (q->subs[i].duration <= 0 ||