Commit 2aceae14 authored by Limin Wang's avatar Limin Wang

avformat/rtpproto: support for rtp read timeout

then we can set the rtp read timeout instead of infinite timeout.

How to test(5s timeout):
./ffprobe -i rtp://192.168.1.67:1234?timeout=5000000Signed-off-by: 's avatarLimin Wang <lance.lmwang@gmail.com>
parent de598267
...@@ -990,6 +990,9 @@ set to 1) or to a default remote address (if set to 0). ...@@ -990,6 +990,9 @@ 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 timeout=@var{n}
Set timeout (in microseconds) of socket I/O operations to @var{n}.
This is a deprecated option. Instead, @option{localrtpport} should be This is a deprecated option. Instead, @option{localrtpport} should be
used. used.
......
...@@ -60,6 +60,7 @@ typedef struct RTPContext { ...@@ -60,6 +60,7 @@ typedef struct RTPContext {
char *sources; char *sources;
char *block; char *block;
char *fec_options_str; char *fec_options_str;
int64_t rw_timeout;
} RTPContext; } RTPContext;
#define OFFSET(x) offsetof(RTPContext, x) #define OFFSET(x) offsetof(RTPContext, x)
...@@ -75,6 +76,7 @@ static const AVOption options[] = { ...@@ -75,6 +76,7 @@ static const AVOption options[] = {
{ "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "write_to_source", "Send packets to the source address of the latest received packet", OFFSET(write_to_source), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E },
{ "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "pkt_size", "Maximum packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
{ "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "dscp", "DSCP class", OFFSET(dscp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E },
{ "timeout", "set timeout (in microseconds) of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
{ "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 },
...@@ -265,6 +267,9 @@ static int rtp_open(URLContext *h, const char *uri, int flags) ...@@ -265,6 +267,9 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
s->dscp = strtol(buf, NULL, 10); s->dscp = strtol(buf, NULL, 10);
} }
if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
s->rw_timeout = strtol(buf, NULL, 10);
}
if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
av_strlcpy(include_sources, buf, sizeof(include_sources)); av_strlcpy(include_sources, buf, sizeof(include_sources));
ff_ip_parse_sources(h, buf, &s->filters); ff_ip_parse_sources(h, buf, &s->filters);
...@@ -280,6 +285,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags) ...@@ -280,6 +285,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
block = s->block; block = s->block;
} }
} }
if (s->rw_timeout >= 0)
h->rw_timeout = s->rw_timeout;
if (s->fec_options_str) { if (s->fec_options_str) {
p = s->fec_options_str; p = s->fec_options_str;
...@@ -375,9 +382,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) ...@@ -375,9 +382,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
RTPContext *s = h->priv_data; RTPContext *s = h->priv_data;
int len, n, i; int len, n, i;
struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100; int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : POLLING_TIME;
struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source }; struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source };
socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len }; socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len };
int runs = h->rw_timeout / 1000 / POLLING_TIME;
for(;;) { for(;;) {
if (ff_check_interrupt(&h->interrupt_callback)) if (ff_check_interrupt(&h->interrupt_callback))
...@@ -401,6 +409,8 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) ...@@ -401,6 +409,8 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
continue; continue;
return len; return len;
} }
} else if (n == 0 && h->rw_timeout > 0 && --runs <= 0) {
return AVERROR(ETIMEDOUT);
} else if (n < 0) { } else if (n < 0) {
if (ff_neterrno() == AVERROR(EINTR)) if (ff_neterrno() == AVERROR(EINTR))
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment