Ticket #368: ffmpeg-0.7.1-multicastif.patch

File ffmpeg-0.7.1-multicastif.patch, 6.0 KB (added by ast@domdv.de, 5 years ago)
  • ffmpeg-0.7.1

    diff -rNu ffmpeg-0.7.1/configure ffmpeg-0.7.1.new/configure
    old new  
    11091109    strerror_r 
    11101110    strtok_r 
    11111111    struct_addrinfo 
     1112    struct_ifreq 
    11121113    struct_ipv6_mreq 
    11131114    struct_sockaddr_in6 
    11141115    struct_sockaddr_sa_len 
     
    11161117    symver 
    11171118    symver_gnu_asm 
    11181119    symver_asm_label 
     1120    sys_ioctl_h 
    11191121    sys_mman_h 
    11201122    sys_resource_h 
    11211123    sys_select_h 
     
    28012803    check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE 
    28022804    check_type netinet/in.h "struct sockaddr_in6" 
    28032805    check_type "sys/types.h sys/socket.h" "struct sockaddr_storage" 
     2806    check_type net/if.h "struct ifreq" -D_SVID_SOURCE 
    28042807    check_struct "sys/types.h sys/socket.h" "struct sockaddr" sa_len 
     2808    check_header sys/ioctl.h 
    28052809    # Prefer arpa/inet.h over winsock2 
    28062810    if check_header arpa/inet.h ; then 
    28072811        check_func closesocket 
  • libavformat/network.h

    diff -rNu ffmpeg-0.7.1/libavformat/network.h ffmpeg-0.7.1.new/libavformat/network.h
    old new  
    5656#define ff_neterrno() AVERROR(errno) 
    5757#endif 
    5858 
     59#if HAVE_STRUCT_IFREQ 
     60#include <net/if.h> 
     61#endif 
     62 
     63#if HAVE_SYS_IOCTL_H 
     64#include <sys/ioctl.h> 
     65#endif 
     66 
    5967#if HAVE_ARPA_INET_H 
    6068#include <arpa/inet.h> 
    6169#endif 
  • libavformat/udp.c

    diff -rNu ffmpeg-0.7.1/libavformat/udp.c ffmpeg-0.7.1.new/libavformat/udp.c
    old new  
    3030#include "avio_internal.h" 
    3131#include "libavutil/parseutils.h" 
    3232#include "libavutil/fifo.h" 
     33#include "libavutil/avstring.h" 
    3334#include <unistd.h> 
    3435#include "internal.h" 
    3536#include "network.h" 
     
    5556    int local_port; 
    5657    int reuse_socket; 
    5758    struct sockaddr_storage dest_addr; 
     59    struct in_addr if_addr; 
    5860    int dest_addr_len; 
    5961    int is_connected; 
    6062 
     
    9294    return 0; 
    9395} 
    9496 
    95 static int udp_join_multicast_group(int sockfd, struct sockaddr *addr) 
     97static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, struct in_addr *ifaddr) 
    9698{ 
    9799#ifdef IP_ADD_MEMBERSHIP 
    98100    if (addr->sa_family == AF_INET) { 
    99101        struct ip_mreq mreq; 
    100102 
    101103        mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; 
    102         mreq.imr_interface.s_addr= INADDR_ANY; 
     104        mreq.imr_interface.s_addr= ifaddr->s_addr; 
    103105        if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { 
    104106            av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP): %s\n", strerror(errno)); 
    105107            return -1; 
     
    121123    return 0; 
    122124} 
    123125 
    124 static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr) 
     126static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr, struct in_addr *ifaddr) 
    125127{ 
    126128#ifdef IP_DROP_MEMBERSHIP 
    127129    if (addr->sa_family == AF_INET) { 
    128130        struct ip_mreq mreq; 
    129131 
    130132        mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; 
    131         mreq.imr_interface.s_addr= INADDR_ANY; 
     133        mreq.imr_interface.s_addr= ifaddr->s_addr; 
    132134        if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { 
    133135            av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP): %s\n", strerror(errno)); 
    134136            return -1; 
     
    246248 * get the local port first, then you must call this function to set 
    247249 * the remote server address. 
    248250 * 
    249  * url syntax: udp://host:port[?option=val...] 
     251 * url syntax: udp://multicastinterface@host:port[?option=val...] 
     252 * multicastinterface@ is optional 
     253 * multicastinterface is ether the name or the ip of the interface 
    250254 * option: 'ttl=n'       : set the ttl value (for multicast only) 
    251255 *         'localport=n' : set the local port 
    252256 *         'pkt_size=n'  : set max packet size 
     
    259263int ff_udp_set_remote_url(URLContext *h, const char *uri) 
    260264{ 
    261265    UDPContext *s = h->priv_data; 
    262     char hostname[256], buf[10]; 
     266    char hostname[256], buf[10], ifaddr[256]; 
    263267    int port; 
    264268    const char *p; 
    265269 
    266     av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); 
     270    av_url_split(NULL, 0, ifaddr, sizeof(ifaddr), hostname, sizeof(hostname), &port, NULL, 0, uri); 
    267271 
    268272    /* set the destination address */ 
    269273    s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port); 
     
    271275        return AVERROR(EIO); 
    272276    } 
    273277    s->is_multicast = ff_is_multicast_address((struct sockaddr*) &s->dest_addr); 
     278    if (s->is_multicast) { 
     279        if (!*ifaddr) 
     280            s->if_addr.s_addr=INADDR_ANY; 
     281        else if (!inet_aton(ifaddr,&s->if_addr)) { 
     282#if defined(HAVE_STRUCT_IFREQ) && defined(HAVE_SYS_IOCTL_H) && defined(SIOCGIFADDR) 
     283            int sock_fd; 
     284            struct ifreq ifr; 
     285 
     286            memset(&ifr,0,sizeof(ifr)); 
     287            av_strlcpy(ifr.ifr_name,ifaddr,sizeof(ifr.ifr_name)); 
     288            sock_fd=socket(AF_INET, SOCK_DGRAM, 0); 
     289            if (sock_fd==-1) 
     290                return AVERROR(EIO); 
     291            if (ioctl(sock_fd, SIOCGIFADDR, &ifr) == -1) { 
     292                close(sock_fd); 
     293                return AVERROR(EIO); 
     294            } 
     295            close(sock_fd); 
     296            s->if_addr=((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr; 
     297#else 
     298            return AVERROR(EIO); 
     299#endif 
     300        } 
     301    } 
    274302    p = strchr(uri, '?'); 
    275303    if (p) { 
    276304        if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { 
     
    483511                goto fail; 
    484512        } else { 
    485513            /* input */ 
    486             if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) 
     514            if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,&s->if_addr) < 0) 
    487515                goto fail; 
    488516        } 
    489517    } 
     
    601629    UDPContext *s = h->priv_data; 
    602630 
    603631    if (s->is_multicast && !(h->flags & AVIO_WRONLY)) 
    604         udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr); 
     632        udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr, &s->if_addr); 
    605633    closesocket(s->udp_fd); 
    606634    av_fifo_free(s->fifo); 
    607635    av_free(s);