diff --git a/core/command.c b/core/command.c index d44521bf1c..aea8fb2017 100644 --- a/core/command.c +++ b/core/command.c @@ -350,14 +350,11 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: ; int step_all = *(int *)arg - chapter; chapter += step_all; - double next_pts = 0; - queue_seek(mpctx, MPSEEK_NONE, 0, 0); - chapter = seek_chapter(mpctx, chapter, &next_pts); - if (chapter >= 0) { - if (next_pts > -1.0) - queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); - } else if (step_all > 0) + if (chapter >= get_chapter_count(mpctx) && step_all > 0) { mpctx->stop_play = PT_NEXT_ENTRY; + } else { + mp_seek_chapter(mpctx, chapter); + } return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; diff --git a/core/mp_core.h b/core/mp_core.h index 2590eefb96..941396c48a 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -303,7 +303,7 @@ void unpause_player(struct MPContext *mpctx); void add_step_frame(struct MPContext *mpctx, int dir); void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, int exact); -int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts); +bool mp_seek_chapter(struct MPContext *mpctx, int chapter); double get_time_length(struct MPContext *mpctx); double get_start_time(struct MPContext *mpctx); double get_current_time(struct MPContext *mpctx); diff --git a/core/mplayer.c b/core/mplayer.c index 7d657edb54..72871bd0f0 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -3113,6 +3113,14 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, abort(); } +static void execute_queued_seek(struct MPContext *mpctx) +{ + if (mpctx->seek.type) { + seek(mpctx, mpctx->seek, false); + mpctx->seek = (struct seek_params){0}; + } +} + double get_time_length(struct MPContext *mpctx) { struct demuxer *demuxer = mpctx->demuxer; @@ -3262,33 +3270,42 @@ int get_chapter_count(struct MPContext *mpctx) return 0; } -int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts) +// Seek to a given chapter. Tries to queue the seek, but might seek immediately +// in some cases. Returns success, no matter if seek is queued or immediate. +bool mp_seek_chapter(struct MPContext *mpctx, int chapter) { - mpctx->last_chapter_seek = -2; - if (mpctx->chapters) { - if (chapter >= mpctx->num_chapters) - return -1; - if (chapter < 0) - chapter = 0; - *seek_pts = mpctx->chapters[chapter].start; - mpctx->last_chapter_seek = chapter; - mpctx->last_chapter_pts = *seek_pts; - return chapter; - } + int num = get_chapter_count(mpctx); + if (num == 0) + return false; + if (chapter < 0 || chapter >= num) + return false; - if (mpctx->master_demuxer) { - int res = demuxer_seek_chapter(mpctx->master_demuxer, chapter, seek_pts); + mpctx->last_chapter_seek = -2; + + double pts; + if (mpctx->chapters) { + pts = mpctx->chapters[chapter].start; + goto do_seek; + } else if (mpctx->master_demuxer) { + int res = demuxer_seek_chapter(mpctx->master_demuxer, chapter, &pts); if (res >= 0) { - if (*seek_pts == -1) - seek_reset(mpctx, true, true); // for DVD - else { - mpctx->last_chapter_seek = res; - mpctx->last_chapter_pts = *seek_pts; + if (pts == -1) { + // for DVD/BD - seek happened via stream layer + seek_reset(mpctx, true, true); + mpctx->seek = (struct seek_params){0}; + return true; } + chapter = res; + goto do_seek; } - return res; } - return -1; + return false; + +do_seek: + queue_seek(mpctx, MPSEEK_ABSOLUTE, pts, 0); + mpctx->last_chapter_seek = chapter; + mpctx->last_chapter_pts = pts; + return true; } static void update_avsync(struct MPContext *mpctx) @@ -3772,10 +3789,7 @@ static void run_playloop(struct MPContext *mpctx) } } - if (mpctx->seek.type) { - seek(mpctx, mpctx->seek, false); - mpctx->seek = (struct seek_params){ 0 }; - } + execute_queued_seek(mpctx); } @@ -4363,23 +4377,19 @@ goto_enable_cache: ; mpctx->playing_msg_shown = false; mpctx->paused = false; mpctx->paused_for_cache = false; + mpctx->seek = (struct seek_params){ 0 }; // If there's a timeline force an absolute seek to initialize state double startpos = rel_time_to_abs(mpctx, opts->play_start, -1); if (startpos != -1 || mpctx->timeline) { queue_seek(mpctx, MPSEEK_ABSOLUTE, startpos, 0); - seek(mpctx, mpctx->seek, false); + execute_queued_seek(mpctx); } if (opts->chapterrange[0] > 0) { - double pts; - if (seek_chapter(mpctx, opts->chapterrange[0] - 1, &pts) >= 0 - && pts > -1.0) { - queue_seek(mpctx, MPSEEK_ABSOLUTE, pts, 0); - seek(mpctx, mpctx->seek, false); - } + if (mp_seek_chapter(mpctx, opts->chapterrange[0] - 1)) + execute_queued_seek(mpctx); } - mpctx->seek = (struct seek_params){ 0 }; get_relative_time(mpctx); // reset current delta if (mpctx->opts.pause)