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.
This commit is contained in:
wm4 2014-08-03 20:25:03 +02:00
parent 0ddbf92d06
commit 0f5aed9c62
5 changed files with 58 additions and 53 deletions

View File

@ -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

View File

@ -919,11 +919,14 @@ OPTIONS
Practical use of this feature is questionable. Disabled by default.
``--frames=<number>``
Play/convert only first ``<number>`` video frames, then quit. For audio
only, run ``<number>`` 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 ``<number>``, and audio is longer than the
video.)
Play/convert only first ``<number>`` 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.

View File

@ -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,
/**

View File

@ -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;

View File

@ -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--;
}
}