Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the demuxer cache the default, reduce stream cache #5250

Merged
merged 6 commits into from Dec 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DOCS/man/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,9 @@ Property list
buffering amount, while the seek ranges represent the buffered data that
can actually be used for cached seeking.

``fw-bytes`` is the number of bytes of packets buffered in the range
starting from the current decoding position.

When querying the property with the client API using ``MPV_FORMAT_NODE``,
or with Lua ``mp.get_property_native``, this will return a mpv_node with
the following contents:
Expand All @@ -1284,6 +1287,7 @@ Property list
MPV_FORMAT_NODE_MAP
"start" MPV_FORMAT_DOUBLE
"end" MPV_FORMAT_DOUBLE
"fw-bytes" MPV_FORMAT_INT64

Other fields (might be changed or removed in the future):

Expand Down
6 changes: 4 additions & 2 deletions DOCS/man/mpv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,10 @@ listed.
(``drop-frame-count`` property.)
- Cache state, e.g. ``Cache: 2s+134KB``. Visible if the stream cache is enabled.
The first value shows the amount of video buffered in the demuxer in seconds,
the second value shows *additional* data buffered in the stream cache in
kilobytes. (``demuxer-cache-duration`` and ``cache-used`` properties.)
the second value shows the sum of the demuxer forward cache size and the
*additional* data buffered in the stream cache in kilobytes.
(``demuxer-cache-duration``, ``demuxer-cache-state``, ``cache-used``
properties.)


PROTOCOLS
Expand Down
8 changes: 5 additions & 3 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3756,7 +3756,7 @@ Cache
between readahead and backbuffer sizes.

``--cache-default=<kBytes|no>``
Set the size of the cache in kilobytes (default: 75000 KB). Using ``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.

Expand All @@ -3777,7 +3777,7 @@ Cache
This option allows control over this.

``--cache-backbuffer=<kBytes>``
Size of the cache back buffer (default: 75000 KB). This will add to the total
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.
Expand Down Expand Up @@ -3835,7 +3835,9 @@ 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 and the value is larger. (Default: 120.)
is enabled and the value is larger. The default value is set to something
very high, so the actually achieved readahead will usually be limited by
the value of the ``--demuxer-max-bytes`` option.

``--cache-pause``, ``--no-cache-pause``
Whether the player should automatically pause when the cache runs low,
Expand Down
63 changes: 49 additions & 14 deletions demux/demux.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const struct m_sub_options demux_conf = {
.max_bytes = 400 * 1024 * 1024,
.max_bytes_bw = 400 * 1024 * 1024,
.min_secs = 1.0,
.min_secs_cache = 120.0,
.min_secs_cache = 10.0 * 60 * 60,
.seekable_cache = -1,
.access_references = 1,
},
Expand Down Expand Up @@ -258,7 +258,8 @@ struct demux_stream {
bool eager; // try to keep at least 1 packet queued
// if false, this stream is disabled, or passively
// read (like subtitles)
bool refreshing;
bool refreshing; // finding old position after track switches
bool eof; // end of demuxed stream? (true if no more packets)

bool global_correct_dts;// all observed so far
bool global_correct_pos;
Expand All @@ -274,11 +275,14 @@ struct demux_stream {
double bitrate;
size_t fw_packs; // number of packets in buffer (forward)
size_t fw_bytes; // total bytes of packets in buffer (forward)
bool eof; // end of demuxed stream? (true if no more packets)
struct demux_packet *reader_head; // points at current decoder position
bool skip_to_keyframe;
bool attached_picture_added;

// for refresh seeks: pos/dts of last packet returned to reader
int64_t last_ret_pos;
double last_ret_dts;

// for closed captions (demuxer_feed_caption)
struct sh_stream *cc;
bool ignore_eof; // ignore stream in underrun detection
Expand Down Expand Up @@ -537,19 +541,26 @@ static void free_empty_cached_ranges(struct demux_internal *in)
}
}

static void ds_clear_reader_state(struct demux_stream *ds)
static void ds_clear_reader_queue_state(struct demux_stream *ds)
{
ds->in->fw_bytes -= ds->fw_bytes;

ds->reader_head = NULL;
ds->fw_bytes = 0;
ds->fw_packs = 0;
ds->eof = false;
}

static void ds_clear_reader_state(struct demux_stream *ds)
{
ds_clear_reader_queue_state(ds);

ds->base_ts = ds->last_br_ts = MP_NOPTS_VALUE;
ds->last_br_bytes = 0;
ds->bitrate = -1;
ds->skip_to_keyframe = false;
ds->attached_picture_added = false;
ds->fw_bytes = 0;
ds->fw_packs = 0;
ds->last_ret_pos = -1;
ds->last_ret_dts = MP_NOPTS_VALUE;
}

