[FFmpeg-cvslog] Merge commit 'a2fc8dbae85339d1b418d296f2982b6c04c53c57'

James Almer git at videolan.org
Fri Mar 30 03:59:43 EEST 2018


ffmpeg | branch: master | James Almer <jamrial at gmail.com> | Thu Mar 29 21:56:19 2018 -0300| [a123e576a485931013c9fae85025d0e78ff3102d] | committer: James Almer

Merge commit 'a2fc8dbae85339d1b418d296f2982b6c04c53c57'

* commit 'a2fc8dbae85339d1b418d296f2982b6c04c53c57':
  Add Haivision SRT protocol

Merged-by: James Almer <jamrial at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a123e576a485931013c9fae85025d0e78ff3102d
---

 Changelog               |   1 +
 configure               |   5 +
 doc/protocols.texi      | 140 +++++++++++++
 libavformat/Makefile    |   1 +
 libavformat/libsrt.c    | 546 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/protocols.c |   1 +
 6 files changed, 694 insertions(+)

diff --git a/Changelog b/Changelog
index 2869dce386..200866d873 100644
--- a/Changelog
+++ b/Changelog
@@ -51,6 +51,7 @@ version <next>:
 - AV1 Support through libaom
 - E-AC-3 dependent frames support
 - bitstream filter for extracting E-AC-3 core
+- Haivision SRT protocol via libsrt
 
 
 version 3.4:
diff --git a/configure b/configure
index a92ac6acb7..99570a1415 100755
--- a/configure
+++ b/configure
@@ -257,6 +257,7 @@ External library support:
   --enable-libsnappy       enable Snappy compression, needed for hap encoding [no]
   --enable-libsoxr         enable Include libsoxr resampling [no]
   --enable-libspeex        enable Speex de/encoding via libspeex [no]
+  --enable-libsrt          enable Haivision SRT protocol via libsrt [no]
   --enable-libssh          enable SFTP protocol via libssh [no]
   --enable-libtesseract    enable Tesseract, needed for ocr filter [no]
   --enable-libtheora       enable Theora encoding via libtheora [no]
@@ -1705,6 +1706,7 @@ EXTERNAL_LIBRARY_LIST="
     libsnappy
     libsoxr
     libspeex
+    libsrt
     libssh
     libtesseract
     libtheora
@@ -3246,6 +3248,8 @@ libssh_protocol_deps="libssh"
 libtls_conflict="openssl gnutls"
 mmsh_protocol_select="http_protocol"
 mmst_protocol_select="network"
+libsrt_protocol_deps="libsrt"
+libsrt_protocol_select="network"
 rtmp_protocol_conflict="librtmp_protocol"
 rtmp_protocol_select="tcp_protocol"
 rtmp_protocol_suggest="zlib"
@@ -6021,6 +6025,7 @@ enabled libsnappy         && require libsnappy snappy-c.h snappy_compress -lsnap
 enabled libsoxr           && require libsoxr soxr.h soxr_create -lsoxr
 enabled libssh            && require_pkg_config libssh libssh libssh/sftp.h sftp_init
 enabled libspeex          && require_pkg_config libspeex speex speex/speex.h speex_decoder_init
+enabled libsrt            && require_pkg_config libsrt "srt >= 1.2.0" srt/srt.h srt_socket
 enabled libtesseract      && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate
 enabled libtheora         && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
 enabled libtls            && require_pkg_config libtls libtls tls.h tls_configure
diff --git a/doc/protocols.texi b/doc/protocols.texi
index c24dc74505..e19504d073 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -1155,6 +1155,146 @@ If set to any value, listen for an incoming connection. Outgoing connection is d
 Set the maximum number of streams. By default no limit is set.
 @end table
 
+ at section srt
+
+Haivision Secure Reliable Transport Protocol via libsrt.
+
+The supported syntax for a SRT URL is:
+ at example
+srt://@var{hostname}:@var{port}[?@var{options}]
+ at end example
+
+ at var{options} contains a list of &-separated options of the form
+ at var{key}=@var{val}.
+
+or
+
+ at example
+ at var{options} srt://@var{hostname}:@var{port}
+ at end example
+
+ at var{options} contains a list of '- at var{key} @var{val}'
+options.
+
+This protocol accepts the following options.
+
+ at table @option
+ at item connect_timeout
+Connection timeout; SRT cannot connect for RTT > 1500 msec
+(2 handshake exchanges) with the default connect timeout of
+3 seconds. This option applies to the caller and rendezvous
+connection modes. The connect timeout is 10 times the value
+set for the rendezvous mode (which can be used as a
+workaround for this connection problem with earlier versions).
+
+ at item ffs=@var{bytes}
+Flight Flag Size (Window Size), in bytes. FFS is actually an
+internal parameter and you should set it to not less than
+ at option{recv_buffer_size} and @option{mss}. The default value
+is relatively large, therefore unless you set a very large receiver buffer,
+you do not need to change this option. Default value is 25600.
+
+ at item inputbw=@var{bytes/seconds}
+Sender nominal input rate, in bytes per seconds. Used along with
+ at option{oheadbw}, when @option{maxbw} is set to relative (0), to
+calculate maximum sending rate when recovery packets are sent
+along with the main media stream:
+ at option{inputbw} * (100 + @option{oheadbw}) / 100
+if @option{inputbw} is not set while @option{maxbw} is set to
+relative (0), the actual input rate is evaluated inside
+the library. Default value is 0.
+
+ at item iptos=@var{tos}
+IP Type of Service. Applies to sender only. Default value is 0xB8.
+
+ at item ipttl=@var{ttl}
+IP Time To Live. Applies to sender only. Default value is 64.
+
+ at item listen_timeout
+Set socket listen timeout.
+
+ at item maxbw=@var{bytes/seconds}
+Maximum sending bandwidth, in bytes per seconds.
+-1 infinite (CSRTCC limit is 30mbps)
+0 relative to input rate (see @option{inputbw})
+>0 absolute limit value
+Default value is 0 (relative)
+
+ at item mode=@var{caller|listener|rendezvous}
+Connection mode.
+ at option{caller} opens client connection.
+ at option{listener} starts server to listen for incoming connections.
+ at option{rendezvous} use Rendez-Vous connection mode.
+Default value is caller.
+
+ at item mss=@var{bytes}
+Maximum Segment Size, in bytes. Used for buffer allocation
+and rate calculation using a packet counter assuming fully
+filled packets. The smallest MSS between the peers is
+used. This is 1500 by default in the overall internet.
+This is the maximum size of the UDP packet and can be
+only decreased, unless you have some unusual dedicated
+network settings. Default value is 1500.
+
+ at item nakreport=@var{1|0}
+If set to 1, Receiver will send `UMSG_LOSSREPORT` messages
+periodically until a lost packet is retransmitted or
+intentionally dropped. Default value is 1.
+
+ at item oheadbw=@var{percents}
+Recovery bandwidth overhead above input rate, in percents.
+See @option{inputbw}. Default value is 25%.
+
+ at item passphrase=@var{string}
+HaiCrypt Encryption/Decryption Passphrase string, length
+from 10 to 79 characters. The passphrase is the shared
+secret between the sender and the receiver. It is used
+to generate the Key Encrypting Key using PBKDF2
+(Password-Based Key Derivation Function). It is used
+only if @option{pbkeylen} is non-zero. It is used on
+the receiver only if the received data is encrypted.
+The configured passphrase cannot be recovered (write-only).
+
+ at item pbkeylen=@var{bytes}
+Sender encryption key length, in bytes.
+Only can be set to 0, 16, 24 and 32.
+Enable sender encryption if not 0.
+Not required on receiver (set to 0),
+key size obtained from sender in HaiCrypt handshake.
+Default value is 0.
+
+ at item recv_buffer_size=@var{bytes}
+Set receive buffer size, expressed in bytes.
+
+ at item send_buffer_size=@var{bytes}
+Set send buffer size, expressed in bytes.
+
+ at item rw_timeout
+Set raise error timeout for read/write optations.
+
+This option is only relevant in read mode:
+if no data arrived in more than this time
+interval, raise error.
+
+ at item tlpktdrop=@var{1|0}
+Too-late Packet Drop. When enabled on receiver, it skips
+missing packets that have not been delivered in time and
+delivers the following packets to the application when
+their time-to-play has come. It also sends a fake ACK to
+the sender. When enabled on sender and enabled on the
+receiving peer, the sender drops the older packets that
+have no chance of being delivered in time. It was
+automatically enabled in the sender if the receiver
+supports it.
+
+ at item tsbpddelay
+Timestamp-based Packet Delivery Delay.
+Used to absorb burst of missed packet retransmission.
+
+ at end table
+
+For more information see: @url{https://github.com/Haivision/srt}.
+
 @section srtp
 
 Secure Real-time Transport Protocol.
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 39ec68c28b..af0823a7db 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -566,6 +566,7 @@ OBJS-$(CONFIG_LIBRTMPE_PROTOCOL)         += librtmp.o
 OBJS-$(CONFIG_LIBRTMPS_PROTOCOL)         += librtmp.o
 OBJS-$(CONFIG_LIBRTMPT_PROTOCOL)         += librtmp.o
 OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL)        += librtmp.o
+OBJS-$(CONFIG_LIBSRT_PROTOCOL)           += libsrt.o
 OBJS-$(CONFIG_LIBSSH_PROTOCOL)           += libssh.o
 OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL)     += libsmbclient.o
 
diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c
new file mode 100644
index 0000000000..0f9529d263
--- /dev/null
+++ b/libavformat/libsrt.c
@@ -0,0 +1,546 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Haivision Open SRT (Secure Reliable Transport) protocol
+ */
+
+#include <srt/srt.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/opt.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/time.h"
+
+#include "avformat.h"
+#include "internal.h"
+#include "network.h"
+#include "os_support.h"
+#include "url.h"
+
+enum SRTMode {
+    SRT_MODE_CALLER = 0,
+    SRT_MODE_LISTENER = 1,
+    SRT_MODE_RENDEZVOUS = 2
+};
+
+typedef struct SRTContext {
+    const AVClass *class;
+    int fd;
+    int eid;
+    int64_t rw_timeout;
+    int64_t listen_timeout;
+    int recv_buffer_size;
+    int send_buffer_size;
+
+    int64_t maxbw;
+    int pbkeylen;
+    char *passphrase;
+    int mss;
+    int ffs;
+    int ipttl;
+    int iptos;
+    int64_t inputbw;
+    int oheadbw;
+    int64_t tsbpddelay;
+    int tlpktdrop;
+    int nakreport;
+    int64_t connect_timeout;
+    enum SRTMode mode;
+} SRTContext;
+
+#define D AV_OPT_FLAG_DECODING_PARAM
+#define E AV_OPT_FLAG_ENCODING_PARAM
+#define OFFSET(x) offsetof(SRTContext, x)
+static const AVOption libsrt_options[] = {
+    { "rw_timeout",     "Timeout of socket I/O operations",                                     OFFSET(rw_timeout),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "listen_timeout", "Connection awaiting timeout",                                          OFFSET(listen_timeout),   AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "send_buffer_size", "Socket send buffer size (in bytes)",                                 OFFSET(send_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+    { "recv_buffer_size", "Socket receive buffer size (in bytes)",                              OFFSET(recv_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+    { "maxbw",          "Maximum bandwidth (bytes per second) that the connection can use",     OFFSET(maxbw),            AV_OPT_TYPE_INT64,    { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "pbkeylen",       "Crypto key len in bytes {16,24,32} Default: 16 (128-bit)",             OFFSET(pbkeylen),         AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 32,        .flags = D|E },
+    { "passphrase",     "Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto",             OFFSET(passphrase),       AV_OPT_TYPE_STRING,   { .str = NULL },              .flags = D|E },
+    { "mss",            "The Maximum Segment Size",                                             OFFSET(mss),              AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1500,      .flags = D|E },
+    { "ffs",            "Flight flag size (window size) (in bytes)",                            OFFSET(ffs),              AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+    { "ipttl",          "IP Time To Live",                                                      OFFSET(ipttl),            AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 255,       .flags = D|E },
+    { "iptos",          "IP Type of Service",                                                   OFFSET(iptos),            AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 255,       .flags = D|E },
+    { "inputbw",        "Estimated input stream rate",                                          OFFSET(inputbw),          AV_OPT_TYPE_INT64,    { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "oheadbw",        "MaxBW ceiling based on % over input stream rate",                      OFFSET(oheadbw),          AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 100,       .flags = D|E },
+    { "tsbpddelay",     "TsbPd receiver delay to absorb burst of missed packet retransmission", OFFSET(tsbpddelay),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "tlpktdrop",      "Enable receiver pkt drop",                                             OFFSET(tlpktdrop),        AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1,         .flags = D|E },
+    { "nakreport",      "Enable receiver to send periodic NAK reports",                         OFFSET(nakreport),        AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1,         .flags = D|E },
+    { "connect_timeout", "Connect timeout. Caller default: 3000, rendezvous (x 10)",            OFFSET(connect_timeout),  AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "mode",           "Connection mode (caller, listener, rendezvous)",                       OFFSET(mode),             AV_OPT_TYPE_INT,      { .i64 = SRT_MODE_CALLER }, SRT_MODE_CALLER, SRT_MODE_RENDEZVOUS, .flags = D|E, "mode" },
+    { "caller",         NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_CALLER },     INT_MIN, INT_MAX, .flags = D|E, "mode" },
+    { "listener",       NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_LISTENER },   INT_MIN, INT_MAX, .flags = D|E, "mode" },
+    { "rendezvous",     NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_RENDEZVOUS }, INT_MIN, INT_MAX, .flags = D|E, "mode" },
+    { NULL }
+};
+
+static int libsrt_neterrno(URLContext *h)
+{
+    int err = srt_getlasterror(NULL);
+    av_log(h, AV_LOG_ERROR, "%s\n", srt_getlasterror_str());
+    if (err == SRT_EASYNCRCV)
+        return AVERROR(EAGAIN);
+    return AVERROR_UNKNOWN;
+}
+
+static int libsrt_socket_nonblock(int socket, int enable)
+{
+    int ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &enable, sizeof(enable));
+    if (ret < 0)
+        return ret;
+    return srt_setsockopt(socket, 0, SRTO_RCVSYN, &enable, sizeof(enable));
+}
+
+static int libsrt_network_wait_fd(URLContext *h, int eid, int fd, int write)
+{
+    int ret, len = 1;
+    int modes = write ? SRT_EPOLL_OUT : SRT_EPOLL_IN;
+    SRTSOCKET ready[1];
+
+    if (srt_epoll_add_usock(eid, fd, &modes) < 0)
+        return libsrt_neterrno(h);
+    if (write) {
+        ret = srt_epoll_wait(eid, 0, 0, ready, &len, POLLING_TIME, 0, 0, 0, 0);
+    } else {
+        ret = srt_epoll_wait(eid, ready, &len, 0, 0, POLLING_TIME, 0, 0, 0, 0);
+    }
+    if (ret < 0) {
+        if (srt_getlasterror(NULL) == SRT_ETIMEOUT)
+            ret = AVERROR(EAGAIN);
+        else
+            ret = libsrt_neterrno(h);
+    } else {
+        ret = 0;
+    }
+    if (srt_epoll_remove_usock(eid, fd) < 0)
+        return libsrt_neterrno(h);
+    return ret;
+}
+
+/* TODO de-duplicate code from ff_network_wait_fd_timeout() */
+
+static int libsrt_network_wait_fd_timeout(URLContext *h, int eid, int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
+{
+    int ret;
+    int64_t wait_start = 0;
+
+    while (1) {
+        if (ff_check_interrupt(int_cb))
+            return AVERROR_EXIT;
+        ret = libsrt_network_wait_fd(h, eid, fd, write);
+        if (ret != AVERROR(EAGAIN))
+            return ret;
+        if (timeout > 0) {
+            if (!wait_start)
+                wait_start = av_gettime_relative();
+            else if (av_gettime_relative() - wait_start > timeout)
+                return AVERROR(ETIMEDOUT);
+        }
+    }
+}
+
+static int libsrt_listen(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, URLContext *h, int timeout)
+{
+    int ret;
+    int reuse = 1;
+    if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse, sizeof(reuse))) {
+        av_log(h, AV_LOG_WARNING, "setsockopt(SRTO_REUSEADDR) failed\n");
+    }
+    ret = srt_bind(fd, addr, addrlen);
+    if (ret)
+        return libsrt_neterrno(h);
+
+    ret = srt_listen(fd, 1);
+    if (ret)
+        return libsrt_neterrno(h);
+
+    while ((ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback))) {
+        switch (ret) {
+        case AVERROR(ETIMEDOUT):
+            continue;
+        default:
+            return ret;
+        }
+    }
+
+    ret = srt_accept(fd, NULL, NULL);
+    if (ret < 0)
+        return libsrt_neterrno(h);
+    if (libsrt_socket_nonblock(ret, 1) < 0)
+        av_log(h, AV_LOG_DEBUG, "libsrt_socket_nonblock failed\n");
+
+    return ret;
+}
+
+static int libsrt_listen_connect(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next)
+{
+    int ret;
+
+    if (libsrt_socket_nonblock(fd, 1) < 0)
+        av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
+
+    while ((ret = srt_connect(fd, addr, addrlen))) {
+        ret = libsrt_neterrno(h);
+        switch (ret) {
+        case AVERROR(EINTR):
+            if (ff_check_interrupt(&h->interrupt_callback))
+                return AVERROR_EXIT;
+            continue;
+        case AVERROR(EINPROGRESS):
+        case AVERROR(EAGAIN):
+            ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback);
+            if (ret < 0)
+                return ret;
+            ret = srt_getlasterror(NULL);
+            srt_clearlasterror();
+            if (ret != 0) {
+                char buf[128];
+                ret = AVERROR(ret);
+                av_strerror(ret, buf, sizeof(buf));
+                if (will_try_next)
+                    av_log(h, AV_LOG_WARNING,
+                           "Connection to %s failed (%s), trying next address\n",
+                           h->filename, buf);
+                else
+                    av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
+                           h->filename, buf);
+            }
+        default:
+            return ret;
+        }
+    }
+    return ret;
+}
+
+static int libsrt_setsockopt(URLContext *h, int fd, SRT_SOCKOPT optname, const char * optnamestr, const void * optval, int optlen)
+{
+    if (srt_setsockopt(fd, 0, optname, optval, optlen) < 0) {
+        av_log(h, AV_LOG_ERROR, "failed to set option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
+        return AVERROR(EIO);
+    }
+    return 0;
+}
+
+/* - The "POST" options can be altered any time on a connected socket.
+     They MAY have also some meaning when set prior to connecting; such
+     option is SRTO_RCVSYN, which makes connect/accept call asynchronous.
+     Because of that this option is treated special way in this app. */
+static int libsrt_set_options_post(URLContext *h, int fd)
+{
+    SRTContext *s = h->priv_data;
+
+    if ((s->inputbw >= 0 && libsrt_setsockopt(h, fd, SRTO_INPUTBW, "SRTO_INPUTBW", &s->inputbw, sizeof(s->inputbw)) < 0) ||
+        (s->oheadbw >= 0 && libsrt_setsockopt(h, fd, SRTO_OHEADBW, "SRTO_OHEADBW", &s->oheadbw, sizeof(s->oheadbw)) < 0)) {
+        return AVERROR(EIO);
+    }
+    return 0;
+}
+
+/* - The "PRE" options must be set prior to connecting and can't be altered
+     on a connected socket, however if set on a listening socket, they are
+     derived by accept-ed socket. */
+static int libsrt_set_options_pre(URLContext *h, int fd)
+{
+    SRTContext *s = h->priv_data;
+    int yes = 1;
+    int tsbpddelay = s->tsbpddelay / 1000;
+    int connect_timeout = s->connect_timeout;
+
+    if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) ||
+        (s->maxbw >= 0 && libsrt_setsockopt(h, fd, SRTO_MAXBW, "SRTO_MAXBW", &s->maxbw, sizeof(s->maxbw)) < 0) ||
+        (s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) ||
+        (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", &s->passphrase, sizeof(s->passphrase)) < 0) ||
+        (s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MMS", &s->mss, sizeof(s->mss)) < 0) ||
+        (s->ffs >= 0 && libsrt_setsockopt(h, fd, SRTO_FC, "SRTO_FC", &s->ffs, sizeof(s->ffs)) < 0) ||
+        (s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_UPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) ||
+        (s->iptos >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTOS, "SRTO_IPTOS", &s->iptos, sizeof(s->iptos)) < 0) ||
+        (tsbpddelay >= 0 && libsrt_setsockopt(h, fd, SRTO_TSBPDDELAY, "SRTO_TSBPDELAY", &tsbpddelay, sizeof(tsbpddelay)) < 0) ||
+        (s->tlpktdrop >= 0 && libsrt_setsockopt(h, fd, SRTO_TLPKTDROP, "SRTO_TLPKDROP", &s->tlpktdrop, sizeof(s->tlpktdrop)) < 0) ||
+        (s->nakreport >= 0 && libsrt_setsockopt(h, fd, SRTO_NAKREPORT, "SRTO_NAKREPORT", &s->nakreport, sizeof(s->nakreport)) < 0) ||
+        (connect_timeout >= 0 && libsrt_setsockopt(h, fd, SRTO_CONNTIMEO, "SRTO_CONNTIMEO", &connect_timeout, sizeof(connect_timeout)) <0 )) {
+        return AVERROR(EIO);
+    }
+    return 0;
+}
+
+
+static int libsrt_setup(URLContext *h, const char *uri, int flags)
+{
+    struct addrinfo hints = { 0 }, *ai, *cur_ai;
+    int port, fd = -1;
+    SRTContext *s = h->priv_data;
+    const char *p;
+    char buf[256];
+    int ret;
+    char hostname[1024],proto[1024],path[1024];
+    char portstr[10];
+    int open_timeout = 5000000;
+    int eid;
+
+    eid = srt_epoll_create();
+    if (eid < 0)
+        return libsrt_neterrno(h);
+    s->eid = eid;
+
+    av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
+        &port, path, sizeof(path), uri);
+    if (strcmp(proto, "srt"))
+        return AVERROR(EINVAL);
+    if (port <= 0 || port >= 65536) {
+        av_log(h, AV_LOG_ERROR, "Port missing in uri\n");
+        return AVERROR(EINVAL);
+    }
+    p = strchr(uri, '?');
+    if (p) {
+        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), "listen_timeout", p)) {
+            s->listen_timeout = strtol(buf, NULL, 10);
+        }
+    }
+    if (s->rw_timeout >= 0) {
+        open_timeout = h->rw_timeout = s->rw_timeout;
+    }
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = SOCK_DGRAM;
+    snprintf(portstr, sizeof(portstr), "%d", port);
+    if (s->mode == SRT_MODE_LISTENER)
+        hints.ai_flags |= AI_PASSIVE;
+    ret = getaddrinfo(hostname[0] ? hostname : NULL, portstr, &hints, &ai);
+    if (ret) {
+        av_log(h, AV_LOG_ERROR,
+               "Failed to resolve hostname %s: %s\n",
+               hostname, gai_strerror(ret));
+        return AVERROR(EIO);
+    }
+
+    cur_ai = ai;
+
+ restart:
+
+    fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0);
+    if (fd < 0) {
+        ret = libsrt_neterrno(h);
+        goto fail;
+    }
+
+    if ((ret = libsrt_set_options_pre(h, fd)) < 0) {
+        goto fail;
+    }
+
+    /* Set the socket's send or receive buffer sizes, if specified.
+       If unspecified or setting fails, system default is used. */
+    if (s->recv_buffer_size > 0) {
+        srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
+    }
+    if (s->send_buffer_size > 0) {
+        srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
+    }
+    if (s->mode == SRT_MODE_LISTENER) {
+        // multi-client
+        if ((ret = libsrt_listen(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h, open_timeout / 1000)) < 0)
+            goto fail1;
+        fd = ret;
+    } else {
+        if (s->mode == SRT_MODE_RENDEZVOUS) {
+            ret = srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
+            if (ret)
+                goto fail1;
+        }
+
+        if ((ret = libsrt_listen_connect(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
+                                          open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) {
+            if (ret == AVERROR_EXIT)
+                goto fail1;
+            else
+                goto fail;
+        }
+    }
+    if ((ret = libsrt_set_options_post(h, fd)) < 0) {
+        goto fail;
+    }
+
+    h->is_streamed = 1;
+    s->fd = fd;
+
+    freeaddrinfo(ai);
+    return 0;
+
+ fail:
+    if (cur_ai->ai_next) {
+        /* Retry with the next sockaddr */
+        cur_ai = cur_ai->ai_next;
+        if (fd >= 0)
+            srt_close(fd);
+        ret = 0;
+        goto restart;
+    }
+ fail1:
+    if (fd >= 0)
+        srt_close(fd);
+    freeaddrinfo(ai);
+    return ret;
+}
+
+static int libsrt_open(URLContext *h, const char *uri, int flags)
+{
+    SRTContext *s = h->priv_data;
+    const char * p;
+    char buf[256];
+
+    if (srt_startup() < 0) {
+        return AVERROR_UNKNOWN;
+    }
+
+    /* SRT options (srt/srt.h) */
+    p = strchr(uri, '?');
+    if (p) {
+        if (av_find_info_tag(buf, sizeof(buf), "maxbw", p)) {
+            s->maxbw = strtoll(buf, NULL, 0);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "pbkeylen", p)) {
+            s->pbkeylen = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "passphrase", p)) {
+            s->passphrase = av_strndup(buf, strlen(buf));
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "mss", p)) {
+            s->mss = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "ffs", p)) {
+            s->ffs = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "ipttl", p)) {
+            s->ipttl = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "iptos", p)) {
+            s->iptos = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "inputbw", p)) {
+            s->inputbw = strtoll(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "oheadbw", p)) {
+            s->oheadbw = strtoll(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "tsbpddelay", p)) {
+            s->tsbpddelay = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "tlpktdrop", p)) {
+            s->tlpktdrop = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "nakreport", p)) {
+            s->nakreport = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "connect_timeout", p)) {
+            s->connect_timeout = strtol(buf, NULL, 10);
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "mode", p)) {
+            if (!strcmp(buf, "caller")) {
+                s->mode = SRT_MODE_CALLER;
+            } else if (!strcmp(buf, "listener")) {
+                s->mode = SRT_MODE_LISTENER;
+            } else if (!strcmp(buf, "rendezvous")) {
+                s->mode = SRT_MODE_RENDEZVOUS;
+            } else {
+                return AVERROR(EIO);
+            }
+        }
+    }
+    return libsrt_setup(h, uri, flags);
+}
+
+static int libsrt_read(URLContext *h, uint8_t *buf, int size)
+{
+    SRTContext *s = h->priv_data;
+    int ret;
+
+    if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
+        ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 0, h->rw_timeout, &h->interrupt_callback);
+        if (ret)
+            return ret;
+    }
+
+    ret = srt_recvmsg(s->fd, buf, size);
+    if (ret < 0) {
+        ret = libsrt_neterrno(h);
+    }
+
+    return ret;
+}
+
+static int libsrt_write(URLContext *h, const uint8_t *buf, int size)
+{
+    SRTContext *s = h->priv_data;
+    int ret;
+
+    if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
+        ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 1, h->rw_timeout, &h->interrupt_callback);
+        if (ret)
+            return ret;
+    }
+
+    ret = srt_sendmsg(s->fd, buf, size, -1, 0);
+    if (ret < 0) {
+        ret = libsrt_neterrno(h);
+    }
+
+    return ret;
+}
+
+static int libsrt_close(URLContext *h)
+{
+    SRTContext *s = h->priv_data;
+
+    srt_close(s->fd);
+
+    srt_epoll_release(s->eid);
+
+    srt_cleanup();
+
+    return 0;
+}
+
+static int libsrt_get_file_handle(URLContext *h)
+{
+    SRTContext *s = h->priv_data;
+    return s->fd;
+}
+
+static const AVClass libsrt_class = {
+    .class_name = "libsrt",
+    .item_name  = av_default_item_name,
+    .option     = libsrt_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const URLProtocol ff_libsrt_protocol = {
+    .name                = "srt",
+    .url_open            = libsrt_open,
+    .url_read            = libsrt_read,
+    .url_write           = libsrt_write,
+    .url_close           = libsrt_close,
+    .url_get_file_handle = libsrt_get_file_handle,
+    .priv_data_size      = sizeof(SRTContext),
+    .flags               = URL_PROTOCOL_FLAG_NETWORK,
+    .priv_data_class     = &libsrt_class,
+};
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
index 669d74d5a8..ad95659795 100644
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@ -65,6 +65,7 @@ extern const URLProtocol ff_librtmpe_protocol;
 extern const URLProtocol ff_librtmps_protocol;
 extern const URLProtocol ff_librtmpt_protocol;
 extern const URLProtocol ff_librtmpte_protocol;
+extern const URLProtocol ff_libsrt_protocol;
 extern const URLProtocol ff_libssh_protocol;
 extern const URLProtocol ff_libsmbclient_protocol;
 


======================================================================

diff --cc Changelog
index 2869dce386,53562a1aa0..200866d873
--- a/Changelog
+++ b/Changelog
@@@ -2,399 -2,40 +2,400 @@@ Entries are sorted chronologically fro
  releases are sorted from youngest to oldest.
  
  version <next>:
 -- Support for spherical videos
 -- Intel QSV-accelerated VP8 and VC-1 decoding
 -- VAAPI-accelerated VP8 and HEVC decoding
 -- VAAPI-accelerated deinterlacing
 -- config.log and other configuration files moved into avbuild/ directory
 -- VAAPI-accelerated MPEG-2 and VP8 encoding
 -- Apple Pixlet decoder
 -- The x86 assembler default switched from yasm to nasm, pass
 -  --x86asmexe=yasm to configure to restore the old behavior.
 -- Cineform HD decoder
 -- VP9 superframe split/merge bitstream filters
 -- FM Screen Capture Codec decoder
 -- ClearVideo decoder (I-frames only)
 -- support for decoding through D3D11VA in avconv
 -- Cinepak encoder
 +- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams
 +- Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now
 +  requires 2.1 (or later) and pkg-config.
 +- VDA dropped (use VideoToolbox instead)
 +- MagicYUV encoder
 +- Raw AMR-NB and AMR-WB demuxers
 +- TiVo ty/ty+ demuxer
  - Intel QSV-accelerated MJPEG encoding
 -- NVIDIA CUVID-accelerated H.264 and HEVC decoding
 +- PCE support for extended channel layouts in the AAC encoder
 +- native aptX and aptX HD encoder and decoder
 +- Raw aptX and aptX HD muxer and demuxer
 +- NVIDIA NVDEC-accelerated H.264, HEVC, MJPEG, MPEG-1/2/4, VC1, VP8/9 hwaccel decoding
  - Intel QSV-accelerated overlay filter
 +- mcompand audio filter
 +- acontrast audio filter
 +- OpenCL overlay filter
 +- video mix filter
 +- video normalize filter
 +- audio lv2 wrapper filter
 +- VAAPI MJPEG and VP8 decoding
 +- AMD AMF H.264 and HEVC encoders
 +- video fillborders filter
 +- video setrange filter
 +- nsp demuxer
 +- support LibreSSL (via libtls)
 +- AVX-512/ZMM support added
 +- Dropped support for building for Windows XP. The minimum supported Windows
 +  version is Windows Vista.
 +- deconvolve video filter
 +- entropy video filter
 +- hilbert audio filter source
 +- aiir audio filter
 +- aiff: add support for CD-ROM XA ADPCM
 +- Removed the ffserver program
 +- Removed the ffmenc and ffmdec muxer and demuxer
 +- VideoToolbox HEVC encoder and hwaccel
 +- VAAPI-accelerated ProcAmp (color balance), denoise and sharpness filters
 +- Add android_camera indev
 +- codec2 en/decoding via libcodec2
 +- muxer/demuxer for raw codec2 files and .c2 files
 +- Moved nvidia codec headers into an external repository.
 +  They can be found at http://git.videolan.org/?p=ffmpeg/nv-codec-headers.git
 +- native SBC encoder and decoder
 +- drmeter audio filter
 +- hapqa_extract bitstream filter
 +- filter_units bitstream filter
  - AV1 Support through libaom
 +- E-AC-3 dependent frames support
 +- bitstream filter for extracting E-AC-3 core
+ - Haivision SRT protocol via libsrt
  
  
 -version 12:
 -- aliases and defaults for Ogg subtypes (opus, spx)
 -- HEVC/H.265 RTP payload format (draft v6) packetizer and depacketizer
 -- avplay now exits by default at the end of playback
 -- XCB-based screen-grabber
 -- creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer
 -- H.261 RTP payload format (RFC 4587) depacketizer and experimental packetizer
 +version 3.4:
 +- deflicker video filter
 +- doubleweave video filter
 +- lumakey video filter
 +- pixscope video filter
 +- oscilloscope video filter
 +- config.log and other configuration files moved into ffbuild/ directory
 +- update cuvid/nvenc headers to Video Codec SDK 8.0.14
 +- afir audio filter
 +- scale_cuda CUDA based video scale filter
 +- librsvg support for svg rasterization
 +- crossfeed audio filter
 +- spec compliant VP9 muxing support in MP4
 +- remove the libnut muxer/demuxer wrappers
 +- remove the libschroedinger encoder/decoder wrappers
 +- surround audio filter
 +- sofalizer filter switched to libmysofa
 +- Gremlin Digital Video demuxer and decoder
 +- headphone audio filter
 +- superequalizer audio filter
 +- roberts video filter
 +- The x86 assembler default switched from yasm to nasm, pass
 +  --x86asmexe=yasm to configure to restore the old behavior.
 +- additional frame format support for Interplay MVE movies
 +- support for decoding through D3D11VA in ffmpeg
 +- limiter video filter
 +- libvmaf video filter
 +- Dolby E decoder and SMPTE 337M demuxer
 +- unpremultiply video filter
 +- tlut2 video filter
 +- floodfill video filter
 +- pseudocolor video filter
 +- raw G.726 muxer and demuxer, left- and right-justified
 +- NewTek NDI input/output device
 +- Some video filters with several inputs now use a common set of options:
 +  blend, libvmaf, lut3d, overlay, psnr, ssim.
 +  They must always be used by name.
 +- FITS demuxer and decoder
 +- FITS muxer and encoder
 +- add --disable-autodetect build switch
 +- drop deprecated qtkit input device (use avfoundation instead)
 +- despill video filter
 +- haas audio filter
 +- SUP/PGS subtitle muxer
 +- convolve video filter
 +- VP9 tile threading support
 +- KMS screen grabber
 +- CUDA thumbnail filter
 +- V4L2 mem2mem HW assisted codecs
 +- Rockchip MPP hardware decoding
 +- vmafmotion video filter
 +- use MIME type "G726" for little-endian G.726, "AAL2-G726" for big-endian G.726
 +
 +
 +version 3.3:
 +- CrystalHD decoder moved to new decode API
 +- add internal ebur128 library, remove external libebur128 dependency
 +- Pro-MPEG CoP #3-R2 FEC protocol
 +- premultiply video filter
 +- Support for spherical videos
 +- configure now fails if autodetect-libraries are requested but not found
 +- PSD Decoder
 +- 16.8 floating point pcm decoder
 +- 24.0 floating point pcm decoder
 +- Apple Pixlet decoder
 +- QDMC audio decoder
 +- NewTek SpeedHQ decoder
 +- MIDI Sample Dump Standard demuxer
 +- readeia608 filter
 +- Sample Dump eXchange demuxer
 +- abitscope multimedia filter
 +- Scenarist Closed Captions demuxer and muxer
 +- threshold filter
 +- midequalizer filter
 +- Optimal Huffman tables for (M)JPEG encoding
 +- VAAPI-accelerated MPEG-2 and VP8 encoding
 +- FM Screen Capture Codec decoder
 +- native Opus encoder
 +- ScreenPressor decoder
 +- incomplete ClearVideo decoder
 +- Intel QSV video scaling and deinterlacing filters
 +- Support MOV with multiple sample description tables
 +- XPM decoder
 +- Removed the legacy X11 screen grabber, use XCB instead
 +- MPEG-7 Video Signature filter
 +- Removed asyncts filter (use af_aresample instead)
 +- Intel QSV-accelerated VP8 video decoding
 +- VAAPI-accelerated deinterlacing
 +
 +
 +version 3.2:
 +- libopenmpt demuxer
 +- tee protocol
 +- Changed metadata print option to accept general urls
 +- Alias muxer for Ogg Video (.ogv)
 +- VP8 in Ogg muxing
 +- curves filter doesn't automatically insert points at x=0 and x=1 anymore
 +- 16-bit support in curves filter and selectivecolor filter
 +- OpenH264 decoder wrapper
 +- MediaCodec H.264/HEVC/MPEG-4/VP8/VP9 hwaccel
 +- True Audio (TTA) muxer
 +- crystalizer audio filter
 +- acrusher audio filter
 +- bitplanenoise video filter
 +- floating point support in als decoder
 +- fifo muxer
 +- maskedclamp filter
 +- hysteresis filter
 +- lut2 filter
 +- yuvtestsrc filter
 +- CUDA CUVID H.263/VP8/VP9/10 bit HEVC (Dithered) Decoding
 +- vaguedenoiser filter
 +- added threads option per filter instance
 +- weave filter
 +- gblur filter
 +- avgblur filter
 +- sobel and prewitt filter
 +- MediaCodec HEVC/MPEG-4/VP8/VP9 decoding
 +- Meridian Lossless Packing (MLP) / TrueHD encoder
 +- Non-Local Means (nlmeans) denoising filter
 +- sdl2 output device and ffplay support
 +- sdl1 output device and sdl1 support removed
 +- extended mov edit list support
 +- libfaac encoder removed
 +- Matroska muxer now writes CRC32 elements by default in all Level 1 elements
 +- sidedata video and asidedata audio filter
 +- Changed mapping of rtp MIME type G726 to codec g726le.
 +- spec compliant VAAPI/DXVA2 VC-1 decoding of slices in frame-coded images
 +
 +
 +version 3.1:
 +- DXVA2-accelerated HEVC Main10 decoding
 +- fieldhint filter
 +- loop video filter and aloop audio filter
 +- Bob Weaver deinterlacing filter
 +- firequalizer filter
 +- datascope filter
 +- bench and abench filters
 +- ciescope filter
 +- protocol blacklisting API
 +- MediaCodec H264 decoding
 +- VC-2 HQ RTP payload format (draft v1) depacketizer and packetizer
 +- VP9 RTP payload format (draft v2) packetizer
 +- AudioToolbox audio decoders
 +- AudioToolbox audio encoders
 +- coreimage filter (GPU based image filtering on OSX)
 +- libdcadec removed
 +- bitstream filter for extracting DTS core
 +- ADPCM IMA DAT4 decoder
 +- musx demuxer
 +- aix demuxer
 +- remap filter
 +- hash and framehash muxers
 +- colorspace filter
 +- hdcd filter
 +- readvitc filter
 +- VAAPI-accelerated format conversion and scaling
 +- libnpp/CUDA-accelerated format conversion and scaling
 +- Duck TrueMotion 2.0 Real Time decoder
 +- Wideband Single-bit Data (WSD) demuxer
 +- VAAPI-accelerated H.264/HEVC/MJPEG encoding
 +- DTS Express (LBR) decoder
 +- Generic OpenMAX IL encoder with support for Raspberry Pi
 +- IFF ANIM demuxer & decoder
 +- Direct Stream Transfer (DST) decoder
 +- loudnorm filter
 +- MTAF demuxer and decoder
 +- MagicYUV decoder
 +- OpenExr improvements (tile data and B44/B44A support)
 +- BitJazz SheerVideo decoder
 +- CUDA CUVID H264/HEVC decoder
 +- 10-bit depth support in native utvideo decoder
 +- libutvideo wrapper removed
 +- YUY2 Lossless Codec decoder
 +- VideoToolbox H.264 encoder
 +
 +
 +version 3.0:
 +- Common Encryption (CENC) MP4 encoding and decoding support
 +- DXV decoding
 +- extrastereo filter
 +- ocr filter
 +- alimiter filter
 +- stereowiden filter
 +- stereotools filter
 +- rubberband filter
 +- tremolo filter
 +- agate filter
 +- chromakey filter
 +- maskedmerge filter
 +- Screenpresso SPV1 decoding
 +- chromaprint fingerprinting muxer
 +- ffplay dynamic volume control
 +- displace filter
 +- selectivecolor filter
 +- extensive native AAC encoder improvements and removal of experimental flag
 +- ADPCM PSX decoder
 +- 3dostr, dcstr, fsb, genh, vag, xvag, ads, msf, svag & vpk demuxer
 +- zscale filter
 +- wve demuxer
 +- zero-copy Intel QSV transcoding in ffmpeg
 +- shuffleframes filter
 +- SDX2 DPCM decoder
 +- vibrato filter
 +- innoHeim/Rsupport Screen Capture Codec decoder
 +- ADPCM AICA decoder
 +- Interplay ACM demuxer and audio decoder
 +- XMA1 & XMA2 decoder
 +- realtime filter
 +- anoisesrc audio filter source
 +- IVR demuxer
 +- compensationdelay filter
 +- acompressor filter
 +- support encoding 16-bit RLE SGI images
 +- apulsator filter
 +- sidechaingate audio filter
 +- mipsdspr1 option has been renamed to mipsdsp
 +- aemphasis filter
 +- mips32r5 option has been removed
 +- mips64r6 option has been removed
 +- DXVA2-accelerated VP9 decoding
 +- SOFAlizer: virtual binaural acoustics filter
 +- VAAPI VP9 hwaccel
 +- audio high-order multiband parametric equalizer
 +- automatic bitstream filtering
 +- showspectrumpic filter
 +- libstagefright support removed
 +- spectrumsynth filter
 +- ahistogram filter
 +- only seek with the right mouse button in ffplay
 +- toggle full screen when double-clicking with the left mouse button in ffplay
 +- afftfilt filter
 +- convolution filter
 +- libquvi support removed
 +- support for dvaudio in wav and avi
 +- libaacplus and libvo-aacenc support removed
 +- Cineform HD decoder
 +- new DCA decoder with full support for DTS-HD extensions
 +- significant performance improvements in Windows Television (WTV) demuxer
 +- nnedi deinterlacer
 +- streamselect video and astreamselect audio filter
 +- swaprect filter
 +- metadata video and ametadata audio filter
 +- SMPTE VC-2 HQ profile support for the Dirac decoder
 +- SMPTE VC-2 native encoder supporting the HQ profile
 +
 +
 +version 2.8:
 +- colorkey video filter
 +- BFSTM/BCSTM demuxer
 +- little-endian ADPCM_THP decoder
 +- Hap decoder and encoder
 +- DirectDraw Surface image/texture decoder
 +- ssim filter
 +- optional new ASF demuxer
 +- showvolume filter
 +- Many improvements to the JPEG 2000 decoder
 +- Go2Meeting decoding support
 +- adrawgraph audio and drawgraph video filter
 +- removegrain video filter
 +- Intel QSV-accelerated MPEG-2 video and HEVC encoding
 +- Intel QSV-accelerated MPEG-2 video and HEVC decoding
 +- Intel QSV-accelerated VC-1 video decoding
 +- libkvazaar HEVC encoder
 +- erosion, dilation, deflate and inflate video filters
 +- Dynamic Audio Normalizer as dynaudnorm filter
 +- Reverse video and areverse audio filter
 +- Random filter
 +- deband filter
 +- AAC fixed-point decoding
 +- sidechaincompress audio filter
 +- bitstream filter for converting HEVC from MP4 to Annex B
 +- acrossfade audio filter
 +- allyuv and allrgb video sources
 +- atadenoise video filter
 +- OS X VideoToolbox support
 +- aphasemeter filter
 +- showfreqs filter
 +- vectorscope filter
 +- waveform filter
 +- hstack and vstack filter
 +- Support DNx100 (1440x1080 at 8)
 +- VAAPI hevc hwaccel
 +- VDPAU hevc hwaccel
 +- framerate filter
 +- Switched default encoders for webm to VP9 and Opus
 +- Removed experimental flag from the JPEG 2000 encoder
 +
 +
 +version 2.7:
 +- FFT video filter
 +- TDSC decoder
 +- DTS lossless extension (XLL) decoding (not lossless, disabled by default)
 +- showwavespic filter
 +- DTS decoding through libdcadec
 +- Drop support for nvenc API before 5.0
 +- nvenc HEVC encoder
 +- Detelecine filter
 +- Intel QSV-accelerated H.264 encoding
 +- MMAL-accelerated H.264 decoding
 +- basic APNG encoder and muxer with default extension "apng"
 +- unpack DivX-style packed B-frames in MPEG-4 bitstream filter
 +- WebM Live Chunk Muxer
 +- nvenc level and tier options
 +- chorus filter
 +- Canopus HQ/HQA decoder
 +- Automatically rotate videos based on metadata in ffmpeg
 +- improved Quickdraw compatibility
 +- VP9 high bit-depth and extended colorspaces decoding support
 +- WebPAnimEncoder API when available for encoding and muxing WebP
 +- Direct3D11-accelerated decoding
 +- Support Secure Transport
 +- Multipart JPEG demuxer
 +
 +
 +version 2.6:
 +- nvenc encoder
 +- 10bit spp filter
 +- colorlevels filter
 +- RIFX format for *.wav files
  - RTP/mpegts muxer
 -- VP8 in Ogg demuxing
 +- non continuous cache protocol support
 +- tblend filter
 +- cropdetect support for non 8bpp, absolute (if limit >= 1) and relative (if limit < 1.0) threshold
 +- Camellia symmetric block cipher
  - OpenH264 encoder wrapper
 +- VOC seeking support
 +- Closed caption Decoder
 +- fspp, uspp, pp7 MPlayer postprocessing filters ported to native filters
 +- showpalette filter
 +- Twofish symmetric block cipher
  - Support DNx100 (960x720 at 8)
 -- Direct3D11-accelerated decoding
 +- eq2 filter ported from libmpcodecs as eq filter
 +- removed libmpcodecs
 +- Changed default DNxHD colour range in QuickTime .mov derivatives to mpeg range
 +- ported softpulldown filter from libmpcodecs as repeatfields filter
 +- dcshift filter
 +- RTP depacketizer for loss tolerant payload format for MP3 audio (RFC 5219)
 +- RTP depacketizer for AC3 payload format (RFC 4184)
 +- palettegen and paletteuse filters
 +- VP9 RTP payload format (draft 0) experimental depacketizer
 +- RTP depacketizer for DV (RFC 6469)
  - DXVA2-accelerated HEVC decoding
  - AAC ELD 480 decoding
  - Intel QSV-accelerated H.264 decoding
diff --cc configure
index a92ac6acb7,7612a6052c..99570a1415
--- a/configure
+++ b/configure
@@@ -198,134 -180,73 +198,135 @@@ External library support
    libraries must be explicitly enabled.
  
    Also note that the following help text describes the purpose of the libraries
 -  themselves, not all their features will necessarily be usable by Libav.
 -
 -  --enable-avisynth          video frameserver
 -  --enable-avxsynth          Linux version of AviSynth
 -  --enable-bzlib             bzip2 compression [autodetect]
 -  --enable-frei0r            video filtering plugins
 -  --enable-gnutls            crypto
 -  --enable-libaom            AV1 video encoding/decoding
 -  --enable-libbs2b           Bauer stereophonic-to-binaural DSP
 -  --enable-libcdio           audio CD input
 -  --enable-libdc1394         IEEE 1394/Firewire camera input
 -  --enable-libdcadec         DCA audio decoding
 -  --enable-libfaac           AAC audio encoding
 -  --enable-libfdk-aac        AAC audio encoding/decoding
 -  --enable-libfontconfig     font configuration and management
 -  --enable-libfreetype       font rendering
 -  --enable-libgsm            GSM audio encoding/decoding
 -  --enable-libhdcd           HDCD decoding filter
 -  --enable-libilbc           ILBC audio encoding/decoding
 -  --enable-libjack           JACK audio sound server
 -  --enable-libkvazaar        HEVC video encoding
 -  --enable-libmp3lame        MP3 audio encoding
 -  --enable-libopencore-amrnb AMR-NB audio encoding/decoding
 -  --enable-libopencore-amrwb AMR-WB audio decoding
 -  --enable-libopencv         computer vision
 -  --enable-libopenh264       H.264 video encoding/decoding
 -  --enable-libopenjpeg       JPEG 2000 image encoding/decoding
 -  --enable-libopus           Opus audio encoding/decoding
 -  --enable-libpulse          Pulseaudio sound server
 -  --enable-librtmp           RTMP streaming
 -  --enable-libschroedinger   Dirac video encoding/decoding
 -  --enable-libsnappy         snappy compression
 -  --enable-libspeex          Speex audio encoding/decoding
 -  --enable-libsrt            Haivision SRT protocol
 -  --enable-libtheora         Theora video encoding/decoding
 -  --enable-libtwolame        MP2 audio encoding
 -  --enable-libvo-aacenc      AAC audio encoding
 -  --enable-libvo-amrwbenc    AMR-WB audio encoding
 -  --enable-libvorbis         Vorbis audio encoding/decoding
 -  --enable-libvpx            VP* video encoding/decoding
 -  --enable-libwavpack        Wavpack audio encoding/decoding
 -  --enable-libwebp           WebP image encoding/decoding
 -  --enable-libx264           H.264 video encoding
 -  --enable-libx265           HEVC video encoding
 -  --enable-libxavs           Chinese AVS video encoding
 -  --enable-libxcb            X window system protocol communication
 -  --enable-libxcb-shm        X11 shm communication [auto]
 -  --enable-libxcb-xfixes     X11 mouse rendering [auto]
 -  --enable-libxvid           MPEG-4 ASP video encoding
 -  --enable-openssl           crypto
 -  --enable-zlib              compression [autodetect]
 +  themselves, not all their features will necessarily be usable by FFmpeg.
 +
 +  --disable-alsa           disable ALSA support [autodetect]
 +  --disable-appkit         disable Apple AppKit framework [autodetect]
 +  --disable-avfoundation   disable Apple AVFoundation framework [autodetect]
 +  --enable-avisynth        enable reading of AviSynth script files [no]
 +  --disable-bzlib          disable bzlib [autodetect]
 +  --disable-coreimage      disable Apple CoreImage framework [autodetect]
 +  --enable-chromaprint     enable audio fingerprinting with chromaprint [no]
 +  --enable-frei0r          enable frei0r video filtering [no]
 +  --enable-gcrypt          enable gcrypt, needed for rtmp(t)e support
 +                           if openssl, librtmp or gmp is not used [no]
 +  --enable-gmp             enable gmp, needed for rtmp(t)e support
 +                           if openssl or librtmp is not used [no]
 +  --enable-gnutls          enable gnutls, needed for https support
 +                           if openssl or libtls is not used [no]
 +  --disable-iconv          disable iconv [autodetect]
 +  --enable-jni             enable JNI support [no]
 +  --enable-ladspa          enable LADSPA audio filtering [no]
 +  --enable-libaom          enable AV1 video encoding/decoding via libaom [no]
 +  --enable-libass          enable libass subtitles rendering,
 +                           needed for subtitles and ass filter [no]
 +  --enable-libbluray       enable BluRay reading using libbluray [no]
 +  --enable-libbs2b         enable bs2b DSP library [no]
 +  --enable-libcaca         enable textual display using libcaca [no]
 +  --enable-libcelt         enable CELT decoding via libcelt [no]
 +  --enable-libcdio         enable audio CD grabbing with libcdio [no]
 +  --enable-libcodec2       enable codec2 en/decoding using libcodec2 [no]
 +  --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
 +                           and libraw1394 [no]
 +  --enable-libfdk-aac      enable AAC de/encoding via libfdk-aac [no]
 +  --enable-libflite        enable flite (voice synthesis) support via libflite [no]
 +  --enable-libfontconfig   enable libfontconfig, useful for drawtext filter [no]
 +  --enable-libfreetype     enable libfreetype, needed for drawtext filter [no]
 +  --enable-libfribidi      enable libfribidi, improves drawtext filter [no]
 +  --enable-libgme          enable Game Music Emu via libgme [no]
 +  --enable-libgsm          enable GSM de/encoding via libgsm [no]
 +  --enable-libiec61883     enable iec61883 via libiec61883 [no]
 +  --enable-libilbc         enable iLBC de/encoding via libilbc [no]
 +  --enable-libjack         enable JACK audio sound server [no]
 +  --enable-libkvazaar      enable HEVC encoding via libkvazaar [no]
 +  --enable-libmodplug      enable ModPlug via libmodplug [no]
 +  --enable-libmp3lame      enable MP3 encoding via libmp3lame [no]
 +  --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore-amrnb [no]
 +  --enable-libopencore-amrwb enable AMR-WB decoding via libopencore-amrwb [no]
 +  --enable-libopencv       enable video filtering via libopencv [no]
 +  --enable-libopenh264     enable H.264 encoding via OpenH264 [no]
 +  --enable-libopenjpeg     enable JPEG 2000 de/encoding via OpenJPEG [no]
 +  --enable-libopenmpt      enable decoding tracked files via libopenmpt [no]
 +  --enable-libopus         enable Opus de/encoding via libopus [no]
 +  --enable-libpulse        enable Pulseaudio input via libpulse [no]
 +  --enable-librsvg         enable SVG rasterization via librsvg [no]
 +  --enable-librubberband   enable rubberband needed for rubberband filter [no]
 +  --enable-librtmp         enable RTMP[E] support via librtmp [no]
 +  --enable-libshine        enable fixed-point MP3 encoding via libshine [no]
 +  --enable-libsmbclient    enable Samba protocol via libsmbclient [no]
 +  --enable-libsnappy       enable Snappy compression, needed for hap encoding [no]
 +  --enable-libsoxr         enable Include libsoxr resampling [no]
 +  --enable-libspeex        enable Speex de/encoding via libspeex [no]
++  --enable-libsrt          enable Haivision SRT protocol via libsrt [no]
 +  --enable-libssh          enable SFTP protocol via libssh [no]
 +  --enable-libtesseract    enable Tesseract, needed for ocr filter [no]
 +  --enable-libtheora       enable Theora encoding via libtheora [no]
 +  --enable-libtls          enable LibreSSL (via libtls), needed for https support
 +                           if openssl or gnutls is not used [no]
 +  --enable-libtwolame      enable MP2 encoding via libtwolame [no]
 +  --enable-libv4l2         enable libv4l2/v4l-utils [no]
 +  --enable-libvidstab      enable video stabilization using vid.stab [no]
 +  --enable-libvmaf         enable vmaf filter via libvmaf [no]
 +  --enable-libvo-amrwbenc  enable AMR-WB encoding via libvo-amrwbenc [no]
 +  --enable-libvorbis       enable Vorbis en/decoding via libvorbis,
 +                           native implementation exists [no]
 +  --enable-libvpx          enable VP8 and VP9 de/encoding via libvpx [no]
 +  --enable-libwavpack      enable wavpack encoding via libwavpack [no]
 +  --enable-libwebp         enable WebP encoding via libwebp [no]
 +  --enable-libx264         enable H.264 encoding via x264 [no]
 +  --enable-libx265         enable HEVC encoding via x265 [no]
 +  --enable-libxavs         enable AVS encoding via xavs [no]
 +  --enable-libxcb          enable X11 grabbing using XCB [autodetect]
 +  --enable-libxcb-shm      enable X11 grabbing shm communication [autodetect]
 +  --enable-libxcb-xfixes   enable X11 grabbing mouse rendering [autodetect]
 +  --enable-libxcb-shape    enable X11 grabbing shape rendering [autodetect]
 +  --enable-libxvid         enable Xvid encoding via xvidcore,
 +                           native MPEG-4/Xvid encoder exists [no]
 +  --enable-libxml2         enable XML parsing using the C library libxml2 [no]
 +  --enable-libzimg         enable z.lib, needed for zscale filter [no]
 +  --enable-libzmq          enable message passing via libzmq [no]
 +  --enable-libzvbi         enable teletext support via libzvbi [no]
 +  --enable-lv2             enable LV2 audio filtering [no]
 +  --disable-lzma           disable lzma [autodetect]
 +  --enable-decklink        enable Blackmagic DeckLink I/O support [no]
 +  --enable-libndi_newtek   enable Newteck NDI I/O support [no]
 +  --enable-mediacodec      enable Android MediaCodec support [no]
 +  --enable-libmysofa       enable libmysofa, needed for sofalizer filter [no]
 +  --enable-openal          enable OpenAL 1.1 capture support [no]
 +  --enable-opencl          enable OpenCL processing [no]
 +  --enable-opengl          enable OpenGL rendering [no]
 +  --enable-openssl         enable openssl, needed for https support
 +                           if gnutls or libtls is not used [no]
 +  --disable-sndio          disable sndio support [autodetect]
 +  --disable-schannel       disable SChannel SSP, needed for TLS support on
 +                           Windows if openssl and gnutls are not used [autodetect]
 +  --disable-sdl2           disable sdl2 [autodetect]
 +  --disable-securetransport disable Secure Transport, needed for TLS support
 +                           on OSX if openssl and gnutls are not used [autodetect]
 +  --disable-xlib           disable xlib [autodetect]
 +  --disable-zlib           disable zlib [autodetect]
  
    The following libraries provide various hardware acceleration features:
 -  --enable-amf     AMF video encoding code [auto]
 -  --enable-cuda    Nvidia CUDA (dynamically linked)
 -  --enable-cuvid   Nvidia CUVID video decode acceleration
 -  --enable-d3d11va Microsoft Direct3D 11 video acceleration [auto]
 -  --enable-dxva2   Microsoft DirectX 9 video acceleration [auto]
 -  --enable-libmfx  Intel MediaSDK (AKA Quick Sync Video)
 -  --enable-libnpp  Nvidia CUDA processing
 -  --enable-mmal    Broadcom Multi-Media Abstraction Layer (Raspberry Pi)
 -  --enable-nvenc   Nvidia video encoding
 -  --enable-omx     OpenMAX IL
 -  --enable-omx-rpi OpenMAX IL for Raspberry Pi
 -  --enable-vaapi   Video Acceleration API (mainly Unix/Intel)
 -  --enable-vda     Apple Video Decode Acceleration [auto]
 -  --enable-vdpau   Nvidia Video Decode and Presentation API for Unix [auto]
 +  --disable-amf            disable AMF video encoding code [autodetect]
 +  --disable-audiotoolbox   disable Apple AudioToolbox code [autodetect]
 +  --enable-cuda-sdk        enable CUDA features that require the CUDA SDK [no]
 +  --disable-cuvid          disable Nvidia CUVID support [autodetect]
 +  --disable-d3d11va        disable Microsoft Direct3D 11 video acceleration code [autodetect]
 +  --disable-dxva2          disable Microsoft DirectX 9 video acceleration code [autodetect]
 +  --disable-ffnvcodec      disable dynamically linked Nvidia code [autodetect]
 +  --enable-libdrm          enable DRM code (Linux) [no]
 +  --enable-libmfx          enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no]
 +  --enable-libnpp          enable Nvidia Performance Primitives-based code [no]
 +  --enable-mmal            enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no]
 +  --disable-nvdec          disable Nvidia video decoding acceleration (via hwaccel) [autodetect]
 +  --disable-nvenc          disable Nvidia video encoding code [autodetect]
 +  --enable-omx             enable OpenMAX IL code [no]
 +  --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
 +  --enable-rkmpp           enable Rockchip Media Process Platform code [no]
 +  --disable-v4l2-m2m       disable V4L2 mem2mem code [autodetect]
 +  --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
 +  --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
 +  --disable-videotoolbox   disable VideoToolbox code [autodetect]
  
  Toolchain options:
    --arch=ARCH              select architecture [$arch]
