summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2023-10-03 13:02:29 -0500
committersfan5 <sfan5@live.de>2023-10-05 17:09:43 +0200
commit034f75dacd01bd0b7c6c03e39b193f891f0d5ef2 (patch)
tree9f9297177be0bcb6c25adf0a8c5143f321a14fda
parentd32f1aac3ffd2e7b766773446c4510a2cad397fb (diff)
downloadmpv-034f75dacd01bd0b7c6c03e39b193f891f0d5ef2.tar.bz2
mpv-034f75dacd01bd0b7c6c03e39b193f891f0d5ef2.tar.xz
loadfile: fix an old wonky playlist heuristic
2c6a3cb1f27e02b2e66390a2465ab648905a64d0 originally added this struct member and then 1be863afdbe9017aa227234e8525b209fb818224 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 #6576, fixes #12548.
-rw-r--r--common/playlist.h11
-rw-r--r--player/loadfile.c26
2 files changed, 20 insertions, 17 deletions
diff --git a/common/playlist.h b/common/playlist.h
index f6111604f3..c5b82781e6 100644
--- a/common/playlist.h
+++ b/common/playlist.h
@@ -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.
diff --git a/player/loadfile.c b/player/loadfile.c
index 745a19a697..3fcc7b633d 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -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) {