(This fixes ticket #1501)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -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 |
... | ... |
@@ -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, \ |