diff options
Diffstat (limited to 'player/playloop.c')
-rw-r--r-- | player/playloop.c | 304 |
1 files changed, 163 insertions, 141 deletions
diff --git a/player/playloop.c b/player/playloop.c index 66ce211322..12239d69ab 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -15,48 +15,47 @@ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ -#include <stddef.h> -#include <stdbool.h> +#include <assert.h> #include <inttypes.h> #include <math.h> -#include <assert.h> +#include <stdbool.h> +#include <stddef.h> -#include "config.h" +#include "client.h" +#include "command.h" +#include "core.h" #include "mpv_talloc.h" +#include "screenshot.h" -#include "common/msg.h" -#include "options/options.h" +#include "audio/out/ao.h" #include "common/common.h" #include "common/encode.h" -#include "common/recorder.h" -#include "filters/f_decoder_wrapper.h" -#include "options/m_config.h" -#include "options/m_property.h" +#include "common/msg.h" #include "common/playlist.h" +#include "common/stats.h" +#include "demux/demux.h" +#include "filters/f_decoder_wrapper.h" +#include "filters/filter_internal.h" #include "input/input.h" - #include "misc/dispatch.h" +#include "options/m_config_frontend.h" +#include "options/m_property.h" +#include "options/options.h" #include "osdep/terminal.h" #include "osdep/timer.h" - -#include "audio/out/ao.h" -#include "demux/demux.h" #include "stream/stream.h" #include "sub/dec_sub.h" #include "sub/osd.h" #include "video/out/vo.h" -#include "core.h" -#include "client.h" -#include "command.h" -#include "screenshot.h" - // Wait until mp_wakeup_core() is called, since the last time // mp_wait_events() was called. void mp_wait_events(struct MPContext *mpctx) { mp_client_send_property_changes(mpctx); + stats_event(mpctx->stats, "iterations"); + bool sleeping = mpctx->sleeptime > 0; if (sleeping) MP_STATS(mpctx, "start sleep"); @@ -76,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); } } @@ -107,23 +106,27 @@ void mp_core_unlock(struct MPContext *mpctx) } // Process any queued user input. -void mp_process_input(struct MPContext *mpctx) +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) @@ -142,6 +145,11 @@ void update_core_idle_state(struct MPContext *mpctx) } } +bool get_internal_paused(struct MPContext *mpctx) +{ + return mpctx->opts->pause || mpctx->paused_for_cache; +} + // The value passed here is the new value for mpctx->opts->pause void set_pause_state(struct MPContext *mpctx, bool user_pause) { @@ -149,16 +157,13 @@ void set_pause_state(struct MPContext *mpctx, bool user_pause) opts->pause = user_pause; - bool internal_paused = opts->pause || mpctx->paused_for_cache; + bool internal_paused = get_internal_paused(mpctx); if (internal_paused != mpctx->paused) { mpctx->paused = internal_paused; - if (mpctx->ao && mpctx->ao_chain) { - if (internal_paused) { - ao_pause(mpctx->ao); - } else { - ao_resume(mpctx->ao); - } + if (mpctx->ao) { + bool eof = mpctx->audio_status == STATUS_EOF; + ao_set_paused(mpctx->ao, internal_paused, eof); } if (mpctx->video_out) @@ -175,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); @@ -196,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); } @@ -229,11 +231,15 @@ void reset_playback_state(struct MPContext *mpctx) struct track *t = mpctx->tracks[n]; // (Often, but not always, this is redundant and also done elsewhere.) if (t->dec) - t->dec->play_dir = mpctx->play_dir; + mp_decoder_wrapper_set_play_dir(t->dec, mpctx->play_dir); if (t->d_sub) 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; @@ -244,7 +250,7 @@ void reset_playback_state(struct MPContext *mpctx) mpctx->restart_complete = false; mpctx->paused_for_cache = false; mpctx->cache_buffer = 100; - mpctx->seek_slave = NULL; + mpctx->cache_update_pts = MP_NOPTS_VALUE; encode_lavc_discontinuity(mpctx->encode_lavc_ctx); @@ -259,8 +265,15 @@ 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_current_time(mpctx); + double current_time = get_playback_time(mpctx); if (current_time == MP_NOPTS_VALUE && seek.type == MPSEEK_RELATIVE) return; if (current_time == MP_NOPTS_VALUE) @@ -285,19 +298,15 @@ 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; - bool hr_seek = opts->correct_pts && seek.exact != MPSEEK_KEYFRAME && - ((opts->hr_seek == 0 && seek.type == MPSEEK_ABSOLUTE) || - opts->hr_seek > 0 || seek.exact >= MPSEEK_EXACT) && - seek_pts != MP_NOPTS_VALUE; - - if (seek.type == MPSEEK_FACTOR || seek.amount < 0 || - (seek.type == MPSEEK_ABSOLUTE && seek.amount < mpctx->last_chapter_pts)) - mpctx->last_chapter_seek = -2; + bool hr_seek = seek.exact != MPSEEK_KEYFRAME && seek_pts != MP_NOPTS_VALUE && + (seek.exact >= MPSEEK_EXACT || opts->hr_seek == 1 || + (opts->hr_seek >= 0 && seek.type == MPSEEK_ABSOLUTE) || + (opts->hr_seek == 2 && (!mpctx->vo_chain || mpctx->vo_chain->is_sparse))); // Under certain circumstances, prefer SEEK_FACTOR. if (seek.type == MPSEEK_FACTOR && !hr_seek && @@ -336,6 +345,8 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) if (!mpctx->demuxer->seekable) demux_flags |= SEEK_CACHED; + demux_flags |= SEEK_BLOCK; + if (!demux_seek(mpctx->demuxer, demux_pts, demux_flags)) { if (!mpctx->demuxer->seekable) { MP_ERR(mpctx, "Cannot seek in this stream.\n"); @@ -347,8 +358,6 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) mpctx->play_dir = play_dir; // Seek external, extra files too: - bool has_video = false; - struct track *external_audio = NULL; for (int t = 0; t < mpctx->num_tracks; t++) { struct track *track = mpctx->tracks[t]; if (track->selected && track->is_external && track->demuxer) { @@ -357,33 +366,21 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) main_new_pos += get_track_seek_offset(mpctx, track); if (demux_flags & SEEK_FACTOR) main_new_pos = seek_pts; - demux_seek(track->demuxer, main_new_pos, demux_flags & SEEK_SATAN); - if (track->type == STREAM_AUDIO && !external_audio) - external_audio = track; + demux_seek(track->demuxer, main_new_pos, + demux_flags & (SEEK_SATAN | SEEK_BLOCK)); } - if (track->selected && !track->is_external && track->stream && - track->type == STREAM_VIDEO && !track->stream->attached_picture) - has_video = true; } if (!(seek.flags & MPSEEK_FLAG_NOFLUSH)) clear_audio_output_buffers(mpctx); reset_playback_state(mpctx); - if (mpctx->recorder) - mp_recorder_mark_discontinuity(mpctx->recorder); - - // When doing keyframe seeks (hr_seek=false) backwards (no SEEK_FORWARD), - // then video can seek before the external audio track (because video seek - // granularity is coarser than audio). The result would be playing video with - // silence until the audio seek target is reached. Work around by blocking - // the demuxer (decoders can't read) and seeking to video position later. - if (has_video && external_audio && !hr_seek && mpctx->play_dir > 0 && - !(demux_flags & SEEK_FORWARD)) - { - MP_VERBOSE(mpctx, "delayed seek for aid=%d\n", external_audio->user_tid); - demux_block_reading(external_audio->demuxer, true); - mpctx->seek_slave = external_audio; + + demux_block_reading(mpctx->demuxer, false); + for (int t = 0; t < mpctx->num_tracks; t++) { + struct track *track = mpctx->tracks[t]; + if (track->selected && track->demuxer) + demux_block_reading(track->demuxer, false); } /* Use the target time as "current position" for further relative @@ -422,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. @@ -451,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, @@ -462,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) @@ -516,24 +515,19 @@ double get_start_time(struct MPContext *mpctx, int dir) double get_current_time(struct MPContext *mpctx) { - struct demuxer *demuxer = mpctx->demuxer; - if (demuxer) { - if (mpctx->playback_pts != MP_NOPTS_VALUE) - return mpctx->playback_pts * mpctx->play_dir; - if (mpctx->last_seek_pts != MP_NOPTS_VALUE) - return mpctx->last_seek_pts; - } - return MP_NOPTS_VALUE; + if (!mpctx->demuxer) + return MP_NOPTS_VALUE; + if (mpctx->playback_pts != MP_NOPTS_VALUE) + return mpctx->playback_pts * mpctx->play_dir; + return mpctx->last_seek_pts; } double get_playback_time(struct MPContext *mpctx) { double cur = get_current_time(mpctx); - if (cur == MP_NOPTS_VALUE) - return cur; // During seeking, the time corresponds to the last seek time - apply some // cosmetics to it. - if (mpctx->playback_pts == MP_NOPTS_VALUE) { + if (cur != MP_NOPTS_VALUE && mpctx->playback_pts == MP_NOPTS_VALUE) { double length = get_time_length(mpctx); if (length >= 0) cur = MPCLAMP(cur, 0, length); @@ -580,7 +574,7 @@ double get_current_pos_ratio(struct MPContext *mpctx, bool use_range) int get_percent_pos(struct MPContext *mpctx) { double pos = get_current_pos_ratio(mpctx, false); - return pos < 0 ? -1 : pos * 100; + return pos < 0 ? -1 : (int)round(pos * 100); } // -2 is no chapters, -1 is before first chapter @@ -593,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) @@ -661,7 +656,7 @@ static void handle_osd_redraw(struct MPContext *mpctx) return; } // Don't redraw immediately during a seek (makes it significantly slower). - bool use_video = mpctx->vo_chain && !mpctx->vo_chain->is_coverart; + bool use_video = mpctx->vo_chain && !mpctx->vo_chain->is_sparse; if (use_video && mp_time_sec() - mpctx->start_timestamp < 0.1) { mp_set_timeout(mpctx, 0.1); return; @@ -671,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) @@ -762,6 +760,8 @@ static void handle_update_cache(struct MPContext *mpctx) // Also update cache properties. bool busy = !s.idle; + if (fabs(mpctx->cache_update_pts - mpctx->playback_pts) >= 1.0) + busy = true; if (busy || mpctx->next_cache_update > 0) { if (mpctx->next_cache_update <= now) { mpctx->next_cache_update = busy ? now + 0.25 : 0; @@ -792,8 +792,10 @@ static void handle_update_cache(struct MPContext *mpctx) if (s.eof && !busy) prefetch_next(mpctx); - if (force_update) + if (force_update) { + mpctx->cache_update_pts = mpctx->playback_pts; mp_notify(mpctx, MP_EVENT_CACHE_UPDATE, NULL); + } } int get_cache_buffering_percentage(struct MPContext *mpctx) @@ -801,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; @@ -849,6 +867,8 @@ static void handle_vo_events(struct MPContext *mpctx) mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL); if (events & VO_EVENT_DPI) mp_notify(mpctx, MP_EVENT_WIN_STATE2, NULL); + if (events & VO_EVENT_FOCUS) + mp_notify(mpctx, MP_EVENT_FOCUS, NULL); } static void handle_sstep(struct MPContext *mpctx) @@ -897,6 +917,11 @@ static void handle_loop_file(struct MPContext *mpctx) } if (target != MP_NOPTS_VALUE) { + if (!mpctx->shown_aframes && !mpctx->shown_vframes) { + MP_WARN(mpctx, "No media data to loop.\n"); + return; + } + mpctx->stop_play = KEEP_PLAYING; set_osd_function(mpctx, OSD_FFW); mark_seek(mpctx); @@ -940,18 +965,20 @@ 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->playback_pts = mpctx->last_vo_pts; + mpctx->audio_status = STATUS_EOF; + mpctx->video_status = STATUS_EOF; + } } if (opts->keep_open_pause) { - if (mpctx->ao) - ao_drain(mpctx->ao); + if (mpctx->ao && ao_is_playing(mpctx->ao)) + return; set_pause_state(mpctx, true); } } @@ -962,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); } } @@ -1023,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); @@ -1075,24 +1109,14 @@ static void handle_playback_time(struct MPContext *mpctx) mpctx->audio_status < STATUS_EOF) { mpctx->playback_pts = playing_audio_pts(mpctx); - } -} - -static void handle_delayed_audio_seek(struct MPContext *mpctx) -{ - if (mpctx->seek_slave) { - if (mpctx->video_pts != MP_NOPTS_VALUE) { - // We know the video position now, so seek external audio to the - // correct position. - double pts = mpctx->video_pts + - get_track_seek_offset(mpctx, mpctx->seek_slave); - demux_seek(mpctx->seek_slave->demuxer, pts, 0); - mpctx->seek_slave = NULL; - } else if (mpctx->video_status >= STATUS_EOF) { - // We won't get a video position; don't stall the audio stream. - demux_block_reading(mpctx->seek_slave->demuxer, false); - mpctx->seek_slave = NULL; - } + } else if (mpctx->video_status == STATUS_EOF && + mpctx->audio_status == STATUS_EOF) + { + double apts = playing_audio_pts(mpctx); + double vpts = mpctx->video_pts; + double mpts = MP_PTS_MAX(apts, vpts); + if (mpts != MP_NOPTS_VALUE) + mpctx->playback_pts = mpts; } } @@ -1102,13 +1126,6 @@ static void handle_playback_restart(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - // Do not wait for video stream if it only has sparse frames. - if (mpctx->vo_chain && mpctx->vo_chain->is_sparse && - mpctx->video_status < STATUS_READY) - { - mpctx->video_status = STATUS_READY; - } - if (mpctx->audio_status < STATUS_READY || mpctx->video_status < STATUS_READY) return; @@ -1119,6 +1136,7 @@ static void handle_playback_restart(struct MPContext *mpctx) mpctx->video_status = STATUS_PLAYING; get_relative_time(mpctx); mp_wakeup_core(mpctx); + MP_DBG(mpctx, "starting video playback\n"); } if (mpctx->audio_status == STATUS_READY) { @@ -1131,23 +1149,14 @@ static void handle_playback_restart(struct MPContext *mpctx) return; } - // Video needed, but not started yet -> wait. - if (mpctx->vo_chain && - !mpctx->vo_chain->is_coverart && - !mpctx->vo_chain->is_sparse && - mpctx->video_status <= STATUS_READY) - return; - - MP_VERBOSE(mpctx, "starting audio playback\n"); - mpctx->audio_status = STATUS_PLAYING; - fill_audio_out_buffers(mpctx); // actually play prepared buffer - mp_wakeup_core(mpctx); + audio_start_ao(mpctx); } if (!mpctx->restart_complete) { 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); @@ -1163,21 +1172,38 @@ 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); } } mpctx->playing_msg_shown = true; mp_wakeup_core(mpctx); update_ab_loop_clip(mpctx); - MP_VERBOSE(mpctx, "playback restart complete @ %f\n", mpctx->playback_pts); + MP_VERBOSE(mpctx, "playback restart complete @ %f, audio=%s, video=%s%s\n", + mpctx->playback_pts, mp_status_str(mpctx->audio_status), + mp_status_str(mpctx->video_status), + get_internal_paused(mpctx) ? " (paused)" : ""); + + // To avoid strange effects when using relative seeks, especially if + // there are no proper audio & video timestamps (seeks after EOF). + double length = get_time_length(mpctx); + if (mpctx->last_seek_pts != MP_NOPTS_VALUE && length >= 0) + mpctx->last_seek_pts = MPCLAMP(mpctx->last_seek_pts, 0, length); + + // Continuous seeks past EOF => treat as EOF instead of repeating seek. + if (mpctx->seek.type == MPSEEK_RELATIVE && mpctx->seek.amount > 0 && + mpctx->video_status == STATUS_EOF && + mpctx->audio_status == STATUS_EOF) + mpctx->seek = (struct seek_params){0}; } } static void handle_eof(struct MPContext *mpctx) { if (mpctx->seek.type) - return; + return; // for proper keep-open operation /* Don't quit while paused and we're displaying the last video frame. On the * other hand, if we don't have a video frame, then the user probably seeked @@ -1200,7 +1226,7 @@ static void handle_eof(struct MPContext *mpctx) void run_playloop(struct MPContext *mpctx) { if (encode_lavc_didfail(mpctx->encode_lavc_ctx)) { - mpctx->stop_play = PT_QUIT; + mpctx->stop_play = PT_ERROR; return; } @@ -1216,8 +1242,6 @@ void run_playloop(struct MPContext *mpctx) fill_audio_out_buffers(mpctx); write_video(mpctx); - handle_delayed_audio_seek(mpctx); - handle_playback_restart(mpctx); handle_playback_time(mpctx); @@ -1225,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); @@ -1247,7 +1271,7 @@ void run_playloop(struct MPContext *mpctx) handle_osd_redraw(mpctx); - if (mp_filter_run(mpctx->filter_root)) + if (mp_filter_graph_run(mpctx->filter_root)) mp_wakeup_core(mpctx); mp_wait_events(mpctx); @@ -1279,9 +1303,7 @@ void idle_loop(struct MPContext *mpctx) { // ================= idle loop (STOP state) ========================= bool need_reinit = true; - while (mpctx->opts->player_idle_mode && !mpctx->playlist->current - && mpctx->stop_play != PT_QUIT) - { + while (mpctx->opts->player_idle_mode && mpctx->stop_play == PT_STOP) { if (need_reinit) { uninit_audio_out(mpctx); handle_force_window(mpctx, true); |