diff options
author | wm4 <wm4@nowhere> | 2013-09-15 05:03:37 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-09-15 05:03:55 +0200 |
commit | 884c179177063ad81cf7a7242c01767f46cd1cf8 (patch) | |
tree | b7f1c8b896541594eff6f59c36a97a65decdca3f /mpvcore/mplayer.c | |
parent | aa43405020e2e710b8b431633b6750e92897c6b9 (diff) | |
download | mpv-884c179177063ad81cf7a7242c01767f46cd1cf8.tar.bz2 mpv-884c179177063ad81cf7a7242c01767f46cd1cf8.tar.xz |
mplayer: attempt to skip playlist entries which can't be played
This is for situations when repeated attempts at playing a playlist
entry failed, and playlist navigation becomes impossible due to that.
For example, it wasn't possible to skip backwards past an unplayable
playlist entry:
mpv file1.mkv doesntexist.mkv file3.mkv
You couldn't skip back to file1.mkv from file3.mkv. When running a
single "playlist_prev" command, doesntexist.mkv would be played, which
would fail to load. As reaction to the failure to load it, the next file
would be played, which is file3.mkv.
To make this even worse, the file could successfully load, but run only
for a split second. So just loading successfully isn't good enough.
Attempt to solve this by marking problematic playlist entries as failed,
and by having playlist_prev skip past such playlist entries. We define
failure as not being able to play more than 3 seconds (or failing to
initialize to begin with). (The 3 seconds are in real time, not file
duration.)
"playlist_prev force" still exhibits the old behavior.
Additionally, use the same mechanism to prevent pointless infinite
reloading if none of the files on the playlist exist. (See github issue
All in all, this is a heuristic, and later adjustments might be
necessary.
Note: forward skips (playlist_next) are not affected at all. (Except for
the interaction with --loop.)
Diffstat (limited to 'mpvcore/mplayer.c')
-rw-r--r-- | mpvcore/mplayer.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c index 06017c7d32..fe5b120c50 100644 --- a/mpvcore/mplayer.c +++ b/mpvcore/mplayer.c @@ -4287,6 +4287,7 @@ static void transfer_playlist(struct MPContext *mpctx, struct playlist *pl) static void play_current_file(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; + double playback_start = -1e100; mpctx->initialized_flags |= INITIALIZED_PLAYBACK; mpctx->stop_play = 0; @@ -4574,6 +4575,7 @@ goto_reopen_demuxer: ; if (mpctx->opts->pause) pause_player(mpctx); + playback_start = mp_time_sec(); mpctx->error_playing = false; while (!mpctx->stop_play) run_playloop(mpctx); @@ -4591,6 +4593,9 @@ goto_reopen_demuxer: ; terminate_playback: // don't jump here after ao/vo/getch initialization! + if (mpctx->stop_play == KEEP_PLAYING) + mpctx->stop_play = AT_END_OF_FILE; + if (opts->position_save_on_quit && mpctx->stop_play == PT_QUIT) mp_write_watch_later_conf(mpctx); @@ -4622,13 +4627,26 @@ terminate_playback: // don't jump here after ao/vo/getch initialization! mpctx->osd->ass_renderer = NULL; ass_clear_fonts(mpctx->ass_library); #endif + + // Played/paused for longer than 3 seconds -> ok + bool playback_failed = mpctx->stop_play == AT_END_OF_FILE && + (playback_start < 0 || mp_time_sec() - playback_start < 3.0); + if (mpctx->playlist->current && !mpctx->playlist->current_was_replaced) + mpctx->playlist->current->playback_failed = playback_failed; } // Determine the next file to play. Note that if this function returns non-NULL, // it can have side-effects and mutate mpctx. -struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction) +// direction: -1 (previous) or +1 (next) +// force: if true, don't skip playlist entries marked as failed +struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction, + bool force) { struct playlist_entry *next = playlist_get_next(mpctx->playlist, direction); + if (direction < 0 && !force) { + while (next && next->playback_failed) + next = next->prev; + } if (!next && mpctx->opts->loop_times >= 0) { if (direction > 0) { if (mpctx->opts->shuffle) @@ -4642,6 +4660,17 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction) } else { next = mpctx->playlist->last; } + if (!force && next && next->playback_failed) { + bool all_failed = true; + struct playlist_entry *cur; + for (cur = mpctx->playlist->first; cur; cur = cur->next) { + all_failed &= cur->playback_failed; + if (!all_failed) + break; + } + if (all_failed) + next = NULL; + } } return next; } @@ -4678,7 +4707,7 @@ static void play_files(struct MPContext *mpctx) struct playlist_entry *new_entry = NULL; if (mpctx->stop_play == PT_NEXT_ENTRY) { - new_entry = mp_next_file(mpctx, +1); + new_entry = mp_next_file(mpctx, +1, false); } else if (mpctx->stop_play == PT_CURRENT_ENTRY) { new_entry = mpctx->playlist->current; } else if (mpctx->stop_play == PT_RESTART) { |