Commit f8678dce authored by Clément Bœsch's avatar Clément Bœsch

avformat/vobsub: fix seeking.

parent 53fb52ac
...@@ -701,6 +701,7 @@ static int vobsub_read_header(AVFormatContext *s) ...@@ -701,6 +701,7 @@ static int vobsub_read_header(AVFormatContext *s)
st->id = stream_id; st->id = stream_id;
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_DVD_SUBTITLE;
avpriv_set_pts_info(st, 64, 1, 1000);
av_dict_set(&st->metadata, "language", id, 0); av_dict_set(&st->metadata, "language", id, 0);
av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id); av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id);
header_parsed = 1; header_parsed = 1;
...@@ -865,6 +866,21 @@ static int vobsub_read_seek(AVFormatContext *s, int stream_index, ...@@ -865,6 +866,21 @@ static int vobsub_read_seek(AVFormatContext *s, int stream_index,
int64_t min_ts, int64_t ts, int64_t max_ts, int flags) int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
{ {
MpegDemuxContext *vobsub = s->priv_data; MpegDemuxContext *vobsub = s->priv_data;
/* Rescale requested timestamps based on the first stream (timebase is the
* same for all subtitles stream within a .idx/.sub). Rescaling is done just
* like in avformat_seek_file(). */
if (stream_index == -1 && s->nb_streams != 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 | AV_ROUND_PASS_MINMAX);
max_ts = av_rescale_rnd(max_ts, time_base.den,
time_base.num * (int64_t)AV_TIME_BASE,
AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
}
return ff_subtitles_queue_seek(&vobsub->q, s, stream_index, return ff_subtitles_queue_seek(&vobsub->q, s, stream_index,
min_ts, ts, max_ts, flags); min_ts, ts, max_ts, flags);
} }
......
...@@ -111,7 +111,8 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st ...@@ -111,7 +111,8 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st
for (i = 0; i < q->nb_subs; i++) { for (i = 0; i < q->nb_subs; i++) {
int64_t pts = q->subs[i].pts; int64_t pts = q->subs[i].pts;
uint64_t ts_diff = FFABS(pts - ts); uint64_t ts_diff = FFABS(pts - ts);
if (pts >= min_ts && pts <= max_ts && ts_diff < min_ts_diff) { 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; min_ts_diff = ts_diff;
idx = i; idx = i;
} }
...@@ -121,13 +122,24 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st ...@@ -121,13 +122,24 @@ int ff_subtitles_queue_seek(FFDemuxSubtitlesQueue *q, AVFormatContext *s, int st
/* look back in the latest subtitles for overlapping subtitles */ /* look back in the latest subtitles for overlapping subtitles */
ts_selected = q->subs[idx].pts; ts_selected = q->subs[idx].pts;
for (i = idx - 1; i >= 0; i--) { for (i = idx - 1; i >= 0; i--) {
if (q->subs[i].duration <= 0) if (q->subs[i].duration <= 0 ||
(stream_index != -1 && q->subs[i].stream_index != stream_index))
continue; continue;
if (q->subs[i].pts > ts_selected - q->subs[i].duration) if (q->subs[i].pts > ts_selected - q->subs[i].duration)
idx = i; idx = i;
else else
break; break;
} }
/* If the queue is used to store multiple subtitles streams (like with
* VobSub) and the stream index is not specified, we need to make sure
* to focus on the smallest file position offset for a same timestamp;
* queue is ordered by pts and then filepos, so we can take the first
* entry for a given timestamp. */
if (stream_index == -1)
while (idx > 0 && q->subs[idx - 1].pts == q->subs[idx].pts)
idx--;
q->current_sub_idx = idx; q->current_sub_idx = idx;
} }
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment