X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fudp.c;h=151e070d191e63aa98de37d9f099e326ce735423;hb=db5effe1a4209e8ace97857e5de0d66a73fe7477;hp=7c18fb7bf05c368b2ca782c881ca90d6021f1223;hpb=f9569249c274ab71b570d6a462903379e9d414fb;p=ffmpeg diff --git a/libavformat/udp.c b/libavformat/udp.c index 7c18fb7bf05..151e070d191 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -30,6 +30,7 @@ #include "avio_internal.h" #include "libavutil/parseutils.h" #include "libavutil/fifo.h" +#include "libavutil/intreadwrite.h" #include #include "internal.h" #include "network.h" @@ -47,6 +48,9 @@ #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP #endif +#define UDP_TX_BUF_SIZE 32768 +#define UDP_MAX_PKT_SIZE 65536 + typedef struct { int udp_fd; int ttl; @@ -65,11 +69,10 @@ typedef struct { #if HAVE_PTHREADS pthread_t circular_buffer_thread; #endif + uint8_t tmp[UDP_MAX_PKT_SIZE+4]; + int remaining_in_dg; } UDPContext; -#define UDP_TX_BUF_SIZE 32768 -#define UDP_MAX_PKT_SIZE 65536 - static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) { @@ -347,26 +350,24 @@ static void *circular_buffer_task( void *_URLContext) /* How much do we have left to the end of the buffer */ /* Whats the minimum we can read so that we dont comletely fill the buffer */ left = av_fifo_space(s->fifo); - left = FFMIN(left, s->fifo->end - s->fifo->wptr); /* No Space left, error, what do we do now */ - if( !left) { + if(left < UDP_MAX_PKT_SIZE + 4) { av_log(h, AV_LOG_ERROR, "circular_buffer: OVERRUN\n"); s->circular_buffer_error = EIO; return NULL; } - - len = recv(s->udp_fd, s->fifo->wptr, left, 0); + left = FFMIN(left, s->fifo->end - s->fifo->wptr); + 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)) { s->circular_buffer_error = EIO; return NULL; } + continue; } - s->fifo->wptr += len; - if (s->fifo->wptr >= s->fifo->end) - s->fifo->wptr = s->fifo->buffer; - s->fifo->wndx += len; + AV_WL32(s->tmp, len); + av_fifo_generic_write(s->fifo, s->tmp, len+4, NULL); } return NULL; @@ -404,7 +405,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { - char *endptr=NULL; + char *endptr = NULL; s->reuse_socket = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) @@ -426,7 +427,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } - if (av_find_info_tag(buf, sizeof(buf), "buf_size", p)) { + if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) { s->circular_buffer_size = strtol(buf, NULL, 10)*188; } } @@ -444,7 +445,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) goto fail; } - if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) + if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; udp_fd = udp_socket_create(s, &my_addr, &len); if (udp_fd < 0) @@ -544,11 +545,17 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) do { avail = av_fifo_size(s->fifo); if (avail) { // >=size) { + uint8_t tmp[4]; + + av_fifo_generic_read(s->fifo, tmp, 4, NULL); + avail= AV_RL32(tmp); + if(avail > size){ + av_log(h, AV_LOG_WARNING, "Part of datagram lost due to insufficient buffer size\n"); + avail= size; + } - // Maximum amount available - size = FFMIN( avail, size); - av_fifo_generic_read(s->fifo, buf, size, NULL); - return size; + av_fifo_generic_read(s->fifo, buf, avail, NULL); + return avail; } else { FD_ZERO(&rfds);