diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst index 3a649144d6..9b810424e6 100644 --- a/DOCS/man/en/changes.rst +++ b/DOCS/man/en/changes.rst @@ -146,7 +146,7 @@ Command Line Switches ``-aspect`` ``--video-aspect`` ``-ass-bottom-margin`` ``--vf=sub=bottom:top`` ``-ass`` ``--sub-ass`` - ``-audiofile-cache`` ``--audio-file-cache`` + ``-audiofile-cache`` (removed; the main cache settings are used) ``-audiofile`` ``--audio-file`` ``-benchmark`` ``--untimed`` (no stats) ``-capture`` ``--stream-capture=`` diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index f1de8b75bd..644ff7bfee 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -275,10 +275,6 @@ OPTIONS Play audio from an external file (WAV, MP3 or Ogg Vorbis) while viewing a movie. -``--audio-file-cache=`` - Enables caching for the stream used by ``--audio-file``, using the - specified amount of memory. - ``--audio-format=`` Select the sample format used for output from the audio filter layer to the sound card. The values that ```` can adopt are listed below in @@ -395,28 +391,33 @@ OPTIONS because no space is reserved for seeking back yet. ``--cache-default=`` - Set the size of the cache in kilobytes (default: 320 KB). Using ``no`` + Set the size of the cache in kilobytes (default: 25000 KB). Using ``no`` 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=`` - If the cache percentage goes below the specified value, pause and wait - until the percentage set by ``--cache-min`` is reached, then resume - playback (default: 10). If ``no`` is specified, this behavior is disabled. +``--cache-pause-below=`` + 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: 500). 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-min=`` - Playback will start when the cache has been filled up to ```` of - the total (default: 20). +``--cache-pause-restart=`` + 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: 1000) -``--cache-seek-min=`` - If a seek is to be made to a position within ```` of the cache +``--cache-initial=`` + Playback will start when the cache has been filled up with this many + kilobytes of data (default: 0). + +``--cache-seek-min=`` + If a seek is to be made to a position within ```` of the cache size from the current position, mpv will wait for the cache to be filled to this position rather than performing a stream seek (default: - 50). + 500). This matters for small forward seeks. With slow streams (especially http streams) there is a tradeoff between skipping the data between current diff --git a/options/m_config.c b/options/m_config.c index 271b2bde8b..857d6591b7 100644 --- a/options/m_config.c +++ b/options/m_config.c @@ -881,7 +881,6 @@ static const char *replaced_opts = "|aspect#--video-aspect" "|ass-bottom-margin#--vf=sub=bottom:top" "|ass#--sub-ass" - "|audiofile-cache#--audio-file-cache" "|audiofile#--audio-file" "|benchmark#--untimed (no stats)" "|capture#--stream-capture=" diff --git a/options/options.c b/options/options.c index 1e17854dba..37bea53472 100644 --- a/options/options.c +++ b/options/options.c @@ -238,18 +238,16 @@ const m_option_t mp_opts[] = { // ------------------------- stream options -------------------- - OPT_CHOICE_OR_INT("cache", stream_cache_size, 0, 32, 0x7fffffff, + OPT_CHOICE_OR_INT("cache", stream_cache.size, 0, 32, 0x7fffffff, ({"no", 0}, - {"auto", -1}), - OPTDEF_INT(-1)), - OPT_CHOICE_OR_INT("cache-default", stream_cache_def_size, 0, 32, 0x7fffffff, - ({"no", 0}), - OPTDEF_INT(320)), - OPT_FLOATRANGE("cache-min", stream_cache_min_percent, 0, 0, 99), - OPT_FLOATRANGE("cache-seek-min", stream_cache_seek_min_percent, 0, - 0, 99), - OPT_CHOICE_OR_INT("cache-pause", stream_cache_pause, 0, - 0, 40, ({"no", -1})), + {"auto", -1})), + OPT_CHOICE_OR_INT("cache-default", stream_cache.def_size, 0, 32, 0x7fffffff, + ({"no", 0})), + OPT_INTRANGE("cache-initial", stream_cache.initial, 0, 0, 0x7fffffff), + OPT_INTRANGE("cache-seek-min", stream_cache.seek_min, 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), {"cdrom-device", &cdrom_device, CONF_TYPE_STRING, 0, 0, 0, NULL}, #if HAVE_DVDREAD || HAVE_DVDNAV @@ -319,7 +317,6 @@ const m_option_t mp_opts[] = { // demuxer.c - select audio/sub file/demuxer OPT_STRING("audio-file", audio_stream, 0), - OPT_INTRANGE("audio-file-cache", audio_stream_cache, 0, 50, 65536), OPT_STRING("demuxer", demuxer_name, 0), OPT_STRING("audio-demuxer", audio_demuxer_name, 0), OPT_STRING("sub-demuxer", sub_demuxer_name, 0), @@ -692,9 +689,14 @@ const struct MPOpts mp_default_opts = { .hr_seek_framedrop = 1, .load_config = 1, .position_resume = 1, - .stream_cache_min_percent = 20.0, - .stream_cache_seek_min_percent = 50.0, - .stream_cache_pause = 10.0, + .stream_cache = { + .size = -1, + .def_size = 25000, + .initial = 0, + .seek_min = 500, + }, + .stream_cache_pause = 500, + .stream_cache_unpause = 1000, .network_rtsp_transport = 2, .chapterrange = {-1, -1}, .edition_id = -1, diff --git a/options/options.h b/options/options.h index e7008846de..d512089b3a 100644 --- a/options/options.h +++ b/options/options.h @@ -40,6 +40,13 @@ typedef struct mp_vo_opts { int fs_missioncontrol; } mp_vo_opts; +struct mp_cache_opts { + int size; + int def_size; + int initial; + int seek_min; +}; + typedef struct MPOpts { int use_terminal; char *msglevels; @@ -108,12 +115,10 @@ typedef struct MPOpts { int load_config; char *force_configdir; int use_filedir_conf; - int stream_cache_size; - int stream_cache_def_size; - float stream_cache_min_percent; - float stream_cache_seek_min_percent; 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; @@ -170,7 +175,6 @@ typedef struct MPOpts { char *sub_cp; char *audio_stream; - int audio_stream_cache; char *demuxer_name; char *audio_demuxer_name; char *sub_demuxer_name; diff --git a/player/loadfile.c b/player/loadfile.c index 723837baa8..2a41149b11 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -743,7 +743,7 @@ static void open_subtitles_from_options(struct MPContext *mpctx) } static struct track *open_external_file(struct MPContext *mpctx, char *filename, - char *demuxer_name, int stream_cache, + char *demuxer_name, enum stream_type filter) { struct MPOpts *opts = mpctx->opts; @@ -755,10 +755,8 @@ static struct track *open_external_file(struct MPContext *mpctx, char *filename, struct stream *stream = stream_open(filename, mpctx->global); if (!stream) goto err_out; - stream_enable_cache_percent(&stream, stream_cache, - opts->stream_cache_def_size, - opts->stream_cache_min_percent, - opts->stream_cache_seek_min_percent); + if (filter != STREAM_SUB) + stream_enable_cache(&stream, &opts->stream_cache); struct demuxer_params params = { .expect_subtitle = filter == STREAM_SUB, }; @@ -799,13 +797,13 @@ static void open_audiofiles_from_options(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; open_external_file(mpctx, opts->audio_stream, opts->audio_demuxer_name, - opts->audio_stream_cache, STREAM_AUDIO); + STREAM_AUDIO); } struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename) { struct MPOpts *opts = mpctx->opts; - return open_external_file(mpctx, filename, opts->sub_demuxer_name, 0, + return open_external_file(mpctx, filename, opts->sub_demuxer_name, STREAM_SUB); } @@ -821,7 +819,7 @@ static void open_subtitles_from_resolve(struct MPContext *mpctx) if (!s) s = talloc_asprintf(NULL, "memory://%s", sub->data); struct track *t = - open_external_file(mpctx, s, opts->sub_demuxer_name, 0, STREAM_SUB); + open_external_file(mpctx, s, opts->sub_demuxer_name, STREAM_SUB); talloc_free(s); if (t) { t->lang = talloc_strdup(t, sub->lang); @@ -1125,12 +1123,7 @@ static void play_current_file(struct MPContext *mpctx) // Must be called before enabling cache. mp_nav_init(mpctx); - // CACHE2: initial prefill: 20% later: 5% (should be set by -cacheopts) - int res = stream_enable_cache_percent(&mpctx->stream, - opts->stream_cache_size, - opts->stream_cache_def_size, - opts->stream_cache_min_percent, - opts->stream_cache_seek_min_percent); + int res = stream_enable_cache(&mpctx->stream, &opts->stream_cache); if (res == 0) if (demux_was_interrupted(mpctx)) goto terminate_playback; diff --git a/player/playloop.c b/player/playloop.c index 9e7a673f73..835d9b0bec 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -650,17 +650,21 @@ static void handle_metadata_update(struct MPContext *mpctx) static void handle_pause_on_low_cache(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - int cache = mp_get_cache_percent(mpctx); + if (!mpctx->stream) + return; + int64_t fill = -1; + stream_control(mpctx->stream, 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 < 0 || cache >= opts->stream_cache_min_percent || idle) { + if (cache_kb < 0 || cache_kb >= opts->stream_cache_unpause || idle) { mpctx->paused_for_cache = false; if (!opts->pause) unpause_player(mpctx); } } else { - if (cache >= 0 && cache <= opts->stream_cache_pause && !idle && - opts->stream_cache_pause < opts->stream_cache_min_percent) + 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); diff --git a/player/timeline/tl_matroska.c b/player/timeline/tl_matroska.c index 176d35c21f..cfcc379867 100644 --- a/player/timeline/tl_matroska.c +++ b/player/timeline/tl_matroska.c @@ -119,7 +119,7 @@ static int enable_cache(struct MPContext *mpctx, struct stream **stream, { struct MPOpts *opts = mpctx->opts; - if (opts->stream_cache_size <= 0) + if (!stream_wants_cache(*stream, &opts->stream_cache)) return 0; char *filename = talloc_strdup(NULL, (*demuxer)->filename); @@ -132,11 +132,7 @@ static int enable_cache(struct MPContext *mpctx, struct stream **stream, return -1; } - stream_enable_cache_percent(stream, - opts->stream_cache_size, - opts->stream_cache_def_size, - opts->stream_cache_min_percent, - opts->stream_cache_seek_min_percent); + stream_enable_cache(stream, &opts->stream_cache); *demuxer = demux_open(*stream, "mkv", params, mpctx->global); if (!*demuxer) { diff --git a/player/timeline/tl_mpv_edl.c b/player/timeline/tl_mpv_edl.c index 277db5b87f..7892d5294d 100644 --- a/player/timeline/tl_mpv_edl.c +++ b/player/timeline/tl_mpv_edl.c @@ -129,11 +129,7 @@ static struct demuxer *open_file(char *filename, struct MPContext *mpctx) struct demuxer *d = NULL; struct stream *s = stream_open(filename, mpctx->global); if (s) { - stream_enable_cache_percent(&s, - opts->stream_cache_size, - opts->stream_cache_def_size, - opts->stream_cache_min_percent, - opts->stream_cache_seek_min_percent); + stream_enable_cache(&s, &opts->stream_cache); d = demux_open(s, NULL, NULL, mpctx->global); } if (!d) { diff --git a/stream/cache.c b/stream/cache.c index 6079f6b976..95ece34a8c 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -56,6 +56,7 @@ #include "osdep/threads.h" #include "common/msg.h" +#include "options/options.h" #include "stream.h" #include "common/common.h" @@ -655,18 +656,18 @@ static void cache_uninit(stream_t *cache) // return 1 on success, 0 if the function was interrupted and -1 on error, or // if the cache is disabled -int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size, - int64_t min, int64_t seek_limit) +int stream_cache_init(stream_t *cache, stream_t *stream, + struct mp_cache_opts *opts) { - if (size < 1) + if (opts->size < 1) return -1; struct priv *s = talloc_zero(NULL, struct priv); s->log = cache->log; - s->seek_limit = seek_limit; + s->seek_limit = opts->seek_min * 1024ULL; - if (resize_cache(s, size) != STREAM_OK) { + if (resize_cache(s, opts->size * 1024ULL) != STREAM_OK) { MP_ERR(s, "Failed to allocate cache buffer.\n"); talloc_free(s); return -1; @@ -687,6 +688,7 @@ int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size, cache->control = cache_control; cache->close = cache_uninit; + int64_t min = opts->initial * 1024ULL; if (min > s->buffer_size - FILL_LIMIT) min = s->buffer_size - FILL_LIMIT; diff --git a/stream/stream.c b/stream/stream.c index 59cd2f7763..b6fec81eb8 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -41,6 +41,7 @@ #include "common/global.h" #include "bstr/bstr.h" #include "common/msg.h" +#include "options/options.h" #include "options/path.h" #include "osdep/timer.h" #include "stream.h" @@ -772,36 +773,33 @@ stream_t *open_memory_stream(void *data, int len) return s; } -static int stream_enable_cache(stream_t **stream, int64_t size, int64_t min, - int64_t seek_limit); - -/** - * \return 1 on success, 0 if the function was interrupted and -1 on error, or - * if the cache is disabled - */ -int stream_enable_cache_percent(stream_t **stream, int64_t stream_cache_size, - int64_t stream_cache_def_size, - float stream_cache_min_percent, - float stream_cache_seek_min_percent) +static struct mp_cache_opts check_cache_opts(stream_t *stream, + struct mp_cache_opts *opts) { - if (stream_cache_size == -1) - stream_cache_size = (*stream)->streaming ? stream_cache_def_size : 0; + struct mp_cache_opts use_opts = *opts; + if (use_opts.size == -1) + use_opts.size = stream->streaming ? use_opts.def_size : 0; - stream_cache_size = stream_cache_size * 1024; // input is in KiB - return stream_enable_cache(stream, stream_cache_size, - stream_cache_size * - (stream_cache_min_percent / 100.0), - stream_cache_size * - (stream_cache_seek_min_percent / 100.0)); + if (stream->mode != STREAM_READ || !stream->allow_caching || use_opts.size < 1) + use_opts.size = 0; + return use_opts; } -static int stream_enable_cache(stream_t **stream, int64_t size, int64_t min, - int64_t seek_limit) +bool stream_wants_cache(stream_t *stream, struct mp_cache_opts *opts) +{ + struct mp_cache_opts use_opts = check_cache_opts(stream, opts); + return use_opts.size > 0; +} + +// return: 1 on success, 0 if the function was interrupted and -1 on error, or +// if the cache is disabled +int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts) { stream_t *orig = *stream; + struct mp_cache_opts use_opts = check_cache_opts(*stream, opts); - if (orig->mode != STREAM_READ || !orig->allow_caching) - return 1; + if (use_opts.size < 1) + return -1; stream_t *cache = new_stream(); cache->uncached_type = orig->type; @@ -822,7 +820,7 @@ static int stream_enable_cache(stream_t **stream, int64_t size, int64_t min, cache->log = mp_log_new(cache, cache->global->log, "cache"); - int res = stream_cache_init(cache, orig, size, min, seek_limit); + int res = stream_cache_init(cache, orig, &use_opts); if (res <= 0) { cache->uncached_stream = NULL; // don't free original stream free_stream(cache); diff --git a/stream/stream.h b/stream/stream.h index 0fabd62b1f..3675ea9732 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -177,14 +177,13 @@ int stream_fill_buffer(stream_t *s); void stream_set_capture_file(stream_t *s, const char *filename); -int stream_enable_cache_percent(stream_t **stream, int64_t stream_cache_size, - int64_t stream_cache_def_size, - float stream_cache_min_percent, - float stream_cache_seek_min_percent); +struct mp_cache_opts; +bool stream_wants_cache(stream_t *stream, struct mp_cache_opts *opts); +int stream_enable_cache(stream_t **stream, struct mp_cache_opts *opts); // Internal -int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size, - int64_t min, int64_t seek_limit); +int stream_cache_init(stream_t *cache, stream_t *stream, + struct mp_cache_opts *opts); int stream_write_buffer(stream_t *s, unsigned char *buf, int len);