summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-29 21:10:36 +0200
committerwm4 <wm4@nowhere>2013-09-29 21:10:45 +0200
commit2c6a3cb1f27e02b2e66390a2465ab648905a64d0 (patch)
tree722c7f5e4a7d55d1442be0b60dab85f124cfdd16
parent5b3ae5aaac4a223f1d92d56905088d1643414cdb (diff)
downloadmpv-2c6a3cb1f27e02b2e66390a2465ab648905a64d0.tar.bz2
mpv-2c6a3cb1f27e02b2e66390a2465ab648905a64d0.tar.xz
mplayer: fix looping of very short files
Commit 884c179 attempted to make it possible to skip backwards through the playlist, even for files which fail to intitialize, or play for a very short time. This was also used to prevent mpv from looping forever and doing nothing if --loop=inf is used, and no file in the playlist is playable. This broke looping of very short files, because mpv was assuming that this case happened. But there are legitimate use cases. Fix this by making the looping case special. Instead of checking whether playback was "very short", check whether something could be decoded and displayed/played. If yes, allow looping.
-rw-r--r--mpvcore/mp_core.h2
-rw-r--r--mpvcore/mplayer.c20
-rw-r--r--mpvcore/playlist.h4
3 files changed, 19 insertions, 7 deletions
diff --git a/mpvcore/mp_core.h b/mpvcore/mp_core.h
index e15ec0355e..28f34ee580 100644
--- a/mpvcore/mp_core.h
+++ b/mpvcore/mp_core.h
@@ -148,6 +148,8 @@ typedef struct MPContext {
bool has_quit_custom_rc;
bool error_playing;
+ int64_t shown_vframes, shown_aframes;
+
struct demuxer **sources;
int num_sources;
diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c
index 50c3db10d7..87e8601153 100644
--- a/mpvcore/mplayer.c
+++ b/mpvcore/mplayer.c
@@ -2146,6 +2146,7 @@ static int write_to_ao(struct MPContext *mpctx, void *data, int len, int flags,
ao->pts = pts;
int played = ao_play(mpctx->ao, data, len, flags);
if (played > 0) {
+ mpctx->shown_aframes += played / (af_fmt2bits(ao->format) / 8);
mpctx->delay += played / bps;
// Keep correct pts for remaining data - could be used to flush
// remaining buffer when closing ao.
@@ -3734,6 +3735,7 @@ static void run_playloop(struct MPContext *mpctx)
// For print_status - VO call finishing early is OK for sync
mpctx->time_frame -= get_relative_time(mpctx);
}
+ mpctx->shown_vframes++;
if (mpctx->restart_playback) {
if (mpctx->sync_audio_to_video) {
mpctx->syncing_audio = true;
@@ -4298,6 +4300,8 @@ static void play_current_file(struct MPContext *mpctx)
mpctx->stop_play = 0;
mpctx->filename = NULL;
+ mpctx->shown_aframes = 0;
+ mpctx->shown_vframes = 0;
if (mpctx->playlist->current)
mpctx->filename = mpctx->playlist->current->filename;
@@ -4635,10 +4639,14 @@ terminate_playback: // don't jump here after ao/vo/getch initialization!
#endif
// Played/paused for longer than 3 seconds -> ok
- bool playback_failed = mpctx->stop_play == AT_END_OF_FILE &&
+ bool playback_short = 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;
+ bool init_failed = mpctx->stop_play == AT_END_OF_FILE &&
+ (mpctx->shown_aframes == 0 && mpctx->shown_vframes == 0);
+ if (mpctx->playlist->current && !mpctx->playlist->current_was_replaced) {
+ mpctx->playlist->current->playback_short = playback_short;
+ mpctx->playlist->current->init_failed = init_failed;
+ }
mp_notify(mpctx, MP_EVENT_TRACKS_CHANGED, NULL);
mp_notify(mpctx, MP_EVENT_END_FILE, NULL);
@@ -4654,7 +4662,7 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
{
struct playlist_entry *next = playlist_get_next(mpctx->playlist, direction);
if (direction < 0 && !force) {
- while (next && next->playback_failed)
+ while (next && next->playback_short)
next = next->prev;
}
if (!next && mpctx->opts->loop_times >= 0) {
@@ -4670,11 +4678,11 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction,
} else {
next = mpctx->playlist->last;
}
- if (!force && next && next->playback_failed) {
+ if (!force && next && next->init_failed) {
bool all_failed = true;
struct playlist_entry *cur;
for (cur = mpctx->playlist->first; cur; cur = cur->next) {
- all_failed &= cur->playback_failed;
+ all_failed &= cur->init_failed;
if (!all_failed)
break;
}
diff --git a/mpvcore/playlist.h b/mpvcore/playlist.h
index 17a5cf6a9b..35d9dab701 100644
--- a/mpvcore/playlist.h
+++ b/mpvcore/playlist.h
@@ -38,7 +38,9 @@ struct playlist_entry {
// 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_failed;
+ bool playback_short : 1;
+ // Set to true if not at least 1 frame (audio or video) could be played.
+ bool init_failed : 1;
};
struct playlist {