mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-01-01 12:22:09 +00:00
avformat/udp: UDP-Lite (RFC 3828) support added
(This fixes ticket #1501) Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
513d57cc4d
commit
07c3a4f693
@ -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
|
||||
|
3
configure
vendored
3
configure
vendored
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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, \
|
||||
|
Loading…
Reference in New Issue
Block a user