From 0f5aed9c62cb29a53dc1039df786207a2bd80d85 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 3 Aug 2014 20:25:03 +0200 Subject: player: some further playloop cleanups Handle --term-playing-msg at a better place. Move MPV_EVENT_TICK hack into a separate function. Also add some words to the client API that you shouldn't use it. (But better leave breaking it for later.) Handle --frames and frame_step differently. Remove the mess from the playloop, and do it after frame display. Give up on the weird semantics for audio-only mode (they didn't make sense anyway), and adjust the manpage accordingly. --- DOCS/man/input.rst | 2 +- DOCS/man/options.rst | 13 +++++---- libmpv/client.h | 6 ++-- player/playloop.c | 78 ++++++++++++++++++++++------------------------------ player/video.c | 12 ++++++++ 5 files changed, 58 insertions(+), 53 deletions(-) diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 04c1dc16fb..dd20d825fc 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -106,7 +106,7 @@ List of Input Commands ``revert_seek`` command itself. ``frame_step`` - Play one frame, then pause. + Play one frame, then pause. Does nothing with audio-only playback. ``frame_back_step`` Go back by one frame, then pause. Note that this can be very slow (it tries diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index e3cef52f99..17257844b5 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -919,11 +919,14 @@ OPTIONS Practical use of this feature is questionable. Disabled by default. ``--frames=`` - Play/convert only first ```` video frames, then quit. For audio - only, run ```` iteration of the playback loop, which is most likely - not what you want. (This behavior also applies to the corner case when there - are fewer video frames than ````, and audio is longer than the - video.) + Play/convert only first ```` video frames, then quit. + + ``--frames=0`` loads the file, but immediately quits before initializing + playback. (Might be useful for scripts which just want to determine some + file properties.) + + For audio-only playback, any value greater than 0 will quit playback + immediately after initialization. The value 0 works as with video. ``--fullscreen``, ``--fs`` Fullscreen playback. diff --git a/libmpv/client.h b/libmpv/client.h index 69bc77c0ac..687611c5e7 100644 --- a/libmpv/client.h +++ b/libmpv/client.h @@ -919,8 +919,10 @@ typedef enum mpv_event_id { */ MPV_EVENT_UNPAUSE = 13, /** - * Sent every time after a video frame is displayed (or in lower frequency - * if there is no video, or playback is paused). + * Sent every time after a video frame is displayed. Note that currently, + * this will be sent in lower frequency if there is no video, or playback + * is paused - but that will be removed in the future, and it will be + * restricted to video frames only. */ MPV_EVENT_TICK = 14, /** diff --git a/player/playloop.c b/player/playloop.c index f8904af028..e372e9232a 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -712,12 +712,20 @@ static void handle_backstep(struct MPContext *mpctx) static void handle_sstep(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - if (opts->step_sec > 0 && !mpctx->stop_play && !mpctx->paused && - mpctx->restart_complete) - { + if (mpctx->stop_play || !mpctx->restart_complete) + return; + + if (opts->step_sec > 0 && !mpctx->paused) { set_osd_function(mpctx, OSD_FFW); queue_seek(mpctx, MPSEEK_RELATIVE, opts->step_sec, 0, true); } + + if (mpctx->video_status >= STATUS_DRAINING) { + if (mpctx->max_frames >= 0) + mpctx->stop_play = PT_NEXT_ENTRY; + if (mpctx->step_frames > 0 && !mpctx->paused) + pause_player(mpctx); + } } static void handle_loop_file(struct MPContext *mpctx) @@ -785,6 +793,17 @@ void handle_force_window(struct MPContext *mpctx, bool reconfig) } } +// Potentially needed by some Lua scripts, which assume TICK always comes. +static void handle_dummy_ticks(struct MPContext *mpctx) +{ + if (mpctx->video_status == STATUS_EOF || mpctx->paused) { + if (mp_time_sec() - mpctx->last_idle_tick > 0.5) { + mpctx->last_idle_tick = mp_time_sec(); + mp_notify(mpctx, MPV_EVENT_TICK, NULL); + } + } +} + static double get_wakeup_period(struct MPContext *mpctx) { double sleeptime = 100.0; // infinite for all practical purposes @@ -806,7 +825,6 @@ void run_playloop(struct MPContext *mpctx) struct MPOpts *opts = mpctx->opts; double endpts = get_play_end_pts(mpctx); bool end_is_new_segment = false; - int64_t shown_vframes = mpctx->shown_vframes; #if HAVE_ENCODING if (encode_lavc_didfail(mpctx->encode_lavc_ctx)) { @@ -840,13 +858,6 @@ void run_playloop(struct MPContext *mpctx) fill_audio_out_buffers(mpctx, endpts); write_video(mpctx, endpts); - if (mpctx->video_status == STATUS_EOF || mpctx->paused) { - if (mp_time_sec() - mpctx->last_idle_tick > 0.5) { - mpctx->last_idle_tick = mp_time_sec(); - mp_notify(mpctx, MPV_EVENT_TICK, NULL); - } - } - // We always make sure audio and video buffers are filled before actually // starting playback. This code handles starting them at the same time. if (mpctx->audio_status >= STATUS_READY && @@ -856,7 +867,6 @@ void run_playloop(struct MPContext *mpctx) mpctx->video_status = STATUS_PLAYING; get_relative_time(mpctx); mpctx->sleeptime = 0; - shown_vframes -= 1; // make framestep think there was a new video frame } if (mpctx->audio_status == STATUS_READY) fill_audio_out_buffers(mpctx, endpts); // actually play prepared buffer @@ -864,6 +874,13 @@ void run_playloop(struct MPContext *mpctx) mpctx->hrseek_active = false; mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL); mpctx->restart_complete = true; + if (opts->playing_msg && !mpctx->playing_msg_shown) { + mpctx->playing_msg_shown = true; + char *msg = + mp_property_expand_escaped_string(mpctx, opts->playing_msg); + MP_INFO(mpctx, "%s\n", msg); + talloc_free(msg); + } } } @@ -876,6 +893,8 @@ void run_playloop(struct MPContext *mpctx) mpctx->playback_pts = a_pos; } + handle_dummy_ticks(mpctx); + update_osd_msg(mpctx); update_subtitles(mpctx); @@ -908,37 +927,7 @@ void run_playloop(struct MPContext *mpctx) handle_keep_open(mpctx); - if (!mpctx->stop_play && mpctx->restart_complete) { - bool new_frame_shown = shown_vframes < mpctx->shown_vframes; - - // If no more video is available, one frame means one playloop iteration. - // Otherwise, one frame means one video frame. - if (mpctx->video_status == STATUS_EOF) - new_frame_shown = true; - - if (opts->playing_msg && !mpctx->playing_msg_shown && new_frame_shown) { - mpctx->playing_msg_shown = true; - char *msg = - mp_property_expand_escaped_string(mpctx, opts->playing_msg); - MP_INFO(mpctx, "%s\n", msg); - talloc_free(msg); - } - - if (mpctx->max_frames >= 0) { - if (new_frame_shown) - mpctx->max_frames--; - if (mpctx->max_frames <= 0) - mpctx->stop_play = PT_NEXT_ENTRY; - } - - if (mpctx->step_frames > 0 && !mpctx->paused) { - if (new_frame_shown) - mpctx->step_frames--; - if (mpctx->step_frames == 0) - pause_player(mpctx); - } - - } + handle_sstep(mpctx); handle_loop_file(mpctx); @@ -960,8 +949,6 @@ void run_playloop(struct MPContext *mpctx) handle_backstep(mpctx); - handle_sstep(mpctx); - handle_chapter_change(mpctx); handle_force_window(mpctx, false); @@ -987,6 +974,7 @@ void idle_loop(struct MPContext *mpctx) handle_force_window(mpctx, true); } need_reinit = false; + handle_dummy_ticks(mpctx); int uninit = INITIALIZED_AO; if (!mpctx->opts->force_vo) uninit |= INITIALIZED_VO; diff --git a/player/video.c b/player/video.c index 7d33538627..c0e1101858 100644 --- a/player/video.c +++ b/player/video.c @@ -896,4 +896,16 @@ void write_video(struct MPContext *mpctx, double endpts) if (!mpctx->sync_audio_to_video) mpctx->video_status = STATUS_EOF; + + if (mpctx->video_status != STATUS_EOF) { + if (mpctx->step_frames > 0) { + mpctx->step_frames--; + if (!mpctx->step_frames && !opts->pause) + pause_player(mpctx); + } + if (mpctx->max_frames == 0) + mpctx->stop_play = PT_NEXT_ENTRY; + if (mpctx->max_frames > 0) + mpctx->max_frames--; + } } -- cgit v1.2.3