Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 27 Jun 2012 22:42:47 +0000 (00:42 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 27 Jun 2012 23:08:52 +0000 (01:08 +0200)
* 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>
configure
doc/protocols.texi
libavcodec/dxva2_internal.h
libavcodec/mss1.c
libavcodec/x86/fft_mmx.asm
libavformat/tcp.c
libavformat/udp.c
libavutil/libm.h

index 09abaf8..f30998b 100755 (executable)
--- 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
index a335fa7..16caa84 100644 (file)
@@ -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.
index 23d4d87..fcf45bc 100644 (file)
 
 #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"
 
index 6163ecf..6299037 100644 (file)
@@ -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);
index 2ff282d..5bf0e2f 100644 (file)
@@ -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]
index 2fb6a8a..42dcee0 100644 (file)
@@ -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",
index 396cf85..e444a7d 100644 (file)
@@ -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);
 }
 
index ef90df0..41b20f6 100644 (file)
@@ -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))