@@@ -1695,21 -1369,15 +1696,22 @@@ EXTERNAL_LIBRARY_LIST=
      libopencv
      libopenh264
      libopenjpeg
 +    libopenmpt
      libopus
      libpulse
 +    librsvg
      librtmp
 -    libschroedinger
 +    libshine
 +    libsmbclient
      libsnappy
 +    libsoxr
      libspeex
+     libsrt
 +    libssh
 +    libtesseract
      libtheora
      libtwolame
 +    libv4l2
      libvorbis
      libvpx
      libwavpack
@@@ -3241,11 -2525,10 +3243,13 @@@ librtmpe_protocol_deps="librtmp
  librtmps_protocol_deps="librtmp"
  librtmpt_protocol_deps="librtmp"
  librtmpte_protocol_deps="librtmp"
 +libsmbclient_protocol_deps="libsmbclient gplv3"
 +libssh_protocol_deps="libssh"
 +libtls_conflict="openssl gnutls"
  mmsh_protocol_select="http_protocol"
  mmst_protocol_select="network"
+ libsrt_protocol_deps="libsrt"
+ libsrt_protocol_select="network"
  rtmp_protocol_conflict="librtmp_protocol"
  rtmp_protocol_select="tcp_protocol"
  rtmp_protocol_suggest="zlib"
