mirror of https://github.com/mpv-player/mpv
cache: refuse to seek outside of cache boundaries
Note that this still happens in the stream level, so we can't have nice highlevel behavior restricting seeking. Instead, if a seek leads to the demuxer requesting data outside of the cached range, the seek will simply fail. This might confuse the demuxer, and the resulting behavior is not necessarily useful. Note that this also doesn't try to skip data on a forward seek. This would just freeze the stream with slow unseekable streams. One nice thing is that stream.h has a separate function for merely skipping data (separate from seeking forward), which is pretty useful in this case: we want skipping of data to work, even if we reject seeking forward by skipping data as too expensive. This probably is or will be useful for demux_mkv.c.
This commit is contained in:
parent
d8dd9a6725
commit
eb17780740
|
@ -75,6 +75,7 @@ struct priv {
|
||||||
int64_t fill_limit; // we should fill buffer only if space>=fill_limit
|
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
|
int64_t seek_limit; // keep filling cache if distance is less that seek limit
|
||||||
struct byte_meta *bm; // additional per-byte metadata
|
struct byte_meta *bm; // additional per-byte metadata
|
||||||
|
bool seekable; // underlying stream is seekable
|
||||||
|
|
||||||
struct mp_log *log;
|
struct mp_log *log;
|
||||||
|
|
||||||
|
@ -475,6 +476,7 @@ static int cache_seek(stream_t *cache, int64_t pos)
|
||||||
{
|
{
|
||||||
struct priv *s = cache->priv;
|
struct priv *s = cache->priv;
|
||||||
assert(s->cache_thread_running);
|
assert(s->cache_thread_running);
|
||||||
|
int r = 1;
|
||||||
|
|
||||||
pthread_mutex_lock(&s->mutex);
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
|
||||||
|
@ -482,12 +484,21 @@ static int cache_seek(stream_t *cache, int64_t pos)
|
||||||
" (cur=%" PRId64 ") <= %" PRId64 " \n",
|
" (cur=%" PRId64 ") <= %" PRId64 " \n",
|
||||||
s->min_filepos, pos, s->read_filepos, s->max_filepos);
|
s->min_filepos, pos, s->read_filepos, s->max_filepos);
|
||||||
|
|
||||||
cache->pos = s->read_filepos = pos;
|
if (!s->seekable && pos > s->max_filepos) {
|
||||||
s->eof = false; // so that cache_read() will actually wait for new data
|
MP_ERR(s, "Attempting to seek past cached data in unseekable stream.\n");
|
||||||
pthread_cond_signal(&s->wakeup);
|
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);
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
return 1;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cache_control(stream_t *cache, int cmd, void *arg)
|
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)
|
if (min > s->buffer_size - s->fill_limit)
|
||||||
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) {
|
if (pthread_create(&s->cache_thread, NULL, cache_thread, s) != 0) {
|
||||||
MP_ERR(s, "Starting cache process/thread failed: %s.\n",
|
MP_ERR(s, "Starting cache process/thread failed: %s.\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|
Loading…
Reference in New Issue