mirror of
https://github.com/mpv-player/mpv
synced 2024-12-28 18:12:22 +00:00
playloop: make chapter property more accurate when seeking chapters
When seeking chapters, `last_chapter_seek` acts as a projection of what the current chapter will be once mpv has a chance to seek to it. This allows for more accurate results from the `chapter` property. It works by comparing the projection to the actual current chapter and returning the larger of the two indexes, but this only works when seeking forward. If we want it to work for both forward and backward chapter seeking, we can instead use a boolean called `last_chapter_flag`, which gets switched on when a chapter seek request is made, and then switched off when the seek has been performed. We should also check to ensure that we don't allow the chapter index to be set to -1 unless there is a span of time between the very beginning of the track and the start of the first chapter. Since the new approach to resetting `last_chapter_seek` no longer depends on `last_chapter_pts`, that member variable can be removed.
This commit is contained in:
parent
27ef1725e7
commit
233f1e46f6
@ -907,8 +907,8 @@ static int mp_property_chapter(void *ctx, struct m_property *prop,
|
||||
} else // Absolute set
|
||||
step_all = *(int *)arg - chapter;
|
||||
chapter += step_all;
|
||||
if (chapter < -1)
|
||||
chapter = -1;
|
||||
if (chapter < 0) // avoid using -1 if first chapter starts at 0
|
||||
chapter = (chapter_start_time(mpctx, 0) <= 0) ? 0 : -1;
|
||||
if (chapter >= num && step_all > 0) {
|
||||
if (mpctx->opts->keep_open) {
|
||||
seek_to_last_frame(mpctx);
|
||||
@ -923,9 +923,9 @@ static int mp_property_chapter(void *ctx, struct m_property *prop,
|
||||
} else {
|
||||
double pts = chapter_start_time(mpctx, chapter);
|
||||
if (pts != MP_NOPTS_VALUE) {
|
||||
queue_seek(mpctx, MPSEEK_ABSOLUTE, pts, MPSEEK_DEFAULT, 0);
|
||||
queue_seek(mpctx, MPSEEK_CHAPTER, pts, MPSEEK_DEFAULT, 0);
|
||||
mpctx->last_chapter_seek = chapter;
|
||||
mpctx->last_chapter_pts = pts;
|
||||
mpctx->last_chapter_flag = true;
|
||||
}
|
||||
}
|
||||
return M_PROPERTY_OK;
|
||||
|
@ -70,6 +70,7 @@ enum seek_type {
|
||||
MPSEEK_ABSOLUTE,
|
||||
MPSEEK_FACTOR,
|
||||
MPSEEK_BACKSTEP,
|
||||
MPSEEK_CHAPTER,
|
||||
};
|
||||
|
||||
enum seek_precision {
|
||||
@ -400,7 +401,7 @@ typedef struct MPContext {
|
||||
* the user wanted to go to, even if we aren't exactly within the
|
||||
* boundaries of that chapter due to an inaccurate seek. */
|
||||
int last_chapter_seek;
|
||||
double last_chapter_pts;
|
||||
bool last_chapter_flag;
|
||||
|
||||
bool paused; // internal pause state
|
||||
bool playback_active; // not paused, restarting, loading, unloading
|
||||
|
@ -1592,7 +1592,7 @@ static void play_current_file(struct MPContext *mpctx)
|
||||
mpctx->shown_aframes = 0;
|
||||
mpctx->shown_vframes = 0;
|
||||
mpctx->last_chapter_seek = -2;
|
||||
mpctx->last_chapter_pts = MP_NOPTS_VALUE;
|
||||
mpctx->last_chapter_flag = false;
|
||||
mpctx->last_chapter = -2;
|
||||
mpctx->paused = false;
|
||||
mpctx->playing_msg_shown = false;
|
||||
|
@ -274,6 +274,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)
|
||||
@ -310,10 +317,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))
|
||||
@ -454,6 +457,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,
|
||||
@ -591,7 +595,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)
|
||||
|
Loading…
Reference in New Issue
Block a user