summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst23
-rw-r--r--demux/demux.c28
-rw-r--r--demux/demux.h6
-rw-r--r--etc/example.conf2
-rw-r--r--options/m_config.c2
-rw-r--r--options/options.c10
-rw-r--r--options/options.h5
-rw-r--r--player/playloop.c54
-rw-r--r--stream/stream.c1
9 files changed, 87 insertions, 44 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index caa2dbbb28..65e7673a1f 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -2751,20 +2751,6 @@ Cache
will not automatically enable the cache e.g. when playing from a network
stream. Note that using ``--cache`` will always override this option.
-``--cache-pause-below=<kBytes|no>``
- If the cache size goes below the specified value (in KB), pause and wait
- until the size set by ``--cache-pause-restart`` is reached, then resume
- playback (default: 50). If ``no`` is specified, this behavior is disabled.
-
- When the player is paused this way, the status line shows ``Buffering``
- instead of ``Paused``, and the OSD uses a clock symbol instead of the
- normal paused symbol.
-
-``--cache-pause-restart=<kBytes>``
- If the cache is paused due to the ``--cache-pause-below`` functionality,
- then the player unpauses as soon as the cache has this much data (in KB).
- (Default: 100)
-
``--cache-initial=<kBytes>``
Playback will start when the cache has been filled up with this many
kilobytes of data (default: 0).
@@ -2809,6 +2795,15 @@ Cache
``--no-cache``
Turn off input stream caching. See ``--cache``.
+``--cache-secs=<seconds>``
+ How many seconds of audio/video to prefetch if the cache is active. This
+ overrides the ``--demuxer-readahead-secs`` option if and only if the cache
+ is enabled. (Default: 10.)
+
+``--cache-pause``, ``--no-cache-pause``
+ Whether the player should automatically pause when the cache runs low,
+ and unpause once more data is available ("buffering").
+
Network
-------
diff --git a/demux/demux.c b/demux/demux.c
index e54027cc9d..2560a0736d 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -109,6 +109,7 @@ struct demux_internal {
bool warned_queue_overflow;
bool last_eof; // last actual global EOF status
bool eof; // whether we're in EOF state (reset for retry)
+ bool idle;
bool autoselect;
double min_secs;
int min_packs;
@@ -144,6 +145,10 @@ struct demux_stream {
struct demux_packet *tail;
};
+// If one of the values is NOPTS, always pick the other one.
+#define MP_PTS_MIN(a, b) ((a) == MP_NOPTS_VALUE || ((a) > (b)) ? (b) : (a))
+#define MP_PTS_MAX(a, b) ((a) == MP_NOPTS_VALUE || ((a) < (b)) ? (b) : (a))
+
static void demuxer_sort_chapters(demuxer_t *demuxer);
static void *demux_thread(void *pctx);
static void update_cache(struct demux_internal *in);
@@ -329,6 +334,7 @@ int demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
static bool read_packet(struct demux_internal *in)
{
in->eof = false;
+ in->idle = true;
// Check if we need to read a new packet. We do this if all queues are below
// the minimum, or if a stream explicitly needs new packets. Also includes
@@ -373,6 +379,7 @@ static bool read_packet(struct demux_internal *in)
// Actually read a packet. Drop the lock while doing so, because waiting
// for disk or network I/O can take time.
+ in->idle = false;
pthread_mutex_unlock(&in->lock);
struct demuxer *demux = in->d_thread;
bool eof = !demux->desc->fill_buffer || demux->desc->fill_buffer(demux) <= 0;
@@ -808,7 +815,8 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.d_thread = talloc(demuxer, struct demuxer),
.d_buffer = talloc(demuxer, struct demuxer),
.d_user = demuxer,
- .min_secs = demuxer->opts->demuxer_min_secs,
+ .min_secs = stream->uncached_stream ? demuxer->opts->demuxer_min_secs_cache
+ : demuxer->opts->demuxer_min_secs,
.min_packs = demuxer->opts->demuxer_min_packs,
.min_bytes = demuxer->opts->demuxer_min_bytes,
};
@@ -1162,6 +1170,24 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg)
in->tracks_switched = true;
pthread_cond_signal(&in->wakeup);
return DEMUXER_CTRL_OK;
+ case DEMUXER_CTRL_GET_READER_STATE: {
+ struct demux_ctrl_reader_state *r = arg;
+ *r = (struct demux_ctrl_reader_state){
+ .eof = in->last_eof,
+ .idle = in->idle,
+ .ts_range = {MP_NOPTS_VALUE, MP_NOPTS_VALUE},
+ };
+ for (int n = 0; n < in->d_user->num_streams; n++) {
+ struct demux_stream *ds = in->d_user->streams[n]->ds;
+ if (ds->active) {
+ r->underrun |= !ds->head;
+ r->ts_range[0] = MP_PTS_MAX(r->ts_range[0], ds->base_ts);
+ r->ts_range[1] = MP_PTS_MIN(r->ts_range[1], ds->last_ts);
+ }
+ }
+ r->idle &= !r->underrun;
+ return DEMUXER_CTRL_OK;
+ }
}
return DEMUXER_CTRL_DONTKNOW;
}
diff --git a/demux/demux.h b/demux/demux.h
index 92ef461077..d0f70c6f57 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -54,6 +54,12 @@ enum demux_ctrl {
DEMUXER_CTRL_RESYNC,
DEMUXER_CTRL_IDENTIFY_PROGRAM,
DEMUXER_CTRL_STREAM_CTRL,
+ DEMUXER_CTRL_GET_READER_STATE,
+};
+
+struct demux_ctrl_reader_state {
+ bool eof, underrun, idle;
+ double ts_range[2]; // start, end
};
struct demux_ctrl_stream_ctrl {
diff --git a/etc/example.conf b/etc/example.conf
index 4efe2c9b77..e335c8ea12 100644
--- a/etc/example.conf
+++ b/etc/example.conf
@@ -86,7 +86,7 @@
#
# Disable the behavior that the player will pause if the cache goes below a
# certain fill size.
-#cache-pause-below=no
+#cache-pause=no
#
# Read ahead about 5 seconds of audio and video packets.
#demuxer-readahead-secs=5.0
diff --git a/options/m_config.c b/options/m_config.c
index d8a5cceccb..479c2e952b 100644
--- a/options/m_config.c
+++ b/options/m_config.c
@@ -974,5 +974,7 @@ static const char *const replaced_opts =
"|status-msg#--term-status-msg"
"|idx#--index"
"|forceidx#--index"
+ "|cache-pause-below#for 'no', use --no-cache-pause"
+ "|no-cache-pause-below#--no-cache-pause"
"|"
;
diff --git a/options/options.c b/options/options.c
index 2ff524f522..a77568858d 100644
--- a/options/options.c
+++ b/options/options.c
@@ -144,9 +144,6 @@ const m_option_t mp_opts[] = {
OPT_INTRANGE("cache-seek-min", stream_cache.seek_min, 0, 0, 0x7fffffff),
OPT_STRING("cache-file", stream_cache.file, 0),
OPT_INTRANGE("cache-file-size", stream_cache.file_max, 0, 0, 0x7fffffff),
- OPT_CHOICE_OR_INT("cache-pause-below", stream_cache_pause, 0, 0, 0x7fffffff,
- ({"no", 0})),
- OPT_INTRANGE("cache-pause-restart", stream_cache_unpause, 0, 0, 0x7fffffff),
#if HAVE_DVDREAD || HAVE_DVDNAV
OPT_STRING("dvd-device", dvd_device, 0),
@@ -220,6 +217,9 @@ const m_option_t mp_opts[] = {
OPT_INTRANGE("demuxer-readahead-packets", demuxer_min_packs, 0, 0, MAX_PACKS),
OPT_INTRANGE("demuxer-readahead-bytes", demuxer_min_bytes, 0, 0, MAX_PACK_BYTES),
+ OPT_DOUBLE("cache-secs", demuxer_min_secs_cache, M_OPT_MIN, .min = 0),
+ OPT_FLAG("cache-pause", cache_pausing, 0),
+
OPT_DOUBLE("mf-fps", mf_fps, 0),
OPT_STRING("mf-type", mf_type, 0),
#if HAVE_TV
@@ -598,13 +598,13 @@ const struct MPOpts mp_default_opts = {
.seek_min = 500,
.file_max = 1024 * 1024,
},
- .stream_cache_pause = 50,
- .stream_cache_unpause = 100,
.demuxer_thread = 1,
.demuxer_min_packs = 0,
.demuxer_min_bytes = 0,
.demuxer_min_secs = 0.2,
.network_rtsp_transport = 2,
+ .demuxer_min_secs_cache = 10,
+ .cache_pausing = 1,
.chapterrange = {-1, -1},
.edition_id = -1,
.default_max_pts_correction = -1,
diff --git a/options/options.h b/options/options.h
index e5436383ad..4468d2abbd 100644
--- a/options/options.h
+++ b/options/options.h
@@ -123,8 +123,6 @@ typedef struct MPOpts {
int use_filedir_conf;
int network_rtsp_transport;
struct mp_cache_opts stream_cache;
- int stream_cache_pause;
- int stream_cache_unpause;
int chapterrange[2];
int edition_id;
int correct_pts;
@@ -189,6 +187,9 @@ typedef struct MPOpts {
char *sub_demuxer_name;
int mkv_subtitle_preroll;
+ double demuxer_min_secs_cache;
+ int cache_pausing;
+
struct image_writer_opts *screenshot_image_opts;
char *screenshot_template;
diff --git a/player/playloop.c b/player/playloop.c
index c96f53471d..026e4fda83 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -520,32 +520,44 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
struct MPOpts *opts = mpctx->opts;
if (!mpctx->demuxer)
return;
- int64_t fill = -1;
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_FILL, &fill);
- int cache_kb = fill > 0 ? (fill + 1023) / 1024 : -1;
- bool idle = mp_get_cache_idle(mpctx);
- if (mpctx->paused && mpctx->paused_for_cache) {
- if (cache_kb < 0 || cache_kb >= opts->stream_cache_unpause || idle) {
- mpctx->paused_for_cache = false;
- if (!opts->pause)
- unpause_player(mpctx);
- }
- mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.2);
- } else {
- if (cache_kb >= 0 && cache_kb <= opts->stream_cache_pause && !idle &&
- opts->stream_cache_pause < opts->stream_cache_unpause)
- {
- bool prev_paused_user = opts->pause;
- pause_player(mpctx);
- mpctx->paused_for_cache = true;
- opts->pause = prev_paused_user;
+
+ struct demux_ctrl_reader_state s =
+ {.idle = true, .ts_range = {MP_NOPTS_VALUE, MP_NOPTS_VALUE}};
+ demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);
+
+ double range = -1;
+ if (s.ts_range[0] != MP_NOPTS_VALUE && s.ts_range[1] != MP_NOPTS_VALUE)
+ range = s.ts_range[1] - s.ts_range[0];
+ if (range < 0)
+ range = 1e20; // unknown/broken timestamps; disable
+
+ if (mpctx->restart_complete) {
+ if (mpctx->paused && mpctx->paused_for_cache) {
+ if (!opts->cache_pausing || range >= 2.0 || s.eof) {
+ 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.eof) {
+ bool prev_paused_user = opts->pause;
+ pause_player(mpctx);
+ mpctx->paused_for_cache = true;
+ opts->pause = prev_paused_user;
+ }
}
}
+
+ int idle = 1;
+ demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_IDLE, &idle);
+
// Also update cache properties.
- if (cache_kb > 0 || mpctx->next_cache_update > 0) {
+ bool busy = idle == 0 || !s.idle;
+ if (busy || mpctx->next_cache_update > 0) {
double now = mp_time_sec();
if (mpctx->next_cache_update <= now) {
- mpctx->next_cache_update = cache_kb > 0 ? now + 0.25 : 0;
+ mpctx->next_cache_update = busy ? now + 0.25 : 0;
mp_notify(mpctx, MP_EVENT_CACHE_UPDATE, NULL);
}
if (mpctx->next_cache_update > 0) {
diff --git a/stream/stream.c b/stream/stream.c
index d600088267..7b8050dec0 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -782,6 +782,7 @@ static stream_t *open_cache(stream_t *orig, const char *name)
cache->demuxer = talloc_strdup(cache, orig->demuxer);
cache->lavf_type = talloc_strdup(cache, orig->lavf_type);
cache->safe_origin = orig->safe_origin;
+ cache->streaming = orig->streaming,
cache->opts = orig->opts;
cache->global = orig->global;