Browse code

avformat/udp: UDP-Lite (RFC 3828) support added

(This fixes ticket #1501)

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Thomas Volkert authored on 2014/11/05 18:59:44
Showing 5 changed files
... ...
@@ -9,6 +9,7 @@ version <next>:
9 9
 - STL subtitle demuxer and decoder
10 10
 - libutvideo YUV 4:2:2 10bit support
11 11
 - XCB-based screen-grabber
12
+- UDP-Lite support (RFC 3828)
12 13
 
13 14
 version 2.4:
14 15
 - Icecast protocol
... ...
@@ -1659,6 +1659,7 @@ HEADERS_LIST="
1659 1659
     sys_un_h
1660 1660
     sys_videoio_h
1661 1661
     termios_h
1662
+    udplite_h
1662 1663
     unistd_h
1663 1664
     windows_h
1664 1665
     winsock2_h
... ...
@@ -2542,6 +2543,7 @@ tcp_protocol_select="network"
2542 2542
 tls_protocol_deps_any="openssl gnutls"
2543 2543
 tls_protocol_select="tcp_protocol"
2544 2544
 udp_protocol_select="network"
2545
+udplite_protocol_select="network"
2545 2546
 unix_protocol_deps="sys_un_h"
2546 2547
 unix_protocol_select="network"
2547 2548
 
... ...
@@ -4745,6 +4747,7 @@ check_header io.h
4745 4745
 check_header libcrystalhd/libcrystalhd_if.h
4746 4746
 check_header mach/mach_time.h
4747 4747
 check_header malloc.h
4748
+check_header net/udplite.h
4748 4749
 check_header poll.h
4749 4750
 check_header sys/mman.h
4750 4751
 check_header sys/param.h
... ...
@@ -371,6 +371,7 @@ void av_register_all(void)
371 371
     REGISTER_PROTOCOL(TCP,              tcp);
372 372
     REGISTER_PROTOCOL(TLS,              tls);
373 373
     REGISTER_PROTOCOL(UDP,              udp);
374
+    REGISTER_PROTOCOL(UDPLITE,          udplite);
374 375
     REGISTER_PROTOCOL(UNIX,             unix);
375 376
 
376 377
     /* external libraries */
... ...
@@ -40,6 +40,20 @@
40 40
 #include "os_support.h"
41 41
 #include "url.h"
42 42
 
43
+#if HAVE_UDPLITE_H
44
+#include "udplite.h"
45
+#else
46
+/* On many Linux systems, udplite.h is missing but the kernel supports UDP-Lite.
47
+ * So, we provide a fallback here.
48
+ */
49
+#define UDPLITE_SEND_CSCOV                               10
50
+#define UDPLITE_RECV_CSCOV                               11
51
+#endif
52
+
53
+#ifndef IPPROTO_UDPLITE
54
+#define IPPROTO_UDPLITE                                  136
55
+#endif
56
+
43 57
 #if HAVE_PTHREAD_CANCEL
44 58
 #include <pthread.h>
45 59
 #endif
... ...
@@ -55,11 +69,13 @@
55 55
 
56 56
 #define UDP_TX_BUF_SIZE 32768
57 57
 #define UDP_MAX_PKT_SIZE 65536
58
+#define UDP_HEADER_SIZE 8
58 59
 
59 60
 typedef struct {
60 61
     const AVClass *class;
61 62
     int udp_fd;
62 63
     int ttl;
64
+    int udplite_coverage;
63 65
     int buffer_size;
64 66
     int is_multicast;
65 67
     int is_broadcast;
... ...
@@ -95,6 +111,7 @@ static const AVOption options[] = {
95 95
 {"buffer_size", "set packet buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
96 96
 {"localport", "set local port to bind to", OFFSET(local_port), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
97 97
 {"localaddr", "choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E },
98
+{"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 },
98 99
 {"pkt_size", "set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E },
99 100
 {"reuse", "explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
100 101
 {"broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
... ...
@@ -114,6 +131,13 @@ static const AVClass udp_context_class = {
114 114
     .version        = LIBAVUTIL_VERSION_INT,
115 115
 };
116 116
 
117
+static const AVClass udplite_context_class = {
118
+    .class_name     = "udplite",
119
+    .item_name      = av_default_item_name,
120
+    .option         = options,
121
+    .version        = LIBAVUTIL_VERSION_INT,
122
+};
123
+
117 124
 static void log_net_error(void *ctx, int level, const char* prefix)
118 125
 {
119 126
     char errbuf[100];
... ...
@@ -335,7 +359,10 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
335 335
     if (!res0)
336 336
         goto fail;
337 337
     for (res = res0; res; res=res->ai_next) {
338
-        udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
338
+        if (s->udplite_coverage)
339
+            udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, IPPROTO_UDPLITE);
340
+        else
341
+            udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
339 342
         if (udp_fd != -1) break;
340 343
         log_net_error(NULL, AV_LOG_ERROR, "socket");
341 344
     }
... ...
@@ -570,6 +597,9 @@ static int udp_open(URLContext *h, const char *uri, int flags)
570 570
         if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
571 571
             s->ttl = strtol(buf, NULL, 10);
572 572
         }
573
+        if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) {
574
+            s->udplite_coverage = strtol(buf, NULL, 10);
575
+        }
573 576
         if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
574 577
             s->local_port = strtol(buf, NULL, 10);
575 578
         }
... ...
@@ -653,6 +683,18 @@ static int udp_open(URLContext *h, const char *uri, int flags)
653 653
            goto fail;
654 654
     }
655 655
 
656
+    /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving.
657
+     * The receiver coverage has to be less than or equal to the sender coverage.
658
+     * Otherwise, the receiver will drop all packets.
659
+     */
660
+    if (s->udplite_coverage) {
661
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
662
+            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_SEND_CSCOV not available");
663
+
664
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
665
+            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_RECV_CSCOV not available");
666
+    }
667
+
656 668
     /* If multicast, try binding the multicast address first, to avoid
657 669
      * receiving UDP packets from other sources aimed at the same UDP
658 670
      * port. This fails on windows. This makes sending to the same address
... ...
@@ -780,6 +822,16 @@ static int udp_open(URLContext *h, const char *uri, int flags)
780 780
     return AVERROR(EIO);
781 781
 }
782 782
 
783
+static int udplite_open(URLContext *h, const char *uri, int flags)
784
+{
785
+    UDPContext *s = h->priv_data;
786
+
787
+    // set default checksum coverage
788
+    s->udplite_coverage = UDP_HEADER_SIZE;
789
+
790
+    return udp_open(h, uri, flags);
791
+}
792
+
783 793
 static int udp_read(URLContext *h, uint8_t *buf, int size)
784 794
 {
785 795
     UDPContext *s = h->priv_data;
... ...
@@ -893,3 +945,15 @@ URLProtocol ff_udp_protocol = {
893 893
     .priv_data_class     = &udp_context_class,
894 894
     .flags               = URL_PROTOCOL_FLAG_NETWORK,
895 895
 };
896
+
897
+URLProtocol ff_udplite_protocol = {
898
+    .name                = "udplite",
899
+    .url_open            = udplite_open,
900
+    .url_read            = udp_read,
901
+    .url_write           = udp_write,
902
+    .url_close           = udp_close,
903
+    .url_get_file_handle = udp_get_file_handle,
904
+    .priv_data_size      = sizeof(UDPContext),
905
+    .priv_data_class     = &udplite_context_class,
906
+    .flags               = URL_PROTOCOL_FLAG_NETWORK,
907
+};
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 56
33 33
 #define LIBAVFORMAT_VERSION_MINOR  12
34
-#define LIBAVFORMAT_VERSION_MICRO 100
34
+#define LIBAVFORMAT_VERSION_MICRO 101
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 37
                                                LIBAVFORMAT_VERSION_MINOR, \