summaryrefslogtreecommitdiffstats
path: root/player/video.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-12-07 02:47:09 +0100
committerwm4 <wm4@nowhere>2014-12-07 02:47:54 +0100
commit090f6cfc30a55c044b45dbd66cd46d8a66ce4b44 (patch)
treee0556ad41324eaf1a48bb368a3369abc59eaaee2 /player/video.c
parent6adaddbe63196ba0c75796ce157d2e041c390b71 (diff)
downloadmpv-090f6cfc30a55c044b45dbd66cd46d8a66ce4b44.tar.bz2
mpv-090f6cfc30a55c044b45dbd66cd46d8a66ce4b44.tar.xz
player: when seeking past EOF with --keep-open, seek to last frame
It feels strange that seeking past EOF with --keep-open actually leaves the player at a random position. You can't even unpause, because the demuxer is in the EOF state, and what you see on screen is just what was around before the seek. Improve this by attempting to seek to the last video frame if EOF happens. We explicitly don't do this if EOF was reached normally to increase robustness (if the VO got a frame since the last seek, it obviously means we had normal playback before EOF). If an error happens when trying to find the last frame (such as not actually finding a last frame because e.g. the demuxer misbehaves), this will probably turn your CPU into a heater. There is no logic to prevent reinitiating the last-frame search if the last-frame search reached EOF. (Pausing usually prevents that EOF is reached again after a successful last-frame search.) Fixes #819.
Diffstat (limited to 'player/video.c')
-rw-r--r--player/video.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/player/video.c b/player/video.c
index 506c7971a7..f0829a2c8d 100644
--- a/player/video.c
+++ b/player/video.c
@@ -214,6 +214,7 @@ void reset_video_state(struct MPContext *mpctx)
mp_image_unrefp(&mpctx->next_frame[0]);
mp_image_unrefp(&mpctx->next_frame[1]);
+ mp_image_unrefp(&mpctx->saved_frame);
mpctx->delay = 0;
mpctx->time_frame = 0;
@@ -534,6 +535,8 @@ static bool have_new_frame(struct MPContext *mpctx)
// returns VD_* code
static int video_output_image(struct MPContext *mpctx, double endpts)
{
+ bool hrseek = mpctx->hrseek_active && mpctx->video_status == STATUS_SYNCING;
+
if (mpctx->d_video->header->attached_picture) {
if (vo_has_frame(mpctx->video_out))
return VD_EOF;
@@ -591,16 +594,18 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
add_frame_pts(mpctx, img->pts);
bool drop = false;
- bool hrseek = mpctx->hrseek_active
- && mpctx->video_status == STATUS_SYNCING;
- if (hrseek && img->pts < mpctx->hrseek_pts - .005)
- drop = true;
if ((endpts != MP_NOPTS_VALUE && img->pts >= endpts) ||
mpctx->max_frames == 0)
{
drop = true;
r = VD_EOF;
}
+ if (!drop && hrseek && mpctx->hrseek_lastframe) {
+ mp_image_setrefp(&mpctx->saved_frame, img);
+ drop = true;
+ }
+ if (hrseek && img->pts < mpctx->hrseek_pts - .005)
+ drop = true;
if (drop) {
talloc_free(img);
} else {
@@ -613,6 +618,13 @@ static int video_output_image(struct MPContext *mpctx, double endpts)
if (have_new_frame(mpctx) || (r <= 0 && mpctx->next_frame[0]))
return VD_NEW_FRAME;
+ // Last-frame seek
+ if (r <= 0 && hrseek && mpctx->hrseek_lastframe && mpctx->saved_frame) {
+ mpctx->next_frame[1] = mpctx->saved_frame;
+ mpctx->saved_frame = NULL;
+ return VD_PROGRESS;
+ }
+
return r;
}