summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/input.rst32
-rw-r--r--DOCS/man/options.rst100
-rw-r--r--demux/demux.c54
-rw-r--r--demux/demux.h3
-rw-r--r--demux/demux_disc.c7
-rw-r--r--demux/demux_mkv_timeline.c10
-rw-r--r--options/options.c3
-rw-r--r--options/options.h12
-rw-r--r--player/command.c134
-rw-r--r--player/core.h2
-rw-r--r--player/loadfile.c1
-rw-r--r--player/misc.c18
-rw-r--r--player/osd.c32
-rw-r--r--player/playloop.c7
-rw-r--r--stream/cache.c809
-rw-r--r--stream/cache_file.c158
-rw-r--r--stream/stream.c97
-rw-r--r--stream/stream.h27
-rw-r--r--stream/stream_avdevice.c1
-rw-r--r--stream/stream_dvb.c1
-rw-r--r--stream/stream_dvdnav.c1
-rw-r--r--stream/stream_edl.c1
-rw-r--r--stream/stream_file.c1
-rw-r--r--stream/stream_memory.c1
-rw-r--r--stream/stream_mf.c1
-rw-r--r--stream/stream_tv.c1
-rw-r--r--wscript_build.py2
27 files changed, 49 insertions, 1467 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index b577b688d0..5413ad79be 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -1455,38 +1455,6 @@ Property list
playing at all. In other words, it's only ``no`` if there's actually
video playing. (Behavior since mpv 0.7.0.)
-``cache``
- Network cache fill state (0-100.0).
-
-``cache-size`` (RW)
- Network cache size in KB. This is similar to ``--cache``. This allows
- setting the cache size at runtime. Currently, it's not possible to enable
- or disable the cache at runtime using this property, just to resize an
- existing cache.
-
- This does not include the backbuffer size (changed after mpv 0.10.0).
-
- Note that this tries to keep the cache contents as far as possible. To make
- this easier, the cache resizing code will allocate the new cache while the
- old cache is still allocated.
-
- Don't use this when playing DVD or Blu-ray.
-
-``cache-free`` (R)
- Total free cache size in KB.
-
-``cache-used`` (R)
- Total used cache size in KB.
-
-``cache-speed`` (R)
- Current I/O read speed between the cache and the lower layer (like network).
- This gives the number bytes per seconds over a 1 second window (using
- the type ``MPV_FORMAT_INT64`` for the client API).
-
-``cache-idle`` (R)
- Returns ``yes`` if the cache is idle, which means the cache is filled as
- much as possible, and is currently not reading more data.
-
``demuxer-cache-duration``
Approximate duration of video buffered in the demuxer, in seconds. The
guess is very unreliable, and often the property will not be available
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 9c66ca35cb..c8e75556c0 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3836,97 +3836,15 @@ TV
Cache
-----
-``--cache=<kBytes|yes|no|auto>``
- Set the size of the cache in kilobytes, disable it with ``no``, or
- automatically enable it if needed with ``auto`` (default: ``auto``).
- With ``auto``, the cache will usually be enabled for network streams,
- using the size set by ``--cache-default``. With ``yes``, the cache will
- always be enabled with the size set by ``--cache-default`` (unless the
- stream cannot be cached, or ``--cache-default`` disables caching).
-
- May be useful when playing files from slow media, but can also have
- negative effects, especially with file formats that require a lot of
- seeking, such as MP4.
-
- Note that half the cache size will be used to allow fast seeking back. This
- is also the reason why a full cache is usually not reported as 100% full.
- The cache fill display does not include the part of the cache reserved for
- seeking back. The actual maximum percentage will usually be the ratio
- between readahead and backbuffer sizes.
-
-``--cache-default=<kBytes|no>``
- Set the size of the cache in kilobytes (default: 10000 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-initial=<kBytes>``
- Playback will start when the cache has been filled up with this many
- kilobytes of data (default: 0).
-
-``--cache-seek-min=<kBytes>``
- If a seek is to be made to a position within ``<kBytes>`` 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:
- 500).
-
- This matters for small forward seeks. With slow streams (especially HTTP
- streams) there is a tradeoff between skipping the data between current
- position and seek destination, or performing an actual seek. Depending
- on the situation, either of these might be slower than the other method.
- This option allows control over this.
-
-``--cache-backbuffer=<kBytes>``
- Size of the cache back buffer (default: 10000 KB). This will add to the total
- cache size, and reserved the amount for seeking back. The reserved amount
- will not be used for readahead, and instead preserves already read data to
- enable fast seeking back.
-
-``--cache-file=<TMP|path>``
- Create a cache file on the filesystem.
-
- There are two ways of using this:
-
- 1. Passing a path (a filename). The file will always be overwritten. When
- the general cache is enabled, this file cache will be used to store
- whatever is read from the source stream.
-
- This will always overwrite the cache file, and you can't use an existing
- cache file to resume playback of a stream. (Technically, mpv wouldn't
- even know which blocks in the file are valid and which not.)
-
- The resulting file will not necessarily contain all data of the source
- stream. For example, if you seek, the parts that were skipped over are
- never read and consequently are not written to the cache. The skipped over
- parts are filled with zeros. This means that the cache file doesn't
- necessarily correspond to a full download of the source stream.
-
- Both of these issues could be improved if there is any user interest.
-
- .. warning:: Causes random corruption when used with ordered chapters or
- with ``--audio-file``.
-
- 2. Passing the string ``TMP``. This will not be interpreted as filename.
- Instead, an invisible temporary file is created. It depends on your
- C library where this file is created (usually ``/tmp/``), and whether
- filename is visible (the ``tmpfile()`` function is used). On some
- systems, automatic deletion of the cache file might not be guaranteed.
-
- If you want to use a file cache, this mode is recommended, because it
- doesn't break ordered chapters or ``--audio-file``. These modes open
- multiple cache streams, and using the same file for them obviously
- clashes.
-
- See also: ``--cache-file-size``.
-
-``--cache-file-size=<kBytes>``
- Maximum size of the file created with ``--cache-file``. For read accesses
- above this size, the cache is simply not used.
-
- Keep in mind that some use-cases, like playing ordered chapters with cache
- enabled, will actually create multiple cache files, each of which will
- use up to this much disk space.
-
- (Default: 1048576, 1 GB.)
+``--cache=<yes|no|auto>``
+ Decide whether to use network cache settings (default: auto).
+
+ If enabled, use the maximum of ``--cache-secs`` and ``--demuxer-max-bytes``
+ for the cache size. If disabled, ``--cache-pause`` and related are
+ implicitly disabled.
+
+ The ``auto`` choice sets this depending on whether the stream is thought to
+ involve network accesses (this is an imperfect heuristic).
``--no-cache``
Turn off input stream caching. See ``--cache``.
diff --git a/demux/demux.c b/demux/demux.c
index 3e9d897bb2..45f472cfc9 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -86,6 +86,7 @@ const demuxer_desc_t *const demuxer_list[] = {
};
struct demux_opts {
+ int enable_cache;
int64_t max_bytes;
int64_t max_bytes_bw;
double min_secs;
@@ -102,6 +103,8 @@ struct demux_opts {
const struct m_sub_options demux_conf = {
.opts = (const struct m_option[]){
+ OPT_CHOICE("cache", enable_cache, 0,
+ ({"no", 0}, {"auto", -1}, {"yes", 1})),
OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0),
// (The MAX_BYTES sizes may not be accurate because the max field is
// of double type.)
@@ -117,6 +120,7 @@ const struct m_sub_options demux_conf = {
},
.size = sizeof(struct demux_opts),
.defaults = &(const struct demux_opts){
+ .enable_cache = -1, // auto
.max_bytes = 150 * 1024 * 1024,
.max_bytes_bw = 50 * 1024 * 1024,
.min_secs = 1.0,
@@ -129,6 +133,8 @@ const struct m_sub_options demux_conf = {
struct demux_internal {
struct mp_log *log;
+ struct demux_opts *opts;
+
// The demuxer runs potentially in another thread, so we keep two demuxer
// structs; the real demuxer can access the shadow struct only.
struct demuxer *d_thread; // accessed by demuxer impl. (producer)
@@ -215,8 +221,6 @@ struct demux_internal {
// Transient state.
double duration;
// Cached state.
- bool force_cache_update;
- struct stream_cache_info stream_cache_info;
int64_t stream_size;
// Updated during init only.
char *stream_base_filename;
@@ -1695,9 +1699,6 @@ static void execute_trackswitch(struct demux_internal *in)
if (in->d_thread->desc->control)
in->d_thread->desc->control(in->d_thread, DEMUXER_CTRL_SWITCHED_TRACKS, 0);
- stream_control(in->d_thread->stream, STREAM_CTRL_SET_READAHEAD,
- &(int){any_selected});
-
pthread_mutex_lock(&in->lock);
}
@@ -1746,13 +1747,6 @@ static bool thread_work(struct demux_internal *in)
if (read_packet(in))
return true; // read_packet unlocked, so recheck conditions
}
- if (in->force_cache_update) {
- pthread_mutex_unlock(&in->lock);
- update_cache(in);
- pthread_mutex_lock(&in->lock);
- in->force_cache_update = false;
- return true;
- }
return false;
}
@@ -2276,6 +2270,19 @@ static void fixup_metadata(struct demux_internal *in)
}
}
+// Return whether "heavy" caching on this stream is enabled. By default, this
+// corresponds to whether the source stream is considered in the network. The
+// only effect should be adjusting display behavior (of cache stats etc.), and
+// possibly switching between which set of options influence cache settings.
+bool demux_is_network_cached(demuxer_t *demuxer)
+{
+ struct demux_internal *in = demuxer->in;
+ bool use_cache = demuxer->is_network;
+ if (in->opts->enable_cache >= 0)
+ use_cache = in->opts->enable_cache == 1;
+ return use_cache;
+}
+
static struct demuxer *open_given_type(struct mpv_global *global,
struct mp_log *log,
const struct demuxer_desc *desc,
@@ -2305,12 +2312,11 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.extended_ctrls = stream->extended_ctrls,
};
demuxer->seekable = stream->seekable;
- if (demuxer->stream->underlying && !demuxer->stream->underlying->seekable)
- demuxer->seekable = false;
struct demux_internal *in = demuxer->in = talloc_ptrtype(demuxer, in);
*in = (struct demux_internal){
.log = demuxer->log,
+ .opts = opts,
.d_thread = talloc(demuxer, struct demuxer),
.d_user = demuxer,
.min_secs = opts->min_secs,
@@ -2371,10 +2377,8 @@ static struct demuxer *open_given_type(struct mpv_global *global,
fixup_metadata(in);
in->events = DEMUX_EVENT_ALL;
demux_update(demuxer);
- stream_control(demuxer->stream, STREAM_CTRL_SET_READAHEAD,
- &(int){params ? params->initial_readahead : false});
int seekable = opts->seekable_cache;
- if (demuxer->is_network || stream->caching) {
+ if (demux_is_network_cached(demuxer)) {
in->min_secs = MPMAX(in->min_secs, opts->min_secs_cache);
if (seekable < 0)
seekable = 1;
@@ -2486,8 +2490,6 @@ struct demuxer *demux_open_url(const char *url,
talloc_free(priv_cancel);
return NULL;
}
- if (!params->disable_cache)
- stream_enable_cache_defaults(&s);
struct demuxer *d = demux_open(s, params, global);
if (d) {
talloc_steal(d->in, priv_cancel);
@@ -3042,15 +3044,12 @@ static void update_cache(struct demux_internal *in)
// Don't lock while querying the stream.
struct mp_tags *stream_metadata = NULL;
- struct stream_cache_info stream_cache_info = {.size = -1};
int64_t stream_size = stream_get_size(stream);
stream_control(stream, STREAM_CTRL_GET_METADATA, &stream_metadata);
- stream_control(stream, STREAM_CTRL_GET_CACHE_INFO, &stream_cache_info);
pthread_mutex_lock(&in->lock);
in->stream_size = stream_size;
- in->stream_cache_info = stream_cache_info;
if (stream_metadata) {
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
@@ -3065,18 +3064,7 @@ static void update_cache(struct demux_internal *in)
// must be called locked
static int cached_stream_control(struct demux_internal *in, int cmd, void *arg)
{
- // If the cache is active, wake up the thread to possibly update cache state.
- if (in->stream_cache_info.size >= 0) {
- in->force_cache_update = true;
- pthread_cond_signal(&in->wakeup);
- }
-
switch (cmd) {
- case STREAM_CTRL_GET_CACHE_INFO:
- if (in->stream_cache_info.size < 0)
- return STREAM_UNSUPPORTED;
- *(struct stream_cache_info *)arg = in->stream_cache_info;
- return STREAM_OK;
case STREAM_CTRL_GET_SIZE:
if (in->stream_size < 0)
return STREAM_UNSUPPORTED;
diff --git a/demux/demux.h b/demux/demux.h
index 7d2924000a..5b92e97f49 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -174,13 +174,11 @@ struct demuxer_params {
bool *matroska_was_valid;
struct timeline *timeline;
bool disable_timeline;
- bool initial_readahead;
bstr init_fragment;
bool skip_lavf_probing;
bool does_not_own_stream; // if false, stream is free'd on demux_free()
// -- demux_open_url() only
int stream_flags;
- bool disable_cache;
// result
bool demuxer_failed;
};
@@ -317,6 +315,7 @@ void demux_metadata_changed(demuxer_t *demuxer);
void demux_update(demuxer_t *demuxer);
void demux_disable_cache(demuxer_t *demuxer);
+bool demux_is_network_cached(demuxer_t *demuxer);
struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d,
enum stream_type t, int id);
diff --git a/demux/demux_disc.c b/demux/demux_disc.c
index 15ccb2313d..e5c63cea17 100644
--- a/demux/demux_disc.c
+++ b/demux/demux_disc.c
@@ -292,11 +292,8 @@ static int d_open(demuxer_t *demuxer, enum demux_check check)
struct stream *cur = demuxer->stream;
const char *sname = "";
- while (cur) {
- if (cur->info)
- sname = cur->info->name;
- cur = cur->underlying; // down the caching chain
- }
+ if (cur->info)
+ sname = cur->info->name;
p->is_cdda = strcmp(sname, "cdda") == 0;
p->is_dvd = strcmp(sname, "dvd") == 0 ||
diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c
index 32eab2ca8f..69cf26e681 100644
--- a/demux/demux_mkv_timeline.c
+++ b/demux/demux_mkv_timeline.c
@@ -172,7 +172,6 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment)
.matroska_wanted_segment = segment,
.matroska_was_valid = &was_valid,
.disable_timeline = true,
- .disable_cache = true,
};
struct mp_cancel *cancel = ctx->tl->cancel;
if (mp_cancel_test(cancel))
@@ -216,15 +215,6 @@ static bool check_file_seg(struct tl_ctx *ctx, char *filename, int segment)
}
}
- if (stream_wants_cache(d->stream, ctx->opts->stream_cache)) {
- demux_free(d);
- params.disable_cache = false;
- params.matroska_wanted_uids = ctx->uids; // potentially reallocated, same data
- d = demux_open_url(filename, &params, cancel, ctx->global);
- if (!d)
- return false;
- }
-
ctx->sources[i] = d;
return true;
}
diff --git a/options/options.c b/options/options.c
index 5a77e9973d..2548759ddb 100644
--- a/options/options.c
+++ b/options/options.c
@@ -59,7 +59,6 @@ extern const struct m_sub_options tv_params_conf;
extern const struct m_sub_options stream_cdda_conf;
extern const struct m_sub_options stream_dvb_conf;
extern const struct m_sub_options stream_lavf_conf;
-extern const struct m_sub_options stream_cache_conf;
extern const struct m_sub_options sws_conf;
extern const struct m_sub_options drm_conf;
extern const struct m_sub_options demux_rawaudio_conf;
@@ -387,8 +386,6 @@ const m_option_t mp_opts[] = {
// ------------------------- stream options --------------------
- OPT_SUBSTRUCT("", stream_cache, stream_cache_conf, 0),
-
#if HAVE_DVDREAD || HAVE_DVDNAV
OPT_SUBSTRUCT("", dvd_opts, dvd_conf, 0),
#endif /* HAVE_DVDREAD */
diff --git a/options/options.h b/options/options.h
index 0eb5451794..a6532b4458 100644
--- a/options/options.h
+++ b/options/options.h
@@ -59,16 +59,6 @@ typedef struct mp_vo_opts {
struct drm_opts *drm_opts;
} mp_vo_opts;
-struct mp_cache_opts {
- int size;
- int def_size;
- int initial;
- int seek_min;
- int back_buffer;
- char *file;
- int file_max;
-};
-
// Subtitle options needed by the subtitle decoders/renderers.
struct mp_subtitle_opts {
int sub_visibility;
@@ -204,7 +194,6 @@ typedef struct MPOpts {
char *force_configdir;
int use_filedir_conf;
int hls_bitrate;
- struct mp_cache_opts *stream_cache;
int chapterrange[2];
int edition_id;
int correct_pts;
@@ -358,7 +347,6 @@ struct filter_opts {
extern const m_option_t mp_opts[];
extern const struct MPOpts mp_default_opts;
extern const struct m_sub_options vo_sub_opts;
-extern const struct m_sub_options stream_cache_conf;
extern const struct m_sub_options dvd_conf;
extern const struct m_sub_options mp_subtitle_sub_opts;
extern const struct m_sub_options mp_osd_render_sub_opts;
diff --git a/player/command.c b/player/command.c
index f556e7211d..ab9a09fcac 100644
--- a/player/command.c
+++ b/player/command.c
@@ -1559,134 +1559,6 @@ static int mp_property_playback_abort(void *ctx, struct m_property *prop,
return m_property_flag_ro(action, arg, !mpctx->playing || mpctx->stop_play);
}
-static int mp_property_cache(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- float cache = mp_get_cache_percent(mpctx);
- if (cache < 0)
- return M_PROPERTY_UNAVAILABLE;
-
- if (action == M_PROPERTY_PRINT) {
- *(char **)arg = talloc_asprintf(NULL, "%d", (int)cache);
- return M_PROPERTY_OK;
- }
-
- return m_property_float_ro(action, arg, cache);
-}
-
-static int property_int_kb_size(int kb_size, int action, void *arg)
-{
- switch (action) {
- case M_PROPERTY_GET:
- *(int *)arg = kb_size;
- return M_PROPERTY_OK;
- case M_PROPERTY_PRINT:
- *(char **)arg = format_file_size(kb_size * 1024LL);
- return M_PROPERTY_OK;
- case M_PROPERTY_GET_TYPE:
- *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT};
- return M_PROPERTY_OK;
- }
- return M_PROPERTY_NOT_IMPLEMENTED;
-}
-
-static int mp_property_cache_size(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- struct demuxer *demuxer = mpctx->demuxer;
- if (!demuxer)
- return M_PROPERTY_UNAVAILABLE;
- switch (action) {
- case M_PROPERTY_GET:
- case M_PROPERTY_PRINT: {
- struct stream_cache_info info = {0};
- demux_stream_control(demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size <= 0)
- break;
- return property_int_kb_size(info.size / 1024, action, arg);
- }
- case M_PROPERTY_GET_TYPE:
- *(struct m_option *)arg = (struct m_option){
- .type = CONF_TYPE_INT,
- .flags = M_OPT_MIN,
- .min = 0,
- };
- return M_PROPERTY_OK;
- case M_PROPERTY_SET: {
- int64_t size = *(int *)arg * 1024LL;
- int r = demux_stream_control(demuxer, STREAM_CTRL_SET_CACHE_SIZE, &size);
- if (r == STREAM_UNSUPPORTED)
- break;
- if (r == STREAM_OK)
- return M_PROPERTY_OK;
- return M_PROPERTY_ERROR;
- }
- }
- return M_PROPERTY_NOT_IMPLEMENTED;
-}
-
-static int mp_property_cache_used(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- if (!mpctx->demuxer)
- return M_PROPERTY_UNAVAILABLE;
-
- struct stream_cache_info info = {0};
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size <= 0)
- return M_PROPERTY_UNAVAILABLE;
- return property_int_kb_size(info.fill / 1024, action, arg);
-}
-
-static int mp_property_cache_free(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- if (!mpctx->demuxer)
- return M_PROPERTY_UNAVAILABLE;
-
- struct stream_cache_info info = {0};
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size <= 0)
- return M_PROPERTY_UNAVAILABLE;
-
- return property_int_kb_size((info.size - info.fill) / 1024, action, arg);
-}
-
-static int mp_property_cache_speed(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- if (!mpctx->demuxer)
- return M_PROPERTY_UNAVAILABLE;
-
- struct stream_cache_info info = {0};
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size <= 0)
- return M_PROPERTY_UNAVAILABLE;
-
- if (action == M_PROPERTY_PRINT) {
- *(char **)arg = talloc_strdup_append(format_file_size(info.speed), "/s");
- return M_PROPERTY_OK;
- }
- return m_property_int64_ro(action, arg, info.speed);
-}
-
-static int mp_property_cache_idle(void *ctx, struct m_property *prop,
- int action, void *arg)
-{
- MPContext *mpctx = ctx;
- struct stream_cache_info info = {0};
- if (mpctx->demuxer)
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size <= 0)
- return M_PROPERTY_UNAVAILABLE;
- return m_property_flag_ro(action, arg, info.idle);
-}
-
static int mp_property_demuxer_cache_duration(void *ctx, struct m_property *prop,
int action, void *arg)
{
@@ -3897,12 +3769,6 @@ static const struct m_property mp_properties_base[] = {
{"eof-reached", mp_property_eof_reached},
{"seeking", mp_property_seeking},
{"playback-abort", mp_property_playback_abort},
- {"cache-percent", mp_property_cache},
- {"cache-free", mp_property_cache_free},
- {"cache-used", mp_property_cache_used},
- {"cache-size", mp_property_cache_size},
- {"cache-idle", mp_property_cache_idle},
- {"cache-speed", mp_property_cache_speed},
{"demuxer-cache-duration", mp_property_demuxer_cache_duration},
{"demuxer-cache-time", mp_property_demuxer_cache_time},
{"demuxer-cache-idle", mp_property_demuxer_cache_idle},
diff --git a/player/core.h b/player/core.h
index 193537652b..7fab8776d7 100644
--- a/player/core.h
+++ b/player/core.h
@@ -554,8 +554,6 @@ double get_play_end_pts(struct MPContext *mpctx);
double get_play_start_pts(struct MPContext *mpctx);
double get_ab_loop_start_time(struct MPContext *mpctx);
void merge_playlist_files(struct playlist *pl);
-float mp_get_cache_percent(struct MPContext *mpctx);
-bool mp_get_cache_idle(struct MPContext *mpctx);
void update_vo_playback_state(struct MPContext *mpctx);
void update_window_title(struct MPContext *mpctx, bool force);
void error_on_track(struct MPContext *mpctx, struct track *track);
diff --git a/player/loadfile.c b/player/loadfile.c
index d854ab04a9..2fb69eb635 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -971,7 +971,6 @@ static void *open_demux_thread(void *ctx)
struct demuxer_params p = {
.force_format = mpctx->open_format,
.stream_flags = mpctx->open_url_flags,
- .initial_readahead = true,
};
mpctx->open_res_demuxer =
demux_open_url(mpctx->open_url, &p, mpctx->open_cancel, mpctx->global);
diff --git a/player/misc.c b/player/misc.c
index f2e6f05173..ce353b9590 100644
--- a/player/misc.c
+++ b/player/misc.c
@@ -203,24 +203,6 @@ void issue_refresh_seek(struct MPContext *mpctx, enum seek_precision min_prec)
queue_seek(mpctx, MPSEEK_ABSOLUTE, get_current_time(mpctx), min_prec, 0);
}
-float mp_get_cache_percent(struct MPContext *mpctx)
-{
- struct stream_cache_info info = {0};
- if (mpctx->demuxer)
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size > 0 && info.fill >= 0)
- return info.fill / (info.size / 100.0);
- return -1;
-}
-
-bool mp_get_cache_idle(struct MPContext *mpctx)
-{
- struct stream_cache_info info = {0};
- if (mpctx->demuxer)
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- return info.idle;
-}
-
void update_vo_playback_state(struct MPContext *mpctx)
{
if (mpctx->video_out && mpctx->video_out->config_ok) {
diff --git a/player/osd.c b/player/osd.c
index 9faf6eb6a5..7d24c01619 100644
--- a/player/osd.c
+++ b/player/osd.c
@@ -229,27 +229,23 @@ static char *get_term_status_msg(struct MPContext *mpctx)
}
}
- if (mpctx->demuxer) {
- struct stream_cache_info info = {0};
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
- if (info.size > 0 || mpctx->demuxer->is_network) {
- saddf(&line, " Cache: ");
+ if (mpctx->demuxer && demux_is_network_cached(mpctx->demuxer)) {
+ saddf(&line, " Cache: ");
- struct demux_ctrl_reader_state s = {.ts_duration = -1};
- demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);
+ struct demux_ctrl_reader_state s = {.ts_duration = -1};
+ demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);
- if (s.ts_duration < 0) {
- saddf(&line, "???");
+ if (s.ts_duration < 0) {
+ saddf(&line, "???");
+ } else {
+ saddf(&line, "%2ds", (int)s.ts_duration);
+ }
+ int64_t cache_size = s.fw_bytes;
+ if (cache_size > 0) {
+ if (cache_size >= 1024 * 1024) {
+ saddf(&line, "+%lldMB", (long long)(cache_size / 1024 / 1024));
} else {
- saddf(&line, "%2ds", (int)s.ts_duration);
- }
- int64_t cache_size = s.fw_bytes + info.fill;
- if (cache_size > 0) {
- if (cache_size >= 1024 * 1024) {
- saddf(&line, "+%lldMB", (long long)(cache_size / 1024 / 1024));
- } else {
- saddf(&line, "+%lldKB", (long long)(cache_size / 1024));
- }
+ saddf(&line, "+%lldKB", (long long)(cache_size / 1024));
}
}
}
diff --git a/player/playloop.c b/player/playloop.c
index fa1cc544cb..59e3211df9 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -627,14 +627,11 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
double now = mp_time_sec();
- struct stream_cache_info c = {.idle = true};
- demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &c);
-
struct demux_ctrl_reader_state s = {.idle = true, .ts_duration = -1};
demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);
int cache_buffer = 100;
- bool use_pause_on_low_cache = (c.size > 0 || mpctx->demuxer->is_network) &&
+ bool use_pause_on_low_cache = demux_is_network_cached(mpctx->demuxer) &&
opts->cache_pause;
if (!mpctx->restart_complete) {
@@ -669,7 +666,7 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
}
// Also update cache properties.
- bool busy = !s.idle || !c.idle;
+ bool busy = !s.idle;
if (busy || mpctx->next_cache_update > 0) {
if (mpctx->next_cache_update <= now) {
mpctx->next_cache_update = busy ? now + 0.25 : 0;
diff --git a/stream/cache.c b/stream/cache.c
deleted file mode 100644
index 424f27910f..0000000000
--- a/stream/cache.c
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-// Time in seconds the main thread waits for the cache thread. On wakeups, the
-// code checks for user requested aborts and also prints warnings that the
-// cache is being slow.
-#define CACHE_WAIT_TIME 1.0
-
-// The time the cache sleeps in idle mode. This controls how often the cache
-// retries reading from the stream after EOF has reached (in case the stream is
-// actually readable again, for example if data has been appended to a file).
-// Note that if this timeout is too low, the player will waste too much CPU
-// when player is paused.
-#define CACHE_IDLE_SLEEP_TIME 1.0
-
-// Time in seconds the cache updates "cached" controls. Note that idle mode
-// will block the cache from doing this, and this timeout is honored only if
-// the cache is active.
-#define CACHE_UPDATE_CONTROLS_TIME 2.0
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <pthread.h>
-#include <time.h>
-#include <math.h>
-#include <sys/time.h>
-
-#include <libavutil/common.h>
-
-#include "config.h"
-
-#include "osdep/timer.h"
-#include "osdep/threads.h"
-
-#include "common/msg.h"
-#include "common/tags.h"
-#include "misc/thread_tools.h"
-#include "options/options.h"
-
-#include "stream.h"
-#include "common/common.h"
-
-#define OPT_BASE_STRUCT struct mp_cache_opts
-
-const struct m_sub_options stream_cache_conf = {
- .opts = (const struct m_option[]){
- OPT_CHOICE_OR_INT("cache", size, 0, 32, 0x7fffffff,
- ({"no", 0},
- {"auto", -1},
- {"yes", -2})),
- OPT_CHOICE_OR_INT("cache-default", def_size, 0, 32, 0x7fffffff,
- ({"no", 0})),
- OPT_INTRANGE("cache-initial", initial, 0, 0, 0x7fffffff),
- OPT_INTRANGE("cache-seek-min", seek_min, 0, 0, 0x7fffffff),
- OPT_INTRANGE("cache-backbuffer", back_buffer, 0, 0, 0x7fffffff),
- OPT_STRING("cache-file", file, M_OPT_FILE),
- OPT_INTRANGE("cache-file-size", file_max, 0, 0, 0x7fffffff),
- {0}
- },
- .size = sizeof(struct mp_cache_opts),
- .defaults = &(const struct mp_cache_opts){
- .size = -1,
- .def_size = 10000,
- .initial = 0,
- .seek_min = 500,
- .back_buffer = 10000,
- .file_max = 1024 * 1024,
- },
-};
-
-// Note: (struct priv*)(cache->priv)->cache == cache
-struct priv {
- pthread_t cache_thread;
- bool cache_thread_running;
- pthread_mutex_t mutex;
- pthread_cond_t wakeup;
-
- // Constants (as long as cache thread is running)
- // Some of these might actually be changed by a synced cache resize.
- unsigned char *buffer; // base pointer of the allocated buffer memory
- int64_t buffer_size; // size of the allocated buffer memory
- int64_t back_size; // keep back_size amount of old bytes for backward seek
- int64_t seek_limit; // keep filling cache if distance is less that seek limit
- bool seekable; // underlying stream is seekable
-
- struct mp_log *log;
-
- // Owned by the main thread
- stream_t *cache; // wrapper stream, used by demuxer etc.
-
- // Owned by the cache thread
- stream_t *stream; // "real" stream, used to read from the source media
- int64_t bytes_until_wakeup; // wakeup cache thread after this many bytes
-
- // All the following members are shared between the threads.
- // You must lock the mutex to access them.
-
- // Ringbuffer
- int64_t min_filepos; // range of file that is cached in the buffer
- int64_t max_filepos; // ... max_filepos being the last read position
- bool eof; // true if max_filepos = EOF
- int64_t offset; // buffer[WRAP(s->max_filepos - offset)] corresponds
- // to the byte at max_filepos (must be wrapped by
- // buffer_size)
-
- bool idle; // cache thread has stopped reading
- int64_t reads; // number of actual read attempts performed
- int64_t speed_start; // start time (us) for calculating download speed
- int64_t speed_amount; // bytes read since speed_start
- double speed;
-
- bool enable_readahead; // actively read beyond read() position
- int64_t read_filepos; // client read position (mirrors cache->pos)
- int64_t read_min; // file position until which the thread should
- // read even if readahead is disabled
-
- int64_t eof_pos;
-
- bool read_seek_failed; // let a read fail because an async seek failed
-
- int control; // requested STREAM_CTRL_... or CACHE_CTRL_...
- void *control_arg; // temporary for executing STREAM_CTRLs
- int control_res;
- bool control_flush;
-
- // Cached STREAM_CTRLs
- double stream_time_length;
- int64_t stream_size;
- struct mp_tags *stream_metadata;
- double start_pts;
- bool has_avseek;
-};
-
-enum {
- CACHE_CTRL_NONE = 0,
- CACHE_CTRL_QUIT = -1,
- CACHE_CTRL_PING = -2,
- CACHE_CTRL_SEEK = -3,
-
- // we should fill buffer only if space>=FILL_LIMIT
- FILL_LIMIT = 16 * 1024,
-};
-
-// Used by the main thread to wakeup the cache thread, and to wait for the
-// cache thread. The cache mutex has to be locked when calling this function.
-// *retry_time should be set to 0 on the first call.
-// Return false if the stream has been aborted.
-static bool cache_wakeup_and_wait(struct priv *s, double *retry_time)
-{
- double start = mp_time_sec();
- if (*retry_time >= CACHE_WAIT_TIME) {
- MP_VERBOSE(s, "Cache is not responding - slow/stuck network connection?\n");
- *retry_time = -1; // do not warn again for this call
- }
-
- pthread_cond_signal(&s->wakeup);
- struct timespec ts = mp_rel_time_to_timespec(CACHE_WAIT_TIME);
- pthread_cond_timedwait(&s->wakeup, &s->mutex, &ts);
-
- if (*retry_time >= 0)
- *retry_time += mp_time_sec() - start;
-
- return !mp_cancel_test(s->cache->cancel);
-}
-
-// Runs in the cache thread
-static void cache_drop_contents(struct priv *s)
-{
- s->offset = s->min_filepos = s->max_filepos = s->read_filepos;
- s->eof = false;
- s->start_pts = MP_NOPTS_VALUE;
-}
-
-static void update_speed(struct priv *s)
-{
- int64_t now = mp_time_us();
- if (s->speed_start + 1000000 <= now) {
- s->speed = s->speed_amount * 1e6 / (now - s->speed_start);
- s->speed_amount = 0;
- s->speed_start = now;
- }
-}
-
-// Copy at most dst_size from the cache at the given absolute file position pos.
-// Return number of bytes that could actually be read.
-// Does not advance the file position, or change anything else.
-// Can be called from anywhere, as long as the mutex is held.
-static size_t read_buffer(struct priv *s, unsigned char *dst,
- size_t dst_size, int64_t pos)
-{
- size_t read = 0;
- while (read < dst_size) {
- if (pos >= s->max_filepos || pos < s->min_filepos)
- break;
- int64_t newb = s->max_filepos - pos; // new bytes in the buffer
-
- int64_t bpos = pos - s->offset; // file pos to buffer memory pos
- if (bpos < 0) {
- bpos += s->buffer_size;
- } else if (bpos >= s->buffer_size) {
- bpos -= s->buffer_size;
- }
-
- if (newb > s->buffer_size - bpos)
- newb = s->buffer_size - bpos; // handle wrap...
-
- newb = MPMIN(newb, dst_size - read);
-
- assert(newb >= 0 && read + newb <= dst_size);
- assert(bpos >= 0 && bpos + newb <= s->buffer_size);
- memcpy(&dst[read], &s->buffer[bpos], newb);
- read += newb;
- pos += newb;
- }
- return read;
-}
-
-// Whether a seek will be needed to get to the position. This honors seek_limit,
-// which is a heuristic to prevent dropping the cache with small forward seeks.
-// This helps in situations where waiting for network a bit longer would quickly
-// reach the target position. Especially if the demuxer seeks back and forth,
-// not dropping the backwards cache will be a major performance win.
-static bool needs_seek(struct priv *s, int64_t pos)
-{
- return pos < s->min_filepos || pos > s->max_filepos + s->seek_limit;
-}
-
-static bool cache_update_stream_position(struct priv *s)
-{
- int64_t read = s->read_filepos;
-
- s->read_seek_failed = false;
-
- if (needs_seek(s, read)) {
- MP_VERBOSE(s, "Dropping cache at pos %"PRId64", "
- "cached range: %"PRId64"-%"PRId64".\n", read,
- s->min_filepos, s->max_filepos);
- cache_drop_contents(s);
- }
-
- if (stream_tell(s->stream) != s->max_filepos && s->seekable) {
- MP_VERBOSE(s, "Seeking underlying stream: %"PRId64" -> %"PRId64"\n",
- stream_tell(s->stream), s->max_filepos);
- if (!stream_seek(s->stream, s->max_filepos)) {
- s->read_seek_failed = true;
- return false;
- }
- }
-
- return stream_tell(s->stream) == s->max_filepos;
-}
-
-// Runs in the cache thread.
-static void cache_fill(struct priv *s)
-{
- int64_t read = s->read_filepos;
- bool read_attempted = false;
- int len = 0;
-
- if (!cache_update_stream_position(s))
- goto done;
-
- if (!s->enable_readahead && s->read_min <= s->max_filepos)
- goto done;
-
- if (mp_cancel_test(s->cache->cancel))
- goto done;
-
- // number of buffer bytes which should be preserved in backwards direction
- int64_t back = MPCLAMP(read - s->min_filepos, 0, s->back_size);
-
- // limit maximum readahead so that the backbuffer space is reserved, even
- // if the backbuffer is not used. limit it to ensure that we don't stall the
- // network when starting a file, or we wouldn't download new data until we
- // get new free space again. (unless everything fits in the cache.)
- if (s->stream_size > s->buffer_size)
- back = MPMAX(back, s->back_size);
-
- // number of buffer bytes that are valid and can be read
- int64_t newb = FFMAX(s->max_filepos - read, 0);
-
- // max. number of bytes that can be written (starting from max_filepos)
- int64_t space = s->buffer_size - (newb + back);
-
- // offset into the buffer that maps to max_filepos
- int64_t pos = s->max_filepos - s->offset;
- if (pos >= s->buffer_size)
- pos -= s->buffer_size; // wrap-around
-
- if (space < FILL_LIMIT)
- goto done;
-
- // limit to end of buffer (without wrapping)
- if (pos + space >= s->buffer_size)
- space = s->buffer_size - pos;
-
- // limit read size (or else would block and read the entire buffer in 1 call)
- space = FFMIN(space, s->stream->read_chunk);
-
- // back+newb+space <= buffer_size
- int64_t back2 = s->buffer_size - (space + newb); // max back size
- if (s->min_filepos < (read - back2))
- s->min_filepos = read - back2;
-
- // The read call might take a long time and block, so drop the lock.
- pthread_mutex_unlock(&s->mutex);
- len = stream_read_partial(s->stream, &s->buffer[pos], space);
- pthread_mutex_lock(&s->mutex);
-
- // Do this after reading a block, because at least libdvdnav updates the
- // stream position only after actually reading something after a seek.
- if (s->start_pts == MP_NOPTS_VALUE) {
- double pts;
- if (stream_control(s->stream, STREAM_CTRL_GET_CURRENT_TIME, &pts) > 0)
- s->start_pts = pts;
- }
-
- s->max_filepos += len;
- if (pos + len == s->buffer_size)
- s->offset += s->buffer_size; // wrap...
- s->speed_amount += len;
-
- read_attempted = true;
-
-done: ;
-
- bool prev_eof = s->eof;
- if (read_attempted)
- s->eof = len <= 0;
- if (!prev_eof && s->eof) {
- s->eof_pos = stream_tell(s->stream);
- MP_VERBOSE(s, "EOF reached.\n");
- }
- s->idle = s->eof || !read_attempted;
- s->reads++;
-
- update_speed(s);
-
- pthread_cond_signal(&s->wakeup);
-}
-
-// This is called both during init and at runtime.
-// The size argument is the readahead half only; s->back_size is the backbuffer.
-static int resize_cache(struct priv *s, int64_t size)
-{
- int64_t min_size = FILL_LIMIT * 2;
- int64_t max_size = ((size_t)-1) / 8;
-
- if (s->stream_size > 0) {
- size = MPMIN(size, s->stream_size);
- if (size >= s->stream_size) {
- MP_VERBOSE(s, "no backbuffer needed\n");
- s->back_size = 0;
- }
- }
-
- int64_t buffer_size = MPCLAMP(size, min_size, max_size);
- s->back_size = MPCLAMP(s->back_size, min_size, max_size);
- buffer_size += s->back_size;
-
- unsigned char *buffer = malloc(buffer_size);
- if (!buffer)
- return STREAM_ERROR;
-
- if (s->buffer) {
- // Copy & free the old ringbuffer data.
- // If the buffer is too small, prefer to copy these regions:
- // 1. Data starting from read_filepos, until cache end
- size_t read_1 = read_buffer(s, buffer, buffer_size, s->read_filepos);
- // 2. then data from before read_filepos until cache start
- // (this one needs to be copied to the end of the ringbuffer)
- size_t read_2 = 0;
- if (s->min_filepos < s->read_filepos) {
- size_t copy_len = buffer_size - read_1;
- copy_len = MPMIN(copy_len, s->read_filepos - s->min_filepos);
- assert(copy_len + read_1 <= buffer_size);
- read_2 = read_buffer(s, buffer + buffer_size - copy_len, copy_len,
- s->read_filepos - copy_len);
- // This shouldn't happen, unless copy_len was computed incorrectly.
- assert(read_2 == copy_len);
- }
- // Set it up such that read_1 is at buffer pos 0, and read_2 wraps
- // around below it, so that it is located at the end of the buffer.
- s->min_filepos = s->read_filepos - read_2;
- s->max_filepos = s->read_filepos + read_1;
- s->offset = s->max_filepos - read_1;
- } else {
- cache_drop_contents(s);
- }
-
- free(s->buffer);
-
- s->buffer_size = buffer_size;
- s->buffer = buffer;
- s->idle = false;
- s->eof = false;
-
- //make sure that we won't wait from cache_fill
- //more data than it is allowed to fill
- if (s->seek_limit > s->buffer_size - FILL_LIMIT)
- s->seek_limit = s->buffer_size - FILL_LIMIT;
-
- MP_VERBOSE(s, "Cache size set to %lld KiB (%lld KiB backbuffer)\n",
- (long long)(s->buffer_size / 1024),
- (long long)(s->back_size / 1024));
-
- assert(s->back_size < s->buffer_size);
-
- return STREAM_OK;
-}
-
-static void update_cached_controls(struct priv *s)
-{
- int64_t i64;
- double d;
- struct mp_tags *tags;
- s->stream_time_length = 0;
- if (stream_control(s->stream, STREAM_CTRL_GET_TIME_LENGTH, &d) == STREAM_OK)
- s->stream_time_length = d;
- if (stream_control(s->stream, STREAM_CTRL_GET_METADATA, &tags) == STREAM_OK) {
- talloc_free(s->stream_metadata);
- s->stream_metadata = talloc_steal(s, tags);
- }
- s->stream_size = s->eof_pos;
- i64 = stream_get_size(s->stream);
- if (i64 >= 0)
- s->stream_size = i64;
- s->has_avseek = stream_control(s->stream, STREAM_CTRL_HAS_AVSEEK, NULL) > 0;
-}
-
-// the core might call these every frame, so cache them...
-static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
-{
- struct priv *s = cache->priv;
- switch (cmd) {
- case STREAM_CTRL_GET_CACHE_INFO:
- *(struct stream_cache_info *)arg = (struct stream_cache_info) {
- .size = s->buffer_size - s->back_size,
- .fill = s->max_filepos - s->read_filepos,
- .idle = s->idle,
- .speed = llrint(s->speed),
- };
- return STREAM_OK;
- case STREAM_CTRL_SET_READAHEAD:
- s->enable_readahead = *(int *)arg;
- pthread_cond_signal(&s->wakeup);
- return STREAM_OK;
- case STREAM_CTRL_GET_TIME_LENGTH:
- *(double *)arg = s->stream_time_length;
- return s->stream_time_length ? STREAM_OK : STREAM_UNSUPPORTED;
- case STREAM_CTRL_GET_SIZE:
- if (s->stream_size < 0)
- return STREAM_UNSUPPORTED;
- *(int64_t *)arg = s->stream_size;
- return STREAM_OK;
- case STREAM_CTRL_GET_CURRENT_TIME: {
- if (s->start_pts == MP_NOPTS_VALUE)
- return STREAM_UNSUPPORTED;
- *(double *)arg = s->start_pts;
- return STREAM_OK;
- }
- case STREAM_CTRL_HAS_AVSEEK:
- return s->has_avseek ? STREAM_OK : STREAM_UNSUPPORTED;
- case STREAM_CTRL_GET_METADATA: {
- if (s->stream_metadata) {
- ta_set_parent(s->stream_metadata, NULL);
- *(struct mp_tags **)arg = s->stream_metadata;
- s->stream_metadata = NULL;
- return STREAM_OK;
- }
- return STREAM_UNSUPPORTED;
- }
- case STREAM_CTRL_AVSEEK:
- if (!s->has_avseek)
- return STREAM_UNSUPPORTED;
- break;
- }
- return STREAM_ERROR;
-}
-
-static bool control_needs_flush(int stream_ctrl)
-{
- switch (stream_ctrl) {
- case STREAM_CTRL_SEEK_TO_TIME:
- case STREAM_CTRL_AVSEEK:
- case STREAM_CTRL_SET_ANGLE:
- case STREAM_CTRL_SET_CURRENT_TITLE:
- case STREAM_CTRL_DVB_SET_CHANNEL:
- case STREAM_CTRL_DVB_SET_CHANNEL_NAME:
- case STREAM_CTRL_DVB_STEP_CHANNEL:
- return true;
- }
- return false;
-}
-
-// Runs in the cache thread
-static void cache_execute_control(struct priv *s)
-{
- uint64_t old_pos = stream_tell(s->stream);
- s->control_flush = false;
-
- switch (s->control) {
- case STREAM_CTRL_SET_CACHE_SIZE:
- s->control_res = resize_cache(s, *(int64_t *)s->control_arg);
- break;
- default:
- s->control_res = stream_control(s->stream, s->control, s->control_arg);
- }
-
- bool pos_changed = old_pos != stream_tell(s->stream);
- bool ok = s->control_res == STREAM_OK;
- if (pos_changed && !ok) {
- MP_ERR(s, "STREAM_CTRL changed stream pos but "
- "returned error, this is not allowed!\n");
- } else if (pos_changed || (ok && control_needs_flush(s->control))) {
- MP_VERBOSE(s, "Dropping cache due to control()\n");
- s->read_filepos = stream_tell(s->stream);
- s->read_min = s->read_filepos;
- s->control_flush = true;
- cache_drop_contents(s);
- }
-
- update_cached_controls(s);
- s->control = CACHE_CTRL_NONE;
- pthread_cond_signal(&s->wakeup);
-}
-
-static void *cache_thread(void *arg)
-{
- struct priv *s = arg;
- mpthread_set_name("cache");
- pthread_mutex_lock(&s->mutex);
- update_cached_controls(s);
- double last = mp_time_sec();
- while (s->control != CACHE_CTRL_QUIT) {
- if (mp_time_sec() - last > CACHE_UPDATE_CONTROLS_TIME) {
- update_cached_controls(s);
- last = mp_time_sec();
- }
- if (s->control > 0) {
- cache_execute_control(s);
- } else if (s->control == CACHE_CTRL_SEEK) {
- s->control_res = cache_update_stream_position(s);
- s->control = CACHE_CTRL_NONE;
- pthread_cond_signal(&s->wakeup);
- } else {
- cache_fill(s);
- }
- if (s->control == CACHE_CTRL_PING) {
- pthread_cond_signal(&s->wakeup);
- s->control = CACHE_CTRL_NONE;
- }
- if (s->idle && s->control == CACHE_CTRL_NONE) {
- struct timespec ts = mp_rel_time_to_timespec(CACHE_IDLE_SLEEP_TIME);
- pthread_cond_timedwait(&s->wakeup, &s->mutex, &ts);
- }
- }
- pthread_cond_signal(&s->wakeup);
- pthread_mutex_unlock(&s->mutex);
- MP_VERBOSE(s, "Cache exiting...\n");
- return NULL;
-}
-
-static int cache_fill_buffer(struct stream *cache, char *buffer, int max_len)
-{
- struct priv *s = cache->priv;
- assert(s->cache_thread_running);
-
- pthread_mutex_lock(&s->mutex);
-
- if (cache->pos != s->read_filepos)
- MP_ERR(s, "!!! read_filepos differs !!! report this bug...\n");
-
- int readb = 0;
- if (max_len > 0) {
- double retry_time = 0;
- int64_t retry = s->reads - 1; // try at least 1 read on EOF
- while (1) {
- s->read_min = s->read_filepos + max_len + 64 * 1024;
- readb = read_buffer(s, buffer, max_len, s->read_filepos);
- s->read_filepos += readb;
- if (readb > 0)
- break;
- if (s->eof && s->read_filepos >= s->max_filepos && s->reads >= retry)
- break;
- s->idle = false;
- if (!cache_wakeup_and_wait(s, &retry_time))
- break;
- if (s->read_seek_failed) {
- MP_ERR(s, "error reading after async seek failed\n");
- s->read_seek_failed = false;
- break;
- }
- }
- }
-
- if (!s->eof) {
- // wakeup the cache thread, possibly make it read more data ahead
- // this is throttled to reduce excessive wakeups during normal reading
- // (using the amount of bytes after which the cache thread most likely
- // can actually read new data)
- s->bytes_until_wakeup -= readb;
- if (s->bytes_until_wakeup <= 0) {
- s->bytes_until_wakeup = MPMAX(FILL_LIMIT, s->stream->read_chunk);
- pthread_cond_signal(&s->wakeup);
- }
- }
- pthread_mutex_unlock(&s->mutex);
- return readb;
-}
-
-static int cache_seek(stream_t *cache, int64_t pos)
-{
- struct priv *s = cache->priv;
- assert(s->cache_thread_running);
- int r = 1;
-
- pthread_mutex_lock(&s->mutex);
-
- MP_DBG(s, "request seek: %" PRId64 " <= to=%" PRId64
- " (cur=%" PRId64 ") <= %" PRId64 " \n",
- s->min_filepos, pos, s->read_filepos, s->max_filepos);
-
- if (!s->seekable && pos > s->max_filepos) {
- MP_ERR(s, "Attempting to seek past cached data in unseekable stream.\n");
- r = 0;
- } else if (!s->seekable && pos < s->min_filepos) {
- MP_ERR(s, "Attempting to seek before cached data in unseekable stream.\n");
- r = 0;
- } else {
- cache->pos = s->read_filepos = s->read_min = pos;
- // Is this seek likely to cause a stream-level seek?
- // If it is, wait until that is complete and return its result.
- // This check is not quite exact - if the reader thread is blocked in
- // a read, the read might advance file position enough that a seek
- // forward is no longer needed.
- if (needs_seek(s, pos)) {
- s->eof = false;
- s->control = CACHE_CTRL_SEEK;
- s->control_res = 0;
- double retry = 0;
- while (s->control != CACHE_CTRL_NONE) {
- if (!cache_wakeup_and_wait(s, &retry))
- break;
- }
- r = s->control_res;
- } else {
- pthread_cond_signal(&s->wakeup);
- r = 1;
- }
- }
-
- s->bytes_until_wakeup = 0;
-
- pthread_mutex_unlock(&s->mutex);
-
- return r;
-}
-
-static int cache_control(stream_t *cache, int cmd, void *arg)
-{
- struct priv *s = cache->priv;
- int r = STREAM_ERROR;
-
- assert(cmd > 0);
-
- pthread_mutex_lock(&s->mutex);
-
- r = cache_get_cached_control(cache, cmd, arg);
- if (r != STREAM_ERROR)
- goto done;
-
- MP_VERBOSE(s, "blocking for STREAM_CTRL %d\n", cmd);
-
- s->control = cmd;
- s->control_arg = arg;
- double retry = 0;
- while (s->control != CACHE_CTRL_NONE) {
- if (!cache_wakeup_and_wait(s, &retry)) {
- s->eof = 1;
- r = STREAM_UNSUPPORTED;
- goto done;
- }
- }
- r = s->control_res;
- if (s->control_flush) {
- stream_drop_buffers(cache);
- cache->pos = s->read_filepos;
- }
-
-done:
- pthread_mutex_unlock(&s->mutex);
- return r;
-}
-
-static void cache_uninit(stream_t *cache)
-{
- struct priv *s = cache->priv;
- if (s->cache_thread_running) {
- MP_VERBOSE(s, "Terminating cache...\n");
- pthread_mutex_lock(&s->mutex);
- s->control = CACHE_CTRL_QUIT;
- pthread_cond_signal(&s->wakeup);
- pthread_mutex_unlock(&s->mutex);
- pthread_join(s->cache_thread, NULL);
- }
- pthread_mutex_destroy(&s->mutex);
- pthread_cond_destroy(&s->wakeup);
- free(s->buffer);
- talloc_free(s);
-}
-
-// return 1 on success, 0 if the cache is disabled/not needed, and -1 on error
-// or if the cache is disabled
-int stream_cache_init(stream_t *cache, stream_t *stream,
- struct mp_cache_opts *opts)
-{
- if (opts->size < 1)
- return 0;
-
- struct priv *s = talloc_zero(NULL, struct priv);
- s->log = cache->log;
- s->eof_pos = -1;
- s->enable_readahead = true;
-
- cache_drop_contents(s);
-
- s->speed_start = mp_time_us();
-
- s->seek_limit = opts->seek_min * 1024ULL;
- s->back_size = opts->back_buffer * 1024ULL;
-
- s->stream_size = stream_get_size(stream);
-
- if (resize_cache(s, opts->size * 1024ULL) != STREAM_OK) {
- MP_ERR(s, "Failed to allocate cache buffer.\n");
- talloc_free(s);
- return -1;
- }
-
- pthread_mutex_init(&s->mutex, NULL);
- pthread_cond_init(&s->wakeup, NULL);
-
- cache->priv = s;
- s->cache = cache;
- s->stream = stream;
-
- cache->seek = cache_seek;
- cache->fill_buffer = cache_fill_buffer;
- 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;
-
- s->seekable = stream->seekable;
-
- if (pthread_create(&s->cache_thread, NULL, cache_thread, s) != 0) {
- MP_ERR(s, "Starting cache thread failed.\n");
- return -1;
- }
- s->cache_thread_running = true;
-
- // wait until cache is filled with at least min bytes
- if (min < 1)
- return 1;
- for (;;) {
- if (mp_cancel_test(cache->cancel))
- return -1;
- struct stream_cache_info info;
- if (stream_control(s->cache, STREAM_CTRL_GET_CACHE_INFO, &info) < 0)
- break;
- mp_msg(s->log, MSGL_STATUS, "Cache fill: %5.2f%% "
- "(%" PRId64 " bytes)", 100.0 * info.fill / s->buffer_size,
- info.fill);
- if (info.fill >= min)
- break;
- if (info.idle)
- break; // file is smaller than prefill size
- // Wake up if the cache is done reading some data (or on timeout/abort)
- pthread_mutex_lock(&s->mutex);
- s->control = CACHE_CTRL_PING;
- pthread_cond_signal(&s->wakeup);
- cache_wakeup_and_wait(s, &(double){0});
- pthread_mutex_unlock(&s->mutex);
- }
- return 1;
-}
diff --git a/stream/cache_file.c b/stream/cache_file.c
deleted file mode 100644
index 4cf7060e83..0000000000
--- a/stream/cache_file.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-
-#include "osdep/io.h"
-
-#include "common/common.h"
-#include "common/msg.h"
-
-#include "options/options.h"
-
-#include "stream.h"
-
-#define BLOCK_SIZE 1024LL
-#define BLOCK_ALIGN(p) ((p) & ~(BLOCK_SIZE - 1))
-
-struct priv {
- struct stream *original;
- FILE *cache_file;
- uint8_t *block_bits; // 1 bit for each BLOCK_SIZE, whether block was read
- int64_t size; // currently known size
- int64_t max_size; // max. size for block_bits and cache_file
-};
-
-static bool test_bit(struct priv *p, int64_t pos)
-{
- if (pos < 0 || pos >= p->size)
- return false;
- size_t block = pos / BLOCK_SIZE;
- return p->block_bits[block / 8] & (1 << (block % 8));
-}
-
-static void set_bit(struct priv *p, int64_t pos, bool bit)
-{
- if (pos < 0 || pos >= p->size)
- return;
- size_t block = pos / BLOCK_SIZE;
- unsigned int m = (1 << (block % 8));
- p->block_bits[block / 8] = (p->block_bits[block / 8] & ~m) | (bit ? m : 0);
-}
-
-static int fill_buffer(stream_t *s, char *buffer, int max_len)
-{
- struct priv *p = s->priv;
- if (s->pos < 0)
- return -1;
- if (s->pos >= p->max_size) {
- if (stream_seek(p->original, s->pos) < 1)
- return -1;
- return stream_read(p->original, buffer, max_len);
- }
- // Size of file changes -> invalidate last block
- if (s->pos >= p->size - BLOCK_SIZE) {
- int64_t new_size = stream_get_size(s);
- if (p->size >= 0 && new_size != p->size)
- set_bit(p, BLOCK_ALIGN(p->size), 0);
- p->size = MPMIN(p->max_size, new_size);
- }
- int64_t aligned = BLOCK_ALIGN(s->pos);
- if (!test_bit(p, aligned)) {
- char tmp[BLOCK_SIZE];
- stream_seek(p->original, aligned);
- int r = stream_read(p->original, tmp, BLOCK_SIZE);
- if (r < BLOCK_SIZE) {
- if (p->size < 0) {
- MP_WARN(s, "suspected EOF\n");
- } else if (aligned + r < p->size) {
- MP_ERR(s, "unexpected EOF\n");
- return -1;
- }
- }
- if (fseeko(p->cache_file, aligned, SEEK_SET))
- return -1;
- if (fwrite(tmp, r, 1, p->cache_file) != 1)
- return -1;
- set_bit(p, aligned, 1);
- }
- if (fseeko(p->cache_file, s->pos, SEEK_SET))
- return -1;
- // align/limit to blocks
- max_len = MPMIN(max_len, BLOCK_SIZE - (s->pos % BLOCK_SIZE));
- // Limit to max. known file size
- if (p->size >= 0)
- max_len = MPMIN(max_len, p->size - s->pos);
- return fread(buffer, 1, max_len, p->cache_file);
-}
-
-static int seek(stream_t *s, int64_t newpos)
-{
- return 1;
-}
-
-static int control(stream_t *s, int cmd, void *arg)
-{
- struct priv *p = s->priv;
- return stream_control(p->original, cmd, arg);
-}
-
-static void s_close(stream_t *s)
-{
- struct priv *p = s->priv;
- if (p->cache_file)
- fclose(p->cache_file);
- talloc_free(p);
-}
-
-// return 1 on success, 0 if disabled, -1 on error
-int stream_file_cache_init(stream_t *cache, stream_t *stream,
- struct mp_cache_opts *opts)
-{
- if (!opts->file || !opts->file[0] || opts->file_max < 1)
- return 0;
-
- if (!stream->seekable) {
- MP_ERR(cache, "can't cache unseekable stream\n");
- return -1;
- }
-
- bool use_anon_file = strcmp(opts->file, "TMP") == 0;
- FILE *file = use_anon_file ? tmpfile() : fopen(opts->file, "wb+");
- if (!file) {
- MP_ERR(cache, "can't open cache file '%s'\n", opts->file);
- return -1;
- }
-
- struct priv *p = talloc_zero(NULL, struct priv);
-
- cache->priv = p;
- p->original = stream;
- p->cache_file = file;
- p->max_size = opts->file_max * 1024LL;
-
- // file_max can be INT_MAX, so this is at most about 256MB
- p->block_bits = talloc_zero_size(p, (p->max_size / BLOCK_SIZE + 1) / 8 + 1);
-
- cache->seek = seek;
- cache->fill_buffer = fill_buffer;
- cache->control = control;
- cache->close = s_close;
-
- return 1;
-}
diff --git a/stream/stream.c b/stream/stream.c
index 072672d1ed..7d093e1913 100644
--- a/stream/stream.c
+++ b/stream/stream.c
@@ -229,7 +229,6 @@ static int open_internal(const stream_info_t *sinfo, const char *url, int flags,
s->global = global;
s->url = talloc_strdup(s, url);
s->path = talloc_strdup(s, path);
- s->allow_caching = true;
s->is_network = sinfo->is_network;
s->mode = flags & (STREAM_READ | STREAM_WRITE);
@@ -256,9 +255,6 @@ static int open_internal(const stream_info_t *sinfo, const char *url, int flags,
if (!s->read_chunk)
s->read_chunk = 4 * (s->sector_size ? s->sector_size : STREAM_BUFFER_SIZE);
- if (!s->fill_buffer)
- s->allow_caching = false;
-
assert(s->seekable == !!s->seek);
if (s->mime_type)
@@ -581,7 +577,6 @@ void free_stream(stream_t *s)
if (s->close)
s->close(s);
- free_stream(s->underlying);
talloc_free(s);
}
@@ -597,98 +592,6 @@ stream_t *open_memory_stream(void *data, int len)
return s;
}
-static stream_t *open_cache(stream_t *orig, const char *name)
-{
- stream_t *cache = new_stream();
- cache->underlying = orig;
- cache->caching = true;
- cache->seekable = true;
- cache->mode = STREAM_READ;
- cache->read_chunk = 4 * STREAM_BUFFER_SIZE;
-
- cache->url = talloc_strdup(cache, orig->url);
- cache->mime_type = talloc_strdup(cache, orig->mime_type);
- cache->demuxer = talloc_strdup(cache, orig->demuxer);
- cache->lavf_type = talloc_strdup(cache, orig->lavf_type);
- cache->streaming = orig->streaming,
- cache->is_network = orig->is_network;
- cache->is_local_file = orig->is_local_file;
- cache->is_directory = orig->is_directory;
- cache->cancel = orig->cancel;
- cache->global = orig->global;
-
- cache->log = mp_log_new(cache, cache->global->log, name);
-
- return cache;
-}
-
-static struct mp_cache_opts check_cache_opts(stream_t *stream,
- struct mp_cache_opts *opts)
-{
- struct mp_cache_opts use_opts = *opts;
- if (use_opts.size == -1)
- use_opts.size = stream->streaming ? use_opts.def_size : 0;
- if (use_opts.size == -2)
- use_opts.size = use_opts.def_size;
-
- if (stream->mode != STREAM_READ || !stream->allow_caching || use_opts.size < 1)
- use_opts.size = 0;
- return use_opts;
-}
-
-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 cache is disabled/not needed, and -1 on error
-// or if the cache is disabled
-static 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 (use_opts.size < 1)
- return 0;
-
- stream_t *fcache = open_cache(orig, "file-cache");
- if (stream_file_cache_init(fcache, orig, &use_opts) <= 0) {
- fcache->underlying = NULL; // don't free original stream
- free_stream(fcache);
- fcache = orig;
- }
-
- stream_t *cache = open_cache(fcache, "cache");
-
- int res = stream_cache_init(cache, fcache, &use_opts);
- if (res <= 0) {
- cache->underlying = NULL; // don't free original stream
- free_stream(cache);
- if (fcache != orig) {
- fcache->underlying = NULL;
- free_stream(fcache);
- }
- } else {
- *stream = cache;
- }
- return res;
-}
-
-// Do some crazy stuff to call stream_enable_cache() with the global options.
-int stream_enable_cache_defaults(stream_t **stream)
-{
- struct mpv_global *global = (*stream)->global;
- if (!global)
- return 0;
- void *tmp = talloc_new(NULL);
- struct mp_cache_opts *opts =
- mp_get_config_group(tmp, global, &stream_cache_conf);
- int r = stream_enable_cache(stream, opts);
- talloc_free(tmp);
- return r;
-}
-
static uint16_t stream_read_word_endian(stream_t *s, bool big_endian)
{
unsigned int y = stream_read_char(s);
diff --git a/stream/stream.h b/stream/stream.h
index 2f59e5318f..c91843de8a 100644
--- a/stream/stream.h
+++ b/stream/stream.h
@@ -52,11 +52,6 @@
enum stream_ctrl {
STREAM_CTRL_GET_SIZE = 1,
- // Cache
- STREAM_CTRL_GET_CACHE_INFO,
- STREAM_CTRL_SET_CACHE_SIZE,
- STREAM_CTRL_SET_READAHEAD,
-
// stream_memory.c
STREAM_CTRL_SET_CONTENTS,
@@ -104,14 +99,6 @@ enum stream_ctrl {
STREAM_CTRL_SET_CURRENT_TITLE,
};
-// for STREAM_CTRL_GET_CACHE_INFO
-struct stream_cache_info {
- int64_t size;
- int64_t fill;
- bool idle;
- int64_t speed;
-};
-
struct stream_lang_req {
int type; // STREAM_AUDIO, STREAM_SUB
int id;
@@ -179,8 +166,6 @@ typedef struct stream {
bool seekable : 1; // presence of general byte seeking support
bool fast_skip : 1; // consider stream fast enough to fw-seek by skipping
bool is_network : 1; // original stream_info_t.is_network flag
- bool allow_caching : 1; // stream cache makes sense
- bool caching : 1; // is a cache, or accesses a cache
bool is_local_file : 1; // from the filesystem
bool is_directory : 1; // directory on the filesystem
bool access_references : 1; // open other streams
@@ -190,24 +175,12 @@ typedef struct stream {
struct mp_cancel *cancel; // cancellation notification
- struct stream *underlying; // e.g. cache wrapper
-
// Includes additional padding in case sizes get rounded up by sector size.
unsigned char buffer[];
} stream_t;
int stream_fill_buffer(stream_t *s);
-struct mp_cache_opts;
-bool stream_wants_cache(stream_t *stream, struct mp_cache_opts *opts);
-int stream_enable_cache_defaults(stream_t **stream);
-
-// Internal
-int stream_cache_init(stream_t *cache, stream_t *stream,
- struct mp_cache_opts *opts);
-int stream_file_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);
inline static int stream_read_char(stream_t *s)
diff --git a/stream/stream_avdevice.c b/stream/stream_avdevice.c
index 2b132cd1a9..5185b7a844 100644
--- a/stream/stream_avdevice.c
+++ b/stream/stream_avdevice.c
@@ -22,7 +22,6 @@
static int open_f(stream_t *stream)
{
stream->demuxer = "lavf";
- stream->allow_caching = false;
return STREAM_OK;
}
diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c
index 9821119cac..fa58f633ec 100644
--- a/stream/stream_dvb.c
+++ b/stream/stream_dvb.c
@@ -1117,7 +1117,6 @@ static int dvb_open(stream_t *stream)
stream->close = dvbin_close;
stream->control = dvbin_stream_control;
stream->streaming = true;
- stream->allow_caching = true;
stream->demuxer = "lavf";
stream->lavf_type = "mpegts";
stream->extended_ctrls = true;
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index 16a3d11d70..55ce771896 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -520,7 +520,6 @@ static int open_s_internal(stream_t *stream)
stream->close = stream_dvdnav_close;
stream->demuxer = "+disc";
stream->lavf_type = "mpeg";
- stream->allow_caching = false;
return STREAM_OK;
}
diff --git a/stream/stream_edl.c b/stream/stream_edl.c
index 11c149b3ab..94bbe58c88 100644
--- a/stream/stream_edl.c
+++ b/stream/stream_edl.c
@@ -6,7 +6,6 @@
static int s_open (struct stream *stream)
{
stream->demuxer = "edl";
- stream->allow_caching = false;
return STREAM_OK;
}
diff --git a/stream/stream_file.c b/stream/stream_file.c
index 20b4d7c0c3..319a92f08b 100644
--- a/stream/stream_file.c
+++ b/stream/stream_file.c
@@ -326,7 +326,6 @@ static int open_f(stream_t *stream)
if (fstat(p->fd, &st) == 0) {
if (S_ISDIR(st.st_mode)) {
stream->is_directory = true;
- stream->allow_caching = false;
MP_INFO(stream, "This is a directory - adding to playlist.\n");
} else if (S_ISREG(st.st_mode)) {
p->regular_file = true;
diff --git a/stream/stream_memory.c b/stream/stream_memory.c
index e0d01ff2d8..8df043201e 100644
--- a/stream/stream_memory.c
+++ b/stream/stream_memory.c
@@ -62,7 +62,6 @@ static int open_f(stream_t *stream)
stream->seekable = true;
stream->control = control;
stream->read_chunk = 1024 * 1024;
- stream->allow_caching = false;
struct priv *p = talloc_zero(stream, struct priv);
stream->priv = p;
diff --git a/stream/stream_mf.c b/stream/stream_mf.c
index fbee82924a..69a6dce58d 100644
--- a/stream/stream_mf.c
+++ b/stream/stream_mf.c
@@ -31,7 +31,6 @@ static int
mf_stream_open (stream_t *stream)
{
stream->demuxer = "mf";
- stream->allow_caching = false;
return STREAM_OK;
}
diff --git a/stream/stream_tv.c b/stream/stream_tv.c
index d9acbe4cf4..bb3c48f269 100644
--- a/stream/stream_tv.c
+++ b/stream/stream_tv.c
@@ -41,7 +41,6 @@ tv_stream_open (stream_t *stream)
stream->close=tv_stream_close;
stream->demuxer = "tv";
- stream->allow_caching = false;
return STREAM_OK;
}
diff --git a/wscript_build.py b/wscript_build.py
index e37eb7e775..066ede1274 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -357,8 +357,6 @@ def build(ctx):
( "stream/ai_oss.c", "oss-audio && audio-input" ),
( "stream/ai_sndio.c", "sndio && audio-input" ),
( "stream/audio_in.c", "audio-input" ),
- ( "stream/cache.c" ),
- ( "stream/cache_file.c" ),
( "stream/cookies.c" ),
( "stream/dvb_tune.c", "dvbin" ),
( "stream/frequencies.c", "tv" ),