Ticket #368: ffmpeg-0.7.1-multicastif.patch

File ffmpeg-0.7.1-multicastif.patch, 6.0 KB (added by ast@domdv.de, 8 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);