27 #define _DEFAULT_SOURCE 47 #include "TargetConditionals.h" 56 #define UDPLITE_SEND_CSCOV 10 57 #define UDPLITE_RECV_CSCOV 11 60 #ifndef IPPROTO_UDPLITE 61 #define IPPROTO_UDPLITE 136 65 #undef HAVE_PTHREAD_CANCEL 66 #define HAVE_PTHREAD_CANCEL 1 69 #if HAVE_PTHREAD_CANCEL 73 #ifndef IPV6_ADD_MEMBERSHIP 74 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP 75 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP 78 #define UDP_TX_BUF_SIZE 32768 79 #define UDP_RX_BUF_SIZE 393216 80 #define UDP_MAX_PKT_SIZE 65536 81 #define UDP_HEADER_SIZE 8 106 #if HAVE_PTHREAD_CANCEL 122 #define OFFSET(x) offsetof(UDPContext, x) 123 #define D AV_OPT_FLAG_DECODING_PARAM 124 #define E AV_OPT_FLAG_ENCODING_PARAM 141 {
"timeout",
"set raise error timeout, in microseconds (only in read mode)",
OFFSET(
timeout),
AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D },
162 struct sockaddr *addr)
164 #ifdef IP_MULTICAST_TTL 165 if (addr->sa_family == AF_INET) {
166 if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL,
sizeof(mcastTTL)) < 0) {
172 #if defined(IPPROTO_IPV6) && defined(IPV6_MULTICAST_HOPS) 173 if (addr->sa_family == AF_INET6) {
174 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL,
sizeof(mcastTTL)) < 0) {
185 #ifdef IP_ADD_MEMBERSHIP 186 if (addr->sa_family == AF_INET) {
189 mreq.imr_multiaddr.s_addr = ((
struct sockaddr_in *)addr)->sin_addr.s_addr;
191 mreq.imr_interface= ((
struct sockaddr_in *)local_addr)->sin_addr;
193 mreq.imr_interface.s_addr = INADDR_ANY;
194 if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (
const void *)&mreq,
sizeof(mreq)) < 0) {
200 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6) 201 if (addr->sa_family == AF_INET6) {
202 struct ipv6_mreq mreq6;
204 memcpy(&mreq6.ipv6mr_multiaddr, &(((
struct sockaddr_in6 *)addr)->sin6_addr),
sizeof(
struct in6_addr));
206 mreq6.ipv6mr_interface = 0;
218 #ifdef IP_DROP_MEMBERSHIP 219 if (addr->sa_family == AF_INET) {
222 mreq.imr_multiaddr.s_addr = ((
struct sockaddr_in *)addr)->sin_addr.s_addr;
224 mreq.imr_interface = ((
struct sockaddr_in *)local_addr)->sin_addr;
226 mreq.imr_interface.s_addr = INADDR_ANY;
227 if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (
const void *)&mreq,
sizeof(mreq)) < 0) {
233 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6) 234 if (addr->sa_family == AF_INET6) {
235 struct ipv6_mreq mreq6;
237 memcpy(&mreq6.ipv6mr_multiaddr, &(((
struct sockaddr_in6 *)addr)->sin6_addr),
sizeof(
struct in6_addr));
239 mreq6.ipv6mr_interface = 0;
250 int sockfd,
struct sockaddr *addr,
253 int nb_sources,
int include)
256 if (addr->sa_family != AF_INET) {
257 #if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE) 262 for (i = 0; i < nb_sources; i++) {
263 struct group_source_req mreqs;
264 int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
267 mreqs.gsr_interface = 0;
268 memcpy(&mreqs.gsr_group, addr, addr_len);
269 memcpy(&mreqs.gsr_source, &sources[i],
sizeof(*sources));
271 if (setsockopt(sockfd, level,
272 include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
273 (
const void *)&mreqs,
sizeof(mreqs)) < 0) {
284 "Setting multicast sources only supported for IPv4\n");
288 #if HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE) 289 for (i = 0; i < nb_sources; i++) {
290 struct ip_mreq_source mreqs;
291 if (sources[i].ss_family != AF_INET) {
292 av_log(h,
AV_LOG_ERROR,
"Source/block address %d is of incorrect protocol family\n", i + 1);
296 mreqs.imr_multiaddr.s_addr = ((
struct sockaddr_in *)addr)->sin_addr.s_addr;
298 mreqs.imr_interface = ((
struct sockaddr_in *)local_addr)->sin_addr;
300 mreqs.imr_interface.s_addr = INADDR_ANY;
301 mreqs.imr_sourceaddr.s_addr = ((
struct sockaddr_in *)&sources[i])->sin_addr.s_addr;
303 if (setsockopt(sockfd, IPPROTO_IP,
304 include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE,
305 (
const void *)&mreqs,
sizeof(mreqs)) < 0) {
320 const char *hostname,
int port)
326 if (!res0)
return AVERROR(EIO);
335 socklen_t *addr_len,
const char *
localaddr)
340 int family = AF_UNSPEC;
342 if (((
struct sockaddr *) &s->
dest_addr)->sa_family)
343 family = ((
struct sockaddr *) &s->
dest_addr)->sa_family;
349 for (res = res0; res; res=res->
ai_next) {
354 if (udp_fd != -1)
break;
378 char sbuf[
sizeof(
int)*3+1];
386 return strtol(sbuf,
NULL, 10);
409 char hostname[256], buf[10];
421 p = strchr(uri,
'?');
462 #if HAVE_PTHREAD_CANCEL 463 static void *circular_buffer_task_rx(
void *_URLContext)
479 socklen_t addr_len =
sizeof(addr);
486 len = recvfrom(s->
udp_fd, s->
tmp+4,
sizeof(s->
tmp)-4, 0, (
struct sockaddr *)&addr, &addr_len);
504 "Surviving due to overrun_nonfatal option\n");
508 "To avoid, increase fifo_size URL option. " 509 "To survive in such case, use overrun_nonfatal option\n");
524 static void *circular_buffer_task_tx(
void *_URLContext)
530 int64_t sent_bits = 0;
571 if (timestamp < target_timestamp) {
572 int64_t delay = target_timestamp - timestamp;
573 if (delay > max_delay) {
575 start_timestamp = timestamp + delay;
580 if (timestamp - burst_interval > target_timestamp) {
581 start_timestamp = timestamp - burst_interval;
585 sent_bits += len * 8;
586 target_timestamp = start_timestamp + sent_bits * 1000000 / s->
bitrate;
594 ret = sendto (s->
udp_fd, p, len, 0,
598 ret = send(s->
udp_fd, p, len, 0);
628 char hostname[1024],
localaddr[1024] =
"";
629 int port,
udp_fd = -1,
tmp, bind_ret = -1, dscp = -1;
654 p = strchr(uri,
'?');
669 if (!HAVE_PTHREAD_CANCEL)
671 "'overrun_nonfatal' option was set but it is not supported " 672 "on this build (pthread support is required)\n");
675 s->
ttl = strtol(buf,
NULL, 10);
693 dscp = strtol(buf,
NULL, 10);
697 if (!HAVE_PTHREAD_CANCEL)
699 "'circular_buffer_size' option was set but it is not supported " 700 "on this build (pthread support is required)\n");
704 if (!HAVE_PTHREAD_CANCEL)
706 "'bitrate' option was set but it is not supported " 707 "on this build (pthread support is required)\n");
713 av_strlcpy(localaddr, buf,
sizeof(localaddr));
741 if (hostname[0] ==
'\0' || hostname[0] ==
'?') {
799 if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp,
sizeof(dscp)) != 0) {
810 bind_ret = bind(udp_fd,(
struct sockaddr *)&s->
dest_addr, len);
815 if (bind_ret < 0 && bind(udp_fd,(
struct sockaddr *)&my_addr, len) < 0) {
821 len =
sizeof(my_addr);
822 getsockname(udp_fd, (
struct sockaddr *)&my_addr, &len);
826 if (h->
flags & AVIO_FLAG_WRITE) {
858 if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &
tmp,
sizeof(
tmp)) < 0) {
866 if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &
tmp,
sizeof(
tmp)) < 0) {
870 if (getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &
tmp, &len) < 0) {
891 #if HAVE_PTHREAD_CANCEL 900 av_log(h,
AV_LOG_WARNING,
"'bitrate' option was set but 'circular_buffer_size' is not, but required\n");
922 ret =
pthread_create(&s->circular_buffer_thread,
NULL, is_output?circular_buffer_task_tx:circular_buffer_task_rx, h);
928 s->thread_started = 1;
933 #if HAVE_PTHREAD_CANCEL 962 socklen_t addr_len =
sizeof(addr);
963 #if HAVE_PTHREAD_CANCEL 988 }
else if(nonblock) {
995 struct timespec tv = { .tv_sec = t / 1000000,
996 .tv_nsec = (t % 1000000) * 1000 };
1000 return AVERROR(err == ETIMEDOUT ? EAGAIN : err);
1013 ret = recvfrom(s->
udp_fd, buf, size, 0, (
struct sockaddr *)&addr, &addr_len);
1026 #if HAVE_PTHREAD_CANCEL 1062 ret = sendto (s->
udp_fd, buf, size, 0,
1066 ret = send(s->
udp_fd, buf, size, 0);
1075 #if HAVE_PTHREAD_CANCEL 1087 #if HAVE_PTHREAD_CANCEL 1088 if (s->thread_started) {
1096 shutdown(s->
udp_fd, SD_RECEIVE);
1099 pthread_cancel(s->circular_buffer_thread);
1123 .priv_data_class = &udp_class,
1135 .priv_data_class = &udplite_context_class,
static int udp_open(URLContext *h, const char *uri, int flags)
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
static const AVClass udplite_context_class
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
#define URL_PROTOCOL_FLAG_NETWORK
#define pthread_mutex_lock(a)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define LIBAVUTIL_VERSION_INT
const URLProtocol ff_udplite_protocol
int is_streamed
true if streamed (no seek possible), default = false
#define AVIO_FLAG_READ
read-only
const char * av_default_item_name(void *ptr)
Return the context name.
int64_t rw_timeout
maximum time to wait for (network) read/write operation completion, in mcs
static int udp_set_url(URLContext *h, struct sockaddr_storage *addr, const char *hostname, int port)
#define AVIO_FLAG_WRITE
write-only
int ff_ip_parse_blocks(void *log_ctx, const char *buf, IPSourceFilters *filters)
Parses the address[,address] source block list in buf and adds it to the filters in the IPSourceFilte...
#define UDPLITE_SEND_CSCOV
struct sockaddr_storage * exclude_addrs
int av_usleep(unsigned usec)
Sleep for a period of time.
#define PTHREAD_CANCEL_ENABLE
static void error(const char *err)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int(*func)(void *, void *, int))
Feed data from a user-supplied callback to an AVFifoBuffer.
int ff_socket(int af, int type, int proto)
int ff_ip_parse_sources(void *log_ctx, const char *buf, IPSourceFilters *filters)
Parses the address[,address] source list in buf and adds it to the filters in the IPSourceFilters str...
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
#define av_assert0(cond)
assert() equivalent, that is always enabled.
#define UDPLITE_RECV_CSCOV
miscellaneous OS support macros and functions.
int ff_udp_get_local_port(URLContext *h)
Return the local port used by the UDP connection.
static av_cold int end(AVCodecContext *avctx)
int av_fifo_space(const AVFifoBuffer *f)
Return the amount of space in bytes in the AVFifoBuffer, that is the amount of data you can write int...
static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr, struct sockaddr *local_addr)
static int udp_port(struct sockaddr_storage *addr, int addr_len)
struct sockaddr_storage * include_addrs
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
static int udp_close(URLContext *h)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int ff_udp_set_remote_url(URLContext *h, const char *uri)
If no filename is given to av_open_input_file because you want to get the local port first...
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void(*func)(void *, void *, int))
Feed data from an AVFifoBuffer to a user-supplied callback.
static int pthread_setcancelstate(int state, int *oldstate)
simple assert() macros that are a bit more flexible than ISO C assert().
void ff_ip_reset_filters(IPSourceFilters *filters)
Resets the IP filter list and frees the internal fields of an IPSourceFilters structure.
int ff_is_multicast_address(struct sockaddr *addr)
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
static const AVOption options[]
uint8_t tmp[UDP_MAX_PKT_SIZE+4]
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
static int udp_get_file_handle(URLContext *h)
Return the udp file handle for select() usage to wait for several RTP streams at the same time...
#define pthread_mutex_unlock(a)
struct sockaddr_storage local_addr_storage
int ff_socket_nonblock(int socket, int enable)
int64_t av_gettime(void)
Get the current time in microseconds.
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
#define IPV6_ADD_MEMBERSHIP
int av_fifo_size(const AVFifoBuffer *f)
Return the amount of data in bytes in the AVFifoBuffer, that is the amount of data you can read from ...
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
#define IPV6_DROP_MEMBERSHIP
a very simple circular buffer FIFO implementation
int ff_ip_check_source_lists(struct sockaddr_storage *source_addr_ptr, IPSourceFilters *s)
Checks the source address against a given IP source filter.
Describe the class of an AVClass context structure.
static int udp_set_multicast_sources(URLContext *h, int sockfd, struct sockaddr *addr, int addr_len, struct sockaddr_storage *local_addr, struct sockaddr_storage *sources, int nb_sources, int include)
#define PTHREAD_CANCEL_DISABLE
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
#define flags(name, subs,...)
int(* cond)(enum AVPixelFormat pix_fmt)
struct sockaddr_storage dest_addr
static int udp_read(URLContext *h, uint8_t *buf, int size)
struct addrinfo * ai_next
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr)
AVFifoBuffer * av_fifo_alloc(unsigned int size)
Initialize an AVFifoBuffer.
static int udplite_open(URLContext *h, const char *uri, int flags)
static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, struct sockaddr *local_addr)
int circular_buffer_error
static int udp_socket_create(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len, const char *localaddr)
struct addrinfo * ff_ip_resolve_host(void *log_ctx, const char *hostname, int port, int type, int family, int flags)
Resolves hostname into an addrinfo structure.
int max_packet_size
if non zero, the stream is packetized with this max packet size
static const AVClass udp_class
int ff_network_wait_fd(int fd, int write)
unbuffered private I/O API
void av_fifo_freep(AVFifoBuffer **f)
Free an AVFifoBuffer and reset pointer to NULL.
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
void av_fifo_drain(AVFifoBuffer *f, int size)
Discard data from the FIFO.
struct sockaddr * ai_addr
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Structure for storing IP (UDP) source filters or block lists.
void ff_log_net_error(void *ctx, int level, const char *prefix)
static int udp_write(URLContext *h, const uint8_t *buf, int size)
const URLProtocol ff_udp_protocol