From ccea588f831906084b8c8235222920e6984beb72 Mon Sep 17 00:00:00 2001 From: Andrey Utkin Date: Mon, 27 Aug 2012 16:31:08 +0300 Subject: [PATCH] avio: Add an option 'rw_timeout' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If set non-zero, this limits duration of the retry_transfer_wrapper() loop, thus affecting ffurl_read*(), ffurl_write(). As soon as one single byte is successfully received/transmitted, the timer restarts. This has further changes by Michael Niedermayer and Martin Storsjö. Signed-off-by: Martin Storsjö --- doc/protocols.texi | 8 ++++++++ libavformat/avio.c | 21 +++++++++++++++++---- libavformat/url.h | 1 + libavformat/version.h | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index f30567d839..c0663ac76a 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -17,6 +17,14 @@ particular protocol using the option The option "-protocols" of the av* tools will display the list of supported protocols. +All protocols accept the following options: + +@table @option +@item rw_timeout +Maximum time to wait for (network) read/write operations to complete, +in microseconds. +@end table + A description of the currently available protocols follows. @section concat diff --git a/libavformat/avio.c b/libavformat/avio.c index 4da6b74165..6039990990 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -49,7 +49,10 @@ static void *urlcontext_child_next(void *obj, void *prev) return NULL; } -static const AVOption options[] = { { NULL } }; +static const AVOption options[] = { + { "rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM }, + { NULL } +}; const AVClass ffurl_context_class = { .class_name = "URLContext", .item_name = urlcontext_to_name, @@ -199,6 +202,7 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, { int ret, len; int fast_retries = 5; + int64_t wait_since = 0; len = 0; while (len < size_min) { @@ -209,14 +213,23 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf, return ret; if (ret == AVERROR(EAGAIN)) { ret = 0; - if (fast_retries) + if (fast_retries) { fast_retries--; - else + } else { + if (h->rw_timeout) { + if (!wait_since) + wait_since = av_gettime_relative(); + else if (av_gettime_relative() > wait_since + h->rw_timeout) + return AVERROR(EIO); + } av_usleep(1000); + } } else if (ret < 1) return (ret < 0 && ret != AVERROR_EOF) ? ret : len; - if (ret) + if (ret) { fast_retries = FFMAX(fast_retries, 2); + wait_since = 0; + } len += ret; if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; diff --git a/libavformat/url.h b/libavformat/url.h index 482658b7fe..408c674ddf 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -49,6 +49,7 @@ typedef struct URLContext { int is_streamed; /**< true if streamed (no seek possible), default = false */ int is_connected; AVIOInterruptCB interrupt_callback; + int64_t rw_timeout; /**< maximum time to wait for (network) read/write operation completion, in microseconds */ } URLContext; typedef struct URLProtocol { diff --git a/libavformat/version.h b/libavformat/version.h index f264076f39..75d765b3e6 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 5 -#define LIBAVFORMAT_VERSION_MICRO 0 +#define LIBAVFORMAT_VERSION_MICRO 1 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \