From 593ad996e0621666d5c6d39c52f8119e5337af03 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 30 Jul 2014 00:22:25 +0200 Subject: player: fix time display wheen seeking past EOF with --keep-open Regression since commit 261506e3. Internally speaking, playback was often not properly terminated, and the main part of handle_keep_open() was just executed once, instead of any time the user tries to seek. This means playback_pts was not set, and the "current time" was determined by the seek target PTS. So fix this aspect of video EOF handling, and also remove the now unnecessary eof_reached field. The pause check before calling pause_player() is a lazy workaround for a strange event feedback loop that happens on EOF with --keep-open. --- player/command.c | 4 +++- player/core.h | 1 - player/loadfile.c | 1 - player/playloop.c | 33 ++++++++++++++++----------------- 4 files changed, 19 insertions(+), 20 deletions(-) (limited to 'player') diff --git a/player/command.c b/player/command.c index d0b310bade..eedbc0bbc7 100644 --- a/player/command.c +++ b/player/command.c @@ -1079,7 +1079,9 @@ static int mp_property_eof_reached(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - return m_property_flag_ro(action, arg, mpctx->eof_reached); + bool eof = mpctx->video_status == STATUS_EOF && + mpctx->audio_status == STATUS_EOF; + return m_property_flag_ro(action, arg, eof); } static int mp_property_cache(void *ctx, struct m_property *prop, diff --git a/player/core.h b/player/core.h index 0c4f50e1d2..b9cb0a3d0b 100644 --- a/player/core.h +++ b/player/core.h @@ -355,7 +355,6 @@ typedef struct MPContext { int last_dvb_step; bool paused; - bool eof_reached; // step this many frames, then pause int step_frames; // Counted down each frame, stop playback if 0 is reached. (-1 = disable) diff --git a/player/loadfile.c b/player/loadfile.c index 6c89057432..e26968000b 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -1276,7 +1276,6 @@ goto_reopen_demuxer: ; mpctx->playing_msg_shown = false; mpctx->paused = false; mpctx->paused_for_cache = false; - mpctx->eof_reached = false; mpctx->last_chapter = -2; mpctx->seek = (struct seek_params){ 0 }; mpctx->video_status = mpctx->d_video ? STATUS_SYNCING : STATUS_EOF; diff --git a/player/playloop.c b/player/playloop.c index 1bbf708740..cfce7aea19 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -174,7 +174,6 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) mpctx->drop_frame_cnt = 0; mpctx->dropped_frames = 0; mpctx->playback_pts = MP_NOPTS_VALUE; - mpctx->eof_reached = false; mpctx->video_status = mpctx->d_video ? STATUS_SYNCING : STATUS_EOF; mpctx->audio_status = mpctx->d_audio ? STATUS_SYNCING : STATUS_EOF; mpctx->restart_complete = false; @@ -815,8 +814,8 @@ static void handle_keep_open(struct MPContext *mpctx) if (opts->keep_open && mpctx->stop_play == AT_END_OF_FILE) { mpctx->stop_play = KEEP_PLAYING; mpctx->playback_pts = mpctx->last_vo_pts; - mpctx->eof_reached = true; - pause_player(mpctx); + if (!mpctx->opts->pause) + pause_player(mpctx); } } @@ -999,8 +998,6 @@ void run_playloop(struct MPContext *mpctx) mpctx->delay = 0; mpctx->last_av_difference = 0; mpctx->video_status = STATUS_EOF; - if (mpctx->paused && vo->hasframe) - mpctx->video_status = STATUS_DRAINING; MP_VERBOSE(mpctx, "video EOF\n"); } else { if (mpctx->video_status > STATUS_PLAYING) @@ -1189,18 +1186,19 @@ void run_playloop(struct MPContext *mpctx) update_osd_msg(mpctx); update_subtitles(mpctx); - /* It's possible for the user to simultaneously switch both audio + /* If we're paused, don't end playback yet. But if video is enabled, is EOF, + * and we don't have a video frame, then the user probably seeked outside + * of the video, and we want to quit. */ + bool prevent_eof = mpctx->paused; + if (mpctx->d_video && mpctx->video_status == STATUS_EOF) + prevent_eof &= mpctx->video_out && mpctx->video_out->hasframe; + /* Handles terminating on end of playback (or switching to next segment). + * + * It's possible for the user to simultaneously switch both audio * and video streams to "disabled" at runtime. Handle this by waiting * rather than immediately stopping playback due to EOF. - * - * We want this check to trigger if we seeked to this position, - * but not if we paused at it with audio possibly still buffered in - * the AO. There's currently no working way to check buffered audio - * inside AO while paused. Thus the "was_audio_restart" check below, which - * should trigger after seek only, when we know there's no audio - * buffered. */ - if ((mpctx->d_audio || mpctx->d_video) && !mpctx->paused && + if ((mpctx->d_audio || mpctx->d_video) && !prevent_eof && mpctx->audio_status == STATUS_EOF && mpctx->video_status == STATUS_EOF) { @@ -1215,6 +1213,8 @@ void run_playloop(struct MPContext *mpctx) mp_handle_nav(mpctx); + handle_keep_open(mpctx); + if (!mpctx->stop_play && mpctx->restart_complete) { // If no more video is available, one frame means one playloop iteration. @@ -1269,8 +1269,6 @@ void run_playloop(struct MPContext *mpctx) handle_loop_file(mpctx); - handle_keep_open(mpctx); - handle_chapter_change(mpctx); handle_force_window(mpctx, false); @@ -1289,7 +1287,8 @@ void idle_loop(struct MPContext *mpctx) while (mpctx->opts->player_idle_mode && !mpctx->playlist->current && mpctx->stop_play != PT_QUIT) { - mpctx->eof_reached = true; + mpctx->video_status = STATUS_EOF; + mpctx->audio_status = STATUS_EOF; if (need_reinit) { mp_notify(mpctx, MPV_EVENT_IDLE, NULL); handle_force_window(mpctx, true); -- cgit v1.2.3