this allows to implement other protocols which use
API similar to BSD sockets (e.g. Haivision SRT)
Signed-off-by: Nablet Developer
---
libavformat/tcp.c | 118 +++---
libavformat/tcp.h | 59 +++
2 files changed, 119 insertions(+), 58 deletions(-)
create mode 100644 libavformat/tcp.h
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 07b4ed9..a775230 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -32,26 +32,12 @@
#include
#endif
-typedef struct TCPContext {
-const AVClass *class;
-int fd;
-int listen;
-int open_timeout;
-int rw_timeout;
-int listen_timeout;
-int recv_buffer_size;
-int send_buffer_size;
-} TCPContext;
-
-#define OFFSET(x) offsetof(TCPContext, x)
+#include "tcp.h"
+
#define D AV_OPT_FLAG_DECODING_PARAM
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
-{ "listen", "Listen for incoming connections", OFFSET(listen),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, .flags = D|E },
-{ "timeout", "set timeout (in microseconds) of socket I/O operations",
OFFSET(rw_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX,
.flags = D|E },
-{ "listen_timeout", "Connection awaiting timeout (in milliseconds)",
OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_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 },
+TCP_COMMON_OPTS
{ NULL }
};
@@ -63,7 +49,7 @@ static const AVClass tcp_class = {
};
/* return non zero if error */
-static int tcp_open(URLContext *h, const char *uri, int flags)
+int ff_tcp_open(URLContext *h, const char *uri, int flags)
{
struct addrinfo hints = { 0 }, *ai, *cur_ai;
int port, fd = -1;
@@ -75,10 +61,15 @@ static int tcp_open(URLContext *h, const char *uri, int
flags)
char portstr[10];
s->open_timeout = 500;
+s->api = s->api ? s->api : _socket_api;
+s->proto = s->proto ? s->proto : "tcp";
+
av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname),
, path, sizeof(path), uri);
-if (strcmp(proto, "tcp"))
+if (strcmp(proto, s->proto)) {
+av_log(h, AV_LOG_ERROR, "incorrect protocol %s %s\n", proto, s->proto);
return AVERROR(EINVAL);
+}
if (port <= 0 || port >= 65536) {
av_log(h, AV_LOG_ERROR, "Port missing in uri\n");
return AVERROR(EINVAL);
@@ -132,37 +123,42 @@ static int tcp_open(URLContext *h, const char *uri, int
flags)
}
#endif
-fd = ff_socket(cur_ai->ai_family,
- cur_ai->ai_socktype,
- cur_ai->ai_protocol);
+fd = s->api->socket(cur_ai->ai_family,
+cur_ai->ai_socktype,
+cur_ai->ai_protocol);
if (fd < 0) {
-ret = ff_neterrno();
+ret = s->api->neterrno();
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) {
-setsockopt (fd, SOL_SOCKET, SO_RCVBUF, >recv_buffer_size, sizeof
(s->recv_buffer_size));
+s->api->setsockopt (fd, SOL_SOCKET, SO_RCVBUF, >recv_buffer_size,
sizeof (s->recv_buffer_size));
}
if (s->send_buffer_size > 0) {
-setsockopt (fd, SOL_SOCKET, SO_SNDBUF, >send_buffer_size, sizeof
(s->send_buffer_size));
+s->api->setsockopt (fd, SOL_SOCKET, SO_SNDBUF, >send_buffer_size,
sizeof (s->send_buffer_size));
+}
+
+if (s->set_options_pre) {
+if ((ret = s->set_options_pre(h, fd)) < 0)
+goto fail1;
}
if (s->listen == 2) {
// multi-client
-if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0)
+if ((ret = ff_listen_ex(s->api, fd, cur_ai->ai_addr,
cur_ai->ai_addrlen)) < 0)
goto fail1;
} else if (s->listen == 1) {
// single client
-if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
- s->listen_timeout, h)) < 0)
+if ((ret = ff_listen_bind_ex(s->api, fd, cur_ai->ai_addr,
cur_ai->ai_addrlen,
+ s->listen_timeout, h)) < 0)
goto fail1;
// Socket descriptor already closed here. Safe to overwrite to client
one.
fd = ret;
} else {
-if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
- s->open_timeout / 1000, h,
!!cur_ai->ai_next)) < 0) {
+if ((ret = ff_listen_connect_ex(s->api,