diff options
author | Thomas Volkert <thomas@homer-conferencing.com> | 2014-11-05 10:59:44 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-11-05 11:16:05 +0100 |
commit | 07c3a4f693360b315ecbc45f7260016c09bf0324 (patch) | |
tree | 97653c7e84f7de988faad2063067e44ae6d723a3 | |
parent | 513d57cc4d3355baf4fca46cb1d2e6a0d82ee82a (diff) | |
download | ffmpeg-07c3a4f693360b315ecbc45f7260016c09bf0324.tar.gz |
avformat/udp: UDP-Lite (RFC 3828) support added
(This fixes ticket #1501)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | libavformat/allformats.c | 1 | ||||
-rw-r--r-- | libavformat/udp.c | 66 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
5 files changed, 71 insertions, 2 deletions
@@ -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 @@ -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 4d7ef2025e..e82ef2bb0d 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 376a544e95..828b741782 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 }, @@ -114,6 +131,13 @@ static const AVClass udp_context_class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVClass udplite_context_class = { + .class_name = "udplite", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + static void log_net_error(void *ctx, int level, const char* prefix) { char errbuf[100]; @@ -335,7 +359,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 +597,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 +683,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 +822,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 +945,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 = &udplite_context_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff --git a/libavformat/version.h b/libavformat/version.h index aba15cb50c..008f350aed 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, \ |