From 3069e70f62fa506c6b86bd7dac4fcb139c886f37 Mon Sep 17 00:00:00 2001 From: Andrey Utkin Date: Mon, 12 Mar 2012 17:09:53 +0200 Subject: udp: Add option overrun_nonfatal Optionize fail/survive on circular buffer overrun Signed-off-by: Michael Niedermayer --- libavformat/udp.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'libavformat/udp.c') diff --git a/libavformat/udp.c b/libavformat/udp.c index b914f9b7e1..17bf434759 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -59,6 +59,7 @@ typedef struct { int is_multicast; int local_port; int reuse_socket; + int overrun_nonfatal; struct sockaddr_storage dest_addr; int dest_addr_len; int is_connected; @@ -260,6 +261,7 @@ static int udp_port(struct sockaddr_storage *addr, int addr_len) * 'localport=n' : set the local port * 'pkt_size=n' : set max packet size * 'reuse=1' : enable reusing the socket + * 'overrun_nonfatal=1': survive in case of circular buffer overrun * * @param h media file context * @param uri of the remote server @@ -358,12 +360,6 @@ static void *circular_buffer_task( void *_URLContext) /* Whats the minimum we can read so that we dont comletely fill the buffer */ left = av_fifo_space(s->fifo); - /* No Space left, error, what do we do now */ - if(left < UDP_MAX_PKT_SIZE + 4) { - av_log(h, AV_LOG_ERROR, "circular_buffer: OVERRUN\n"); - s->circular_buffer_error = AVERROR(EIO); - goto end; - } len = recv(s->udp_fd, s->tmp+4, sizeof(s->tmp)-4, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { @@ -373,6 +369,20 @@ static void *circular_buffer_task( void *_URLContext) continue; } AV_WL32(s->tmp, len); + if(left < len + 4) { + /* No Space left */ + if (s->overrun_nonfatal) { + av_log(h, AV_LOG_WARNING, "Circular buffer overrun. " + "Surviving due to overrun_nonfatal option\n"); + continue; + } else { + av_log(h, AV_LOG_ERROR, "Circular buffer overrun. " + "To avoid, increase fifo_size URL option. " + "To survive in such case, use overrun_nonfatal option\n"); + s->circular_buffer_error = AVERROR(EIO); + goto end; + } + } pthread_mutex_lock(&s->mutex); av_fifo_generic_write(s->fifo, s->tmp, len+4, NULL); pthread_cond_signal(&s->cond); @@ -421,6 +431,13 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->reuse_socket = 1; reuse_specified = 1; } + if (av_find_info_tag(buf, sizeof(buf), "overrun_nonfatal", p)) { + char *endptr = NULL; + s->overrun_nonfatal = strtol(buf, &endptr, 10); + /* assume if no digits were found it is a request to enable it */ + if (buf == endptr) + s->overrun_nonfatal = 1; + } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); } -- cgit v1.2.3