summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-07 02:46:19 +0200
committerwm4 <wm4@nowhere>2013-09-07 08:52:14 +0200
commitf5572919e40f5f1bbd0d5043ad837921603f6c98 (patch)
tree6bfe7c57f735f35033a5b8c936faa675e1eeced7
parent93bf6eba3b2eb8fc149551cf8e1d27054236892a (diff)
downloadmpv-f5572919e40f5f1bbd0d5043ad837921603f6c98.tar.bz2
mpv-f5572919e40f5f1bbd0d5043ad837921603f6c98.tar.xz
demux_lavf: workaround for broken libavformat subtitle seeking
The really funny thing about this commit is that this code is added on top of another work around. Basically, subtitle seeking in libavformat is completely broken. To make it useful, we have to add yet another workaround. The basic problem is that libavformat's subtitle seeking code always uses the stream time base, instead of AV_TIME_BASE if stream index -1 is passed to the avformat_seek_file() function. Fixes github issue #216. Hopefully this will be fixed in ffmpeg too at some point.
-rw-r--r--demux/demux_lavf.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 4a9d127974..0f6e0f6be8 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -863,12 +863,31 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs,
// API by default, because there are some major issues.
// Set max_ts==ts, so that demuxing starts from an earlier position in
// the worst case.
- int r = avformat_seek_file(priv->avfc, -1, INT64_MIN,
- priv->last_pts, priv->last_pts, avsflags);
+ // To make this horrible situation even worse, some lavf demuxers have
+ // broken timebase handling (everything that uses
+ // ff_subtitles_queue_seek()), and always uses the stream timebase. So
+ // we use the timebase and stream index of the first enabled stream
+ // (i.e. a stream which can participate in seeking).
+ int stream_index = -1;
+ AVRational time_base = {1, AV_TIME_BASE};
+ for (int n = 0; n < priv->num_streams; n++) {
+ struct sh_stream *stream = priv->streams[n];
+ AVStream *st = priv->avfc->streams[n];
+ if (stream && st->discard != AVDISCARD_ALL) {
+ stream_index = n;
+ time_base = st->time_base;
+ break;
+ }
+ }
+ int64_t pts = priv->last_pts;
+ if (pts != AV_NOPTS_VALUE)
+ pts = pts / (double)AV_TIME_BASE * av_q2d(av_inv_q(time_base));
+ int r = avformat_seek_file(priv->avfc, stream_index, INT64_MIN,
+ pts, pts, avsflags);
// Similar issue as in the normal seeking codepath.
if (r < 0) {
- avformat_seek_file(priv->avfc, -1, INT64_MIN,
- priv->last_pts, INT64_MAX, avsflags);
+ avformat_seek_file(priv->avfc, stream_index, INT64_MIN,
+ pts, INT64_MAX, avsflags);
}
}
}