summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream/cache.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/stream/cache.c b/stream/cache.c
index d96f46daaf..040e30a558 100644
--- a/stream/cache.c
+++ b/stream/cache.c
@@ -75,6 +75,7 @@ struct priv {
int64_t fill_limit; // we should fill buffer only if space>=fill_limit
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;
@@ -475,6 +476,7 @@ static int cache_seek(stream_t *cache, int64_t pos)
{
struct priv *s = cache->priv;
assert(s->cache_thread_running);
+ int r = 1;
pthread_mutex_lock(&s->mutex);
@@ -482,12 +484,21 @@ static int cache_seek(stream_t *cache, int64_t pos)
" (cur=%" PRId64 ") <= %" PRId64 " \n",
s->min_filepos, pos, s->read_filepos, s->max_filepos);
- cache->pos = s->read_filepos = pos;
- s->eof = false; // so that cache_read() will actually wait for new data
- pthread_cond_signal(&s->wakeup);
+ if (!s->seekable && pos > s->max_filepos) {
+ MP_ERR(s, "Attempting to seek past cached data in unseekable stream.\n");
+ r = 0;
+ } else if (!s->seekable && pos < s->min_filepos) {
+ MP_ERR(s, "Attempting to seek before cached data in unseekable stream.\n");
+ r = 0;
+ } else {
+ cache->pos = s->read_filepos = pos;
+ s->eof = false; // so that cache_read() will actually wait for new data
+ pthread_cond_signal(&s->wakeup);
+ }
+
pthread_mutex_unlock(&s->mutex);
- return 1;
+ return r;
}
static int cache_control(stream_t *cache, int cmd, void *arg)
@@ -600,6 +611,9 @@ int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size,
if (min > s->buffer_size - s->fill_limit)
min = s->buffer_size - s->fill_limit;
+ s->seekable = (stream->flags & MP_STREAM_SEEK) == MP_STREAM_SEEK &&
+ stream->end_pos > 0;
+
if (pthread_create(&s->cache_thread, NULL, cache_thread, s) != 0) {
MP_ERR(s, "Starting cache process/thread failed: %s.\n",
strerror(errno));