From dd0c85679b22ff9ab2ceb682c162053036772991 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Mon, 9 Nov 2015 04:52:07 -0800 Subject: stream_libarchive: make libarchive seek callback lazy This fixes problems seeking http streams to their end. --- stream/stream_libarchive.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'stream') diff --git a/stream/stream_libarchive.c b/stream/stream_libarchive.c index 7aa7feb073..a164da85b8 100644 --- a/stream/stream_libarchive.c +++ b/stream/stream_libarchive.c @@ -27,43 +27,61 @@ struct mp_archive_volume { struct mp_archive *mpa; struct stream *src; + int64_t seek_to; char *url; }; +static bool volume_seek(struct mp_archive_volume *vol) +{ + if (vol->seek_to < 0) + return true; + bool r = stream_seek(vol->src, vol->seek_to); + vol->seek_to = -1; + return r; +} + static ssize_t read_cb(struct archive *arch, void *priv, const void **buffer) { struct mp_archive_volume *vol = priv; + if (!volume_seek(vol)) + return -1; int res = stream_read_partial(vol->src, vol->mpa->buffer, sizeof(vol->mpa->buffer)); *buffer = vol->mpa->buffer; return MPMAX(res, 0); } +// lazy seek to avoid problems with end seeking over http static int64_t seek_cb(struct archive *arch, void *priv, int64_t offset, int whence) { struct mp_archive_volume *vol = priv; switch (whence) { case SEEK_SET: + vol->seek_to = offset; break; case SEEK_CUR: - offset += vol->src->pos; + if (vol->seek_to < 0) + vol->seek_to = stream_tell(vol->src); + vol->seek_to += offset; break; case SEEK_END: ; int64_t size = stream_get_size(vol->src); if (size < 0) return -1; - offset += size; + vol->seek_to = size + offset; break; default: return -1; } - return stream_seek(vol->src, offset) ? offset : -1; + return vol->seek_to; } static int64_t skip_cb(struct archive *arch, void *priv, int64_t request) { struct mp_archive_volume *vol = priv; + if (!volume_seek(vol)) + return -1; int64_t old = stream_tell(vol->src); stream_skip(vol->src, request); return stream_tell(vol->src) - old; @@ -72,6 +90,7 @@ static int64_t skip_cb(struct archive *arch, void *priv, int64_t request) static int open_cb(struct archive *arch, void *priv) { struct mp_archive_volume *vol = priv; + vol->seek_to = -1; if (!vol->src) { vol->src = stream_create(vol->url, STREAM_READ, vol->mpa->primary_src->cancel, -- cgit v1.2.3