summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure12
-rw-r--r--doc/protocols.texi8
-rw-r--r--libavcodec/dxva2_internal.h7
-rw-r--r--libavcodec/mss1.c8
-rw-r--r--libavcodec/x86/fft_mmx.asm37
-rw-r--r--libavformat/tcp.c7
-rw-r--r--libavformat/udp.c114
-rw-r--r--libavutil/libm.h21
8 files changed, 184 insertions, 30 deletions
diff --git a/configure b/configure
index 09abaf8538..f30998b37c 100755
--- a/configure
+++ b/configure
@@ -1192,6 +1192,7 @@ HAVE_LIST="
dlfcn_h
dlopen
dos_paths
+ dxva_h
ebp_available
ebx_available
exp2
@@ -1215,6 +1216,8 @@ HAVE_LIST="
inet_aton
inline_asm
isatty
+ isinf
+ isnan
jack_port_get_latency_range
kbhit
ldbrx
@@ -1259,6 +1262,8 @@ HAVE_LIST="
strerror_r
strptime
struct_addrinfo
+ struct_group_source_req
+ struct_ip_mreq_source
struct_ipv6_mreq
struct_rusage_ru_maxrss
struct_sockaddr_in6
@@ -3116,6 +3121,8 @@ fi
if enabled network; then
check_type "sys/types.h sys/socket.h" socklen_t
check_type netdb.h "struct addrinfo"
+ check_type netinet/in.h "struct group_source_req" -D_BSD_SOURCE
+ check_type netinet/in.h "struct ip_mreq_source" -D_BSD_SOURCE
check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE
check_type netinet/in.h "struct sockaddr_in6"
check_type "sys/types.h sys/socket.h" "struct sockaddr_storage"
@@ -3131,6 +3138,8 @@ if enabled network; then
network_extralibs="-lws2_32"; }
check_type ws2tcpip.h socklen_t
check_type ws2tcpip.h "struct addrinfo"
+ check_type ws2tcpip.h "struct group_source_req"
+ check_type ws2tcpip.h "struct ip_mreq_source"
check_type ws2tcpip.h "struct ipv6_mreq"
check_type ws2tcpip.h "struct sockaddr_in6"
check_type ws2tcpip.h "struct sockaddr_storage"
@@ -3180,6 +3189,7 @@ check_func_headers windows.h VirtualAlloc
check_func_headers glob.h glob
check_header dlfcn.h
+check_header dxva.h
check_header dxva2api.h -D_WIN32_WINNT=0x0600
check_header libcrystalhd/libcrystalhd_if.h
check_header malloc.h
@@ -3250,6 +3260,8 @@ enabled vaapi && require vaapi va/va.h vaInitialize -lva
check_mathfunc cbrtf
check_mathfunc exp2
check_mathfunc exp2f
+check_mathfunc isinf
+check_mathfunc isnan
check_mathfunc llrint
check_mathfunc llrintf
check_mathfunc log2
diff --git a/doc/protocols.texi b/doc/protocols.texi
index a335fa7d21..16caa84fe0 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -566,6 +566,14 @@ and makes writes return with AVERROR(ECONNREFUSED) if "destination
unreachable" is received.
For receiving, this gives the benefit of only receiving packets from
the specified peer address/port.
+
+@item sources=@var{address}[,@var{address}]
+Only receive packets sent to the multicast group from one of the
+specified sender IP addresses.
+
+@item block=@var{address}[,@var{address}]
+Ignore packets sent to the multicast group from the specified
+sender IP addresses.
@end table
Some usage examples of the udp protocol with @command{ffmpeg} follow.
diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
index 23d4d87522..fcf45bc664 100644
--- a/libavcodec/dxva2_internal.h
+++ b/libavcodec/dxva2_internal.h
@@ -25,7 +25,14 @@
#define _WIN32_WINNT 0x0600
#define COBJMACROS
+
+#include "config.h"
+
#include "dxva2.h"
+#if HAVE_DXVA_H
+#include <dxva.h>
+#endif
+
#include "avcodec.h"
#include "mpegvideo.h"
diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c
index 6163ecf26e..6299037d01 100644
--- a/libavcodec/mss1.c
+++ b/libavcodec/mss1.c
@@ -557,7 +557,7 @@ static int decode_pal(MSS1Context *ctx, ArithCoder *acoder)
*pal++ = (0xFF << 24) | (r << 16) | (g << 8) | b;
}
- return 1;
+ return !!ncol;
}
static int decode_pivot(MSS1Context *ctx, ArithCoder *acoder, int base)
@@ -783,8 +783,10 @@ static av_cold int mss1_decode_init(AVCodecContext *avctx)
av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n",
AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8));
c->free_colours = AV_RB32(avctx->extradata + 48);
- if (c->free_colours < 0 || c->free_colours > 256) {
- av_log(avctx, AV_LOG_ERROR, "Invalid free colours %d\n", c->free_colours);
+ if ((unsigned)c->free_colours > 256) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Incorrect number of changeable palette entries: %d\n",
+ c->free_colours);
return AVERROR_INVALIDDATA;
}
av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours);
diff --git a/libavcodec/x86/fft_mmx.asm b/libavcodec/x86/fft_mmx.asm
index 2ff282d51c..5bf0e2f259 100644
--- a/libavcodec/x86/fft_mmx.asm
+++ b/libavcodec/x86/fft_mmx.asm
@@ -616,8 +616,6 @@ cglobal fft_calc, 2,5,8
.end:
REP_RET
-cextern_naked memcpy
-
cglobal fft_permute, 2,7,1
mov r4, [r0 + FFTContext.revtab]
mov r5, [r0 + FFTContext.tmpbuf]
@@ -638,29 +636,18 @@ cglobal fft_permute, 2,7,1
cmp r0, r2
jl .loop
shl r2, 3
-%if ARCH_X86_64
- mov r0, r1
- mov r1, r5
-%endif
-%if WIN64
- sub rsp, 8
- call memcpy
- add rsp, 8
- RET
-%elif ARCH_X86_64
-%ifdef PIC
- jmp memcpy wrt ..plt
-%else
- jmp memcpy
-%endif
-%else
- push r2
- push r5
- push r1
- call memcpy
- add esp, 12
- RET
-%endif
+ add r1, r2
+ add r5, r2
+ neg r2
+; nbits >= 2 (FFT4) and sizeof(FFTComplex)=8 => at least 32B
+.loopcopy:
+ movaps xmm0, [r5 + r2]
+ movaps xmm1, [r5 + r2 + 16]
+ movaps [r1 + r2], xmm0
+ movaps [r1 + r2 + 16], xmm1
+ add r2, 32
+ jl .loopcopy
+ REP_RET
cglobal imdct_calc, 3,5,3
mov r3d, [r0 + FFTContext.mdctsize]
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 2fb6a8a584..42dcee0c16 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -63,7 +63,12 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(portstr, sizeof(portstr), "%d", port);
- ret = getaddrinfo(hostname, portstr, &hints, &ai);
+ if (listen_socket)
+ hints.ai_flags |= AI_PASSIVE;
+ if (!hostname[0])
+ ret = getaddrinfo(NULL, portstr, &hints, &ai);
+ else
+ ret = getaddrinfo(hostname, portstr, &hints, &ai);
if (ret) {
av_log(h, AV_LOG_ERROR,
"Failed to resolve hostname %s: %s\n",
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 396cf85ea0..e444a7d102 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -188,6 +188,79 @@ static struct addrinfo* udp_resolve_host(const char *hostname, int port,
return res;
}
+static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr,
+ int addr_len, char **sources,
+ int nb_sources, int include)
+{
+#if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE) && !defined(_WIN32)
+ /* These ones are available in the microsoft SDK, but don't seem to work
+ * as on linux, so just prefer the v4-only approach there for now. */
+ int i;
+ for (i = 0; i < nb_sources; i++) {
+ struct group_source_req mreqs;
+ int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+ struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0,
+ SOCK_DGRAM, AF_UNSPEC,
+ AI_NUMERICHOST);
+ if (!sourceaddr)
+ return AVERROR(ENOENT);
+
+ mreqs.gsr_interface = 0;
+ memcpy(&mreqs.gsr_group, addr, addr_len);
+ memcpy(&mreqs.gsr_source, sourceaddr->ai_addr, sourceaddr->ai_addrlen);
+ freeaddrinfo(sourceaddr);
+
+ if (setsockopt(sockfd, level,
+ include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
+ (const void *)&mreqs, sizeof(mreqs)) < 0) {
+ if (include)
+ log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)");
+ else
+ log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)");
+ return ff_neterrno();
+ }
+ }
+#elif HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
+ int i;
+ if (addr->sa_family != AF_INET) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Setting multicast sources only supported for IPv4\n");
+ return AVERROR(EINVAL);
+ }
+ for (i = 0; i < nb_sources; i++) {
+ struct ip_mreq_source mreqs;
+ struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0,
+ SOCK_DGRAM, AF_UNSPEC,
+ AI_NUMERICHOST);
+ if (!sourceaddr)
+ return AVERROR(ENOENT);
+ if (sourceaddr->ai_addr->sa_family != AF_INET) {
+ freeaddrinfo(sourceaddr);
+ av_log(NULL, AV_LOG_ERROR, "%s is of incorrect protocol family\n",
+ sources[i]);
+ return AVERROR(EINVAL);
+ }
+
+ mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+ mreqs.imr_interface.s_addr = INADDR_ANY;
+ mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)sourceaddr->ai_addr)->sin_addr.s_addr;
+ freeaddrinfo(sourceaddr);
+
+ if (setsockopt(sockfd, IPPROTO_IP,
+ include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE,
+ (const void *)&mreqs, sizeof(mreqs)) < 0) {
+ if (include)
+ log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP)");
+ else
+ log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE)");
+ return ff_neterrno();
+ }
+ }
+#else
+ return AVERROR(ENOSYS);
+#endif
+ return 0;
+}
static int udp_set_url(struct sockaddr_storage *addr,
const char *hostname, int port)
{
@@ -394,6 +467,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
struct sockaddr_storage my_addr;
int len;
int reuse_specified = 0;
+ int i, include = 0, num_sources = 0;
+ char *sources[32];
h->is_streamed = 1;
h->max_packet_size = 1472;
@@ -443,6 +518,25 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
av_strlcpy(localaddr, buf, sizeof(localaddr));
}
+ if (av_find_info_tag(buf, sizeof(buf), "sources", p))
+ include = 1;
+ if (include || av_find_info_tag(buf, sizeof(buf), "block", p)) {
+ char *source_start;
+
+ source_start = buf;
+ while (1) {
+ char *next = strchr(source_start, ',');
+ if (next)
+ *next = '\0';
+ sources[num_sources] = av_strdup(source_start);
+ if (!sources[num_sources])
+ goto fail;
+ source_start = next + 1;
+ num_sources++;
+ if (num_sources >= FF_ARRAY_ELEMS(sources) || !next)
+ break;
+ }
+ }
}
/* fill the dest addr */
@@ -500,8 +594,21 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
if (h->flags & AVIO_FLAG_READ) {
/* input */
- if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
+ if (num_sources == 0 || !include) {
+ if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
+ goto fail;
+
+ if (num_sources) {
+ if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 0) < 0)
+ goto fail;
+ }
+ } else if (include && num_sources) {
+ if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 1) < 0)
+ goto fail;
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n");
goto fail;
+ }
}
}
@@ -529,6 +636,9 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
}
+ for (i = 0; i < num_sources; i++)
+ av_free(sources[i]);
+
s->udp_fd = udp_fd;
#if HAVE_PTHREAD_CANCEL
@@ -567,6 +677,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (udp_fd >= 0)
closesocket(udp_fd);
av_fifo_free(s->fifo);
+ for (i = 0; i < num_sources; i++)
+ av_free(sources[i]);
return AVERROR(EIO);
}
diff --git a/libavutil/libm.h b/libavutil/libm.h
index ef90df0384..41b20f64c1 100644
--- a/libavutil/libm.h
+++ b/libavutil/libm.h
@@ -27,6 +27,7 @@
#include <math.h>
#include "config.h"
#include "attributes.h"
+#include "intfloat.h"
#if HAVE_MIPSFPU && HAVE_INLINE_ASM
#include "libavutil/mips/libm_mips.h"
@@ -49,6 +50,26 @@ static av_always_inline float cbrtf(float x)
#define exp2f(x) ((float)exp2(x))
#endif /* HAVE_EXP2F */
+#if !HAVE_ISINF
+static av_always_inline av_const int isinf(float x)
+{
+ uint32_t v = av_float2int(x);
+ if ((v & 0x7f800000) != 0x7f800000)
+ return 0;
+ return !(v & 0x007fffff);
+}
+#endif /* HAVE_ISINF */
+
+#if !HAVE_ISNAN
+static av_always_inline av_const int isnan(float x)
+{
+ uint32_t v = av_float2int(x);
+ if ((v & 0x7f800000) != 0x7f800000)
+ return 0;
+ return v & 0x007fffff;
+}
+#endif /* HAVE_ISNAN */
+
#if !HAVE_LLRINT
#undef llrint
#define llrint(x) ((long long)rint(x))