player: slightly better cache underrun detection

Use the "native" underrun detection, instead of guessing by a low cache
duration. The new underrun detection (which was added with the original
commit) might have the problem that it's easy for the playloop to miss
the underrun event. The underrun is actually not stored as state, so if
the demuxer thread adds a new packet before the playloop happens to see
the state, it's as if it never happened. On the other hand, this means
that network was fast enough, so it should be just fine.

Also, should it happen that we don't know the cached range (the
ts_duration < 0 case), just wait until the demuxer goes idle (i.e.
read_packet() decides to stop). This pretty much should affect broken or
unusual files only, and there might be various things that could go
wrong. But it's more robust in the normal case: this situation also
happens when no packets have been read yet, and we don't want to
consider this as reason to resume playback.
This commit is contained in:
wm4 2014-08-27 22:51:06 +02:00
parent 7bb1afb8ea
commit cb642e7c84
2 changed files with 3 additions and 5 deletions

View File

@ -1187,6 +1187,7 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg)
}
}
r->idle = (in->idle && !r->underrun) || r->eof;
r->underrun &= !r->idle;
if (r->ts_range[0] != MP_NOPTS_VALUE && r->ts_range[1] != MP_NOPTS_VALUE)
r->ts_duration = r->ts_range[1] - r->ts_range[0];
return DEMUXER_CTRL_OK;

View File

@ -527,19 +527,16 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
struct demux_ctrl_reader_state s = {.idle = true, .ts_duration = -1};
demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);
// disable on unknown/broken timestamps
double range = s.ts_duration >= 0 ? s.ts_duration : 1e20;
if (mpctx->restart_complete && idle != -1) {
if (mpctx->paused && mpctx->paused_for_cache) {
if (!opts->cache_pausing || range >= 2.0 || s.idle) {
if (!opts->cache_pausing || s.ts_duration >= 2.0 || s.idle) {
mpctx->paused_for_cache = false;
if (!opts->pause)
unpause_player(mpctx);
}
mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.2);
} else {
if (opts->cache_pausing && range < 0.5 && !s.idle) {
if (opts->cache_pausing && s.underrun) {
bool prev_paused_user = opts->pause;
pause_player(mpctx);
mpctx->paused_for_cache = true;