Ejemplo n.º 1
0
/**
 * If no filename is given to av_open_input_file because you want to
 * get the local port first, then you must call this function to set
 * the remote server address.
 *
 * @param s1 media file context
 * @param uri of the remote server
 * @return zero if no error.
 */
int rtp_set_remote_url(URLContext *h, const char *uri)
{
    RTPContext *s = h->priv_data;
    char hostname[256];
    int port;

    char buf[1024];
    char path[1024];

    url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
              path, sizeof(path), uri);

    snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port, path);
    udp_set_remote_url(s->rtp_hd, buf);

    snprintf(buf, sizeof(buf), "udp://%s:%d%s", hostname, port + 1, path);
    udp_set_remote_url(s->rtcp_hd, buf);
    return 0;
}
Ejemplo n.º 2
0
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024];
    int port, udp_fd = -1, tmp, bind_ret = -1;
    UDPContext *s = NULL;
    int is_output;
    const char *p;
    char buf[256];
#if !CONFIG_IPV6
    struct sockaddr_in my_addr;
#else
    struct sockaddr_storage my_addr;
#endif
    int len;

    h->is_streamed = 1;
    h->max_packet_size = 1472;

    is_output = (flags & URL_WRONLY);

    if(!ff_network_init())
        return AVERROR(EIO);

    s = av_mallocz(sizeof(UDPContext));
    if (!s)
        return AVERROR(ENOMEM);

    h->priv_data = s;
    s->ttl = 16;
    s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;

    p = strchr(uri, '?');
    if (p) {
        s->reuse_socket = find_info_tag(buf, sizeof(buf), "reuse", p);
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            h->max_packet_size = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
            s->buffer_size = strtol(buf, NULL, 10);
        }
    }

    /* fill the dest addr */
    url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);

    /* XXX: fix url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (flags & URL_WRONLY)
            goto fail;
    } else {
        udp_set_remote_url(h, uri);
    }

    if (s->is_multicast && !(h->flags & URL_WRONLY))
        s->local_port = port;
    udp_fd = udp_socket_create(s, &my_addr, &len);
    if (udp_fd < 0)
        goto fail;

    if (s->reuse_socket)
        if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
            goto fail;

    /* the bind is needed to give a port to the socket now */
    /* if multicast, try the multicast address bind first */
    if (s->is_multicast && !(h->flags & URL_WRONLY)) {
        bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
    }
    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0)
        goto fail;

    len = sizeof(my_addr);
    getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
    s->local_port = udp_port(&my_addr, len);

    if (s->is_multicast) {
        if (h->flags & URL_WRONLY) {
            /* output */
            if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        } else {
            /* input */
            if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
    }

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(NULL, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno));
            goto fail;
        }
    } else {
        /* set udp recv buffer size to the largest possible udp packet size to
         * avoid losing data on OSes that set this too low by default. */
        tmp = s->buffer_size;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
            av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_RECVBUF): %s\n", strerror(errno));
        }
        /* make the socket non-blocking */
        ff_socket_nonblock(udp_fd, 1);
    }

    s->udp_fd = udp_fd;
    return 0;
 fail:
    if (udp_fd >= 0)
        closesocket(udp_fd);
    av_free(s);
    return AVERROR(EIO);
}
Ejemplo n.º 3
0
Archivo: udp.c Proyecto: suborb/reelvdr
/* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags)
{
    char hostname[1024];
    int port, udp_fd = -1, tmp;
    UDPContext *s = NULL;
    int is_output;
    const char *p;
    char buf[256];
#ifndef CONFIG_IPV6
    struct sockaddr_in my_addr, my_addr1;
    int len;
#endif

    h->is_streamed = 1;
    h->max_packet_size = 1472;

    is_output = (flags & URL_WRONLY);
    
    s = av_malloc(sizeof(UDPContext));
    if (!s)
        return -ENOMEM;

    h->priv_data = s;
    s->ttl = 16;
    s->is_multicast = 0;
    s->local_port = 0;
    p = strchr(uri, '?');
    if (p) {
        s->is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
            s->ttl = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
            s->local_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            h->max_packet_size = strtol(buf, NULL, 10);
        }
    }

    /* fill the dest addr */
    url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
    
    /* XXX: fix url_split */
    if (hostname[0] == '\0' || hostname[0] == '?') {
        /* only accepts null hostname if input */
        if (s->is_multicast || (flags & URL_WRONLY))
            goto fail;
    } else {
        udp_set_remote_url(h, uri);
    }

