udp: buffer datagrams in circular buffer instead of a bytestream
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 25 Aug 2011 19:33:54 +0000 (21:33 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 25 Aug 2011 19:33:54 +0000 (21:33 +0200)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavformat/udp.c

index dda7ec2..a0fde28 100644 (file)
@@ -30,6 +30,7 @@
 #include "avio_internal.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/fifo.h"
+#include "libavutil/intreadwrite.h"
 #include <unistd.h>
 #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,23 @@ 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;
             }
         }
-        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;
@@ -544,11 +544,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);