[FFmpeg-devel] [PATCH] udp: add option "timeout" for read

Nicolas George nicolas.george at normalesup.org
Fri Aug 17 18:33:32 CEST 2012


Le nonidi 29 thermidor, an CCXX, Andrey Utkin a écrit :
> Let UDP reading return error if cannot get data in timeout.
> Parameter takes value in same units as av_gettime(), microseconds.

Do you have a reason for implementing that for UDP and not for all protocols
at once?

> ---
>  doc/protocols.texi |    3 +++
>  libavformat/udp.c  |   23 +++++++++++++++++++++--
>  2 files changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/doc/protocols.texi b/doc/protocols.texi
> index be19239..265fe13 100644
> --- a/doc/protocols.texi
> +++ b/doc/protocols.texi
> @@ -686,6 +686,9 @@ packets with size of 188 bytes. If not specified defaults to 7*4096.
>  @item overrun_nonfatal=@var{1|0}
>  Survive in case of UDP receiving circular buffer overrun. Default
>  value is 0.
> +
> + at item timeout=@var{microseconds}
> +In read mode: if no data arrived in more than this time interval, raise error.
>  @end table
>  
>  Some usage examples of the UDP protocol with @command{ffmpeg} follow.
> diff --git a/libavformat/udp.c b/libavformat/udp.c
> index f93c607..5ed47e8 100644
> --- a/libavformat/udp.c
> +++ b/libavformat/udp.c
> @@ -64,6 +64,7 @@ typedef struct {
>      struct sockaddr_storage dest_addr;
>      int dest_addr_len;
>      int is_connected;
> +    int64_t read_timeout;
>  
>      /* Circular Buffer variables for use in UDP receive code */
>      int circular_buffer_size;
> @@ -77,6 +78,7 @@ typedef struct {
>  #endif
>      uint8_t tmp[UDP_MAX_PKT_SIZE+4];
>      int remaining_in_dg;
> +    int64_t waiting_data_since_time;  /* used for 'timeout' option */
>  } UDPContext;
>  
>  static void log_net_error(void *ctx, int level, const char* prefix)
> @@ -549,6 +551,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
>                      break;
>              }
>          }
> +        if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p))
> +            s->read_timeout = strtol(buf, NULL, 10);
>      }
>  
>      /* fill the dest addr */
> @@ -700,6 +704,8 @@ static int udp_read(URLContext *h, uint8_t *buf, int size)
>      int ret;
>      int avail, nonblock = h->flags & AVIO_FLAG_NONBLOCK;
>  
> +    if (s->waiting_data_since_time && (av_gettime() - s->waiting_data_since_time > s->read_timeout))
> +        return AVERROR(EIO);

The error value seems wrong: ETIMEDOUT seems more appropriate.

>  #if HAVE_PTHREAD_CANCEL
>      if (s->fifo) {
>          pthread_mutex_lock(&s->mutex);
> @@ -718,6 +724,7 @@ static int udp_read(URLContext *h, uint8_t *buf, int size)
>                  av_fifo_generic_read(s->fifo, buf, avail, NULL);
>                  av_fifo_drain(s->fifo, AV_RL32(tmp) - avail);
>                  pthread_mutex_unlock(&s->mutex);
> +                s->waiting_data_since_time = 0;

Why this?

>                  return avail;
>              } else if(s->circular_buffer_error){
>                  int err = s->circular_buffer_error;
> @@ -725,9 +732,13 @@ static int udp_read(URLContext *h, uint8_t *buf, int size)
>                  return err;
>              } else if(nonblock) {
>                  pthread_mutex_unlock(&s->mutex);
> +                if (s->read_timeout && !s->waiting_data_since_time)
> +                    s->waiting_data_since_time = av_gettime();
>                  return AVERROR(EAGAIN);
>              }
>              else {
> +                if (s->read_timeout && !s->waiting_data_since_time)
> +                    s->waiting_data_since_time = av_gettime();
>                  /* FIXME: using the monotonic clock would be better,
>                     but it does not exist on all supported platforms. */
>                  int64_t t = av_gettime() + 100000;
> @@ -743,12 +754,20 @@ static int udp_read(URLContext *h, uint8_t *buf, int size)
>  
>      if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
>          ret = ff_network_wait_fd(s->udp_fd, 0);
> -        if (ret < 0)
> +        if (ret < 0) {
> +            if (s->read_timeout && (ret == AVERROR(EAGAIN)) && !s->waiting_data_since_time)
> +                s->waiting_data_since_time = av_gettime();
>              return ret;
> +        }
>      }
>      ret = recv(s->udp_fd, buf, size, 0);
>  
> -    return ret < 0 ? ff_neterrno() : ret;
> +    if (ret < 0) {
> +        return ff_neterrno();
> +    } else {
> +        s->waiting_data_since_time = 0;
> +        return ret;
> +    }
>  }
>  
>  static int udp_write(URLContext *h, const uint8_t *buf, int size)

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120817/c7e98d8b/attachment.asc>


More information about the ffmpeg-devel mailing list