@@@ -5934,137 -4642,63 +5938,138 @@@ for func in $MATH_FUNCS; d
      eval check_mathfunc $func \${${func}_args:-1} $libm_extralibs
  done
  
 +for func in $COMPLEX_FUNCS; do
 +    eval check_complexfunc $func \${${func}_args:-1}
 +done
 +
  # these are off by default, so fail if requested and not available
 -enabled amf               && require_cpp_condition AMF/core/Version.h "(AMF_VERSION_MAJOR << 48 | AMF_VERSION_MINOR << 32 | AMF_VERSION_RELEASE << 16 | AMF_VERSION_BUILD_NUM) >= 0x0001000400040001"
 -enabled avisynth          && require_header avisynth/avisynth_c.h
 -enabled avxsynth          && require_header avxsynth/avxsynth_c.h
 -enabled cuda              && require cuda cuda.h cuInit -lcuda
 -enabled cuvid             && require cuvid cuviddec.h cuvidCreateDecoder -lnvcuvid
 +enabled cuda_sdk          && require cuda_sdk cuda.h cuCtxCreate -lcuda
 +enabled chromaprint       && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
 +enabled decklink          && { require_header DeckLinkAPI.h &&
 +                               { test_cpp_condition DeckLinkAPIVersion.h "BLACKMAGIC_DECKLINK_API_VERSION >= 0x0a060100" || die "ERROR: Decklink API version must be >= 10.6.1."; } }
 +enabled libndi_newtek     && require_header Processing.NDI.Lib.h
  enabled frei0r            && require_header frei0r.h
 -enabled gnutls            && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init &&
 -                             check_lib gmp gmp.h mpz_export -lgmp
 +enabled gmp               && require gmp gmp.h mpz_export -lgmp
 +enabled gnutls            && require_pkg_config gnutls gnutls gnutls/gnutls.h gnutls_global_init
 +enabled jni               && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads || die "ERROR: jni not found"; }
 +enabled ladspa            && require_header ladspa.h
  enabled libaom            && require_pkg_config libaom "aom >= 0.1.0" aom/aom_codec.h aom_codec_version
 +enabled lv2               && require_pkg_config lv2 lilv-0 "lilv-0/lilv/lilv.h" lilv_world_new
 +enabled libiec61883       && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883
 +enabled libass            && require_pkg_config libass libass ass/ass.h ass_library_init
 +enabled libbluray         && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open
  enabled libbs2b           && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open
 +enabled libcelt           && require libcelt celt/celt.h celt_decode -lcelt0 &&
 +                             { check_lib libcelt celt/celt.h celt_decoder_create_custom -lcelt0 ||
 +                               die "ERROR: libcelt must be installed and version must be >= 0.11.0."; }
 +enabled libcaca           && require_pkg_config libcaca caca caca.h caca_create_canvas
 +enabled libcodec2         && require libcodec2 codec2/codec2.h codec2_create -lcodec2
  enabled libdc1394         && require_pkg_config libdc1394 libdc1394-2 dc1394/dc1394.h dc1394_new
 -enabled libdcadec         && require libdcadec libdcadec/dca_context.h dcadec_context_create -ldcadec
 -enabled libfaac           && require libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
 -enabled libfdk_aac        && require_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen
 +enabled libdrm            && require_pkg_config libdrm libdrm xf86drm.h drmGetVersion
 +enabled libfdk_aac        && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen ||
 +                               { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac &&
 +                                 warn "using libfdk without pkg-config"; } }
 +flite_extralibs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite"
 +enabled libflite          && require libflite "flite/flite.h" flite_init $flite_extralibs
 +enabled fontconfig        && enable libfontconfig
  enabled libfontconfig     && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit
  enabled libfreetype       && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType
 -enabled libgsm            && require libgsm gsm.h gsm_create -lgsm
 -enabled libhdcd           && require_pkg_config libhdcd libhdcd "hdcd/hdcd_simple.h" hdcd_new
 -enabled libilbc           && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc
 +enabled libfribidi        && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info
 +enabled libgme            && { check_pkg_config libgme libgme gme/gme.h gme_new_emu ||
 +                               require libgme gme/gme.h gme_new_emu -lgme -lstdc++; }
 +enabled libgsm            && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do
 +                                   check_lib libgsm "${gsm_hdr}" gsm_create -lgsm && break;
 +                               done || die "ERROR: libgsm not found"; }
 +enabled libilbc           && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc $pthreads_extralibs
  enabled libkvazaar        && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get
 -enabled libmfx            && require_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit
 -enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
 -enabled libnpp            && require libnpp npp.h nppGetLibVersion -lnppi -lnppc
 +# While it may appear that require is being used as a pkg-config
 +# fallback for libmfx, it is actually being used to detect a different
 +# installation route altogether.  If libmfx is installed via the Intel
 +# Media SDK or Intel Media Server Studio, these don't come with
 +# pkg-config support.  Instead, users should make sure that the build
 +# can find the libraries and headers through other means.
 +enabled libmfx            && { check_pkg_config libmfx libmfx "mfx/mfxvideo.h" MFXInit ||
 +                               { require libmfx "mfx/mfxvideo.h" MFXInit "-llibmfx $advapi32_extralibs" && warn "using libmfx without pkg-config"; } }
 +enabled libmodplug        && require_pkg_config libmodplug libmodplug libmodplug/modplug.h ModPlug_Load
 +enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame $libm_extralibs
 +enabled libmysofa         && require libmysofa "mysofa.h" mysofa_load -lmysofa $zlib_extralibs
 +enabled libnpp            && { check_lib libnpp npp.h nppGetLibVersion -lnppig -lnppicc -lnppc ||
 +                               check_lib libnpp npp.h nppGetLibVersion -lnppi -lnppc ||
 +                               die "ERROR: libnpp not found"; }
  enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
  enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
 -enabled libopencv         && require_pkg_config libopencv opencv opencv/cv.h cvCreateImageHeader
 +enabled libopencv         && { check_header opencv2/core/core_c.h &&
 +                               { check_pkg_config libopencv opencv opencv2/core/core_c.h cvCreateImageHeader ||
 +                                 require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } ||
 +                               require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; }
  enabled libopenh264       && require_pkg_config libopenh264 openh264 wels/codec_api.h WelsGetCodecVersion
 -enabled libopenjpeg       && { check_lib libopenjpeg openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC ||
 -                               require_pkg_config libopenjpeg libopenjpeg1 openjpeg.h opj_version -DOPJ_STATIC; }
 -enabled libopus           && require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create
 -enabled libpulse          && require_pkg_config libpulse libpulse-simple pulse/simple.h pa_simple_new
 +enabled libopenjpeg       && { check_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version ||
 +                               { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } }
 +enabled libopenmpt        && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++"
 +enabled libopus           && {
 +    enabled libopus_decoder && {
 +        require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create
 +    }
 +    enabled libopus_encoder && {
 +        require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create
 +    }
 +}
 +enabled libpulse          && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new
 +enabled librsvg           && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo
  enabled librtmp           && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket
 -enabled libschroedinger   && require_pkg_config libschroedinger schroedinger-1.0 schroedinger/schro.h schro_init
 -enabled libsnappy         && require libsnappy snappy-c.h snappy_compress -lsnappy
 +enabled librubberband     && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && append librubberband_extralibs "-lstdc++"
 +enabled libshine          && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer
 +enabled libsmbclient      && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init ||
 +                               require libsmbclient libsmbclient.h smbc_init -lsmbclient; }
 +enabled libsnappy         && require libsnappy snappy-c.h snappy_compress -lsnappy -lstdc++
 +enabled libsoxr           && require libsoxr soxr.h soxr_create -lsoxr
 +enabled libssh            && require_pkg_config libssh libssh libssh/sftp.h sftp_init
  enabled libspeex          && require_pkg_config libspeex speex speex/speex.h speex_decoder_init