#ifndef CONFIG_IPV6
    udp_fd = socket(PF_INET, SOCK_DGRAM, 0);
    if (udp_fd < 0)
        goto fail;

    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
    if (s->is_multicast && !(h->flags & URL_WRONLY)) {
        /* special case: the bind must be done on the multicast address port */
        my_addr.sin_port = s->dest_addr.sin_port;
    } else {
        my_addr.sin_port = htons(s->local_port);
    }

    /* the bind is needed to give a port to the socket now */
    if (bind(udp_fd,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 
        goto fail;

    len = sizeof(my_addr1);
    getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len);
    s->local_port = ntohs(my_addr1.sin_port);

#ifndef CONFIG_BEOS_NETSERVER
    if (s->is_multicast) {
        if (h->flags & URL_WRONLY) {
            /* output */
            if (setsockopt(udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, 
                           &s->ttl, sizeof(s->ttl)) < 0) {
                perror("IP_MULTICAST_TTL");
                goto fail;
            }
        } else {
            /* input */
            memset(&s->mreq, 0, sizeof(s->mreq));
            s->mreq.imr_multiaddr = s->dest_addr.sin_addr;
            s->mreq.imr_interface.s_addr = htonl (INADDR_ANY);
            if (setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
                           &s->mreq, sizeof(s->mreq)) < 0) {
                perror("rtp: IP_ADD_MEMBERSHIP");
                goto fail;
            }
        }
    }
#endif
#else
    if (s->is_multicast && !(h->flags & URL_WRONLY))
        s->local_port = port;
    udp_fd = udp_ipv6_set_local(h);
    if (udp_fd < 0)
        goto fail;
#ifndef CONFIG_BEOS_NETSERVER
    if (s->is_multicast) {
        if (h->flags & URL_WRONLY) {
            if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        } else {
            if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
                goto fail;
        }
    }
#endif          
#endif

    if (is_output) {
        /* limit the tx buf size to limit latency */
        tmp = UDP_TX_BUF_SIZE;
        if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
            perror("setsockopt sndbuf");
            goto fail;
        }
    }

    s->udp_fd = udp_fd;
    return 0;
 fail:
    if (udp_fd >= 0)
#ifdef CONFIG_BEOS_NETSERVER
        closesocket(udp_fd);
#else
        close(udp_fd);
#endif
    av_free(s);
    return AVERROR_IO;
}
Ejemplo n.º 4
0
int udp_open( hnd_t *p_handle, obe_udp_opts_t *udp_opts )
{
    int udp_fd = -1, tmp, bind_ret = -1;
    struct sockaddr_storage my_addr;
    int len;

    obe_udp_ctx *s = calloc( 1, sizeof(*s) );
    *p_handle = NULL;
    if( !s )
        return -1;

    strncpy( s->hostname, udp_opts->hostname, sizeof(s->hostname) );
    s->port = udp_opts->port;
    s->local_port = udp_opts->local_port;
    s->reuse_socket = udp_opts->reuse_socket;
    s->ttl = udp_opts->ttl;
    s->buffer_size = udp_opts->buffer_size;
    s->miface = udp_opts->miface;

    if( udp_set_remote_url( s ) < 0 )
        goto fail;

    udp_fd = udp_socket_create( s, &my_addr, &len );
    if( udp_fd < 0 )
        goto fail;

    if( s->reuse_socket || s->is_multicast )
    {
        s->reuse_socket = 1;
        if( setsockopt( udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket) ) != 0)
            goto fail;
    }

    /* bind to the local address if not multicast or if the multicast
     * bind failed */
    if( bind_ret < 0 && bind( udp_fd, (struct sockaddr *)&my_addr, len ) < 0 )
        goto fail;

    len = sizeof(my_addr);
    getsockname( udp_fd, (struct sockaddr *)&my_addr, (socklen_t *) &len );
    s->local_port = udp_port( &my_addr, len );

    /* set output multicast ttl */
    if( s->is_multicast && udp_set_multicast_opts( udp_fd, s ) < 0 )
        goto fail;

    /* limit the tx buf size to limit latency */
    tmp = s->buffer_size;
    if( setsockopt( udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp) ) < 0 )
        goto fail;

    if( s->is_connected && connect( udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len ) )
        goto fail;

    s->udp_fd = udp_fd;
    *p_handle = s;
    return 0;

