This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 4f5d91e43fd616c6415ef08802469a7f4da25d4e Author: Niklas Haas <[email protected]> AuthorDate: Fri Jan 23 11:19:17 2026 +0100 Commit: Niklas Haas <[email protected]> CommitDate: Sat Feb 7 10:02:36 2026 +0000 avformat/http: allow limiting initial request size Sometimes, HTTP sources require a lot of seeking during probing / header parsing (especially for formats like MXF). Currently, we need to completely tear down and re-establish the connection most times this happens, which puts a lot of stress on the network stack and also results in transmission of possibly many unnecessary bytes. This patch adds an option to allow FFmpeg to request partial ranges during the initialization stage. This is done until the initial request size is fully read, after which we fall back to the normal behavior (i.e. infinite streaming via an unbounded request). The usefulness of this is limited without also specifying -multiple_requests 1, since otherwise there is little point to requesting partial ranges to begin with. (However, it is semantically independent, so we keep it that way.) --- doc/protocols.texi | 13 +++++++++++++ libavformat/http.c | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 350c52a465..9c068075d5 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -473,6 +473,19 @@ Set the Referer header. Include 'Referer: URL' header in HTTP request. @item multiple_requests Use persistent connections if set to 1, default is 0. +@item initial_request_size +Limit the size of initial requests. This is useful when dealing with formats +that require frequent seeks during initial parsing. This lasts until the +demuxer makes a read request larger than this size (without a seek in between), +after which the implementation will continue using unbounded requests as usual. +Disabled (set to 0) by default. + +Note that if enabling this option, it's strongly recommended to also enable +the @option{multiple_requests} option, as well as setting +@option{short_seek_size} to the same value or higher. Doing so allows FFmpeg +to reuse a single HTTP connection wherever possible, even for formats like +MXF or MOV that require frequent small seeks during initial parsing. + @item post_data Set custom HTTP post data. diff --git a/libavformat/http.c b/libavformat/http.c index 8c98ea0a8f..b0803f26aa 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -146,6 +146,8 @@ typedef struct HTTPContext { unsigned int retry_after; int reconnect_max_retries; int reconnect_delay_total_max; + uint64_t initial_request_size; + int partial_requests; /* whether or not to limit requests to initial_request_size */ } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -162,6 +164,7 @@ static const AVOption options[] = { { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D }, { "referer", "override referer header", OFFSET(referer), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D }, { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D | E }, + { "initial_request_size", "size (in bytes) of initial requests made during probing / header parsing", OFFSET(initial_request_size), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D }, { "post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D | E }, { "mime_type", "export the MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, { "http_version", "export the http response version", OFFSET(http_version), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY }, @@ -754,6 +757,7 @@ static int http_open(URLContext *h, const char *uri, int flags, else h->is_streamed = 1; + s->partial_requests = s->seekable != 0 && s->initial_request_size > 0; s->filesize = UINT64_MAX; s->location = av_strdup(uri); @@ -1455,6 +1459,9 @@ static int http_read_header(URLContext *h) if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000) h->is_streamed = 1; /* we can in fact _not_ seek */ + if (h->is_streamed) + s->partial_requests = 0; /* unable to use partial requests */ + // add any new cookies into the existing cookie string cookie_string(s->cookie_dict, &s->cookies); av_dict_free(&s->cookie_dict); @@ -1564,7 +1571,15 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, // server supports seeking by analysing the reply headers. if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable != 0)) { av_bprintf(&request, "Range: bytes=%"PRIu64"-", s->off); - if (s->end_off) + if (s->partial_requests && s->seekable != 0) { + uint64_t target_off = s->off + s->initial_request_size; + if (target_off < s->off) /* overflow */ + target_off = UINT64_MAX; + if (s->end_off) + target_off = FFMIN(target_off, s->end_off); + if (target_off != UINT64_MAX) + av_bprintf(&request, "%"PRId64, target_off - 1); + } else if (s->end_off) av_bprintf(&request, "%"PRId64, s->end_off - 1); av_bprintf(&request, "\r\n"); } @@ -1802,6 +1817,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) AVDictionary *options = NULL; if (s->willclose) ffurl_closep(&s->hd); + s->partial_requests = 0; /* continue streaming uninterrupted from now on */ read_ret = http_open_cnx(h, &options); av_dict_free(&options); if (read_ret == 0) _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
