summaryrefslogtreecommitdiff
path: root/stream/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'stream/cache.c')
-rw-r--r--stream/cache.c120
1 files changed, 26 insertions, 94 deletions
diff --git a/stream/cache.c b/stream/cache.c
index db05073..6bd729c 100644
--- a/stream/cache.c
+++ b/stream/cache.c
@@ -56,6 +56,7 @@
#include "osdep/threads.h"
#include "common/msg.h"
+#include "common/tags.h"
#include "options/options.h"
#include "stream.h"
@@ -75,7 +76,6 @@ struct priv {
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
- struct byte_meta *bm; // additional per-byte metadata
bool seekable; // underlying stream is seekable
struct mp_log *log;
@@ -109,25 +109,12 @@ struct priv {
// Cached STREAM_CTRLs
double stream_time_length;
- double stream_start_time;
int64_t stream_size;
- bool stream_manages_timeline;
- unsigned int stream_num_chapters;
- int stream_cache_idle;
- int stream_cache_fill;
- char **stream_metadata;
- char *disc_name;
-};
-
-// Store additional per-byte metadata. Since per-byte would be way too
-// inefficient, store it only for every BYTE_META_CHUNK_SIZE byte.
-struct byte_meta {
- float stream_pts;
+ struct mp_tags *stream_metadata;
+ double start_pts;
};
enum {
- BYTE_META_CHUNK_SIZE = 8 * 1024,
-
CACHE_INTERRUPTED = -1,
CACHE_CTRL_NONE = 0,
@@ -135,7 +122,7 @@ enum {
CACHE_CTRL_PING = -2,
// we should fill buffer only if space>=FILL_LIMIT
- FILL_LIMIT = FFMAX(16 * 1024, BYTE_META_CHUNK_SIZE * 2),
+ FILL_LIMIT = 16 * 1024,
};
static int64_t mp_clipi64(int64_t val, int64_t min, int64_t max)
@@ -180,6 +167,7 @@ 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;
}
// Copy at most dst_size from the cache at the given absolute file position pos.
@@ -279,13 +267,12 @@ static bool cache_fill(struct priv *s)
len = stream_read_partial(s->stream, &s->buffer[pos], space);
pthread_mutex_lock(&s->mutex);
- double pts;
- if (stream_control(s->stream, STREAM_CTRL_GET_CURRENT_TIME, &pts) <= 0)
- pts = MP_NOPTS_VALUE;
- for (int64_t b_pos = pos; b_pos < pos + len + BYTE_META_CHUNK_SIZE;
- b_pos += BYTE_META_CHUNK_SIZE)
- {
- s->bm[b_pos / BYTE_META_CHUNK_SIZE] = (struct byte_meta){.stream_pts = pts};
+ // 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;
@@ -312,11 +299,8 @@ static int resize_cache(struct priv *s, int64_t size)
int64_t buffer_size = MPMIN(MPMAX(size, min_size), max_size);
unsigned char *buffer = malloc(buffer_size);
- struct byte_meta *bm = calloc(buffer_size / BYTE_META_CHUNK_SIZE + 2,
- sizeof(struct byte_meta));
- if (!buffer || !bm) {
+ if (!buffer) {
free(buffer);
- free(bm);
return STREAM_ERROR;
}
@@ -347,12 +331,10 @@ static int resize_cache(struct priv *s, int64_t size)
}
free(s->buffer);
- free(s->bm);
s->buffer_size = buffer_size;
s->back_size = buffer_size / 2;
s->buffer = buffer;
- s->bm = bm;
s->idle = false;
s->eof = false;
@@ -361,39 +343,20 @@ static int resize_cache(struct priv *s, int64_t size)
if (s->seek_limit > s->buffer_size - FILL_LIMIT)
s->seek_limit = s->buffer_size - FILL_LIMIT;
- for (size_t n = 0; n < s->buffer_size / BYTE_META_CHUNK_SIZE + 2; n++)
- s->bm[n] = (struct byte_meta){.stream_pts = MP_NOPTS_VALUE};
-
return STREAM_OK;
}
static void update_cached_controls(struct priv *s)
{
- unsigned int ui;
int64_t i64;
double d;
- char **m;
- char *t;
+ 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;
- s->stream_start_time = MP_NOPTS_VALUE;
- if (stream_control(s->stream, STREAM_CTRL_GET_START_TIME, &d) == STREAM_OK)
- s->stream_start_time = d;
- s->stream_manages_timeline = false;
- if (stream_control(s->stream, STREAM_CTRL_MANAGES_TIMELINE, NULL) == STREAM_OK)
- s->stream_manages_timeline = true;
- s->stream_num_chapters = 0;
- if (stream_control(s->stream, STREAM_CTRL_GET_NUM_CHAPTERS, &ui) == STREAM_OK)
- s->stream_num_chapters = ui;
- if (stream_control(s->stream, STREAM_CTRL_GET_METADATA, &m) == STREAM_OK) {
+ if (stream_control(s->stream, STREAM_CTRL_GET_METADATA, &tags) == STREAM_OK) {
talloc_free(s->stream_metadata);
- s->stream_metadata = talloc_steal(s, m);
- }
- if (stream_control(s->stream, STREAM_CTRL_GET_DISC_NAME, &t) == STREAM_OK)
- {
- talloc_free(s->disc_name);
- s->disc_name = talloc_steal(s, t);
+ s->stream_metadata = talloc_steal(s, tags);
}
s->stream_size = -1;
if (stream_control(s->stream, STREAM_CTRL_GET_SIZE, &i64) == STREAM_OK)
@@ -417,59 +380,26 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
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_START_TIME:
- if (s->stream_start_time == MP_NOPTS_VALUE)
- return STREAM_UNSUPPORTED;
- *(double *)arg = s->stream_start_time;
- return STREAM_OK;
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_MANAGES_TIMELINE:
- return s->stream_manages_timeline ? STREAM_OK : STREAM_UNSUPPORTED;
- case STREAM_CTRL_GET_NUM_CHAPTERS:
- *(unsigned int *)arg = s->stream_num_chapters;
- return STREAM_OK;
case STREAM_CTRL_GET_CURRENT_TIME: {
- if (s->read_filepos >= s->min_filepos &&
- s->read_filepos <= s->max_filepos &&
- s->min_filepos < s->max_filepos)
- {
- int64_t fpos = FFMIN(s->read_filepos, s->max_filepos - 1);
- int64_t pos = fpos - s->offset;
- if (pos < 0)
- pos += s->buffer_size;
- else if (pos >= s->buffer_size)
- pos -= s->buffer_size;
- double pts = s->bm[pos / BYTE_META_CHUNK_SIZE].stream_pts;
- *(double *)arg = pts;
- return pts == MP_NOPTS_VALUE ? STREAM_UNSUPPORTED : STREAM_OK;
- }
- return STREAM_UNSUPPORTED;
+ if (s->start_pts == MP_NOPTS_VALUE)
+ return STREAM_UNSUPPORTED;
+ *(double *)arg = s->start_pts;
+ return STREAM_OK;
}
case STREAM_CTRL_GET_METADATA: {
- if (s->stream_metadata && s->stream_metadata[0]) {
- char **m = talloc_new(NULL);
- int num_m = 0;
- for (int n = 0; s->stream_metadata[n]; n++) {
- char *t = talloc_strdup(m, s->stream_metadata[n]);
- MP_TARRAY_APPEND(NULL, m, num_m, t);
- }
- MP_TARRAY_APPEND(NULL, m, num_m, NULL);
- MP_TARRAY_APPEND(NULL, m, num_m, NULL);
- *(char ***)arg = m;
+ 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_GET_DISC_NAME: {
- if (!s->disc_name)
- return STREAM_UNSUPPORTED;
- *(char **)arg = talloc_strdup(NULL, s->disc_name);
- return STREAM_OK;
- }
case STREAM_CTRL_RESUME_CACHE:
s->idle = s->eof = false;
pthread_cond_signal(&s->wakeup);
@@ -482,6 +412,7 @@ 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:
return true;
@@ -662,7 +593,6 @@ static void cache_uninit(stream_t *cache)
pthread_mutex_destroy(&s->mutex);
pthread_cond_destroy(&s->wakeup);
free(s->buffer);
- free(s->bm);
talloc_free(s);
}
@@ -677,6 +607,8 @@ int stream_cache_init(stream_t *cache, stream_t *stream,
struct priv *s = talloc_zero(NULL, struct priv);
s->log = cache->log;
+ cache_drop_contents(s);
+
s->seek_limit = opts->seek_min * 1024ULL;
if (resize_cache(s, opts->size * 1024ULL) != STREAM_OK) {