summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-07-07 19:09:37 +0200
committerwm4 <wm4@nowhere>2014-07-07 19:09:37 +0200
commit49813670219c3f1f3ab47835d407d355a6698174 (patch)
tree8e65a6b1d490934d0aad326f5013cfdcf7e74d71 /stream
parent4d829d750cc872ae4e6bf31117022f8934230972 (diff)
downloadmpv-49813670219c3f1f3ab47835d407d355a6698174.tar.bz2
mpv-49813670219c3f1f3ab47835d407d355a6698174.tar.xz
cache, dvd, bluray: simplify stream time handling
We used a complicated and approximate method to cache the stream timestamp, which is basically per-byte. (To reduce overhead, it was only cached per 8KB-block, so it was approximate.) Simplify this, and read/keep the timestamp only on discontinuities. This is when demux_disc.c actually needs the timestamp. Note that caching is currently disabled for dvdnav, but we still read the timestamp only after some data is read. libdvdread behaves well, but I don't know about libbluray, and the previous code also read the timestamp only after reading data, so try to keep it safe. Also drop the start_time offset. It wouldn't be correct anymore if used with the cache, and the idea behind it wasn't very sane either (making the player to offset the initial playback time to 0).
Diffstat (limited to 'stream')
-rw-r--r--stream/cache.c58
1 files changed, 16 insertions, 42 deletions
diff --git a/stream/cache.c b/stream/cache.c
index 91662cec47..197f7d3391 100644
--- a/stream/cache.c
+++ b/stream/cache.c
@@ -76,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;
@@ -116,17 +115,10 @@ struct priv {
int stream_cache_fill;
struct mp_tags *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;
+ double start_pts;
};
enum {
- BYTE_META_CHUNK_SIZE = 8 * 1024,
-
CACHE_INTERRUPTED = -1,
CACHE_CTRL_NONE = 0,
@@ -134,7 +126,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)
@@ -179,6 +171,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.
@@ -278,13 +271,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;
@@ -311,11 +303,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;
}
@@ -346,12 +335,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;
@@ -360,9 +347,6 @@ 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;
}
@@ -419,21 +403,10 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
*(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) {
@@ -642,7 +615,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);
}
@@ -657,6 +629,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) {