+ enabled libsrt            && require_pkg_config libsrt "srt >= 1.2.0" srt/srt.h srt_socket
 +enabled libtesseract      && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate
  enabled libtheora         && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
 -enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame
 -enabled libvo_aacenc      && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc
 +enabled libtls            && require_pkg_config libtls libtls tls.h tls_configure
 +enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame &&
 +                             { check_lib libtwolame twolame.h twolame_encode_buffer_float32_interleaved -ltwolame ||
 +                               die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; }
 +enabled libv4l2           && require_pkg_config libv4l2 libv4l2 libv4l2.h v4l2_ioctl
 +enabled libvidstab        && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
 +enabled libvmaf           && require_pkg_config libvmaf "libvmaf >= 0.6.2" libvmaf.h compute_vmaf
  enabled libvo_amrwbenc    && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc
 -enabled libvorbis         && require libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg
 -enabled libvpx            && require_pkg_config libvpx "vpx >= 1.3.0" vpx/vpx_codec.h vpx_codec_version &&
 -                             { enabled libvpx_vp8_decoder &&
 -                                   check_pkg_config libvpx_vp8_decoder vpx "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx
 -                               enabled libvpx_vp8_encoder &&
 -                                   check_pkg_config libvpx_vp8_encoder vpx "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx
 -                               enabled libvpx_vp9_decoder &&
 -                                   check_pkg_config libvpx_vp9_decoder vpx "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx
 -                               enabled libvpx_vp9_encoder &&
 -                                   check_pkg_config libvpx_vp9_encoder vpx "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx
 -                               disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder &&
 -                                   die "libvpx enabled but no supported decoders/encoders found"
 -                             }
 +enabled libvorbis         && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init &&
 +                             require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init
 +
 +enabled libvpx            && {
 +    enabled libvpx_vp8_decoder && {
 +        check_pkg_config libvpx_vp8_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx ||
 +            check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_dec_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx ||
 +                die "ERROR: libvpx decoder version must be >=1.4.0";
 +    }
 +    enabled libvpx_vp8_encoder && {
 +        check_pkg_config libvpx_vp8_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx ||
 +            check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx ||
 +                die "ERROR: libvpx encoder version must be >=1.4.0";
 +    }
 +    enabled libvpx_vp9_decoder && {
 +        check_pkg_config libvpx_vp9_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx ||
 +            check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs"
 +    }
 +    enabled libvpx_vp9_encoder && {
 +        check_pkg_config libvpx_vp9_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx ||
 +            check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs"
 +    }
 +    if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then
 +        die "libvpx enabled but no supported decoders found"
 +    fi
 +}
 +
  enabled libwavpack        && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput  -lwavpack
 -enabled libwebp           && require_pkg_config libwebp libwebp webp/encode.h WebPGetEncoderVersion
 -enabled libx264           && require_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode &&
 +enabled libwebp           && {
 +    enabled libwebp_encoder      && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion
 +    enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; }
 +enabled libx264           && { check_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode ||
 +                               { require libx264 "stdint.h x264.h" x264_encoder_encode "-lx264 $pthreads_extralibs $libm_extralibs" &&
 +                                 warn "using libx264 without pkg-config"; } } &&
                               require_cpp_condition x264.h "X264_BUILD >= 118" &&
                               check_cpp_condition libx262 x264.h "X264_MPEG2"
  enabled libx265           && require_pkg_config libx265 x265 x265.h x265_api_get &&
