summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorSultan Alsawaf <sultan@kerneltoast.com>2022-12-28 22:01:07 -0800
committersfan5 <sfan5@live.de>2022-12-30 10:30:22 +0100
commiteb29aa4839254b9ec7420342da900e0329289547 (patch)
tree4ed6849b831a50040d877126a5af96c088d2931e /demux
parentb6c98461128e4d9ead56aa42639effb7ac173dca (diff)
downloadmpv-eb29aa4839254b9ec7420342da900e0329289547.tar.bz2
mpv-eb29aa4839254b9ec7420342da900e0329289547.tar.xz
demux: add --demuxer-hysteresis-secs option to save power with caching
Buffering ahead nonstop into the cache results in nonstop disk or network activity to read stream data from wherever it may originate. Currently, there's no way to configure the demuxer to back off once it's buffered ahead enough data, since the cache limit will be perpetually not-reached as a stream continues to play, until the entire stream is eventually buffered. On a laptop with an i9-12900H with decoding performed by the iGPU, watching a locally-saved 1080p video which hasn't been buffered into the page cache consumes approximately 15 W even with caching enabled. When configuring a hysteresis to make the demuxer back off, power consumption drops to 9 W when watching the same video, resulting in a whopping 6 W of power savings. To make it possible to attain significant power savings via caching, add a --demuxer-hysteresis-secs option to configure a hysteresis to make the demuxer back off until there's only the configured number of seconds remaining in the cache from the current playback position. This feature is disabled by default.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 29b5dccfc7..e1ef65a733 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -91,6 +91,7 @@ struct demux_opts {
int64_t max_bytes_bw;
int donate_fw;
double min_secs;
+ double hyst_secs;
int force_seekable;
double min_secs_cache;
int access_references;
@@ -115,6 +116,7 @@ const struct m_sub_options demux_conf = {
{"no", 0}, {"auto", -1}, {"yes", 1})},
{"cache-on-disk", OPT_FLAG(disk_cache)},
{"demuxer-readahead-secs", OPT_DOUBLE(min_secs), M_RANGE(0, DBL_MAX)},
+ {"demuxer-hysteresis-secs", OPT_DOUBLE(hyst_secs), M_RANGE(0, DBL_MAX)},
{"demuxer-max-bytes", OPT_BYTE_SIZE(max_bytes),
M_RANGE(0, M_MAX_MEM_BYTES)},
{"demuxer-max-back-bytes", OPT_BYTE_SIZE(max_bytes_bw),
@@ -210,6 +212,8 @@ struct demux_internal {
bool warned_queue_overflow;
bool eof; // whether we're in EOF state
double min_secs;
+ double hyst_secs; // stop reading till there's hyst_secs remaining
+ bool hyst_active;
size_t max_bytes;
size_t max_bytes_bw;
bool seekable_cache;
@@ -2205,8 +2209,12 @@ static bool read_packet(struct demux_internal *in)
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 &&
- !in->back_demuxing)
- prefetch_more |= ds->queue->last_ts - ds->base_ts < in->min_secs;
+ !in->back_demuxing) {
+ if (ds->queue->last_ts - ds->base_ts <= in->hyst_secs)
+ in->hyst_active = false;
+ if (!in->hyst_active)
+ prefetch_more |= ds->queue->last_ts - ds->base_ts < in->min_secs;
+ }
total_fw_bytes += get_foward_buffered_bytes(ds);
}
@@ -2214,8 +2222,10 @@ static bool read_packet(struct demux_internal *in)
(size_t)total_fw_bytes, read_more, prefetch_more, refresh_more);
if (total_fw_bytes >= in->max_bytes) {
// if we hit the limit just by prefetching, simply stop prefetching
- if (!read_more)
+ if (!read_more) {
+ in->hyst_active = !!in->hyst_secs;
return false;
+ }
if (!in->warned_queue_overflow) {
in->warned_queue_overflow = true;
MP_WARN(in, "Too many packets in the demuxer packet queues:\n");
@@ -2466,6 +2476,7 @@ static void update_opts(struct demux_internal *in)
struct demux_opts *opts = in->opts;
in->min_secs = opts->min_secs;
+ in->hyst_secs = opts->hyst_secs;
in->max_bytes = opts->max_bytes;
in->max_bytes_bw = opts->max_bytes_bw;