[vlc-devel] [PATCH] RFC: http: add support for byte range requests

Francois Cartegnie fcvlcdev at free.fr
Fri Jun 14 17:25:21 CEST 2019


ByteRange support in HTTP requests is mandatory
for adaptive.
-> replace adaptive custom http code
-> replace adaptive usage of streamUrl
---
 modules/access/http/file.c | 72 +++++++++++++++++++++++++++++---------
 modules/access/http/file.h | 20 +++++++++++
 2 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/modules/access/http/file.c b/modules/access/http/file.c
index 322c0b2fbe..f7f3ea293d 100644
--- a/modules/access/http/file.c
+++ b/modules/access/http/file.c
@@ -39,17 +39,23 @@
 
 #pragma GCC visibility push(default)
 
+struct vlc_http_file_bytepos
+{
+    uintmax_t offset;
+    uintmax_t offset_max;
+};
+
 struct vlc_http_file
 {
     struct vlc_http_resource resource;
-    uintmax_t offset;
+    struct vlc_http_file_bytepos pos;
 };
 
 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;
+    struct vlc_http_file_bytepos *pos = opaque;
 
     if (file->resource.response != NULL)
     {
@@ -69,16 +75,30 @@ static int vlc_http_file_req(const struct vlc_http_resource *res,
         }
     }
 
-    if (vlc_http_msg_add_header(req, "Range", "bytes=%" PRIuMAX "-", *offset)
-     && *offset != 0)
+    int ret;
+    if(pos->offset_max == (uintmax_t)-1)
+    {
+        ret = vlc_http_msg_add_header(req, "Range", "bytes=%"
+                                            PRIuMAX "-",
+                                            pos->offset);
+    }
+    else
+    {
+        ret = vlc_http_msg_add_header(req, "Range", "bytes=%"
+                                            PRIuMAX "-%" PRIuMAX,
+                                            pos->offset, pos->offset_max);
+    }
+
+    if (ret && pos->offset != 0)
         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_bytepos *pos = opaque;
 
     if (vlc_http_msg_get_status(resp) == 206)
     {
@@ -90,7 +110,7 @@ static int vlc_http_file_resp(const struct vlc_http_resource *res,
 
         uintmax_t start, end;
         if (sscanf(str, "bytes %" SCNuMAX "-%" SCNuMAX, &start, &end) != 2
-         || start != *offset || start > end)
+         || start != pos->offset || start > end)
             /* A single range response is what we asked for, but not at that
              * start offset. */
             goto fail;
@@ -110,9 +130,11 @@ static const struct vlc_http_resource_cbs vlc_http_file_callbacks =
     vlc_http_file_resp,
 };
 
-struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
-                                               const char *uri, const char *ua,
-                                               const char *ref)
+struct vlc_http_resource *vlc_http_file_create_ranged(struct vlc_http_mgr *mgr,
+                                                      const char *uri, const char *ua,
+                                                      const char *ref,
+                                                      uintmax_t rangelow,
+                                                      uintmax_t rangehigh)
 {
     struct vlc_http_file *file = malloc(sizeof (*file));
     if (unlikely(file == NULL))
@@ -125,10 +147,18 @@ struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
         return NULL;
     }
 
-    file->offset = 0;
+    file->pos.offset_max = (rangehigh > rangelow) ? rangehigh : (uintmax_t)-1;
+    file->pos.offset = rangelow;
     return &file->resource;
 }
 
+struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
+                                               const char *uri, const char *ua,
+                                               const char *ref)
+{
+    return vlc_http_file_create_ranged(mgr, uri, ua, ref, 0, 0);
+}
+
 static uintmax_t vlc_http_msg_get_file_size(const struct vlc_http_msg *resp)
 {
     int status = vlc_http_msg_get_status(resp);
@@ -203,11 +233,19 @@ 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);
-    if (resp == NULL)
+    struct vlc_http_file *file = (struct vlc_http_file *)res;
+    if(offset > file->pos.offset_max)
         return -1;
 
-    struct vlc_http_file *file = (struct vlc_http_file *)res;
+    struct vlc_http_file_bytepos pos =
+    {
+        .offset = offset,
+        .offset_max = file->pos.offset_max,
+    };
+
+    struct vlc_http_msg *resp = vlc_http_res_open(res, &pos);
+    if (resp == NULL)
+        return -1;
 
     int status = vlc_http_msg_get_status(resp);
     if (res->response != NULL)
@@ -225,7 +263,7 @@ int vlc_http_file_seek(struct vlc_http_resource *res, uintmax_t offset)
     }
 
     res->response = resp;
-    file->offset = offset;
+    file->pos = pos;
     return 0;
 }
 
@@ -238,8 +276,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->pos.offset < vlc_http_msg_get_file_size(res->response)
+         && vlc_http_file_seek(res, file->pos.offset) == 0)
             block = vlc_http_res_read(res);
 
         if (block == vlc_http_error)
@@ -249,6 +287,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->pos.offset += block->i_buffer;
     return block;
 }
diff --git a/modules/access/http/file.h b/modules/access/http/file.h
index 802cf8f93a..259238089f 100644
--- a/modules/access/http/file.h
+++ b/modules/access/http/file.h
@@ -46,6 +46,26 @@ struct vlc_http_resource *vlc_http_file_create(struct vlc_http_mgr *mgr,
                                                const char *url, const char *ua,
                                                const char *ref);
 
+/**
+ * Creates an HTTP file from byte range.
+ *
+ * Allocates a structure for a remote HTTP-served read-only file.
+ * Using this API will fail if the server does not provide
+ * Content-Range support
+ *
+ * @param url URL of the file to read
+ * @param ua user agent string (or NULL to ignore)
+ * @param ref referral URL (or NULL to ignore)
+ * @param rangelow byte range start
+ * @param ref referral URL (< rangelow or (uintmax_t)-1 to ignore)
+ *
+ * @return an HTTP resource object pointer, or NULL on error
+ */
+struct vlc_http_resource *vlc_http_file_create_ranged(struct vlc_http_mgr *mgr,
+                                                      const char *url, const char *ua,
+                                                      const char *ref,
+                                                      uintmax_t rangelow,
+                                                      uintmax_t rangehigh);
 /**
  * Gets file size.
  *
-- 
2.20.1



More information about the vlc-devel mailing list