Hi,
Attached patch fixes issue #6007 for me.
I think it could improved / extended because the "if (s->seekable == -1 && 
(!s->is_akamai || s->content_range_len != 2147483647))" is probably better 
placed http_read_header along with the similar is_mediagateway workaround. I 
wasn't sure whether the is_akamai should only be triggered if the filesize was 
read from the Content-Range header.
Philip
From 0ac79d03981e823a1922e7e1f58af7f3b02dca7d Mon Sep 17 00:00:00 2001
From: Philip de Nier <phil...@rd.bbc.co.uk>
Date: Wed, 7 Dec 2016 15:09:09 +0000
Subject: [PATCH] http: allow content range to set filesize

Set filesize to Content-Length if present and Transfer-Encoding is
not chunked. Otherwise set to Content-Range instance length if present.

Solves issue where filesize is set to unknown when using byte range
requests in combination with chunked transfers.

Fixes issue #6007
---
 libavformat/http.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 944a6cf..8dfaa5d 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -63,6 +63,7 @@ typedef struct HTTPContext {
     int http_code;
     /* Used if "Transfer-Encoding: chunked" otherwise -1. */
     uint64_t chunksize;
+    uint64_t content_len, content_range_len;
     uint64_t off, end_off, filesize;
     char *location;
     HTTPAuthState auth_state;
@@ -618,9 +619,9 @@ static void parse_content_range(URLContext *h, const char *p)
         p     += 6;
         s->off = strtoull(p, NULL, 10);
         if ((slash = strchr(p, '/')) && strlen(slash) > 0)
-            s->filesize = strtoull(slash + 1, NULL, 10);
+            s->content_range_len = strtoull(slash + 1, NULL, 10);
     }
-    if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
+    if (s->seekable == -1 && (!s->is_akamai || s->content_range_len != 2147483647))
         h->is_streamed = 0; /* we _can_ in fact seek */
 }
 
@@ -810,7 +811,7 @@ static int process_line(URLContext *h, char *line, int line_count,
             *new_location = 1;
         } else if (!av_strcasecmp(tag, "Content-Length") &&
                    s->filesize == UINT64_MAX) {
-            s->filesize = strtoull(p, NULL, 10);
+            s->content_len = strtoull(p, NULL, 10);
         } else if (!av_strcasecmp(tag, "Content-Range")) {
             parse_content_range(h, p);
         } else if (!av_strcasecmp(tag, "Accept-Ranges") &&
@@ -819,7 +820,6 @@ static int process_line(URLContext *h, char *line, int line_count,
             h->is_streamed = 0;
         } else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
                    !av_strncasecmp(p, "chunked", 7)) {
-            s->filesize  = UINT64_MAX;
             s->chunksize = 0;
         } else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
             ff_http_auth_handle_header(&s->auth_state, tag, p);
@@ -974,6 +974,8 @@ static int http_read_header(URLContext *h, int *new_location)
     int err = 0;
 
     s->chunksize = UINT64_MAX;
+    s->content_range_len = UINT64_MAX;
+    s->content_len = UINT64_MAX;
 
     for (;;) {
         if ((err = http_get_line(s, line, sizeof(line))) < 0)
@@ -989,6 +991,13 @@ static int http_read_header(URLContext *h, int *new_location)
         s->line_count++;
     }
 
+    if (s->filesize == UINT64_MAX) {
+        if (s->chunksize == UINT64_MAX && s->content_len != UINT64_MAX)
+            s->filesize = s->content_len;
+        else if (s->content_range_len != UINT64_MAX)
+            s->filesize = s->content_range_len;
+    }
+
     if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000)
         h->is_streamed = 1; /* we can in fact _not_ seek */
 
-- 
1.9.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to