diff --cc doc/protocols.texi
index c24dc74505,e2d06a0675..e19504d073
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@@ -1134,94 -652,149 +1134,234 @@@ ffplay sap:/
  To play back the first stream announced on one the default IPv6 SAP multicast address:
  
  @example
 -avplay sap://[ff0e::2:7ffe]
 +ffplay sap://[ff0e::2:7ffe]
 + at end example
 +
 + at section sctp
 +
 +Stream Control Transmission Protocol.
 +
 +The accepted URL syntax is:
 + at example
 +sctp://@var{host}:@var{port}[?@var{options}]
  @end example
  
 +The protocol accepts the following options:
 + at table @option
 + at item listen
 +If set to any value, listen for an incoming connection. Outgoing connection is done by default.
 +
 + at item max_streams
 +Set the maximum number of streams. By default no limit is set.
 + at end table
 +
+ @section srt
+ 
+ Haivision Secure Reliable Transport Protocol via libsrt.
+ 
+ The supported syntax for a SRT URL is:
+ @example
+ srt://@var{hostname}:@var{port}[?@var{options}]
+ @end example
+ 
+ @var{options} contains a list of &-separated options of the form
+ @var{key}=@var{val}.
+ 
+ or
+ 
+ @example
+ @var{options} srt://@var{hostname}:@var{port}
+ @end example
+ 
+ @var{options} contains a list of '- at var{key} @var{val}'
+ options.
+ 
+ This protocol accepts the following options.
+ 
+ @table @option
+ @item connect_timeout
+ Connection timeout; SRT cannot connect for RTT > 1500 msec
+ (2 handshake exchanges) with the default connect timeout of
+ 3 seconds. This option applies to the caller and rendezvous
+ connection modes. The connect timeout is 10 times the value
+ set for the rendezvous mode (which can be used as a
+ workaround for this connection problem with earlier versions).
+ 
+ @item ffs=@var{bytes}
+ Flight Flag Size (Window Size), in bytes. FFS is actually an
+ internal parameter and you should set it to not less than
+ @option{recv_buffer_size} and @option{mss}. The default value
+ is relatively large, therefore unless you set a very large receiver buffer,
+ you do not need to change this option. Default value is 25600.
+ 
+ @item inputbw=@var{bytes/seconds}
+ Sender nominal input rate, in bytes per seconds. Used along with
+ @option{oheadbw}, when @option{maxbw} is set to relative (0), to
+ calculate maximum sending rate when recovery packets are sent
+ along with the main media stream:
+ @option{inputbw} * (100 + @option{oheadbw}) / 100
+ if @option{inputbw} is not set while @option{maxbw} is set to
+ relative (0), the actual input rate is evaluated inside
+ the library. Default value is 0.
+ 
+ @item iptos=@var{tos}
+ IP Type of Service. Applies to sender only. Default value is 0xB8.
+ 
+ @item ipttl=@var{ttl}
+ IP Time To Live. Applies to sender only. Default value is 64.
+ 
+ @item listen_timeout
+ Set socket listen timeout.
+ 
+ @item maxbw=@var{bytes/seconds}
+ Maximum sending bandwidth, in bytes per seconds.
+ -1 infinite (CSRTCC limit is 30mbps)
+ 0 relative to input rate (see @option{inputbw})
+ >0 absolute limit value
+ Default value is 0 (relative)
+ 
+ @item mode=@var{caller|listener|rendezvous}
+ Connection mode.
+ @option{caller} opens client connection.
+ @option{listener} starts server to listen for incoming connections.
+ @option{rendezvous} use Rendez-Vous connection mode.
+ Default value is caller.
+ 
+ @item mss=@var{bytes}
+ Maximum Segment Size, in bytes. Used for buffer allocation
+ and rate calculation using a packet counter assuming fully
+ filled packets. The smallest MSS between the peers is
+ used. This is 1500 by default in the overall internet.
+ This is the maximum size of the UDP packet and can be
+ only decreased, unless you have some unusual dedicated
+ network settings. Default value is 1500.
+ 
+ @item nakreport=@var{1|0}
+ If set to 1, Receiver will send `UMSG_LOSSREPORT` messages
+ periodically until a lost packet is retransmitted or
+ intentionally dropped. Default value is 1.
+ 
+ @item oheadbw=@var{percents}
+ Recovery bandwidth overhead above input rate, in percents.
+ See @option{inputbw}. Default value is 25%.
+ 
+ @item passphrase=@var{string}
+ HaiCrypt Encryption/Decryption Passphrase string, length
+ from 10 to 79 characters. The passphrase is the shared
+ secret between the sender and the receiver. It is used
+ to generate the Key Encrypting Key using PBKDF2
+ (Password-Based Key Derivation Function). It is used
+ only if @option{pbkeylen} is non-zero. It is used on
+ the receiver only if the received data is encrypted.
+ The configured passphrase cannot be recovered (write-only).
+ 
+ @item pbkeylen=@var{bytes}
+ Sender encryption key length, in bytes.
+ Only can be set to 0, 16, 24 and 32.
+ Enable sender encryption if not 0.
+ Not required on receiver (set to 0),
+ key size obtained from sender in HaiCrypt handshake.
+ Default value is 0.
+ 
+ @item recv_buffer_size=@var{bytes}
+ Set receive buffer size, expressed in bytes.
+ 
+ @item send_buffer_size=@var{bytes}
+ Set send buffer size, expressed in bytes.
+ 
+ @item rw_timeout
+ Set raise error timeout for read/write optations.
+ 
+ This option is only relevant in read mode:
+ if no data arrived in more than this time
+ interval, raise error.
+ 
+ @item tlpktdrop=@var{1|0}
+ Too-late Packet Drop. When enabled on receiver, it skips
+ missing packets that have not been delivered in time and
+ delivers the following packets to the application when
+ their time-to-play has come. It also sends a fake ACK to
+ the sender. When enabled on sender and enabled on the
+ receiving peer, the sender drops the older packets that
+ have no chance of being delivered in time. It was
+ automatically enabled in the sender if the receiver
+ supports it.
+ 
+ @item tsbpddelay
+ Timestamp-based Packet Delivery Delay.
+ Used to absorb burst of missed packet retransmission.
+ 
+ @end table
+ 
+ For more information see: @url{https://github.com/Haivision/srt}.
+ 
 + at section srtp
 +
 +Secure Real-time Transport Protocol.
 +
 +The accepted options are:
 + at table @option
 + at item srtp_in_suite
 + at item srtp_out_suite
 +Select input and output encoding suites.
 +
 +Supported values:
 + at table @samp
 + at item AES_CM_128_HMAC_SHA1_80
 + at item SRTP_AES128_CM_HMAC_SHA1_80
 + at item AES_CM_128_HMAC_SHA1_32
 + at item SRTP_AES128_CM_HMAC_SHA1_32
 + at end table
 +
 + at item srtp_in_params
 + at item srtp_out_params
 +Set input and output encoding parameters, which are expressed by a
 +base64-encoded representation of a binary block. The first 16 bytes of
 +this binary block are used as master key, the following 14 bytes are
 +used as master salt.
 + at end table
 +
 + at section subfile
 +
 +Virtually extract a segment of a file or another stream.
 +The underlying stream must be seekable.
 +
 +Accepted options:
 + at table @option
 + at item start
 +Start offset of the extracted segment, in bytes.
 + at item end
 +End offset of the extracted segment, in bytes.
 +If set to 0, extract till end of file.
 + at end table
 +
 +Examples:
 +
 +Extract a chapter from a DVD VOB file (start and end sectors obtained
 +externally and multiplied by 2048):
 + at example
 +subfile,,start,153391104,end,268142592,,:/media/dvd/VIDEO_TS/VTS_08_1.VOB
 + at end example
 +
 +Play an AVI file directly from a TAR archive:
 + at example
 +subfile,,start,183241728,end,366490624,,:archive.tar
 + at end example
 +
 +Play a MPEG-TS file from start offset till end:
 + at example
 +subfile,,start,32815239,end,0,,:video.ts
 + at end example
 +
 + at section tee
 +
 +Writes the output to multiple protocols. The individual outputs are separated
 +by |
 +
 + at example
 +tee:file://path/to/local/this.avi|file://path/to/local/that.avi
 + at end example
 +
  @section tcp
  
  Transmission Control Protocol.
diff --cc libavformat/Makefile
index 39ec68c28b,96085d20c6..af0823a7db
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@@ -557,26 -379,12 +557,27 @@@ OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER
  
  # external libraries
  OBJS-$(CONFIG_AVISYNTH_DEMUXER)          += avisynth.o
 -OBJS-$(CONFIG_LIBRTMP)                   += librtmp.o
 +OBJS-$(CONFIG_CHROMAPRINT_MUXER)         += chromaprint.o
 +OBJS-$(CONFIG_LIBGME_DEMUXER)            += libgme.o
 +OBJS-$(CONFIG_LIBMODPLUG_DEMUXER)        += libmodplug.o
 +OBJS-$(CONFIG_LIBOPENMPT_DEMUXER)        += libopenmpt.o
 +OBJS-$(CONFIG_LIBRTMP_PROTOCOL)          += librtmp.o
 +OBJS-$(CONFIG_LIBRTMPE_PROTOCOL)         += librtmp.o
 +OBJS-$(CONFIG_LIBRTMPS_PROTOCOL)         += librtmp.o
 +OBJS-$(CONFIG_LIBRTMPT_PROTOCOL)         += librtmp.o
 +OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL)        += librtmp.o