static void update_stream_selection_state(struct demux_internal *in,
Expand Down Expand Up @@ -1206,18 +1217,18 @@ static bool read_packet(struct demux_internal *in)
// 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
// safe-guards against packet queue overflow.
bool read_more = false, prefetch_more = false;
bool read_more = false, prefetch_more = false, refresh_more = false;
for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;
read_more |= ds->eager && !ds->reader_head;
prefetch_more |= ds->refreshing;
refresh_more |= ds->refreshing;
if (ds->eager && ds->queue->last_ts != MP_NOPTS_VALUE &&
in->min_secs > 0 && ds->base_ts != MP_NOPTS_VALUE &&
ds->queue->last_ts >= ds->base_ts)
prefetch_more |= ds->queue->last_ts - ds->base_ts < in->min_secs;
}
MP_TRACE(in, "bytes=%zd, read_more=%d prefetch_more=%d\n",
in->fw_bytes, read_more, prefetch_more);
MP_TRACE(in, "bytes=%zd, read_more=%d prefetch_more=%d, refresh_more=%d\n",
in->fw_bytes, read_more, prefetch_more, refresh_more);
if (in->fw_bytes >= in->max_bytes) {
// if we hit the limit just by prefetching, simply stop prefetching
if (!read_more)
Expand Down Expand Up @@ -1249,7 +1260,7 @@ static bool read_packet(struct demux_internal *in)
return false;
}

if (!read_more && !prefetch_more)
if (!read_more && !prefetch_more && !refresh_more)
return false;

// Actually read a packet. Drop the lock while doing so, because waiting
Expand Down Expand Up @@ -1474,6 +1485,9 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds)
ds->fw_bytes -= bytes;
ds->in->fw_bytes -= bytes;

ds->last_ret_pos = pkt->pos;
ds->last_ret_dts = pkt->dts;

// The returned packet is mutated etc. and will be owned by the user.
pkt = demux_copy_packet(pkt);
if (!pkt)
Expand Down Expand Up @@ -2449,10 +2463,31 @@ static void initiate_refresh_seek(struct demux_internal *in,

for (int n = 0; n < in->num_streams; n++) {
struct demux_stream *ds = in->streams[n]->ds;

bool correct_pos = ds->queue->correct_pos;
bool correct_dts = ds->queue->correct_dts;

// We need to re-read all packets anyway, so discard the buffered
// data. (In theory, we could keep the packets, and be able to use
// it for seeking if partially read streams are deselected again,
// but this causes other problems like queue overflows when
// selecting a new stream.)
ds_clear_reader_queue_state(ds);
clear_queue(ds->queue);

// Streams which didn't have any packets yet will return all packets,
// other streams return packets only starting from the last position.
if (ds->queue->last_pos != -1 || ds->queue->last_dts != MP_NOPTS_VALUE)
ds->refreshing |= ds->selected;
if (ds->selected && (ds->last_ret_pos != -1 ||
ds->last_ret_dts != MP_NOPTS_VALUE))
{
ds->refreshing = true;
ds->queue->correct_dts = correct_dts;
ds->queue->correct_pos = correct_pos;
ds->queue->last_pos = ds->last_ret_pos;
ds->queue->last_dts = ds->last_ret_dts;
}

update_seek_ranges(in->current_range);
}

start_ts -= 1.0; // small offset to get correct overlap
Expand Down
8 changes: 6 additions & 2 deletions player/lua/osc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1835,12 +1835,16 @@ function osc_init()

ne.content = function ()
local dmx_cache = mp.get_property_number("demuxer-cache-duration")
local cache_used = mp.get_property_number("cache-used")
local cache_used = mp.get_property_number("cache-used", 0)
local dmx_cache_state = mp.get_property_native("demuxer-cache-state", {})
local is_network = mp.get_property_native("demuxer-via-network")
if dmx_cache then
dmx_cache = string.format("%3.0fs", dmx_cache)
end
if cache_used then
if dmx_cache_state["fw-bytes"] then
cache_used = cache_used + dmx_cache_state["fw-bytes"] / 1024
end
if cache_used > 0 then
local suffix = " KiB"
if (cache_used >= 1024) then
cache_used = cache_used/1024
Expand Down
9 changes: 5 additions & 4 deletions player/osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,12 @@ static void term_osd_print_status_lazy(struct MPContext *mpctx)
} else {
saddf(&line, "%2ds", (int)s.ts_duration);
}
if (info.size > 0) {
if (info.fill >= 1024 * 1024) {
saddf(&line, "+%lldMB", (long long)(info.fill / 1024 / 1024));
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)(info.fill / 1024));
saddf(&line, "+%lldKB", (long long)(cache_size / 1024));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions stream/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ const struct m_sub_options stream_cache_conf = {
.size = sizeof(struct mp_cache_opts),
.defaults = &(const struct mp_cache_opts){
.size = -1,
.def_size = 75000,
.def_size = 10000,
.initial = 0,
.seek_min = 500,
.back_buffer = 75000,
.back_buffer = 10000,
.file_max = 1024 * 1024,
},
};
Expand Down