Originally committed as revision 12830 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -84,28 +84,25 @@ static void url_add_option(char *buf, int buf_size, const char *fmt, ...) | |||
| static void build_udp_url(char *buf, int buf_size, | |||
| const char *hostname, int port, | |||
| int local_port, int multicast, int ttl) | |||
| int local_port, int ttl) | |||
| { | |||
| snprintf(buf, buf_size, "udp://%s:%d", hostname, port); | |||
| if (local_port >= 0) | |||
| url_add_option(buf, buf_size, "localport=%d", local_port); | |||
| if (multicast) | |||
| url_add_option(buf, buf_size, "multicast=1"); | |||
| if (ttl >= 0) | |||
| url_add_option(buf, buf_size, "ttl=%d", ttl); | |||
| } | |||
| /* | |||
| * url syntax: rtp://host:port[?option=val...] | |||
| * option: 'multicast=1' : enable multicast | |||
| * 'ttl=n' : set the ttl value (for multicast only) | |||
| * option: 'ttl=n' : set the ttl value (for multicast only) | |||
| * 'localport=n' : set the local port to n | |||
| * | |||
| */ | |||
| static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| { | |||
| RTPContext *s; | |||
| int port, is_output, is_multicast, ttl, local_port; | |||
| int port, is_output, ttl, local_port; | |||
| char hostname[256]; | |||
| char buf[1024]; | |||
| char path[1024]; | |||
| @@ -121,12 +118,10 @@ static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, | |||
| path, sizeof(path), uri); | |||
| /* extract parameters */ | |||
| is_multicast = 0; | |||
| ttl = -1; | |||
| local_port = -1; | |||
| p = strchr(uri, '?'); | |||
| if (p) { | |||
| is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p); | |||
| if (find_info_tag(buf, sizeof(buf), "ttl", p)) { | |||
| ttl = strtol(buf, NULL, 10); | |||
| } | |||
| @@ -136,7 +131,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| } | |||
| build_udp_url(buf, sizeof(buf), | |||
| hostname, port, local_port, is_multicast, ttl); | |||
| hostname, port, local_port, ttl); | |||
| if (url_open(&s->rtp_hd, buf, flags) < 0) | |||
| goto fail; | |||
| local_port = udp_get_local_port(s->rtp_hd); | |||
| @@ -145,7 +140,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) | |||
| /* well, should suppress localport in path */ | |||
| build_udp_url(buf, sizeof(buf), | |||
| hostname, port + 1, local_port + 1, is_multicast, ttl); | |||
| hostname, port + 1, local_port + 1, ttl); | |||
| if (url_open(&s->rtcp_hd, buf, flags) < 0) | |||
| goto fail; | |||
| @@ -973,7 +973,7 @@ make_setup_request (AVFormatContext *s, const char *host, int port, int protocol | |||
| struct in_addr in; | |||
| in.s_addr = htonl(reply->transports[0].destination); | |||
| snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", | |||
| snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d", | |||
| inet_ntoa(in), | |||
| reply->transports[0].port_min, | |||
| reply->transports[0].ttl); | |||
| @@ -1413,7 +1413,7 @@ static int sdp_read_header(AVFormatContext *s, | |||
| for(i=0;i<rt->nb_rtsp_streams;i++) { | |||
| rtsp_st = rt->rtsp_streams[i]; | |||
| snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d", | |||
| snprintf(url, sizeof(url), "rtp://%s:%d?ttl=%d", | |||
| inet_ntoa(rtsp_st->sdp_ip), | |||
| rtsp_st->sdp_port, | |||
| rtsp_st->sdp_ttl); | |||
| @@ -27,6 +27,12 @@ | |||
| #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | |||
| #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP | |||
| #endif | |||
| #ifndef IN_MULTICAST | |||
| #define IN_MULTICAST(a) ((((uint32_t)(a)) & 0xf0000000) == 0xe0000000) | |||
| #endif | |||
| #ifndef IN6_IS_ADDR_MULTICAST | |||
| #define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff) | |||
| #endif | |||
| typedef struct { | |||
| int udp_fd; | |||
| @@ -159,6 +165,18 @@ static int udp_set_url(struct sockaddr_storage *addr, const char *hostname, int | |||
| return addr_len; | |||
| } | |||
| static int is_multicast_address(struct sockaddr_storage *addr) | |||
| { | |||
| if (addr->ss_family == AF_INET) { | |||
| return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr)); | |||
| } | |||
| if (addr->ss_family == AF_INET6) { | |||
| return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr); | |||
| } | |||
| return 0; | |||
| } | |||
| static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, int *addr_len) | |||
| { | |||
| int udp_fd = -1; | |||
| @@ -219,6 +237,11 @@ static int udp_set_url(struct sockaddr_in *addr, const char *hostname, int port) | |||
| return sizeof(struct sockaddr_in); | |||
| } | |||
| static int is_multicast_address(struct sockaddr_in *addr) | |||
| { | |||
| return IN_MULTICAST(ntohl(addr->sin_addr.s_addr)); | |||
| } | |||
| static int udp_socket_create(UDPContext *s, struct sockaddr_in *addr, int *addr_len) | |||
| { | |||
| int fd; | |||
| @@ -248,8 +271,7 @@ static int udp_port(struct sockaddr_in *addr, int len) | |||
| * the remote server address. | |||
| * | |||
| * url syntax: udp://host:port[?option=val...] | |||
| * option: 'multicast=1' : enable multicast | |||
| * 'ttl=n' : set the ttl value (for multicast only) | |||
| * option: 'ttl=n' : set the ttl value (for multicast only) | |||
| * 'localport=n' : set the local port | |||
| * 'pkt_size=n' : set max packet size | |||
| * 'reuse=1' : enable reusing the socket | |||
| @@ -271,6 +293,7 @@ int udp_set_remote_url(URLContext *h, const char *uri) | |||
| if (s->dest_addr_len < 0) { | |||
| return AVERROR(EIO); | |||
| } | |||
| s->is_multicast = is_multicast_address(&s->dest_addr); | |||
| return 0; | |||
| } | |||
| @@ -327,7 +350,6 @@ static int udp_open(URLContext *h, const char *uri, int flags) | |||
| s->ttl = 16; | |||
| p = strchr(uri, '?'); | |||
| if (p) { | |||
| s->is_multicast = find_info_tag(buf, sizeof(buf), "multicast", 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); | |||
| @@ -346,7 +368,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) | |||
| /* XXX: fix url_split */ | |||
| if (hostname[0] == '\0' || hostname[0] == '?') { | |||
| /* only accepts null hostname if input */ | |||
| if (s->is_multicast || (flags & URL_WRONLY)) | |||
| if (flags & URL_WRONLY) | |||
| goto fail; | |||
| } else { | |||
| udp_set_remote_url(h, uri); | |||