* qatar/master: mss1: validate number of changeable palette entries mss1: report palette changed when some additional colours were decoded x86: fft: replace call to memcpy by a loop udp: Support IGMPv3 source specific multicast and source blocking dxva2: include dxva.h if found libm: Provide fallback definitions for isnan() and isinf() tcp: Pass NULL as hostname to getaddrinfo if the string is empty tcp: Set AI_PASSIVE when the socket will be used for listening Conflicts: configure libavcodec/mss1.c libavformat/udp.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.0
| @@ -1192,6 +1192,7 @@ HAVE_LIST=" | |||||
| dlfcn_h | dlfcn_h | ||||
| dlopen | dlopen | ||||
| dos_paths | dos_paths | ||||
| dxva_h | |||||
| ebp_available | ebp_available | ||||
| ebx_available | ebx_available | ||||
| exp2 | exp2 | ||||
| @@ -1215,6 +1216,8 @@ HAVE_LIST=" | |||||
| inet_aton | inet_aton | ||||
| inline_asm | inline_asm | ||||
| isatty | isatty | ||||
| isinf | |||||
| isnan | |||||
| jack_port_get_latency_range | jack_port_get_latency_range | ||||
| kbhit | kbhit | ||||
| ldbrx | ldbrx | ||||
| @@ -1259,6 +1262,8 @@ HAVE_LIST=" | |||||
| strerror_r | strerror_r | ||||
| strptime | strptime | ||||
| struct_addrinfo | struct_addrinfo | ||||
| struct_group_source_req | |||||
| struct_ip_mreq_source | |||||
| struct_ipv6_mreq | struct_ipv6_mreq | ||||
| struct_rusage_ru_maxrss | struct_rusage_ru_maxrss | ||||
| struct_sockaddr_in6 | struct_sockaddr_in6 | ||||
| @@ -3116,6 +3121,8 @@ fi | |||||
| if enabled network; then | if enabled network; then | ||||
| check_type "sys/types.h sys/socket.h" socklen_t | check_type "sys/types.h sys/socket.h" socklen_t | ||||
| check_type netdb.h "struct addrinfo" | 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 ipv6_mreq" -D_DARWIN_C_SOURCE | ||||
| check_type netinet/in.h "struct sockaddr_in6" | check_type netinet/in.h "struct sockaddr_in6" | ||||
| check_type "sys/types.h sys/socket.h" "struct sockaddr_storage" | check_type "sys/types.h sys/socket.h" "struct sockaddr_storage" | ||||
| @@ -3131,6 +3138,8 @@ if enabled network; then | |||||
| network_extralibs="-lws2_32"; } | network_extralibs="-lws2_32"; } | ||||
| check_type ws2tcpip.h socklen_t | check_type ws2tcpip.h socklen_t | ||||
| check_type ws2tcpip.h "struct addrinfo" | 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 ipv6_mreq" | ||||
| check_type ws2tcpip.h "struct sockaddr_in6" | check_type ws2tcpip.h "struct sockaddr_in6" | ||||
| check_type ws2tcpip.h "struct sockaddr_storage" | check_type ws2tcpip.h "struct sockaddr_storage" | ||||
| @@ -3180,6 +3189,7 @@ check_func_headers windows.h VirtualAlloc | |||||
| check_func_headers glob.h glob | check_func_headers glob.h glob | ||||
| check_header dlfcn.h | check_header dlfcn.h | ||||
| check_header dxva.h | |||||
| check_header dxva2api.h -D_WIN32_WINNT=0x0600 | check_header dxva2api.h -D_WIN32_WINNT=0x0600 | ||||
| check_header libcrystalhd/libcrystalhd_if.h | check_header libcrystalhd/libcrystalhd_if.h | ||||
| check_header malloc.h | check_header malloc.h | ||||
| @@ -3250,6 +3260,8 @@ enabled vaapi && require vaapi va/va.h vaInitialize -lva | |||||
| check_mathfunc cbrtf | check_mathfunc cbrtf | ||||
| check_mathfunc exp2 | check_mathfunc exp2 | ||||
| check_mathfunc exp2f | check_mathfunc exp2f | ||||
| check_mathfunc isinf | |||||
| check_mathfunc isnan | |||||
| check_mathfunc llrint | check_mathfunc llrint | ||||
| check_mathfunc llrintf | check_mathfunc llrintf | ||||
| check_mathfunc log2 | check_mathfunc log2 | ||||
| @@ -566,6 +566,14 @@ and makes writes return with AVERROR(ECONNREFUSED) if "destination | |||||
| unreachable" is received. | unreachable" is received. | ||||
| For receiving, this gives the benefit of only receiving packets from | For receiving, this gives the benefit of only receiving packets from | ||||
| the specified peer address/port. | 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 | @end table | ||||
| Some usage examples of the udp protocol with @command{ffmpeg} follow. | Some usage examples of the udp protocol with @command{ffmpeg} follow. | ||||
| @@ -25,7 +25,14 @@ | |||||
| #define _WIN32_WINNT 0x0600 | #define _WIN32_WINNT 0x0600 | ||||
| #define COBJMACROS | #define COBJMACROS | ||||
| #include "config.h" | |||||
| #include "dxva2.h" | #include "dxva2.h" | ||||
| #if HAVE_DXVA_H | |||||
| #include <dxva.h> | |||||
| #endif | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| #include "mpegvideo.h" | #include "mpegvideo.h" | ||||
| @@ -557,7 +557,7 @@ static int decode_pal(MSS1Context *ctx, ArithCoder *acoder) | |||||
| *pal++ = (0xFF << 24) | (r << 16) | (g << 8) | b; | *pal++ = (0xFF << 24) | (r << 16) | (g << 8) | b; | ||||
| } | } | ||||
| return 1; | |||||
| return !!ncol; | |||||
| } | } | ||||
| static int decode_pivot(MSS1Context *ctx, ArithCoder *acoder, int base) | 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_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d\n", | ||||
| AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); | AV_RB32(avctx->extradata + 4), AV_RB32(avctx->extradata + 8)); | ||||
| c->free_colours = AV_RB32(avctx->extradata + 48); | 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; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); | av_log(avctx, AV_LOG_DEBUG, "%d free colour(s)\n", c->free_colours); | ||||
| @@ -616,8 +616,6 @@ cglobal fft_calc, 2,5,8 | |||||
| .end: | .end: | ||||
| REP_RET | REP_RET | ||||
| cextern_naked memcpy | |||||
| cglobal fft_permute, 2,7,1 | cglobal fft_permute, 2,7,1 | ||||
| mov r4, [r0 + FFTContext.revtab] | mov r4, [r0 + FFTContext.revtab] | ||||
| mov r5, [r0 + FFTContext.tmpbuf] | mov r5, [r0 + FFTContext.tmpbuf] | ||||
| @@ -638,29 +636,18 @@ cglobal fft_permute, 2,7,1 | |||||
| cmp r0, r2 | cmp r0, r2 | ||||
| jl .loop | jl .loop | ||||
| shl r2, 3 | 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 | cglobal imdct_calc, 3,5,3 | ||||
| mov r3d, [r0 + FFTContext.mdctsize] | mov r3d, [r0 + FFTContext.mdctsize] | ||||
| @@ -63,7 +63,12 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | |||||
| hints.ai_family = AF_UNSPEC; | hints.ai_family = AF_UNSPEC; | ||||
| hints.ai_socktype = SOCK_STREAM; | hints.ai_socktype = SOCK_STREAM; | ||||
| snprintf(portstr, sizeof(portstr), "%d", port); | 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) { | if (ret) { | ||||
| av_log(h, AV_LOG_ERROR, | av_log(h, AV_LOG_ERROR, | ||||
| "Failed to resolve hostname %s: %s\n", | "Failed to resolve hostname %s: %s\n", | ||||
| @@ -188,6 +188,79 @@ static struct addrinfo* udp_resolve_host(const char *hostname, int port, | |||||
| return res; | 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, | static int udp_set_url(struct sockaddr_storage *addr, | ||||
| const char *hostname, int port) | 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; | struct sockaddr_storage my_addr; | ||||
| int len; | int len; | ||||
| int reuse_specified = 0; | int reuse_specified = 0; | ||||
| int i, include = 0, num_sources = 0; | |||||
| char *sources[32]; | |||||
| h->is_streamed = 1; | h->is_streamed = 1; | ||||
| h->max_packet_size = 1472; | 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)) { | if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { | ||||
| av_strlcpy(localaddr, buf, sizeof(localaddr)); | 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 */ | /* 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) { | if (h->flags & AVIO_FLAG_READ) { | ||||
| /* input */ | /* 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; | 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; | s->udp_fd = udp_fd; | ||||
| #if HAVE_PTHREAD_CANCEL | #if HAVE_PTHREAD_CANCEL | ||||
| @@ -567,6 +677,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) | |||||
| if (udp_fd >= 0) | if (udp_fd >= 0) | ||||
| closesocket(udp_fd); | closesocket(udp_fd); | ||||
| av_fifo_free(s->fifo); | av_fifo_free(s->fifo); | ||||
| for (i = 0; i < num_sources; i++) | |||||
| av_free(sources[i]); | |||||
| return AVERROR(EIO); | return AVERROR(EIO); | ||||
| } | } | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include <math.h> | #include <math.h> | ||||
| #include "config.h" | #include "config.h" | ||||
| #include "attributes.h" | #include "attributes.h" | ||||
| #include "intfloat.h" | |||||
| #if HAVE_MIPSFPU && HAVE_INLINE_ASM | #if HAVE_MIPSFPU && HAVE_INLINE_ASM | ||||
| #include "libavutil/mips/libm_mips.h" | #include "libavutil/mips/libm_mips.h" | ||||
| @@ -49,6 +50,26 @@ static av_always_inline float cbrtf(float x) | |||||
| #define exp2f(x) ((float)exp2(x)) | #define exp2f(x) ((float)exp2(x)) | ||||
| #endif /* HAVE_EXP2F */ | #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 | #if !HAVE_LLRINT | ||||
| #undef llrint | #undef llrint | ||||
| #define llrint(x) ((long long)rint(x)) | #define llrint(x) ((long long)rint(x)) | ||||