X-Git-Url: https://git.piment-noir.org/?p=deb_ffmpeg.git;a=blobdiff_plain;f=ffmpeg%2Flibavformat%2Fudp.c;fp=ffmpeg%2Flibavformat%2Fudp.c;h=91c7910a95b380884ef9067b687ae9fa1178e1cd;hp=376a544e95a38da9c2be0b74450dc0ae94e41efc;hb=f6fa7814ccfe3e76514b36cf04f5cd3cb657c8cf;hpb=2ba45a602cbfa7b771effba9b11bb4245c21bc00 diff --git a/ffmpeg/libavformat/udp.c b/ffmpeg/libavformat/udp.c index 376a544..91c7910 100644 --- a/ffmpeg/libavformat/udp.c +++ b/ffmpeg/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 #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"); } @@ -529,7 +556,7 @@ static int parse_source_list(char *buf, char **sources, int *num_sources, static int udp_open(URLContext *h, const char *uri, int flags) { char hostname[1024], localaddr[1024] = ""; - int port, udp_fd = -1, tmp, bind_ret = -1; + int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1; UDPContext *s = h->priv_data; int is_output; const char *p; @@ -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); } @@ -582,6 +612,9 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } + if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { + dscp = strtol(buf, NULL, 10); + } if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) { s->circular_buffer_size = strtol(buf, NULL, 10); if (!HAVE_PTHREAD_CANCEL) @@ -653,6 +686,24 @@ 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 (dscp >= 0) { + dscp <<= 2; + if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0) + goto fail; + } + /* 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 +831,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 +954,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, +};