1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-04 14:12:10 +00:00

loadfile: fix an old wonky playlist heuristic

2c6a3cb1f2 originally added this struct
member and then 1be863afdb later added
some more logic to loadfile that uses this. There's been more changes
since then of course, but bits using playback_short and playback_start
have mostly stayed the same. It's a bit strange it's worked this way for
so long since it makes an assumption on how long files should be and
leads to weird, broken behavior on playlists with shorter videos. The
main reason for playlist_short, as far as I can tell, is to deal with
some fringe cases with short videos and trying to go back in the
playlist. More specifically, if you use --loop=inf on a very short video
(say less than 1 second) and try to go back in the playlist, you won't
be able to without any of this special logic that deals with it. But the
current approach has several side effects like going back multiple items
in the playlist instead of just one if the video is less than one
second. This is just bad so delete everything related to playlist_short
and playlist_start.

Instead, let's handle this by keeping track of playlist-prev attempts.
Going forward in the playlist doesn't require any special handling since
a bad/broken file will just advance to the next one. So it's only going
backwards that requires some special consideration. If we're going
backwards and the user isn't using force, then mark the playlist entry
with a special flag. If the file loads successfully in
play_current_file, we can just clear the flag and not worry about it.
However if there's a failure, then we set a bool telling
play_current_file that it should go back one more item in the playlist
if possible and try again. This way, we avoid the previously mentioned
--loop=inf edgecase and the user can still attempt to retry previously
failed items in the playlist (like a url or such).

Fixes , fixes .
This commit is contained in:
Dudemanguy 2023-10-03 13:02:29 -05:00 committed by sfan5
parent d32f1aac3f
commit 034f75dacd
2 changed files with 20 additions and 17 deletions

View File

@ -43,11 +43,12 @@ struct playlist_entry {
// Used for unshuffling: the pl_index before it was shuffled. -1 => unknown.
int original_index;
// Set to true if playback didn't seem to work, or if the file could be
// played only for a very short time. This is used to make playlist
// navigation just work in case the user has unplayable files in the
// playlist.
bool playback_short : 1;
// Set to true if this playlist entry was selected while trying to go backwards
// in the playlist. If this is true and the playlist entry fails to play later,
// then mpv tries to go to the next previous entry. This flag is always cleared
// regardless if the attempt was successful or not.
bool playlist_prev_attempt : 1;
// Set to true if not at least 1 frame (audio or video) could be played.
bool init_failed : 1;
// Entry was removed with playlist_remove (etc.), but not deallocated.

View File

@ -1567,7 +1567,6 @@ static void load_external_opts(struct MPContext *mpctx)
static void play_current_file(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
double playback_start = -1e100;
assert(mpctx->stop_play);
mpctx->stop_play = 0;
@ -1787,6 +1786,7 @@ static void play_current_file(struct MPContext *mpctx)
MP_VERBOSE(mpctx, "Starting playback...\n");
mpctx->playback_initialized = true;
mpctx->playing->playlist_prev_attempt = false;
mp_notify(mpctx, MPV_EVENT_FILE_LOADED, NULL);
update_screensaver_state(mpctx);
clear_playlist_paths(mpctx);
@ -1828,7 +1828,6 @@ static void play_current_file(struct MPContext *mpctx)
update_internal_pause_state(mpctx);
playback_start = mp_time_sec();
mpctx->error_playing = 0;
mpctx->in_playloop = true;
while (!mpctx->stop_play)
@ -1885,6 +1884,7 @@ terminate_playback:
bool nothing_played = !mpctx->shown_aframes && !mpctx->shown_vframes &&
mpctx->error_playing <= 0;
bool playlist_prev_continue = false;
switch (mpctx->stop_play) {
case PT_ERROR:
case AT_END_OF_FILE:
@ -1900,10 +1900,10 @@ terminate_playback:
end_event.reason = MPV_END_FILE_REASON_EOF;
}
if (mpctx->playing) {
// Played/paused for longer than 1 second -> ok
mpctx->playing->playback_short =
playback_start < 0 || mp_time_sec() - playback_start < 1.0;
mpctx->playing->init_failed = nothing_played;
playlist_prev_continue = mpctx->playing->playlist_prev_attempt &&
nothing_played;
mpctx->playing->playlist_prev_attempt = false;
}
break;
}
@ -1939,6 +1939,14 @@ terminate_playback:
assert(mpctx->stop_play);
process_hooks(mpctx, "on_after_end_file");
if (playlist_prev_continue) {
struct playlist_entry *e = mp_next_file(mpctx, -1, false, true);
if (e) {
mp_set_playlist_entry(mpctx, e);
play_current_file(mpctx);
}
}
}
// Determine the next file to play. Note that if this function returns non-NULL,
@ -1951,12 +1959,9 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
{
struct playlist_entry *next = playlist_get_next(mpctx->playlist, direction);
if (next && direction < 0 && !force) {
// Don't jump to files that would immediately go to next file anyway
while (next && next->playback_short)
next = playlist_entry_get_rel(next, -1);
// Always allow jumping to first file
if (!next && mpctx->opts->loop_times == 1)
next = playlist_get_first(mpctx->playlist);
next->playlist_prev_attempt = true;
}
if (!next && mpctx->opts->loop_times != 1) {
if (direction > 0) {
@ -1970,9 +1975,6 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
}
} else {
next = playlist_get_last(mpctx->playlist);
// Don't jump to files that would immediately go to next file anyway
while (next && next->playback_short)
next = playlist_entry_get_rel(next, -1);
}
bool ignore_failures = mpctx->opts->loop_times == -2;
if (!force && next && next->init_failed && !ignore_failures) {