summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-07 02:46:19 +0200
committerwm4 <wm4@nowhere>2013-09-07 02:56:28 +0200
commitc8f49be919ffaf983bde77b63d75f96a593ec7a8 (patch)
treef069cd60d78a389fb5d6d7756f238e9a1b08fc13 /demux
parentdb79db8444d5daa2870a3228057b3000892ba074 (diff)
downloadmpv-c8f49be919ffaf983bde77b63d75f96a593ec7a8.tar.bz2
mpv-c8f49be919ffaf983bde77b63d75f96a593ec7a8.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.
Diffstat (limited to 'demux')
-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 659dcacb7d..908eb3c111 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -862,12 +862,31 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, int flags)
// 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);
}
}
}