[vlc-devel] [PATCH] Proof of Concept: http: add range support
Francois Cartegnie
fcvlcdev at free.fr
Mon Sep 12 20:07:32 CEST 2016
Variable hack for creating streamUrl with
Byte-Range support, required for switching
adaptive backend to regular access.
Also strips Range header for non ranged request.
Tests missing.
---
modules/access/http/access.c | 21 +++++++++++++---
modules/access/http/file.c | 55 ++++++++++++++++++++++++++++++-----------
modules/access/http/file.h | 3 ++-
modules/access/http/file_test.c | 27 ++++++++++----------
4 files changed, 74 insertions(+), 32 deletions(-)
diff --git a/modules/access/http/access.c b/modules/access/http/access.c
index 3f926db..d68273b 100644
--- a/modules/access/http/access.c
+++ b/modules/access/http/access.c
@@ -186,9 +186,18 @@ static int Open(vlc_object_t *obj)
char *ua = var_InheritString(obj, "http-user-agent");
char *referer = var_InheritString(obj, "http-referrer");
bool live = var_InheritBool(obj, "http-continuous");
-
- sys->resource = (live ? vlc_http_live_create : vlc_http_file_create)(
- sys->manager, access->psz_url, ua, referer);
+ if(live)
+ {
+ sys->resource = vlc_http_live_create(sys->manager, access->psz_url,
+ ua, referer);
+ }
+ else
+ {
+ int64_t rangestart = var_InheritInteger(obj, "http-range-start");
+ int64_t rangeend = var_InheritInteger(obj, "http-range-end");
+ sys->resource = vlc_http_file_create( sys->manager, access->psz_url,
+ ua, referer, rangestart, ++rangeend);
+ }
free(referer);
free(ua);
@@ -314,4 +323,10 @@ vlc_module_begin()
"e.g. \"FooBar/1.2.3\"."), true)
change_safe()
change_private()
+ add_integer("http-range-start", 0, NULL, NULL, true)
+ change_safe()
+ change_volatile()
+ add_integer("http-range-end", -1, NULL, NULL, true)
+ change_safe()
+ change_volatile()
vlc_module_end()
diff --git a/modules/access/http/file.c b/modules/access/http/file.c
index ce101f6..7a61765 100644
--- a/modules/access/http/file.c
+++ b/modules/access/http/file.c
@@ -38,18 +38,23 @@
#include "file.h"
#pragma GCC visibility push(default)
+struct vlc_http_file_range
+{
+ uintmax_t start;
+ uintmax_t endplusone;
+};
struct vlc_http_file
{
struct vlc_http_resource resource;
- uintmax_t offset;
+ struct vlc_http_file_range range;
};
static int vlc_http_file_req(const struct vlc_http_resource *res,
struct vlc_http_msg *req, void *opaque)
{
struct vlc_http_file *file = (struct vlc_http_file *)res;
- const uintmax_t *offset = opaque;
+ const struct vlc_http_file_range *range = opaque;
if (file->resource.response != NULL)
{
@@ -69,16 +74,27 @@ static int vlc_http_file_req(const struct vlc_http_resource *res,
}
}
- if (vlc_http_msg_add_header(req, "Range", "bytes=%ju-", *offset)
- && *offset != 0)
- return -1;
+ if(range->start != 0 || range->endplusone)
+ {
+ if(range->endplusone)
+ {
+ if (vlc_http_msg_add_header(req, "Range", "bytes=%ju-%ju",
+ range->start, range->endplusone - 1))
+ return -1;
+ }
+ else if(vlc_http_msg_add_header(req, "Range", "bytes=%ju-", range->start))
+ {
+ return -1;
+ }
+ }
return 0;
}
static int vlc_http_file_resp(const struct vlc_http_resource *res,
const struct vlc_http_msg *resp, void *opaque)
{
- const uintmax_t *offset = opaque;
+ const struct vlc_http_file_range *range = opaque;
+ struct vlc_http_file *file = (struct vlc_http_file *)res;
if (vlc_http_msg_get_status(resp) == 206)
{
@@ -90,13 +106,15 @@ static int vlc_http_file_resp(const struct vlc_http_resource *res,
uintmax_t start, end;
if (sscanf(str, "bytes %ju-%ju", &start, &end) != 2
- || start != *offset || start > end)
+ || start != range->start || start > end
+ || (range->endplusone && end != range->endplusone - 1))
/* A single range response is what we asked for, but not at that
* start offset. */
goto fail;
+ file->range.start = start;
+ file->range.endplusone = end + 1;
}
- (void) res;
return 0;
fail:
@@ -112,7 +130,9 @@ static const struct vlc_http_resource_cbs vlc_http_file_callbacks =
struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
const char *uri, const char *ua,
- const char *ref)
+ const char *ref,
+ uintmax_t rangestart,
+ uintmax_t rangeendplusone)
{
struct vlc_http_file *file = malloc(sizeof (*file));
if (unlikely(file == NULL))
@@ -125,7 +145,8 @@ struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
return NULL;
}
- file->offset = 0;
+ file->range.start = rangestart;
+ file->range.endplusone = rangeendplusone;
return &file->resource;
}
@@ -203,7 +224,11 @@ bool vlc_http_file_can_seek(struct vlc_http_resource *res)
int vlc_http_file_seek(struct vlc_http_resource *res, uintmax_t offset)
{
- struct vlc_http_msg *resp = vlc_http_res_open(res, &offset);
+ struct vlc_http_file_range range;
+ range.start = offset;
+ range.endplusone = 0;
+
+ struct vlc_http_msg *resp = vlc_http_res_open(res, &range);
if (resp == NULL)
return -1;
@@ -225,7 +250,7 @@ int vlc_http_file_seek(struct vlc_http_resource *res, uintmax_t offset)
}
res->response = resp;
- file->offset = offset;
+ file->range = range;
return 0;
}
@@ -238,8 +263,8 @@ block_t *vlc_http_file_read(struct vlc_http_resource *res)
{ /* Automatically reconnect on error if server supports seek */
if (res->response != NULL
&& vlc_http_msg_can_seek(res->response)
- && file->offset < vlc_http_msg_get_file_size(res->response)
- && vlc_http_file_seek(res, file->offset) == 0)
+ && file->range.start < vlc_http_msg_get_file_size(res->response)
+ && vlc_http_file_seek(res, file->range.start) == 0)
block = vlc_http_res_read(res);
if (block == vlc_http_error)
@@ -249,6 +274,6 @@ block_t *vlc_http_file_read(struct vlc_http_resource *res)
if (block == NULL)
return NULL; /* End of stream */
- file->offset += block->i_buffer;
+ file->range.start += block->i_buffer;
return block;
}
diff --git a/modules/access/http/file.h b/modules/access/http/file.h
index 802cf8f..6946f8f 100644
--- a/modules/access/http/file.h
+++ b/modules/access/http/file.h
@@ -44,7 +44,8 @@ struct block_t;
*/
struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
const char *url, const char *ua,
- const char *ref);
+ const char *ref,
+ uintmax_t, uintmax_t);
/**
* Gets file size.
diff --git a/modules/access/http/file_test.c b/modules/access/http/file_test.c
index 64fab07..6155df8 100644
--- a/modules/access/http/file_test.c
+++ b/modules/access/http/file_test.c
@@ -57,7 +57,7 @@ int main(void)
jar = vlc_http_cookies_new();
/* Request failure test */
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
vlc_http_res_set_login(f, NULL, NULL);
vlc_http_res_set_login(f, "john", NULL);
@@ -81,7 +81,7 @@ int main(void)
offset = 0;
etags = true;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(vlc_http_file_get_status(f) == 200);
assert(!vlc_http_file_can_seek(f));
@@ -104,7 +104,7 @@ int main(void)
"\r\n";
offset = 0;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(vlc_http_file_can_seek(f));
assert(vlc_http_file_get_size(f) == 2345);
@@ -139,7 +139,7 @@ int main(void)
"\r\n";
offset = 0;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(!vlc_http_file_can_seek(f));
assert(vlc_http_file_get_size(f) == (uintmax_t)-1);
@@ -156,7 +156,7 @@ int main(void)
"Content-Length: 9999\r\n"
"\r\n";
offset = 0;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(vlc_http_file_get_size(f) == 9999);
assert(vlc_http_file_get_redirect(f) == NULL);
@@ -170,7 +170,7 @@ int main(void)
offset = 0;
etags = false;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(vlc_http_file_can_seek(f));
@@ -187,7 +187,7 @@ int main(void)
"\r\n";
offset = 0;
- f = vlc_http_file_create(NULL, url, ua, NULL);
+ f = vlc_http_file_create(NULL, url, ua, NULL, 0, 0);
assert(f != NULL);
assert(vlc_http_file_get_size(f) == (uintmax_t)-1);
@@ -238,7 +238,7 @@ int main(void)
secure = false;
lang = -1;
- f = vlc_http_file_create(NULL, url_http, ua, NULL);
+ f = vlc_http_file_create(NULL, url_http, ua, NULL, 0, 0);
assert(f != NULL);
/* Protocol redirect hacks - over insecure HTTP */
@@ -260,11 +260,11 @@ int main(void)
vlc_http_file_destroy(f);
/* Dummy API calls */
- f = vlc_http_file_create(NULL, "ftp://localhost/foo", NULL, NULL);
+ f = vlc_http_file_create(NULL, "ftp://localhost/foo", NULL, NULL, 0, 0);
assert(f == NULL);
- f = vlc_http_file_create(NULL, "/foo", NULL, NULL);
+ f = vlc_http_file_create(NULL, "/foo", NULL, NULL, 0, 0);
assert(f == NULL);
- f = vlc_http_file_create(NULL, "http://www.example.com", NULL, NULL);
+ f = vlc_http_file_create(NULL, "http://www.example.com", NULL, NULL, 0, 0);
assert(f != NULL);
vlc_http_file_destroy(f);
@@ -370,8 +370,9 @@ struct vlc_http_msg *vlc_http_mgr_request(struct vlc_http_mgr *mgr, bool https,
assert(str == NULL);
str = vlc_http_msg_get_header(req, "Range");
- assert(str != NULL && !strncmp(str, "bytes=", 6)
- && strtoul(str + 6, &end, 10) == offset && *end == '-');
+ assert((str == NULL && offset == 0)
+ || (str != NULL && !strncmp(str, "bytes=", 6)
+ && strtoul(str + 6, &end, 10) == offset && *end == '-' ));
time_t mtime = vlc_http_msg_get_time(req, "If-Unmodified-Since");
str = vlc_http_msg_get_header(req, "If-Match");
--
2.7.4
More information about the vlc-devel
mailing list