diff options
Diffstat (limited to 'player/playloop.c')
-rw-r--r-- | player/playloop.c | 102 |
1 files changed, 71 insertions, 31 deletions
diff --git a/player/playloop.c b/player/playloop.c index 6cff3c9108..12239d69ab 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -23,7 +23,6 @@ #include "client.h" #include "command.h" -#include "config.h" #include "core.h" #include "mpv_talloc.h" #include "screenshot.h" @@ -33,7 +32,6 @@ #include "common/encode.h" #include "common/msg.h" #include "common/playlist.h" -#include "common/recorder.h" #include "common/stats.h" #include "demux/demux.h" #include "filters/f_decoder_wrapper.h" @@ -77,7 +75,7 @@ void mp_set_timeout(struct MPContext *mpctx, double sleeptime) { if (mpctx->sleeptime > sleeptime) { mpctx->sleeptime = sleeptime; - int64_t abstime = mp_add_timeout(mp_time_us(), sleeptime); + int64_t abstime = mp_time_ns_add(mp_time_ns(), sleeptime); mp_dispatch_adjust_timeout(mpctx->dispatch, abstime); } } @@ -110,21 +108,25 @@ void mp_core_unlock(struct MPContext *mpctx) // Process any queued user input. static void mp_process_input(struct MPContext *mpctx) { + int processed = 0; for (;;) { mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input); if (!cmd) break; run_command(mpctx, cmd, NULL, NULL, NULL); + processed = 1; } mp_set_timeout(mpctx, mp_input_get_delay(mpctx->input)); + if (processed) + mp_notify(mpctx, MP_EVENT_INPUT_PROCESSED, NULL); } double get_relative_time(struct MPContext *mpctx) { - int64_t new_time = mp_time_us(); + int64_t new_time = mp_time_ns(); int64_t delta = new_time - mpctx->last_time; mpctx->last_time = new_time; - return delta * 0.000001; + return delta * 1e-9; } void update_core_idle_state(struct MPContext *mpctx) @@ -159,8 +161,10 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause) if (internal_paused != mpctx->paused) { mpctx->paused = internal_paused; - if (mpctx->ao) - ao_set_paused(mpctx->ao, internal_paused); + if (mpctx->ao) { + bool eof = mpctx->audio_status == STATUS_EOF; + ao_set_paused(mpctx->ao, internal_paused, eof); + } if (mpctx->video_out) vo_set_paused(mpctx->video_out, internal_paused); @@ -176,10 +180,6 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause) } else { (void)get_relative_time(mpctx); // ignore time that passed during pause } - - // For some reason, these events are supposed to be sent even if only - // the internal pause state changed (and "pause" property didn't)... OK. - mp_notify(mpctx, opts->pause ? MPV_EVENT_PAUSE : MPV_EVENT_UNPAUSE, 0); } update_core_idle_state(mpctx); @@ -197,7 +197,8 @@ void update_screensaver_state(struct MPContext *mpctx) if (!mpctx->video_out) return; - bool saver_state = !mpctx->playback_active || !mpctx->opts->stop_screensaver; + bool saver_state = (!mpctx->playback_active || !mpctx->opts->stop_screensaver) && + mpctx->opts->stop_screensaver != 2; vo_control_async(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER : VOCTRL_KILL_SCREENSAVER, NULL); } @@ -235,6 +236,10 @@ void reset_playback_state(struct MPContext *mpctx) sub_set_play_dir(t->d_sub, mpctx->play_dir); } + // May need unpause first + if (mpctx->paused_for_cache) + update_internal_pause_state(mpctx); + mpctx->hrseek_active = false; mpctx->hrseek_lastframe = false; mpctx->hrseek_backstep = false; @@ -260,6 +265,13 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) if (!mpctx->demuxer || !seek.type || seek.amount == MP_NOPTS_VALUE) return; + if (seek.type == MPSEEK_CHAPTER) { + mpctx->last_chapter_flag = false; + seek.type = MPSEEK_ABSOLUTE; + } else { + mpctx->last_chapter_seek = -2; + } + bool hr_seek_very_exact = seek.exact == MPSEEK_VERY_EXACT; double current_time = get_playback_time(mpctx); if (current_time == MP_NOPTS_VALUE && seek.type == MPSEEK_RELATIVE) @@ -286,7 +298,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) if (len >= 0) seek_pts = seek.amount * len; break; - default: abort(); + default: MP_ASSERT_UNREACHABLE(); } double demux_pts = seek_pts; @@ -296,10 +308,6 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) (opts->hr_seek >= 0 && seek.type == MPSEEK_ABSOLUTE) || (opts->hr_seek == 2 && (!mpctx->vo_chain || mpctx->vo_chain->is_sparse))); - if (seek.type == MPSEEK_FACTOR || seek.amount < 0 || - (seek.type == MPSEEK_ABSOLUTE && seek.amount < mpctx->last_chapter_pts)) - mpctx->last_chapter_seek = -2; - // Under certain circumstances, prefer SEEK_FACTOR. if (seek.type == MPSEEK_FACTOR && !hr_seek && (mpctx->demuxer->ts_resets_possible || seek_pts == MP_NOPTS_VALUE)) @@ -367,8 +375,6 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) clear_audio_output_buffers(mpctx); reset_playback_state(mpctx); - if (mpctx->recorder) - mp_recorder_mark_discontinuity(mpctx->recorder); demux_block_reading(mpctx->demuxer, false); for (int t = 0; t < mpctx->num_tracks; t++) { @@ -413,6 +419,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) update_ab_loop_clip(mpctx); mpctx->current_seek = seek; + redraw_subs(mpctx); } // This combines consecutive seek requests. @@ -442,6 +449,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, case MPSEEK_ABSOLUTE: case MPSEEK_FACTOR: case MPSEEK_BACKSTEP: + case MPSEEK_CHAPTER: *seek = (struct seek_params) { .type = type, .amount = amount, @@ -453,7 +461,7 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, *seek = (struct seek_params){ 0 }; return; } - abort(); + MP_ASSERT_UNREACHABLE(); } void execute_queued_seek(struct MPContext *mpctx) @@ -579,7 +587,8 @@ int get_current_chapter(struct MPContext *mpctx) for (i = 0; i < mpctx->num_chapters; i++) if (current_pts < mpctx->chapters[i].pts) break; - return MPMAX(mpctx->last_chapter_seek, i - 1); + return mpctx->last_chapter_flag ? + mpctx->last_chapter_seek : MPMAX(mpctx->last_chapter_seek, i - 1); } char *chapter_display_name(struct MPContext *mpctx, int chapter) @@ -657,6 +666,9 @@ static void handle_osd_redraw(struct MPContext *mpctx) if (!want_redraw) return; vo_redraw(mpctx->video_out); + // Even though we just redrew, it may need to be done again for certain + // cases of subtitles on an image. + redraw_subs(mpctx); } static void clear_underruns(struct MPContext *mpctx) @@ -791,6 +803,22 @@ int get_cache_buffering_percentage(struct MPContext *mpctx) return mpctx->demuxer ? mpctx->cache_buffer : -1; } +static void handle_update_subtitles(struct MPContext *mpctx) +{ + if (mpctx->video_status == STATUS_EOF) { + update_subtitles(mpctx, mpctx->playback_pts); + return; + } + + for (int n = 0; n < mpctx->num_tracks; n++) { + struct track *track = mpctx->tracks[n]; + if (track->type == STREAM_SUB && !track->demuxer_ready) { + update_subtitles(mpctx, mpctx->playback_pts); + break; + } + } +} + static void handle_cursor_autohide(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; @@ -937,13 +965,16 @@ static void handle_keep_open(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; if (opts->keep_open && mpctx->stop_play == AT_END_OF_FILE && - (opts->keep_open == 2 || !playlist_get_next(mpctx->playlist, 1)) && - opts->loop_times == 1) + (opts->keep_open == 2 || + (!playlist_get_next(mpctx->playlist, 1) && opts->loop_times == 1))) { mpctx->stop_play = KEEP_PLAYING; if (mpctx->vo_chain) { - if (!vo_has_frame(mpctx->video_out)) // EOF not reached normally + if (!vo_has_frame(mpctx->video_out)) { // EOF not reached normally seek_to_last_frame(mpctx); + mpctx->audio_status = STATUS_EOF; + mpctx->video_status = STATUS_EOF; + } } if (opts->keep_open_pause) { if (mpctx->ao && ao_is_playing(mpctx->ao)) @@ -958,7 +989,7 @@ static void handle_chapter_change(struct MPContext *mpctx) int chapter = get_current_chapter(mpctx); if (chapter != mpctx->last_chapter) { mpctx->last_chapter = chapter; - mp_notify(mpctx, MPV_EVENT_CHAPTER_CHANGE, NULL); + mp_notify(mpctx, MP_EVENT_CHAPTER_CHANGE, NULL); } } @@ -1019,15 +1050,22 @@ int handle_force_window(struct MPContext *mpctx, bool force) break; } } + + // Use a 16:9 aspect ratio so that fullscreen on a 16:9 screen will not + // have vertical margins, which can lead to a different size or position + // of subtitles than with 16:9 videos. int w = 960; - int h = 480; + int h = 540; struct mp_image_params p = { .imgfmt = config_format, .w = w, .h = h, .p_w = 1, .p_h = 1, + .force_window = true, }; if (vo_reconfig(vo, &p) < 0) goto err; + struct track *track = mpctx->current_track[0][STREAM_VIDEO]; + update_content_type(mpctx, track); update_screensaver_state(mpctx); vo_set_paused(vo, true); vo_redraw(vo); @@ -1074,8 +1112,7 @@ static void handle_playback_time(struct MPContext *mpctx) } else if (mpctx->video_status == STATUS_EOF && mpctx->audio_status == STATUS_EOF) { - double apts = - mpctx->ao_chain ? mpctx->ao_chain->last_out_pts : MP_NOPTS_VALUE; + double apts = playing_audio_pts(mpctx); double vpts = mpctx->video_pts; double mpts = MP_PTS_MAX(apts, vpts); if (mpts != MP_NOPTS_VALUE) @@ -1119,6 +1156,7 @@ static void handle_playback_restart(struct MPContext *mpctx) mpctx->hrseek_active = false; mpctx->restart_complete = true; mpctx->current_seek = (struct seek_params){0}; + run_command_opts(mpctx); handle_playback_time(mpctx); mp_notify(mpctx, MPV_EVENT_PLAYBACK_RESTART, NULL); update_core_idle_state(mpctx); @@ -1134,7 +1172,9 @@ static void handle_playback_restart(struct MPContext *mpctx) if (opts->osd_playing_msg && opts->osd_playing_msg[0]) { char *msg = mp_property_expand_escaped_string(mpctx, opts->osd_playing_msg); - set_osd_msg(mpctx, 1, opts->osd_duration, "%s", msg); + set_osd_msg(mpctx, 1, opts->osd_playing_msg_duration ? + opts->osd_playing_msg_duration : opts->osd_duration, + "%s", msg); talloc_free(msg); } } @@ -1209,8 +1249,8 @@ void run_playloop(struct MPContext *mpctx) handle_dummy_ticks(mpctx); update_osd_msg(mpctx); - if (mpctx->video_status == STATUS_EOF) - update_subtitles(mpctx, mpctx->playback_pts); + + handle_update_subtitles(mpctx); handle_each_frame_screenshot(mpctx); |