[FFmpeg-devel] [PATCH] avformat/udp: UDP-Lite (RFC 3828) support added

Thomas Volkert silvo at gmx.net
Tue Nov 4 23:48:05 CET 2014


From: Thomas Volkert <thomas at homer-conferencing.com>

---
 Changelog                |  1 +
 configure                |  3 +++
 libavformat/allformats.c |  1 +
 libavformat/udp.c        | 59 +++++++++++++++++++++++++++++++++++++++++++++++-
 libavformat/version.h    |  2 +-
 5 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/Changelog b/Changelog
index ec6abba..b960622 100644
--- a/Changelog
+++ b/Changelog
@@ -9,6 +9,7 @@ version <next>:
 - STL subtitle demuxer and decoder
 - libutvideo YUV 4:2:2 10bit support
 - XCB-based screen-grabber
+  UDP-Lite support (RFC 3828)
 
 version 2.4:
 - Icecast protocol
diff --git a/configure b/configure
index 40d1f07..ae20b53 100755
--- a/configure
+++ b/configure
@@ -1659,6 +1659,7 @@ HEADERS_LIST="
     sys_un_h
     sys_videoio_h
     termios_h
+    udplite_h
     unistd_h
     windows_h
     winsock2_h
@@ -2542,6 +2543,7 @@ tcp_protocol_select="network"
 tls_protocol_deps_any="openssl gnutls"
 tls_protocol_select="tcp_protocol"
 udp_protocol_select="network"
+udplite_protocol_select="network"
 unix_protocol_deps="sys_un_h"
 unix_protocol_select="network"
 
@@ -4745,6 +4747,7 @@ check_header io.h
 check_header libcrystalhd/libcrystalhd_if.h
 check_header mach/mach_time.h
 check_header malloc.h
+check_header net/udplite.h
 check_header poll.h
 check_header sys/mman.h
 check_header sys/param.h
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 4d7ef20..e82ef2b 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -371,6 +371,7 @@ void av_register_all(void)
     REGISTER_PROTOCOL(TCP,              tcp);
     REGISTER_PROTOCOL(TLS,              tls);
     REGISTER_PROTOCOL(UDP,              udp);
+    REGISTER_PROTOCOL(UDPLITE,          udplite);
     REGISTER_PROTOCOL(UNIX,             unix);
 
     /* external libraries */
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 376a544..beae4a1 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -40,6 +40,20 @@
 #include "os_support.h"
 #include "url.h"
 
+#if HAVE_UDPLITE_H
+#include "udplite.h"
+#else
+/* On many Linux systems, udplite.h is missing but the kernel supports UDP-Lite.
+ * So, we provide a fallback here.
+ */
+#define UDPLITE_SEND_CSCOV     				             10
+#define UDPLITE_RECV_CSCOV     		                     11
+#endif
+
+#ifndef IPPROTO_UDPLITE
+#define IPPROTO_UDPLITE                                  136
+#endif
+
 #if HAVE_PTHREAD_CANCEL
 #include <pthread.h>
 #endif
@@ -55,11 +69,13 @@
 
 #define UDP_TX_BUF_SIZE 32768
 #define UDP_MAX_PKT_SIZE 65536
+#define UDP_HEADER_SIZE 8
 
 typedef struct {
     const AVClass *class;
     int udp_fd;
     int ttl;
+    int udplite_coverage;
     int buffer_size;
     int is_multicast;
     int is_broadcast;
@@ -95,6 +111,7 @@ static const AVOption options[] = {
 {"buffer_size", "set packet buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"localport", "set local port to bind to", OFFSET(local_port), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"localaddr", "choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E },
+{"udplite_coverage", "choose UDPLite head size which should be validated by checksum", OFFSET(udplite_coverage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"pkt_size", "set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E },
 {"reuse", "explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
 {"broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
@@ -335,7 +352,10 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
     if (!res0)
         goto fail;
     for (res = res0; res; res=res->ai_next) {
-        udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
+        if (s->udplite_coverage)
+        	udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, IPPROTO_UDPLITE);
+        else
+        	udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
         if (udp_fd != -1) break;
         log_net_error(NULL, AV_LOG_ERROR, "socket");
     }
@@ -570,6 +590,9 @@ static int udp_open(URLContext *h, const char *uri, int flags)
         if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
             s->ttl = strtol(buf, NULL, 10);
         }
+        if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) {
+            s->udplite_coverage = strtol(buf, NULL, 10);
+        }
         if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
             s->local_port = strtol(buf, NULL, 10);
         }
@@ -653,6 +676,18 @@ static int udp_open(URLContext *h, const char *uri, int flags)
            goto fail;
     }
 
+    /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving.
+     * The receiver coverage has to be less than or equal to the sender coverage.
+     * Otherwise, the receiver will drop all packets.
+     */
+    if (s->udplite_coverage) {
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
+           av_log(h, AV_LOG_WARNING, "socket option UDPLITE_SEND_CSCOV not available");
+
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
+            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_RECV_CSCOV not available");
+    }
+
     /* If multicast, try binding the multicast address first, to avoid
      * receiving UDP packets from other sources aimed at the same UDP
      * port. This fails on windows. This makes sending to the same address
@@ -780,6 +815,16 @@ static int udp_open(URLContext *h, const char *uri, int flags)
     return AVERROR(EIO);
 }
 
+static int udplite_open(URLContext *h, const char *uri, int flags)
+{
+	UDPContext *s = h->priv_data;
+
+	// set default checksum coverage
+	s->udplite_coverage = UDP_HEADER_SIZE;
+
+	return udp_open(h, uri, flags);
+}
+
 static int udp_read(URLContext *h, uint8_t *buf, int size)
 {
     UDPContext *s = h->priv_data;
@@ -893,3 +938,15 @@ URLProtocol ff_udp_protocol = {
     .priv_data_class     = &udp_context_class,
     .flags               = URL_PROTOCOL_FLAG_NETWORK,
 };
+
+URLProtocol ff_udplite_protocol = {
+    .name                = "udplite",
+    .url_open            = udplite_open,
+    .url_read            = udp_read,
+    .url_write           = udp_write,
+    .url_close           = udp_close,
+    .url_get_file_handle = udp_get_file_handle,
+    .priv_data_size      = sizeof(UDPContext),
+    .priv_data_class     = &udp_context_class,
+    .flags               = URL_PROTOCOL_FLAG_NETWORK,
+};
diff --git a/libavformat/version.h b/libavformat/version.h
index aba15cb..008f350 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -31,7 +31,7 @@
 
 #define LIBAVFORMAT_VERSION_MAJOR 56
 #define LIBAVFORMAT_VERSION_MINOR  12
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MICRO 101
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
-- 
1.9.1



More information about the ffmpeg-devel mailing list