summaryrefslogtreecommitdiffstats
path: root/player/playloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/playloop.c')
-rw-r--r--player/playloop.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/player/playloop.c b/player/playloop.c
index e0d0056d7d..99069401de 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -660,18 +660,36 @@ static void handle_osd_redraw(struct MPContext *mpctx)
vo_redraw(mpctx->video_out);
}
+static void clear_underruns(struct MPContext *mpctx)
+{
+ if (mpctx->ao_chain && mpctx->ao_chain->underrun) {
+ mpctx->ao_chain->underrun = false;
+ mp_wakeup_core(mpctx);
+ }
+
+ if (mpctx->vo_chain && mpctx->vo_chain->underrun) {
+ mpctx->vo_chain->underrun = false;
+ mp_wakeup_core(mpctx);
+ }
+}
+
static void handle_update_cache(struct MPContext *mpctx)
{
bool force_update = false;
struct MPOpts *opts = mpctx->opts;
- if (!mpctx->demuxer)
+
+ if (!mpctx->demuxer) {
+ clear_underruns(mpctx);
return;
+ }
double now = mp_time_sec();
struct demux_reader_state s;
demux_get_reader_state(mpctx->demuxer, &s);
+ mpctx->demux_underrun |= s.underrun;
+
int cache_buffer = 100;
bool use_pause_on_low_cache = demux_is_network_cached(mpctx->demuxer) &&
opts->cache_pause && mpctx->play_dir > 0;
@@ -690,17 +708,43 @@ static void handle_update_cache(struct MPContext *mpctx)
// Enter buffering state only if there actually was an underrun (or if
// initial caching before playback restart is used).
- if (is_low && !mpctx->paused_for_cache && mpctx->restart_complete)
- is_low = s.underrun;
+ bool need_wait = is_low;
+ if (is_low && !mpctx->paused_for_cache && mpctx->restart_complete) {
+ // Wait only if an output underrun was registered. (Or if there is no
+ // underrun detection.)
+ bool output_underrun = false;
+
+ if (mpctx->ao_chain) {
+ output_underrun |=
+ !(mpctx->ao && ao_get_reports_underruns(mpctx->ao)) ||
+ mpctx->ao_chain->underrun;
+ }
+ if (mpctx->vo_chain)
+ output_underrun |= mpctx->vo_chain->underrun;
+
+ // Output underruns could be sporadic (unrelated to demuxer buffer state
+ // and for example caused by slow decoding), so use a past demuxer
+ // underrun as indication that the underrun was possibly due to a
+ // demuxer underrun.
+ need_wait = mpctx->demux_underrun && output_underrun;
+ }
+
+ // Let the underrun flag "stick" around until the cache has fully recovered.
+ // See logic where demux_underrun is used.
+ if (!is_low)
+ mpctx->demux_underrun = false;
- if (mpctx->paused_for_cache != is_low) {
- mpctx->paused_for_cache = is_low;
+ if (mpctx->paused_for_cache != need_wait) {
+ mpctx->paused_for_cache = need_wait;
update_internal_pause_state(mpctx);
force_update = true;
- if (is_low)
+ if (mpctx->paused_for_cache)
mpctx->cache_stop_time = now;
}
+ if (!mpctx->paused_for_cache)
+ clear_underruns(mpctx);
+
if (mpctx->paused_for_cache) {
cache_buffer =
100 * MPCLAMP(s.ts_duration / opts->cache_pause_wait, 0, 0.99);