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