summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-05-24 15:20:07 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:04 +0200
commit4f7684463fd1326febe5eebe3134f24c0f834e19 (patch)
tree472e88da642ca8ee7fefa524b37de763ff441584
parenta8b9ba10ac8ad3cf45aeec88f4509e7b4450af60 (diff)
downloadmpv-4f7684463fd1326febe5eebe3134f24c0f834e19.tar.bz2
mpv-4f7684463fd1326febe5eebe3134f24c0f834e19.tar.xz
demux: redo backstep seek handling slightly again
Backstepping still could get "stuck" if the demuxer didn't seek far back enough. This commit fixes getting stuck if playing backwards from the end, and audio has ended much earlier than the video. In commit "demux: fix initial backward demuxing state in some cases", I claimed that the backward seek semantics ("snapping" backward in normal seeking, unrelated to backward playing) would take care of this. Unfortunately, this is not always quite true. In theory, a seek to any position (that does not use SEEK_FORWARD, i.e. backward snapping) should return a packet for every stream. But I have a mkv sample, where audio ends much earlier than video. Its mkvmerge created index does not have entries for audio packets, so the video index is used. This index has its last entry somewhere close after the end of audio. So no audio packets will be returned. With a "too small" back_seek_size, the demuxer will retry a seek target that ends up in this place forever. (This does not happen if you use --index=recreate. It also doesn't happen with libavformat, which always prefers its own index, while mpv's internal mkv demuxer strictly prefers the index from the file if it can be read.) Fix this by adding the back_seek_size every time we fail to see enough packets. This way the seek step can add up until it works. To prevent that back_seek_pos just "runs away" towards negative infinity by subtracting back_seek_size every time we back step to undo forward reading (e.g. if --no-cache is used), readjust the back_seek_pos to the lowest known resume position. (If the cache is active, kf_seek_pts can be used, but to work in all situations, the code needs to grab the minimum PTS in the keyframe range.)
-rw-r--r--demux/demux.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 89e608f891..3bfb7e0126 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -1256,8 +1256,6 @@ static void perform_backward_seek(struct demux_internal *in)
target = PTS_OR_DEF(target, in->d_thread->start_time);
- target -= in->opts->back_seek_size;
-
MP_VERBOSE(in, "triggering backward seek to get more packets\n");
queue_seek(in, target, SEEK_SATAN | SEEK_HR, false);
in->reading = true;
@@ -1390,6 +1388,15 @@ static void find_backward_restart_pos(struct demux_stream *ds)
assert(0); // target must be in list
}
+ double seek_pts = MP_NOPTS_VALUE;
+ for (struct demux_packet *cur = target; cur; cur = cur->next) {
+ seek_pts = MP_PTS_MIN(seek_pts, cur->pts);
+ if (cur->next && cur->next->keyframe)
+ break;
+ }
+ if (seek_pts != MP_NOPTS_VALUE)
+ ds->back_seek_pos = seek_pts;
+
ds->back_restarting = false;
ds->back_range_started = false;
ds->back_range_min = got_preroll + 1;
@@ -1417,6 +1424,7 @@ resume_earlier:
}
}
+ ds->back_seek_pos -= in->opts->back_seek_size;
in->need_back_seek = true;
}