summaryrefslogtreecommitdiffstats
path: root/stream
diff options
context:
space:
mode:
authorKevin Mitchell <kevmitch@gmail.com>2015-11-09 04:52:07 -0800
committerKevin Mitchell <kevmitch@gmail.com>2015-11-09 22:41:19 -0800
commitdd0c85679b22ff9ab2ceb682c162053036772991 (patch)
treeba0967c4471b9c1ce932cc3770ba152a9c2c954e /stream
parent4efadb280892afb7c051292e3090737420546099 (diff)
downloadmpv-dd0c85679b22ff9ab2ceb682c162053036772991.tar.bz2
mpv-dd0c85679b22ff9ab2ceb682c162053036772991.tar.xz
stream_libarchive: make libarchive seek callback lazy
This fixes problems seeking http streams to their end.
Diffstat (limited to 'stream')
-rw-r--r--stream/stream_libarchive.c25
1 files changed, 22 insertions, 3 deletions
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,