Quoting Martin Storsjö (2016-03-18 13:01:36)
> From: Andrey Utkin <[email protected]>
> 
> 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ö.
> ---
> Andrey's original version didn't reset the timer on successful
> transfers, but I think this is closer to how most people may
> want it to work.
> 
> I also added an AVOption for setting this, to allow it to be set
> generically for any URLProtocol.
> ---
>  libavformat/avio.c | 21 +++++++++++++++++----
>  libavformat/url.h  |  1 +
>  2 files changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/libavformat/avio.c b/libavformat/avio.c
> index 4da6b74..6039990 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);

ETIMEDOUT might be more appropriate perhaps?

> +                }
>                  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 482658b..5ae6cf2 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 mcs */
                                                                                
                                ^
c?

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to