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 #3003.
This commit is contained in:
parent
e1264d3976
commit
57506b27ed
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
12
player/osd.c
12
player/osd.c
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user