This is useful if sending multicast data on a host with
multiple interfaces.
Signed-off-by: Martin Storsjö <martin@martin.st>
... | ... |
@@ -446,6 +446,11 @@ set the UDP buffer size in bytes |
446 | 446 |
@item localport=@var{port} |
447 | 447 |
override the local UDP port to bind with |
448 | 448 |
|
449 |
+@item localaddr=@var{addr} |
|
450 |
+Choose the local IP address. This is useful e.g. if sending multicast |
|
451 |
+and the host has multiple interfaces, where the user can choose |
|
452 |
+which interface to send on by specifying the IP address of that interface. |
|
453 |
+ |
|
449 | 454 |
@item pkt_size=@var{size} |
450 | 455 |
set the size in bytes of UDP packets |
451 | 456 |
|
... | ... |
@@ -29,6 +29,7 @@ |
29 | 29 |
#include "avformat.h" |
30 | 30 |
#include "avio_internal.h" |
31 | 31 |
#include "libavutil/parseutils.h" |
32 |
+#include "libavutil/avstring.h" |
|
32 | 33 |
#include <unistd.h> |
33 | 34 |
#include "internal.h" |
34 | 35 |
#include "network.h" |
... | ... |
@@ -178,8 +179,8 @@ static int udp_set_url(struct sockaddr_storage *addr, |
178 | 178 |
return addr_len; |
179 | 179 |
} |
180 | 180 |
|
181 |
-static int udp_socket_create(UDPContext *s, |
|
182 |
- struct sockaddr_storage *addr, int *addr_len) |
|
181 |
+static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, |
|
182 |
+ int *addr_len, const char *localaddr) |
|
183 | 183 |
{ |
184 | 184 |
int udp_fd = -1; |
185 | 185 |
struct addrinfo *res0 = NULL, *res = NULL; |
... | ... |
@@ -187,7 +188,8 @@ static int udp_socket_create(UDPContext *s, |
187 | 187 |
|
188 | 188 |
if (((struct sockaddr *) &s->dest_addr)->sa_family) |
189 | 189 |
family = ((struct sockaddr *) &s->dest_addr)->sa_family; |
190 |
- res0 = udp_resolve_host(0, s->local_port, SOCK_DGRAM, family, AI_PASSIVE); |
|
190 |
+ res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port, |
|
191 |
+ SOCK_DGRAM, family, AI_PASSIVE); |
|
191 | 192 |
if (res0 == 0) |
192 | 193 |
goto fail; |
193 | 194 |
for (res = res0; res; res=res->ai_next) { |
... | ... |
@@ -302,7 +304,7 @@ static int udp_get_file_handle(URLContext *h) |
302 | 302 |
/* return non zero if error */ |
303 | 303 |
static int udp_open(URLContext *h, const char *uri, int flags) |
304 | 304 |
{ |
305 |
- char hostname[1024]; |
|
305 |
+ char hostname[1024], localaddr[1024] = ""; |
|
306 | 306 |
int port, udp_fd = -1, tmp, bind_ret = -1; |
307 | 307 |
UDPContext *s = NULL; |
308 | 308 |
int is_output; |
... | ... |
@@ -350,6 +352,9 @@ static int udp_open(URLContext *h, const char *uri, int flags) |
350 | 350 |
if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { |
351 | 351 |
s->is_connected = strtol(buf, NULL, 10); |
352 | 352 |
} |
353 |
+ if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { |
|
354 |
+ av_strlcpy(localaddr, buf, sizeof(localaddr)); |
|
355 |
+ } |
|
353 | 356 |
} |
354 | 357 |
|
355 | 358 |
/* fill the dest addr */ |
... | ... |
@@ -367,7 +372,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) |
367 | 367 |
|
368 | 368 |
if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ)) |
369 | 369 |
s->local_port = port; |
370 |
- udp_fd = udp_socket_create(s, &my_addr, &len); |
|
370 |
+ udp_fd = udp_socket_create(s, &my_addr, &len, localaddr); |
|
371 | 371 |
if (udp_fd < 0) |
372 | 372 |
goto fail; |
373 | 373 |
|