diff mbox series

[FFmpeg-devel,2/6] avformat/rtpproto: support for rtp read timeout

Message ID 1602686103-3427-2-git-send-email-lance.lmwang@gmail.com
State Accepted
Commit 2aceae1438ab4234161186712e9486e87be15be3
Headers show
Series [FFmpeg-devel,1/6] avformat/rtpdec: update the previous with new seq | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished

Commit Message

Lance Wang Oct. 14, 2020, 2:34 p.m. UTC
From: Limin Wang <lance.lmwang@gmail.com>

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=5000000

Signed-off-by: Limin Wang <lance.lmwang@gmail.com>
---
 doc/protocols.texi     |  3 +++
 libavformat/rtpproto.c | 12 +++++++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/doc/protocols.texi b/doc/protocols.texi
index 7b3df96..b4efa14 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -990,6 +990,9 @@  set to 1) or to a default remote address (if set to 0).
 @item localport=@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
 used.
 
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 19e940d..7dd6042 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -60,6 +60,7 @@  typedef struct RTPContext {
     char *sources;
     char *block;
     char *fec_options_str;
+    int64_t rw_timeout;
 } RTPContext;
 
 #define OFFSET(x) offsetof(RTPContext, x)
@@ -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 },
     { "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 },
+    { "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 },
     { "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 },
@@ -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)) {
             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)) {
             av_strlcpy(include_sources, buf, sizeof(include_sources));
             ff_ip_parse_sources(h, buf, &s->filters);
@@ -280,6 +285,8 @@  static int rtp_open(URLContext *h, const char *uri, int flags)
             block = s->block;
         }
     }
+    if (s->rw_timeout >= 0)
+        h->rw_timeout = s->rw_timeout;
 
     if (s->fec_options_str) {
         p = s->fec_options_str;
@@ -375,9 +382,10 @@  static int rtp_read(URLContext *h, uint8_t *buf, int size)
     RTPContext *s = h->priv_data;
     int len, n, i;
     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 };
     socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len };
+    int runs = h->rw_timeout / 1000 / POLLING_TIME;
 
     for(;;) {
         if (ff_check_interrupt(&h->interrupt_callback))
@@ -401,6 +409,8 @@  static int rtp_read(URLContext *h, uint8_t *buf, int size)
                     continue;
                 return len;
             }
+        } else if (n == 0 && h->rw_timeout > 0 && --runs <= 0) {
+            return AVERROR(ETIMEDOUT);
         } else if (n < 0) {
             if (ff_neterrno() == AVERROR(EINTR))
                 continue;