From ff3624b1ad9dc4374c9adf7ba65ac3ed6d05c0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Fri, 23 Nov 2012 21:40:46 +0100 Subject: [PATCH] lavf/subtitles: add ff_subtitles_queue_seek(). This function is almost identical to lavf/assdec:read_seek2(). It performs a generic seek for text subtitles demuxers for the new seeking API. The only difference with assdec:read_seek2 is the ts_diff being unsigned to avoid overflows. The seek callback in the ASS demuxer will be removed when it is redesigned to use FFDemuxSubtitlesQueue. --- libavformat/subtitles.c | 38 ++++++++++++++++++++++++++++++++++++++ libavformat/subtitles.h | 7 +++++++ 2 files changed, 45 insertions(+) diff --git a/libavformat/subtitles.c b/libavformat/subtitles.c index 12045262eb..290eaa02aa 100644 --- a/libavformat/subtitles.c +++ b/libavformat/subtitles.c @@ -91,6 +91,44 @@ int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt) return 0; } +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) +{ + if (flags & AVSEEK_FLAG_BYTE) { + return AVERROR(ENOSYS); + } else if (flags & AVSEEK_FLAG_FRAME) { + if (ts < 0 || ts >= q->nb_subs) + return AVERROR(ERANGE); + q->current_sub_idx = ts; + } else { + int i, idx = -1; + int64_t min_ts_diff = INT64_MAX; + if (stream_index == -1) { + AVRational time_base = s->streams[0]->time_base; + ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base); + min_ts = av_rescale_rnd(min_ts, time_base.den, + time_base.num * (int64_t)AV_TIME_BASE, + AV_ROUND_UP); + max_ts = av_rescale_rnd(max_ts, time_base.den, + time_base.num * (int64_t)AV_TIME_BASE, + AV_ROUND_DOWN); + } + /* 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 (pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) { + min_ts_diff = ts_diff; + idx = i; + } + } + if (idx < 0) + return AVERROR(ERANGE); + q->current_sub_idx = idx; + } + return 0; +} + void ff_subtitles_queue_clean(FFDemuxSubtitlesQueue *q) { int i; diff --git a/libavformat/subtitles.h b/libavformat/subtitles.h index b089bb2a87..55e6182922 100644 --- a/libavformat/subtitles.h +++ b/libavformat/subtitles.h @@ -54,6 +54,13 @@ void ff_subtitles_queue_finalize(FFDemuxSubtitlesQueue *q); */ int ff_subtitles_queue_read_packet(FFDemuxSubtitlesQueue *q, AVPacket *pkt); +/** + * Update current_sub_idx to emulate a seek. Except the first parameter, it + * matches AVInputFormat->read_seek2 prototypes. + */ +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); + /** * Remove and destroy all the subtitles packets. */