++OBJS-$(CONFIG_LIBSRT_PROTOCOL)           += libsrt.o
 +OBJS-$(CONFIG_LIBSSH_PROTOCOL)           += libssh.o
 +OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL)     += libsmbclient.o
  
  # protocols I/O
 +OBJS-$(CONFIG_ASYNC_PROTOCOL)            += async.o
  OBJS-$(CONFIG_APPLEHTTP_PROTOCOL)        += hlsproto.o
 +OBJS-$(CONFIG_BLURAY_PROTOCOL)           += bluray.o
 +OBJS-$(CONFIG_CACHE_PROTOCOL)            += cache.o
  OBJS-$(CONFIG_CONCAT_PROTOCOL)           += concat.o
  OBJS-$(CONFIG_CRYPTO_PROTOCOL)           += crypto.o
 +OBJS-$(CONFIG_DATA_PROTOCOL)             += data_uri.o
  OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL)      += rtmpcrypt.o rtmpdigest.o rtmpdh.o
  OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL)       += rtmphttp.o
  OBJS-$(CONFIG_FILE_PROTOCOL)             += file.o
diff --cc libavformat/libsrt.c
index 0000000000,3e50dab64f..0f9529d263
mode 000000,100644..100644
--- a/libavformat/libsrt.c
+++ b/libavformat/libsrt.c
@@@ -1,0 -1,546 +1,546 @@@
+ /*
 - * This file is part of Libav.
++ * This file is part of FFmpeg.
+  *
 - * Libav is free software; you can redistribute it and/or
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ 
+ /**
+  * @file
+  * Haivision Open SRT (Secure Reliable Transport) protocol
+  */
+ 
+ #include <srt/srt.h>
+ 
+ #include "libavutil/avassert.h"
+ #include "libavutil/opt.h"
+ #include "libavutil/parseutils.h"
+ #include "libavutil/time.h"
+ 
+ #include "avformat.h"
+ #include "internal.h"
+ #include "network.h"
+ #include "os_support.h"
+ #include "url.h"
+ 
+ enum SRTMode {
+     SRT_MODE_CALLER = 0,
+     SRT_MODE_LISTENER = 1,
+     SRT_MODE_RENDEZVOUS = 2
+ };
+ 
+ typedef struct SRTContext {
+     const AVClass *class;
+     int fd;
+     int eid;
+     int64_t rw_timeout;
+     int64_t listen_timeout;
+     int recv_buffer_size;
+     int send_buffer_size;
+ 
+     int64_t maxbw;
+     int pbkeylen;
+     char *passphrase;
+     int mss;
+     int ffs;
+     int ipttl;
+     int iptos;
+     int64_t inputbw;
+     int oheadbw;
+     int64_t tsbpddelay;
+     int tlpktdrop;
+     int nakreport;
+     int64_t connect_timeout;
+     enum SRTMode mode;
+ } SRTContext;
+ 
+ #define D AV_OPT_FLAG_DECODING_PARAM
+ #define E AV_OPT_FLAG_ENCODING_PARAM
+ #define OFFSET(x) offsetof(SRTContext, x)
+ static const AVOption libsrt_options[] = {
+     { "rw_timeout",     "Timeout of socket I/O operations",                                     OFFSET(rw_timeout),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "listen_timeout", "Connection awaiting timeout",                                          OFFSET(listen_timeout),   AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "send_buffer_size", "Socket send buffer size (in bytes)",                                 OFFSET(send_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+     { "recv_buffer_size", "Socket receive buffer size (in bytes)",                              OFFSET(recv_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+     { "maxbw",          "Maximum bandwidth (bytes per second) that the connection can use",     OFFSET(maxbw),            AV_OPT_TYPE_INT64,    { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "pbkeylen",       "Crypto key len in bytes {16,24,32} Default: 16 (128-bit)",             OFFSET(pbkeylen),         AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 32,        .flags = D|E },
+     { "passphrase",     "Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto",             OFFSET(passphrase),       AV_OPT_TYPE_STRING,   { .str = NULL },              .flags = D|E },
+     { "mss",            "The Maximum Segment Size",                                             OFFSET(mss),              AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1500,      .flags = D|E },
+     { "ffs",            "Flight flag size (window size) (in bytes)",                            OFFSET(ffs),              AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
+     { "ipttl",          "IP Time To Live",                                                      OFFSET(ipttl),            AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 255,       .flags = D|E },
+     { "iptos",          "IP Type of Service",                                                   OFFSET(iptos),            AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 255,       .flags = D|E },
+     { "inputbw",        "Estimated input stream rate",                                          OFFSET(inputbw),          AV_OPT_TYPE_INT64,    { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "oheadbw",        "MaxBW ceiling based on % over input stream rate",                      OFFSET(oheadbw),          AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 100,       .flags = D|E },
+     { "tsbpddelay",     "TsbPd receiver delay to absorb burst of missed packet retransmission", OFFSET(tsbpddelay),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "tlpktdrop",      "Enable receiver pkt drop",                                             OFFSET(tlpktdrop),        AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1,         .flags = D|E },
+     { "nakreport",      "Enable receiver to send periodic NAK reports",                         OFFSET(nakreport),        AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 1,         .flags = D|E },
+     { "connect_timeout", "Connect timeout. Caller default: 3000, rendezvous (x 10)",            OFFSET(connect_timeout),  AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+     { "mode",           "Connection mode (caller, listener, rendezvous)",                       OFFSET(mode),             AV_OPT_TYPE_INT,      { .i64 = SRT_MODE_CALLER }, SRT_MODE_CALLER, SRT_MODE_RENDEZVOUS, .flags = D|E, "mode" },
+     { "caller",         NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_CALLER },     INT_MIN, INT_MAX, .flags = D|E, "mode" },
+     { "listener",       NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_LISTENER },   INT_MIN, INT_MAX, .flags = D|E, "mode" },
+     { "rendezvous",     NULL, 0, AV_OPT_TYPE_CONST,  { .i64 = SRT_MODE_RENDEZVOUS }, INT_MIN, INT_MAX, .flags = D|E, "mode" },
+     { NULL }
+ };
+ 
+ static int libsrt_neterrno(URLContext *h)
+ {
+     int err = srt_getlasterror(NULL);
+     av_log(h, AV_LOG_ERROR, "%s\n", srt_getlasterror_str());
+     if (err == SRT_EASYNCRCV)
+         return AVERROR(EAGAIN);
+     return AVERROR_UNKNOWN;
+ }
+ 
+ static int libsrt_socket_nonblock(int socket, int enable)
+ {
+     int ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &enable, sizeof(enable));
+     if (ret < 0)
+         return ret;
+     return srt_setsockopt(socket, 0, SRTO_RCVSYN, &enable, sizeof(enable));
+ }
+ 
+ static int libsrt_network_wait_fd(URLContext *h, int eid, int fd, int write)
+ {
+     int ret, len = 1;
+     int modes = write ? SRT_EPOLL_OUT : SRT_EPOLL_IN;
+     SRTSOCKET ready[1];
+ 
+     if (srt_epoll_add_usock(eid, fd, &modes) < 0)
+         return libsrt_neterrno(h);
+     if (write) {
+         ret = srt_epoll_wait(eid, 0, 0, ready, &len, POLLING_TIME, 0, 0, 0, 0);
+     } else {
+         ret = srt_epoll_wait(eid, ready, &len, 0, 0, POLLING_TIME, 0, 0, 0, 0);
+     }
+     if (ret < 0) {
+         if (srt_getlasterror(NULL) == SRT_ETIMEOUT)
+             ret = AVERROR(EAGAIN);
+         else
+             ret = libsrt_neterrno(h);
+     } else {
+         ret = 0;
+     }
+     if (srt_epoll_remove_usock(eid, fd) < 0)
+         return libsrt_neterrno(h);
+     return ret;
+ }
+ 
+ /* TODO de-duplicate code from ff_network_wait_fd_timeout() */
+ 
+ static int libsrt_network_wait_fd_timeout(URLContext *h, int eid, int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
+ {
+     int ret;
+     int64_t wait_start = 0;
+ 
+     while (1) {
+         if (ff_check_interrupt(int_cb))
+             return AVERROR_EXIT;
+         ret = libsrt_network_wait_fd(h, eid, fd, write);
+         if (ret != AVERROR(EAGAIN))
+             return ret;
+         if (timeout > 0) {
+             if (!wait_start)
+                 wait_start = av_gettime_relative();
+             else if (av_gettime_relative() - wait_start > timeout)
+                 return AVERROR(ETIMEDOUT);
+         }
+     }
+ }
+ 
+ static int libsrt_listen(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, URLContext *h, int timeout)
+ {
+     int ret;
+     int reuse = 1;
+     if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse, sizeof(reuse))) {
+         av_log(h, AV_LOG_WARNING, "setsockopt(SRTO_REUSEADDR) failed\n");
+     }
+     ret = srt_bind(fd, addr, addrlen);
+     if (ret)
+         return libsrt_neterrno(h);
+ 
+     ret = srt_listen(fd, 1);
+     if (ret)
+         return libsrt_neterrno(h);
+ 
+     while ((ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback))) {
+         switch (ret) {
+         case AVERROR(ETIMEDOUT):
+             continue;
+         default:
+             return ret;
+         }
+     }
+ 
+     ret = srt_accept(fd, NULL, NULL);
+     if (ret < 0)
+         return libsrt_neterrno(h);
+     if (libsrt_socket_nonblock(ret, 1) < 0)
+         av_log(h, AV_LOG_DEBUG, "libsrt_socket_nonblock failed\n");
+ 
+     return ret;
+ }
+ 
+ static int libsrt_listen_connect(int eid, int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next)
+ {
+     int ret;
+ 
+     if (libsrt_socket_nonblock(fd, 1) < 0)
+         av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
+ 
+     while ((ret = srt_connect(fd, addr, addrlen))) {
+         ret = libsrt_neterrno(h);
+         switch (ret) {
+         case AVERROR(EINTR):
+             if (ff_check_interrupt(&h->interrupt_callback))
+                 return AVERROR_EXIT;
+             continue;
+         case AVERROR(EINPROGRESS):
+         case AVERROR(EAGAIN):
+             ret = libsrt_network_wait_fd_timeout(h, eid, fd, 1, timeout, &h->interrupt_callback);
+             if (ret < 0)
+                 return ret;
+             ret = srt_getlasterror(NULL);
+             srt_clearlasterror();
+             if (ret != 0) {
+                 char buf[128];
+                 ret = AVERROR(ret);
+                 av_strerror(ret, buf, sizeof(buf));
+                 if (will_try_next)
+                     av_log(h, AV_LOG_WARNING,
+                            "Connection to %s failed (%s), trying next address\n",
+                            h->filename, buf);
+                 else
+                     av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
+                            h->filename, buf);
+             }
+         default:
+             return ret;
+         }
+     }
+     return ret;
+ }
+ 
+ static int libsrt_setsockopt(URLContext *h, int fd, SRT_SOCKOPT optname, const char * optnamestr, const void * optval, int optlen)
+ {
+     if (srt_setsockopt(fd, 0, optname, optval, optlen) < 0) {
+         av_log(h, AV_LOG_ERROR, "failed to set option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
+         return AVERROR(EIO);
+     }
+     return 0;
+ }
+ 
+ /* - The "POST" options can be altered any time on a connected socket.
+      They MAY have also some meaning when set prior to connecting; such
+      option is SRTO_RCVSYN, which makes connect/accept call asynchronous.
+      Because of that this option is treated special way in this app. */
+ static int libsrt_set_options_post(URLContext *h, int fd)
+ {
+     SRTContext *s = h->priv_data;
+ 
+     if ((s->inputbw >= 0 && libsrt_setsockopt(h, fd, SRTO_INPUTBW, "SRTO_INPUTBW", &s->inputbw, sizeof(s->inputbw)) < 0) ||
+         (s->oheadbw >= 0 && libsrt_setsockopt(h, fd, SRTO_OHEADBW, "SRTO_OHEADBW", &s->oheadbw, sizeof(s->oheadbw)) < 0)) {
+         return AVERROR(EIO);
+     }
+     return 0;
+ }
+ 
+ /* - The "PRE" options must be set prior to connecting and can't be altered
+      on a connected socket, however if set on a listening socket, they are
+      derived by accept-ed socket. */
+ static int libsrt_set_options_pre(URLContext *h, int fd)
+ {
+     SRTContext *s = h->priv_data;
+     int yes = 1;
+     int tsbpddelay = s->tsbpddelay / 1000;
+     int connect_timeout = s->connect_timeout;
+ 
+     if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) ||
+         (s->maxbw >= 0 && libsrt_setsockopt(h, fd, SRTO_MAXBW, "SRTO_MAXBW", &s->maxbw, sizeof(s->maxbw)) < 0) ||
+         (s->pbkeylen >= 0 && libsrt_setsockopt(h, fd, SRTO_PBKEYLEN, "SRTO_PBKEYLEN", &s->pbkeylen, sizeof(s->pbkeylen)) < 0) ||
+         (s->passphrase && libsrt_setsockopt(h, fd, SRTO_PASSPHRASE, "SRTO_PASSPHRASE", &s->passphrase, sizeof(s->passphrase)) < 0) ||
+         (s->mss >= 0 && libsrt_setsockopt(h, fd, SRTO_MSS, "SRTO_MMS", &s->mss, sizeof(s->mss)) < 0) ||
+         (s->ffs >= 0 && libsrt_setsockopt(h, fd, SRTO_FC, "SRTO_FC", &s->ffs, sizeof(s->ffs)) < 0) ||
+         (s->ipttl >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTTL, "SRTO_UPTTL", &s->ipttl, sizeof(s->ipttl)) < 0) ||
+         (s->iptos >= 0 && libsrt_setsockopt(h, fd, SRTO_IPTOS, "SRTO_IPTOS", &s->iptos, sizeof(s->iptos)) < 0) ||
+         (tsbpddelay >= 0 && libsrt_setsockopt(h, fd, SRTO_TSBPDDELAY, "SRTO_TSBPDELAY", &tsbpddelay, sizeof(tsbpddelay)) < 0) ||
+         (s->tlpktdrop >= 0 && libsrt_setsockopt(h, fd, SRTO_TLPKTDROP, "SRTO_TLPKDROP", &s->tlpktdrop, sizeof(s->tlpktdrop)) < 0) ||
+         (s->nakreport >= 0 && libsrt_setsockopt(h, fd, SRTO_NAKREPORT, "SRTO_NAKREPORT", &s->nakreport, sizeof(s->nakreport)) < 0) ||
+         (connect_timeout >= 0 && libsrt_setsockopt(h, fd, SRTO_CONNTIMEO, "SRTO_CONNTIMEO", &connect_timeout, sizeof(connect_timeout)) <0 )) {
+         return AVERROR(EIO);
+     }
+     return 0;
+ }
+ 
+ 
+ static int libsrt_setup(URLContext *h, const char *uri, int flags)
+ {
+     struct addrinfo hints = { 0 }, *ai, *cur_ai;
+     int port, fd = -1;
+     SRTContext *s = h->priv_data;
+     const char *p;
+     char buf[256];
+     int ret;
+     char hostname[1024],proto[1024],path[1024];
+     char portstr[10];
+     int open_timeout = 5000000;
+     int eid;
+ 
+     eid = srt_epoll_create();
+     if (eid < 0)
+         return libsrt_neterrno(h);
+     s->eid = eid;
+ 
+     av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
+         &port, path, sizeof(path), uri);
+     if (strcmp(proto, "srt"))
+         return AVERROR(EINVAL);
+     if (port <= 0 || port >= 65536) {
+         av_log(h, AV_LOG_ERROR, "Port missing in uri\n");
+         return AVERROR(EINVAL);
+     }
+     p = strchr(uri, '?');
+     if (p) {
+         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), "listen_timeout", p)) {
+             s->listen_timeout = strtol(buf, NULL, 10);
+         }
+     }
+     if (s->rw_timeout >= 0) {
+         open_timeout = h->rw_timeout = s->rw_timeout;
+     }
+     hints.ai_family = AF_UNSPEC;
+     hints.ai_socktype = SOCK_DGRAM;
+     snprintf(portstr, sizeof(portstr), "%d", port);
+     if (s->mode == SRT_MODE_LISTENER)
+         hints.ai_flags |= AI_PASSIVE;
+     ret = getaddrinfo(hostname[0] ? hostname : NULL, portstr, &hints, &ai);
+     if (ret) {
+         av_log(h, AV_LOG_ERROR,
+                "Failed to resolve hostname %s: %s\n",
+                hostname, gai_strerror(ret));
+         return AVERROR(EIO);
+     }
+ 
+     cur_ai = ai;
+ 
+  restart:
+ 
+     fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0);
+     if (fd < 0) {
+         ret = libsrt_neterrno(h);
+         goto fail;
+     }
+ 
+     if ((ret = libsrt_set_options_pre(h, fd)) < 0) {
+         goto fail;
+     }
+ 
+     /* Set the socket's send or receive buffer sizes, if specified.
+        If unspecified or setting fails, system default is used. */
+     if (s->recv_buffer_size > 0) {
+         srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size));
+     }
+     if (s->send_buffer_size > 0) {
+         srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size));
+     }
+     if (s->mode == SRT_MODE_LISTENER) {
+         // multi-client
+         if ((ret = libsrt_listen(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h, open_timeout / 1000)) < 0)
+             goto fail1;
+         fd = ret;
+     } else {
+         if (s->mode == SRT_MODE_RENDEZVOUS) {
+             ret = srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
+             if (ret)
+                 goto fail1;
+         }
+ 
+         if ((ret = libsrt_listen_connect(s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
+                                           open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) {
+             if (ret == AVERROR_EXIT)
+                 goto fail1;
+             else
+                 goto fail;
+         }
+     }
+     if ((ret = libsrt_set_options_post(h, fd)) < 0) {
+         goto fail;
+     }
+ 
+     h->is_streamed = 1;
+     s->fd = fd;
+ 
+     freeaddrinfo(ai);
+     return 0;
+ 
+  fail:
+     if (cur_ai->ai_next) {
+         /* Retry with the next sockaddr */
+         cur_ai = cur_ai->ai_next;
+         if (fd >= 0)
+             srt_close(fd);
+         ret = 0;
+         goto restart;
+     }
+  fail1:
+     if (fd >= 0)
+         srt_close(fd);
+     freeaddrinfo(ai);
+     return ret;
+ }
+ 
+ static int libsrt_open(URLContext *h, const char *uri, int flags)
+ {
+     SRTContext *s = h->priv_data;
+     const char * p;
+     char buf[256];
+ 
+     if (srt_startup() < 0) {
+         return AVERROR_UNKNOWN;
+     }
+ 
+     /* SRT options (srt/srt.h) */
+     p = strchr(uri, '?');
+     if (p) {
+         if (av_find_info_tag(buf, sizeof(buf), "maxbw", p)) {
+             s->maxbw = strtoll(buf, NULL, 0);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "pbkeylen", p)) {
+             s->pbkeylen = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "passphrase", p)) {
+             s->passphrase = av_strndup(buf, strlen(buf));
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "mss", p)) {
+             s->mss = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "ffs", p)) {
+             s->ffs = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "ipttl", p)) {
+             s->ipttl = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "iptos", p)) {
+             s->iptos = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "inputbw", p)) {
+             s->inputbw = strtoll(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "oheadbw", p)) {
+             s->oheadbw = strtoll(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "tsbpddelay", p)) {
+             s->tsbpddelay = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "tlpktdrop", p)) {
+             s->tlpktdrop = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "nakreport", p)) {
+             s->nakreport = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "connect_timeout", p)) {
+             s->connect_timeout = strtol(buf, NULL, 10);
+         }
+         if (av_find_info_tag(buf, sizeof(buf), "mode", p)) {
+             if (!strcmp(buf, "caller")) {
+                 s->mode = SRT_MODE_CALLER;
+             } else if (!strcmp(buf, "listener")) {
+                 s->mode = SRT_MODE_LISTENER;
+             } else if (!strcmp(buf, "rendezvous")) {
+                 s->mode = SRT_MODE_RENDEZVOUS;
+             } else {
+                 return AVERROR(EIO);
+             }
+         }
+     }
+     return libsrt_setup(h, uri, flags);
+ }
+ 
+ static int libsrt_read(URLContext *h, uint8_t *buf, int size)
+ {
+     SRTContext *s = h->priv_data;
+     int ret;
+ 
+     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
+         ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 0, h->rw_timeout, &h->interrupt_callback);
+         if (ret)
+             return ret;
+     }
+ 
+     ret = srt_recvmsg(s->fd, buf, size);
+     if (ret < 0) {
+         ret = libsrt_neterrno(h);
+     }
+ 
+     return ret;
+ }
+ 
+ static int libsrt_write(URLContext *h, const uint8_t *buf, int size)
+ {
+     SRTContext *s = h->priv_data;
+     int ret;
+ 
+     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
+         ret = libsrt_network_wait_fd_timeout(h, s->eid, s->fd, 1, h->rw_timeout, &h->interrupt_callback);
+         if (ret)
+             return ret;
+     }
+ 
+     ret = srt_sendmsg(s->fd, buf, size, -1, 0);
+     if (ret < 0) {
+         ret = libsrt_neterrno(h);
+     }
+ 
+     return ret;
+ }
+ 
+ static int libsrt_close(URLContext *h)
+ {
+     SRTContext *s = h->priv_data;
+ 
+     srt_close(s->fd);
+ 
+     srt_epoll_release(s->eid);
+ 
+     srt_cleanup();
+ 
+     return 0;
+ }
+ 
+ static int libsrt_get_file_handle(URLContext *h)
+ {
+     SRTContext *s = h->priv_data;
+     return s->fd;
+ }
+ 
+ static const AVClass libsrt_class = {
+     .class_name = "libsrt",
+     .item_name  = av_default_item_name,
+     .option     = libsrt_options,
+     .version    = LIBAVUTIL_VERSION_INT,
+ };
+ 
+ const URLProtocol ff_libsrt_protocol = {
+     .name                = "srt",
+     .url_open            = libsrt_open,
+     .url_read            = libsrt_read,
+     .url_write           = libsrt_write,
+     .url_close           = libsrt_close,
+     .url_get_file_handle = libsrt_get_file_handle,
+     .priv_data_size      = sizeof(SRTContext),
+     .flags               = URL_PROTOCOL_FLAG_NETWORK,
+     .priv_data_class     = &libsrt_class,
+ };
diff --cc libavformat/protocols.c
index 669d74d5a8,15b9ed736d..ad95659795
--- a/libavformat/protocols.c
+++ b/libavformat/protocols.c
@@@ -65,8 -56,7 +65,9 @@@ extern const URLProtocol ff_librtmpe_pr
  extern const URLProtocol ff_librtmps_protocol;
  extern const URLProtocol ff_librtmpt_protocol;
  extern const URLProtocol ff_librtmpte_protocol;
+ extern const URLProtocol ff_libsrt_protocol;
 +extern const URLProtocol ff_libssh_protocol;
 +extern const URLProtocol ff_libsmbclient_protocol;
  
  #include "libavformat/protocol_list.c"
  



More information about the ffmpeg-cvslog mailing list