38 #ifndef SRT_LIVE_DEFAULT_PAYLOAD_SIZE
39 #define SRT_LIVE_DEFAULT_PAYLOAD_SIZE 1316
43 #ifndef SRT_LIVE_MAX_PAYLOAD_SIZE
44 #define SRT_LIVE_MAX_PAYLOAD_SIZE 1456
89 #define D AV_OPT_FLAG_DECODING_PARAM
90 #define E AV_OPT_FLAG_ENCODING_PARAM
91 #define OFFSET(x) offsetof(SRTContext, x)
93 {
"rw_timeout",
"Timeout of socket I/O operations",
OFFSET(rw_timeout),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
94 {
"listen_timeout",
"Connection awaiting timeout",
OFFSET(listen_timeout),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
95 {
"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 },
96 {
"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 },
101 {
"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 },
102 {
"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 },
103 {
"passphrase",
"Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto",
OFFSET(passphrase),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
105 {
"ffs",
"Flight flag size (window size) (in bytes)",
OFFSET(ffs),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
108 {
"inputbw",
"Estimated input stream rate",
OFFSET(inputbw),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
109 {
"oheadbw",
"MaxBW ceiling based on % over input stream rate",
OFFSET(oheadbw),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, .flags =
D|
E },
110 {
"latency",
"receiver delay to absorb bursts of missed packet retransmissions",
OFFSET(latency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
111 {
"tsbpddelay",
"deprecated, same effect as latency option",
OFFSET(latency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
114 {
"tlpktdrop",
"Enable receiver pkt drop",
OFFSET(tlpktdrop),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags =
D|
E },
115 {
"nakreport",
"Enable receiver to send periodic NAK reports",
OFFSET(nakreport),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags =
D|
E },
116 {
"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 },
117 {
"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" },
121 {
"sndbuf",
"Send buffer size (in bytes)",
OFFSET(sndbuf),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
122 {
"rcvbuf",
"Receive buffer size (in bytes)",
OFFSET(rcvbuf),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
123 {
"lossmaxttl",
"Maximum possible packet reorder tolerance",
OFFSET(lossmaxttl),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
124 {
"minversion",
"The minimum SRT version that is required from the peer",
OFFSET(minversion),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
125 {
"streamid",
"A string of up to 512 characters that an Initiator can pass to a Responder",
OFFSET(streamid),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
126 {
"smoother",
"The type of Smoother used for the transmission for that socket",
OFFSET(smoother),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
127 {
"messageapi",
"Enable message API",
OFFSET(messageapi),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, .flags =
D|
E },
128 {
"transtype",
"The transmission type for the socket",
OFFSET(transtype),
AV_OPT_TYPE_INT, { .i64 = SRTT_INVALID }, SRTT_LIVE, SRTT_INVALID, .flags =
D|
E,
"transtype" },
136 int err = srt_getlasterror(
NULL);
138 if (err == SRT_EASYNCRCV)
145 int ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &enable,
sizeof(enable));
148 return srt_setsockopt(socket, 0, SRTO_RCVSYN, &enable,
sizeof(enable));
154 int modes = write ? SRT_EPOLL_OUT : SRT_EPOLL_IN;
157 if (srt_epoll_add_usock(eid, fd, &
modes) < 0)
165 if (srt_getlasterror(
NULL) == SRT_ETIMEOUT)
172 if (srt_epoll_remove_usock(eid, fd) < 0)
182 int64_t wait_start = 0;
203 if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse,
sizeof(reuse))) {
206 ret = srt_bind(fd, addr, addrlen);
210 ret = srt_listen(fd, 1);
239 while ((
ret = srt_connect(fd, addr, addrlen))) {
252 srt_clearlasterror();
259 "Connection to %s failed (%s), trying next address\n",
274 if (srt_setsockopt(fd, 0, optname, optval, optlen) < 0) {
275 av_log(
h,
AV_LOG_ERROR,
"failed to set option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
283 if (srt_getsockopt(fd, 0, optname, optval, optlen) < 0) {
284 av_log(
h,
AV_LOG_ERROR,
"failed to get option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
298 if ((
s->inputbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_INPUTBW,
"SRTO_INPUTBW", &
s->inputbw,
sizeof(
s->inputbw)) < 0) ||
299 (
s->oheadbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_OHEADBW,
"SRTO_OHEADBW", &
s->oheadbw,
sizeof(
s->oheadbw)) < 0)) {
312 int latency =
s->latency / 1000;
313 int rcvlatency =
s->rcvlatency / 1000;
314 int peerlatency =
s->peerlatency / 1000;
315 int connect_timeout =
s->connect_timeout;
318 (
s->transtype != SRTT_INVALID &&
libsrt_setsockopt(
h, fd, SRTO_TRANSTYPE,
"SRTO_TRANSTYPE", &
s->transtype,
sizeof(
s->transtype)) < 0) ||
319 (
s->maxbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MAXBW,
"SRTO_MAXBW", &
s->maxbw,
sizeof(
s->maxbw)) < 0) ||
320 (
s->pbkeylen >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PBKEYLEN,
"SRTO_PBKEYLEN", &
s->pbkeylen,
sizeof(
s->pbkeylen)) < 0) ||
321 (
s->passphrase &&
libsrt_setsockopt(
h, fd, SRTO_PASSPHRASE,
"SRTO_PASSPHRASE",
s->passphrase, strlen(
s->passphrase)) < 0) ||
324 (
s->ipttl >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_IPTTL,
"SRTO_UPTTL", &
s->ipttl,
sizeof(
s->ipttl)) < 0) ||
325 (
s->iptos >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_IPTOS,
"SRTO_IPTOS", &
s->iptos,
sizeof(
s->iptos)) < 0) ||
326 (
s->latency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_LATENCY,
"SRTO_LATENCY", &latency,
sizeof(latency)) < 0) ||
327 (
s->rcvlatency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_RCVLATENCY,
"SRTO_RCVLATENCY", &rcvlatency,
sizeof(rcvlatency)) < 0) ||
328 (
s->peerlatency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PEERLATENCY,
"SRTO_PEERLATENCY", &peerlatency,
sizeof(peerlatency)) < 0) ||
329 (
s->tlpktdrop >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_TLPKTDROP,
"SRTO_TLPKDROP", &
s->tlpktdrop,
sizeof(
s->tlpktdrop)) < 0) ||
330 (
s->nakreport >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_NAKREPORT,
"SRTO_NAKREPORT", &
s->nakreport,
sizeof(
s->nakreport)) < 0) ||
331 (connect_timeout >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_CONNTIMEO,
"SRTO_CONNTIMEO", &connect_timeout,
sizeof(connect_timeout)) <0 ) ||
332 (
s->sndbuf >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_SNDBUF,
"SRTO_SNDBUF", &
s->sndbuf,
sizeof(
s->sndbuf)) < 0) ||
333 (
s->rcvbuf >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_RCVBUF,
"SRTO_RCVBUF", &
s->rcvbuf,
sizeof(
s->rcvbuf)) < 0) ||
334 (
s->lossmaxttl >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_LOSSMAXTTL,
"SRTO_LOSSMAXTTL", &
s->lossmaxttl,
sizeof(
s->lossmaxttl)) < 0) ||
335 (
s->minversion >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MINVERSION,
"SRTO_MINVERSION", &
s->minversion,
sizeof(
s->minversion)) < 0) ||
336 (
s->streamid &&
libsrt_setsockopt(
h, fd, SRTO_STREAMID,
"SRTO_STREAMID",
s->streamid, strlen(
s->streamid)) < 0) ||
337 (
s->smoother &&
libsrt_setsockopt(
h, fd, SRTO_SMOOTHER,
"SRTO_SMOOTHER",
s->smoother, strlen(
s->smoother)) < 0) ||
338 (
s->messageapi >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MESSAGEAPI,
"SRTO_MESSAGEAPI", &
s->messageapi,
sizeof(
s->messageapi)) < 0) ||
339 (
s->payload_size >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PAYLOADSIZE,
"SRTO_PAYLOADSIZE", &
s->payload_size,
sizeof(
s->payload_size)) < 0) ||
349 struct addrinfo hints = { 0 }, *ai, *cur_ai;
355 char hostname[1024],proto[1024],path[1024];
357 int open_timeout = 5000000;
360 eid = srt_epoll_create();
366 &port, path,
sizeof(path), uri);
367 if (strcmp(proto,
"srt"))
369 if (port <= 0 || port >= 65536) {
373 p = strchr(uri,
'?');
376 s->rw_timeout = strtol(
buf,
NULL, 10);
379 s->listen_timeout = strtol(
buf,
NULL, 10);
382 if (
s->rw_timeout >= 0) {
383 open_timeout =
h->rw_timeout =
s->rw_timeout;
387 snprintf(portstr,
sizeof(portstr),
"%d", port);
393 "Failed to resolve hostname %s: %s\n",
402 fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0);
414 if (
s->recv_buffer_size > 0) {
415 srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_RCVBUF, &
s->recv_buffer_size, sizeof (
s->recv_buffer_size));
417 if (
s->send_buffer_size > 0) {
418 srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &
s->send_buffer_size, sizeof (
s->send_buffer_size));
422 if ((
ret =
libsrt_listen(
s->eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
h, open_timeout / 1000)) < 0)
427 ret = srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
433 open_timeout / 1000,
h, !!cur_ai->ai_next)) < 0) {
446 int optlen =
sizeof(packet_size);
451 h->max_packet_size = packet_size;
461 if (cur_ai->ai_next) {
463 cur_ai = cur_ai->ai_next;
482 if (srt_startup() < 0) {
487 p = strchr(uri,
'?');
493 s->pbkeylen = strtol(
buf,
NULL, 10);
511 s->inputbw = strtoll(
buf,
NULL, 10);
514 s->oheadbw = strtoll(
buf,
NULL, 10);
523 s->rcvlatency = strtol(
buf,
NULL, 10);
526 s->peerlatency = strtol(
buf,
NULL, 10);
529 s->tlpktdrop = strtol(
buf,
NULL, 10);
532 s->nakreport = strtol(
buf,
NULL, 10);
535 s->connect_timeout = strtol(
buf,
NULL, 10);
539 s->payload_size = strtol(
buf,
NULL, 10);
542 if (!strcmp(
buf,
"caller")) {
544 }
else if (!strcmp(
buf,
"listener")) {
546 }
else if (!strcmp(
buf,
"rendezvous")) {
559 s->lossmaxttl = strtol(
buf,
NULL, 10);
562 s->minversion = strtol(
buf,
NULL, 0);
573 s->messageapi = strtol(
buf,
NULL, 10);
576 if (!strcmp(
buf,
"live")) {
577 s->transtype = SRTT_LIVE;
578 }
else if (!strcmp(
buf,
"file")) {
579 s->transtype = SRTT_FILE;
632 srt_epoll_release(
s->eid);