1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-07 01:53:06 +00:00

cache: use a single STREAM_CTRL for various cache info

Instead of having a separate for each, which also requires separate
additional caching in the demuxer. (The demuxer adds an indirection,
since STREAM_CTRLs are not thread-safe.)

Since this includes the cache speed, this should fix .
This commit is contained in:
wm4 2016-03-29 11:29:52 +02:00
parent e1264d3976
commit 57506b27ed
7 changed files with 69 additions and 95 deletions

View File

@ -137,10 +137,8 @@ struct demux_internal {
bool force_cache_update; bool force_cache_update;
double time_length; double time_length;
struct mp_tags *stream_metadata; struct mp_tags *stream_metadata;
struct stream_cache_info stream_cache_info;
int64_t stream_size; int64_t stream_size;
int64_t stream_cache_size;
int64_t stream_cache_fill;
int stream_cache_idle;
// Updated during init only. // Updated during init only.
char *stream_base_filename; char *stream_base_filename;
}; };
@ -1407,9 +1405,7 @@ static void update_cache(struct demux_internal *in)
// Don't lock while querying the stream. // Don't lock while querying the stream.
double time_length = -1; double time_length = -1;
struct mp_tags *stream_metadata = NULL; struct mp_tags *stream_metadata = NULL;
int64_t stream_cache_size = -1; struct stream_cache_info stream_cache_info = {.size = -1};
int64_t stream_cache_fill = -1;
int stream_cache_idle = -1;
if (demuxer->desc->control) { if (demuxer->desc->control) {
demuxer->desc->control(demuxer, DEMUXER_CTRL_GET_TIME_LENGTH, demuxer->desc->control(demuxer, DEMUXER_CTRL_GET_TIME_LENGTH,
@ -1418,16 +1414,12 @@ static void update_cache(struct demux_internal *in)
int64_t stream_size = stream_get_size(stream); int64_t stream_size = stream_get_size(stream);
stream_control(stream, STREAM_CTRL_GET_METADATA, &stream_metadata); stream_control(stream, STREAM_CTRL_GET_METADATA, &stream_metadata);
stream_control(stream, STREAM_CTRL_GET_CACHE_SIZE, &stream_cache_size); stream_control(stream, STREAM_CTRL_GET_CACHE_INFO, &stream_cache_info);
stream_control(stream, STREAM_CTRL_GET_CACHE_FILL, &stream_cache_fill);
stream_control(stream, STREAM_CTRL_GET_CACHE_IDLE, &stream_cache_idle);
pthread_mutex_lock(&in->lock); pthread_mutex_lock(&in->lock);
in->time_length = time_length; in->time_length = time_length;
in->stream_size = stream_size; in->stream_size = stream_size;
in->stream_cache_size = stream_cache_size; in->stream_cache_info = stream_cache_info;
in->stream_cache_fill = stream_cache_fill;
in->stream_cache_idle = stream_cache_idle;
if (stream_metadata) { if (stream_metadata) {
talloc_free(in->stream_metadata); talloc_free(in->stream_metadata);
in->stream_metadata = talloc_steal(in, stream_metadata); in->stream_metadata = talloc_steal(in, stream_metadata);
@ -1440,26 +1432,16 @@ static void update_cache(struct demux_internal *in)
static int cached_stream_control(struct demux_internal *in, int cmd, void *arg) 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 the cache is active, wake up the thread to possibly update cache state.
if (in->stream_cache_size >= 0) { if (in->stream_cache_info.size >= 0) {
in->force_cache_update = true; in->force_cache_update = true;
pthread_cond_signal(&in->wakeup); pthread_cond_signal(&in->wakeup);
} }
switch (cmd) { switch (cmd) {
case STREAM_CTRL_GET_CACHE_SIZE: case STREAM_CTRL_GET_CACHE_INFO:
if (in->stream_cache_size < 0) if (in->stream_cache_info.size < 0)
return STREAM_UNSUPPORTED; return STREAM_UNSUPPORTED;
*(int64_t *)arg = in->stream_cache_size; *(struct stream_cache_info *)arg = in->stream_cache_info;
return STREAM_OK;
case STREAM_CTRL_GET_CACHE_FILL:
if (in->stream_cache_fill < 0)
return STREAM_UNSUPPORTED;
*(int64_t *)arg = in->stream_cache_fill;
return STREAM_OK;
case STREAM_CTRL_GET_CACHE_IDLE:
if (in->stream_cache_idle < 0)
return STREAM_UNSUPPORTED;
*(int *)arg = in->stream_cache_idle;
return STREAM_OK; return STREAM_OK;
case STREAM_CTRL_GET_SIZE: case STREAM_CTRL_GET_SIZE:
if (in->stream_size < 0) if (in->stream_size < 0)

View File

@ -1370,11 +1370,11 @@ static int mp_property_cache_size(void *ctx, struct m_property *prop,
switch (action) { switch (action) {
case M_PROPERTY_GET: case M_PROPERTY_GET:
case M_PROPERTY_PRINT: { case M_PROPERTY_PRINT: {
int64_t size = -1; struct stream_cache_info info = {0};
demux_stream_control(demuxer, STREAM_CTRL_GET_CACHE_SIZE, &size); demux_stream_control(demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (size <= 0) if (info.size <= 0)
break; break;
return property_int_kb_size(size / 1024, action, arg); return property_int_kb_size(info.size / 1024, action, arg);
} }
case M_PROPERTY_GET_TYPE: case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){ *(struct m_option *)arg = (struct m_option){
@ -1403,11 +1403,11 @@ static int mp_property_cache_used(void *ctx, struct m_property *prop,
if (!mpctx->demuxer) if (!mpctx->demuxer)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
int64_t size = -1; struct stream_cache_info info = {0};
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_FILL, &size); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (size < 0) if (info.size <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
return property_int_kb_size(size / 1024, action, arg); return property_int_kb_size(info.fill / 1024, action, arg);
} }
static int mp_property_cache_free(void *ctx, struct m_property *prop, static int mp_property_cache_free(void *ctx, struct m_property *prop,
@ -1417,17 +1417,12 @@ static int mp_property_cache_free(void *ctx, struct m_property *prop,
if (!mpctx->demuxer) if (!mpctx->demuxer)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
int64_t size_used = -1; struct stream_cache_info info = {0};
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_FILL, &size_used); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (size_used < 0) if (info.size <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
int64_t size = -1; return property_int_kb_size((info.size - info.fill) / 1024, action, arg);
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_SIZE, &size);
if (size <= 0)
return M_PROPERTY_UNAVAILABLE;
return property_int_kb_size((size - size_used) / 1024, action, arg);
} }
static int mp_property_cache_speed(void *ctx, struct m_property *prop, static int mp_property_cache_speed(void *ctx, struct m_property *prop,
@ -1437,29 +1432,28 @@ static int mp_property_cache_speed(void *ctx, struct m_property *prop,
if (!mpctx->demuxer) if (!mpctx->demuxer)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
double f_speed = -1; struct stream_cache_info info = {0};
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_SPEED, &f_speed); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (f_speed < 0) if (info.size <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
int64_t speed = llrint(f_speed);
if (action == M_PROPERTY_PRINT) { if (action == M_PROPERTY_PRINT) {
*(char **)arg = talloc_strdup_append(format_file_size(speed), "/s"); *(char **)arg = talloc_strdup_append(format_file_size(info.speed), "/s");
return M_PROPERTY_OK; return M_PROPERTY_OK;
} }
return m_property_int64_ro(action, arg, speed); return m_property_int64_ro(action, arg, info.speed);
} }
static int mp_property_cache_idle(void *ctx, struct m_property *prop, static int mp_property_cache_idle(void *ctx, struct m_property *prop,
int action, void *arg) int action, void *arg)
{ {
MPContext *mpctx = ctx; MPContext *mpctx = ctx;
int idle = -1; struct stream_cache_info info = {0};
if (mpctx->demuxer) if (mpctx->demuxer)
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_IDLE, &idle); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (idle < 0) if (info.size <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
return m_property_flag_ro(action, arg, !!idle); return m_property_flag_ro(action, arg, info.idle);
} }
static int mp_property_demuxer_cache_duration(void *ctx, struct m_property *prop, static int mp_property_demuxer_cache_duration(void *ctx, struct m_property *prop,

View File

@ -95,23 +95,20 @@ double get_play_end_pts(struct MPContext *mpctx)
float mp_get_cache_percent(struct MPContext *mpctx) float mp_get_cache_percent(struct MPContext *mpctx)
{ {
if (mpctx->demuxer) { struct stream_cache_info info = {0};
int64_t size = -1; if (mpctx->demuxer)
int64_t fill = -1; demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_SIZE, &size); if (info.size > 0 && info.fill >= 0)
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_FILL, &fill); return info.fill / (info.size / 100.0);
if (size > 0 && fill >= 0)
return fill / (size / 100.0);
}
return -1; return -1;
} }
bool mp_get_cache_idle(struct MPContext *mpctx) bool mp_get_cache_idle(struct MPContext *mpctx)
{ {
int idle = 0; struct stream_cache_info info = {0};
if (mpctx->demuxer) if (mpctx->demuxer)
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_IDLE, &idle); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
return idle; return info.idle;
} }
void update_vo_playback_state(struct MPContext *mpctx) void update_vo_playback_state(struct MPContext *mpctx)

View File

@ -257,9 +257,9 @@ static void print_status(struct MPContext *mpctx)
} }
if (mpctx->demuxer) { if (mpctx->demuxer) {
int64_t fill = -1; struct stream_cache_info info = {0};
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_FILL, &fill); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
if (fill >= 0) { if (info.fill >= 0) {
saddf(&line, " Cache: "); saddf(&line, " Cache: ");
struct demux_ctrl_reader_state s = {.ts_duration = -1}; struct demux_ctrl_reader_state s = {.ts_duration = -1};
@ -270,10 +270,10 @@ static void print_status(struct MPContext *mpctx)
} else { } else {
saddf(&line, "%2ds", (int)s.ts_duration); saddf(&line, "%2ds", (int)s.ts_duration);
} }
if (fill >= 1024 * 1024) { if (info.fill >= 1024 * 1024) {
saddf(&line, "+%lldMB", (long long)(fill / 1024 / 1024)); saddf(&line, "+%lldMB", (long long)(info.fill / 1024 / 1024));
} else { } else {
saddf(&line, "+%lldKB", (long long)(fill / 1024)); saddf(&line, "+%lldKB", (long long)(info.fill / 1024));
} }
} }
} }

View File

@ -522,8 +522,9 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
if (!mpctx->demuxer) if (!mpctx->demuxer)
return; return;
int idle = -1; struct stream_cache_info info = {0};
demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_IDLE, &idle); demux_stream_control(mpctx->demuxer, STREAM_CTRL_GET_CACHE_INFO, &info);
int idle = info.size > 0 ? info.idle : -1;
struct demux_ctrl_reader_state s = {.idle = true, .ts_duration = -1}; struct demux_ctrl_reader_state s = {.idle = true, .ts_duration = -1};
demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s); demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_READER_STATE, &s);

View File

@ -42,6 +42,7 @@
#include <assert.h> #include <assert.h>
#include <pthread.h> #include <pthread.h>
#include <time.h> #include <time.h>
#include <math.h>
#include <sys/time.h> #include <sys/time.h>
#include <libavutil/common.h> #include <libavutil/common.h>
@ -401,17 +402,13 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
{ {
struct priv *s = cache->priv; struct priv *s = cache->priv;
switch (cmd) { switch (cmd) {
case STREAM_CTRL_GET_CACHE_SIZE: case STREAM_CTRL_GET_CACHE_INFO:
*(int64_t *)arg = s->buffer_size - s->back_size; *(struct stream_cache_info *)arg = (struct stream_cache_info) {
return STREAM_OK; .size = s->buffer_size - s->back_size,
case STREAM_CTRL_GET_CACHE_FILL: .fill = s->max_filepos - s->read_filepos,
*(int64_t *)arg = s->max_filepos - s->read_filepos; .idle = s->idle,
return STREAM_OK; .speed = llrint(s->speed),
case STREAM_CTRL_GET_CACHE_IDLE: };
*(int *)arg = s->idle;
return STREAM_OK;
case STREAM_CTRL_GET_CACHE_SPEED:
*(double *)arg = s->speed;
return STREAM_OK; return STREAM_OK;
case STREAM_CTRL_SET_READAHEAD: case STREAM_CTRL_SET_READAHEAD:
s->enable_readahead = *(int *)arg; s->enable_readahead = *(int *)arg;
@ -712,17 +709,15 @@ int stream_cache_init(stream_t *cache, stream_t *stream,
for (;;) { for (;;) {
if (mp_cancel_test(cache->cancel)) if (mp_cancel_test(cache->cancel))
return -1; return -1;
int64_t fill; struct stream_cache_info info;
int idle; if (stream_control(s->cache, STREAM_CTRL_GET_CACHE_INFO, &info) < 0)
if (stream_control(s->cache, STREAM_CTRL_GET_CACHE_FILL, &fill) < 0)
break;
if (stream_control(s->cache, STREAM_CTRL_GET_CACHE_IDLE, &idle) < 0)
break; break;
MP_INFO(s, "\rCache fill: %5.2f%% " MP_INFO(s, "\rCache fill: %5.2f%% "
"(%" PRId64 " bytes) ", 100.0 * fill / s->buffer_size, fill); "(%" PRId64 " bytes) ", 100.0 * info.fill / s->buffer_size,
if (fill >= min) info.fill);
if (info.fill >= min)
break; break;
if (idle) if (info.idle)
break; // file is smaller than prefill size break; // file is smaller than prefill size
// Wake up if the cache is done reading some data (or on timeout/abort) // Wake up if the cache is done reading some data (or on timeout/abort)
pthread_mutex_lock(&s->mutex); pthread_mutex_lock(&s->mutex);

View File

@ -67,11 +67,8 @@ enum stream_ctrl {
STREAM_CTRL_GET_SIZE = 1, STREAM_CTRL_GET_SIZE = 1,
// Cache // Cache
STREAM_CTRL_GET_CACHE_SIZE, STREAM_CTRL_GET_CACHE_INFO,
STREAM_CTRL_SET_CACHE_SIZE, STREAM_CTRL_SET_CACHE_SIZE,
STREAM_CTRL_GET_CACHE_FILL,
STREAM_CTRL_GET_CACHE_IDLE,
STREAM_CTRL_GET_CACHE_SPEED,
STREAM_CTRL_SET_READAHEAD, STREAM_CTRL_SET_READAHEAD,
// stream_memory.c // stream_memory.c
@ -122,6 +119,14 @@ enum stream_ctrl {
STREAM_CTRL_SET_CURRENT_TITLE, 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 { struct stream_lang_req {
int type; // STREAM_AUDIO, STREAM_SUB int type; // STREAM_AUDIO, STREAM_SUB
int id; int id;