avformat/rtp: add localaddr for network interface selection
Reviewed-by: Martin Storsjö <martin@martin.st> Signed-off-by: Limin Wang <lance.lmwang@gmail.com>
This commit is contained in:
parent
57adb26d05
commit
7bf4c06809
|
@ -1087,6 +1087,10 @@ set to 1) or to a default remote address (if set to 0).
|
||||||
@item localport=@var{n}
|
@item localport=@var{n}
|
||||||
Set the local RTP port to @var{n}.
|
Set the local RTP port to @var{n}.
|
||||||
|
|
||||||
|
@item localaddr=@var{addr}
|
||||||
|
Local IP address of a network interface used for sending packets or joining
|
||||||
|
multicast groups.
|
||||||
|
|
||||||
@item timeout=@var{n}
|
@item timeout=@var{n}
|
||||||
Set timeout (in microseconds) of socket I/O operations to @var{n}.
|
Set timeout (in microseconds) of socket I/O operations to @var{n}.
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ typedef struct RTPContext {
|
||||||
char *block;
|
char *block;
|
||||||
char *fec_options_str;
|
char *fec_options_str;
|
||||||
int64_t rw_timeout;
|
int64_t rw_timeout;
|
||||||
|
char *localaddr;
|
||||||
} RTPContext;
|
} RTPContext;
|
||||||
|
|
||||||
#define OFFSET(x) offsetof(RTPContext, x)
|
#define OFFSET(x) offsetof(RTPContext, x)
|
||||||
|
@ -80,6 +81,7 @@ static const AVOption options[] = {
|
||||||
{ "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
|
{ "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
|
||||||
{ "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
|
{ "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
|
||||||
{ "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E },
|
{ "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E },
|
||||||
|
{ "localaddr", "Local address", OFFSET(localaddr), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -173,6 +175,7 @@ static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const
|
||||||
static void build_udp_url(RTPContext *s,
|
static void build_udp_url(RTPContext *s,
|
||||||
char *buf, int buf_size,
|
char *buf, int buf_size,
|
||||||
const char *hostname,
|
const char *hostname,
|
||||||
|
const char *localaddr,
|
||||||
int port, int local_port,
|
int port, int local_port,
|
||||||
const char *include_sources,
|
const char *include_sources,
|
||||||
const char *exclude_sources)
|
const char *exclude_sources)
|
||||||
|
@ -195,6 +198,8 @@ static void build_udp_url(RTPContext *s,
|
||||||
url_add_option(buf, buf_size, "sources=%s", include_sources);
|
url_add_option(buf, buf_size, "sources=%s", include_sources);
|
||||||
if (exclude_sources && exclude_sources[0])
|
if (exclude_sources && exclude_sources[0])
|
||||||
url_add_option(buf, buf_size, "block=%s", exclude_sources);
|
url_add_option(buf, buf_size, "block=%s", exclude_sources);
|
||||||
|
if (localaddr && localaddr[0])
|
||||||
|
url_add_option(buf, buf_size, "localaddr=%s", localaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,6 +289,12 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||||
ff_ip_parse_blocks(h, s->block, &s->filters);
|
ff_ip_parse_blocks(h, s->block, &s->filters);
|
||||||
block = s->block;
|
block = s->block;
|
||||||
}
|
}
|
||||||
|
if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
|
||||||
|
av_freep(&s->localaddr);
|
||||||
|
s->localaddr = av_strdup(buf);
|
||||||
|
if (!s->localaddr)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s->rw_timeout >= 0)
|
if (s->rw_timeout >= 0)
|
||||||
h->rw_timeout = s->rw_timeout;
|
h->rw_timeout = s->rw_timeout;
|
||||||
|
@ -314,7 +325,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||||
|
|
||||||
for (i = 0; i < max_retry_count; i++) {
|
for (i = 0; i < max_retry_count; i++) {
|
||||||
build_udp_url(s, buf, sizeof(buf),
|
build_udp_url(s, buf, sizeof(buf),
|
||||||
hostname, rtp_port, s->local_rtpport,
|
hostname, s->localaddr, rtp_port, s->local_rtpport,
|
||||||
sources, block);
|
sources, block);
|
||||||
if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
|
if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
|
||||||
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
|
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
|
||||||
|
@ -328,7 +339,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||||
if (s->local_rtcpport < 0) {
|
if (s->local_rtcpport < 0) {
|
||||||
s->local_rtcpport = s->local_rtpport + 1;
|
s->local_rtcpport = s->local_rtpport + 1;
|
||||||
build_udp_url(s, buf, sizeof(buf),
|
build_udp_url(s, buf, sizeof(buf),
|
||||||
hostname, s->rtcp_port, s->local_rtcpport,
|
hostname, s->localaddr, s->rtcp_port, s->local_rtcpport,
|
||||||
sources, block);
|
sources, block);
|
||||||
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
|
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
|
||||||
&h->interrupt_callback, NULL,
|
&h->interrupt_callback, NULL,
|
||||||
|
@ -339,7 +350,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
build_udp_url(s, buf, sizeof(buf),
|
build_udp_url(s, buf, sizeof(buf),
|
||||||
hostname, s->rtcp_port, s->local_rtcpport,
|
hostname, s->localaddr, s->rtcp_port, s->local_rtcpport,
|
||||||
sources, block);
|
sources, block);
|
||||||
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
|
if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
|
||||||
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
|
NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
|
||||||
|
|
|
@ -105,6 +105,7 @@ static const AVOption sdp_options[] = {
|
||||||
{ "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" },
|
{ "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" },
|
||||||
{ "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" },
|
{ "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" },
|
||||||
{ "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC },
|
{ "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC },
|
||||||
|
{ "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \
|
||||||
RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
|
RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
|
||||||
COMMON_OPTS(),
|
COMMON_OPTS(),
|
||||||
{ NULL },
|
{ NULL },
|
||||||
|
@ -113,6 +114,7 @@ static const AVOption sdp_options[] = {
|
||||||
static const AVOption rtp_options[] = {
|
static const AVOption rtp_options[] = {
|
||||||
RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"),
|
RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"),
|
||||||
{ "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC },
|
{ "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC },
|
||||||
|
{ "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \
|
||||||
RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
|
RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"),
|
||||||
COMMON_OPTS(),
|
COMMON_OPTS(),
|
||||||
{ NULL },
|
{ NULL },
|
||||||
|
@ -125,6 +127,8 @@ static AVDictionary *map_to_opts(RTSPState *rt)
|
||||||
|
|
||||||
av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0);
|
av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0);
|
||||||
av_dict_set_int(&opts, "pkt_size", rt->pkt_size, 0);
|
av_dict_set_int(&opts, "pkt_size", rt->pkt_size, 0);
|
||||||
|
if (rt->localaddr && rt->localaddr[0])
|
||||||
|
av_dict_set(&opts, "localaddr", rt->localaddr, 0);
|
||||||
|
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
@ -2407,6 +2411,8 @@ static int sdp_read_header(AVFormatContext *s)
|
||||||
|
|
||||||
if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
|
if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) {
|
||||||
AVDictionary *opts = map_to_opts(rt);
|
AVDictionary *opts = map_to_opts(rt);
|
||||||
|
char buf[MAX_URL_SIZE];
|
||||||
|
const char *p;
|
||||||
|
|
||||||
err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip,
|
err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip,
|
||||||
sizeof(rtsp_st->sdp_ip),
|
sizeof(rtsp_st->sdp_ip),
|
||||||
|
@ -2424,6 +2430,11 @@ static int sdp_read_header(AVFormatContext *s)
|
||||||
rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
|
rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0,
|
||||||
rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0);
|
rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0);
|
||||||
|
|
||||||
|
p = strchr(s->url, '?');
|
||||||
|
if (p && av_find_info_tag(buf, sizeof(buf), "localaddr", p))
|
||||||
|
av_strlcatf(url, sizeof(url), "&localaddr=%s", buf);
|
||||||
|
else if (rt->localaddr && rt->localaddr[0])
|
||||||
|
av_strlcatf(url, sizeof(url), "&localaddr=%s", rt->localaddr);
|
||||||
append_source_addrs(url, sizeof(url), "sources",
|
append_source_addrs(url, sizeof(url), "sources",
|
||||||
rtsp_st->nb_include_source_addrs,
|
rtsp_st->nb_include_source_addrs,
|
||||||
rtsp_st->include_source_addrs);
|
rtsp_st->include_source_addrs);
|
||||||
|
|
|
@ -419,6 +419,7 @@ typedef struct RTSPState {
|
||||||
char default_lang[4];
|
char default_lang[4];
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
int pkt_size;
|
int pkt_size;
|
||||||
|
char *localaddr;
|
||||||
} RTSPState;
|
} RTSPState;
|
||||||
|
|
||||||
#define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets -
|
#define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets -
|
||||||
|
|
Loading…
Reference in New Issue