fail:
    if( udp_fd >= 0 )
        close( udp_fd );

    free( s );
    return -1;
}
Ejemplo n.º 5
0
static int rtp_read(URLContext *h, uint8_t *buf, int size)
{
    RTPContext *s = h->priv_data;
    struct sockaddr_in from;
    socklen_t from_len;
    int len, fd_max, n;
    fd_set rfds;
#if 0
    for(;;) {
        from_len = sizeof(from);
        len = recvfrom (s->rtp_fd, buf, size, 0,
                        (struct sockaddr *)&from, &from_len);
        if (len < 0) {
            if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                ff_neterrno() == FF_NETERROR(EINTR))
                continue;
            return AVERROR(EIO);
        }
        break;
    }
#else
    for(;;) {
        /* build fdset to listen to RTP and RTCP packets */
        FD_ZERO(&rfds);
        fd_max = s->rtp_fd;
        FD_SET(s->rtp_fd, &rfds);
        if (s->rtcp_fd) {
            if (s->rtcp_fd > fd_max)
                fd_max = s->rtcp_fd;
            FD_SET(s->rtcp_fd, &rfds);
        }
        n = select(fd_max + 1, &rfds, NULL, NULL, NULL);
        if (n > 0) {
            /* first try RTCP */
            if (FD_ISSET(s->rtcp_fd, &rfds)) {
                from_len = sizeof(from);
                len = recvfrom (s->rtcp_fd, buf, size, 0,
                                (struct sockaddr *)&from, &from_len);
                if (len < 0) {
                    if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                        ff_neterrno() == FF_NETERROR(EINTR))
                        continue;
                    return AVERROR(EIO);
                } else {
                    /* update remote rtcp address */
                    char buf[1024];
                    snprintf(buf, sizeof(buf), "udp://%s:%d",
                            inet_ntoa(from.sin_addr), ntohs(from.sin_port));
                    udp_set_remote_url(s->rtcp_hd, buf);
                }
                break;
            }
            /* then RTP */
            if (FD_ISSET(s->rtp_fd, &rfds)) {
                from_len = sizeof(from);
                len = recvfrom (s->rtp_fd, buf, size, 0,
                                (struct sockaddr *)&from, &from_len);
                if (len < 0) {
                    if (ff_neterrno() == FF_NETERROR(EAGAIN) ||
                        ff_neterrno() == FF_NETERROR(EINTR))
                        continue;
                    return AVERROR(EIO);
                } else if (s->rtcp_hd) {
                    /* update remote rtcp address (only if empty) */
                    typedef struct {
                        int udp_fd;
                        int ttl;
                        int buffer_size;
                        int is_multicast;
                        int local_port;
                        int reuse_socket;
#if !CONFIG_IPV6
                        struct sockaddr_in dest_addr;
#else
                        struct sockaddr_storage dest_addr;
#endif
                        int dest_addr_len;
                    } UDPContext;
                    URLContext *hd = s->rtcp_hd;
                    UDPContext *h = hd->priv_data;
                    if (h->dest_addr.sin_addr.s_addr == 0) {
                        char buf[1024];
                        snprintf(buf, sizeof(buf), "udp://%s:%d",
                                inet_ntoa(from.sin_addr), ntohs(from.sin_port)+1);
                        udp_set_remote_url(s->rtcp_hd, buf);
                    }
                }
                break;
            }
        }
    }
#endif
    return len;
}