PR #21703 opened by Niklas Haas (haasn)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21703
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21703.patch

It has come to my attention that a way to limit the request range size
would be useful in general, for reasons beyond just speeding up initial
header parsing.

This patch generalizez -initial_request_size to -request_size. I decided
to continue allowing both options to be used simultaneously, so users can
e.g. set -request_size to something large like 10 MiB, but still use a smaller
size for initial header parsing (e.g. 256 KiB).


>From 72ef7e4ae316f042761e457333fee6ff7ac4a3b9 Mon Sep 17 00:00:00 2001
From: Niklas Haas <[email protected]>
Date: Mon, 9 Feb 2026 16:56:25 +0100
Subject: [PATCH] avformat/http: add -request-size option

It has come to my attention that a way to limit the request range size
would be useful in general, for reasons beyond just speeding up initial
header parsing.

This patch generalizez -initial_request_size to -request_size. I decided
to continue allowing both options to be used simultaneously, so users can
e.g. set -request_size to something large like 10 MiB, but still use a smaller
size for initial header parsing (e.g. 256 KiB).
---
 doc/protocols.texi | 25 +++++++++++++++++--------
 libavformat/http.c | 15 +++++++++------
 2 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/doc/protocols.texi b/doc/protocols.texi
index 9c068075d5..0d9cc3c83e 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -473,18 +473,27 @@ 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.
+@item request_size
+Limit the size of requests made. This is useful for some pathological servers
+that throttle unbounded range requests, as well as when expecting to seek
+frequently. 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.
+to reuse a single HTTP connection wherever possible.
+
+@item initial_request_size
+Limit the size of initial requests. Similar to @code{request_size}, but only
+used during initial format parsing. Useful for formats like MXF or MOV that
+require frequent seeks during header parsing. Lasts until the demuxer makes a
+read request larger than this size (without a seek in between), after which
+the implementation will continue using 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.
 
 @item post_data
 Set custom HTTP post data.
diff --git a/libavformat/http.c b/libavformat/http.c
index 805e3eff9f..c62892ed43 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -147,7 +147,8 @@ typedef struct HTTPContext {
     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 */
+    uint64_t request_size;
+    int initial_requests; /* whether or not to limit requests to 
initial_request_size */
     /* Connection statistics */
     int nb_connections;
     int nb_requests;
@@ -172,6 +173,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 },
+    { "request_size", "size (in bytes) of requests to make", 
OFFSET(request_size), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
     { "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 },
@@ -769,7 +771,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->initial_requests = s->seekable != 0 && s->initial_request_size > 0;
     s->filesize = UINT64_MAX;
 
     s->location = av_strdup(uri);
@@ -1472,7 +1474,7 @@ static int http_read_header(URLContext *h)
         h->is_streamed = 1; /* we can in fact _not_ seek */
 
     if (h->is_streamed)
-        s->partial_requests = 0; /* unable to use partial requests */
+        s->initial_requests = 0; /* unable to use partial requests */
 
     // add any new cookies into the existing cookie string
     cookie_string(s->cookie_dict, &s->cookies);
@@ -1583,8 +1585,9 @@ 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->partial_requests && s->seekable != 0) {
-            uint64_t target_off = s->off + s->initial_request_size;
+        if ((s->initial_requests || s->request_size) && s->seekable != 0) {
+            uint64_t req_size = s->initial_requests ? s->initial_request_size 
: s->request_size;
+            uint64_t target_off = s->off + req_size;
             if (target_off < s->off) /* overflow */
                 target_off = UINT64_MAX;
             if (s->end_off)
@@ -1835,7 +1838,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 */
+            s->initial_requests = 0; /* continue streaming uninterrupted from 
now on */
             read_ret = http_open_cnx(h, &options);
             av_dict_free(&options);
             if (read_ret == 0)
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to