This way is possible to have simple micro-server act like
ffmpeg -i file.nut -vcodec copy -acodec copy -f nut tcp://foo:1234?listen
... | ... |
@@ -402,6 +402,23 @@ ffplay sap://[ff0e::2:7ffe] |
402 | 402 |
|
403 | 403 |
Trasmission Control Protocol. |
404 | 404 |
|
405 |
+The required syntax for a TCP url is: |
|
406 |
+@example |
|
407 |
+tcp://@var{hostname}:@var{port}[?@var{options}] |
|
408 |
+@end example |
|
409 |
+ |
|
410 |
+@table @option |
|
411 |
+ |
|
412 |
+@item listen |
|
413 |
+Listen for an incoming connection |
|
414 |
+ |
|
415 |
+@example |
|
416 |
+ffmpeg -i @var{input} -f @var{format} tcp://@var{hostname}:@var{port}?listen |
|
417 |
+ffplay tcp://@var{hostname}:@var{port} |
|
418 |
+@end example |
|
419 |
+ |
|
420 |
+@end table |
|
421 |
+ |
|
405 | 422 |
@section udp |
406 | 423 |
|
407 | 424 |
User Datagram Protocol. |
... | ... |
@@ -19,6 +19,7 @@ |
19 | 19 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | 20 |
*/ |
21 | 21 |
#include "avformat.h" |
22 |
+#include "libavutil/parseutils.h" |
|
22 | 23 |
#include <unistd.h> |
23 | 24 |
#include "internal.h" |
24 | 25 |
#include "network.h" |
... | ... |
@@ -38,6 +39,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
38 | 38 |
struct addrinfo hints, *ai, *cur_ai; |
39 | 39 |
int port, fd = -1; |
40 | 40 |
TCPContext *s = NULL; |
41 |
+ int listen_socket = 0; |
|
42 |
+ const char *p; |
|
43 |
+ char buf[256]; |
|
41 | 44 |
int ret; |
42 | 45 |
socklen_t optlen; |
43 | 46 |
char hostname[1024],proto[1024],path[1024]; |
... | ... |
@@ -48,6 +52,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
48 | 48 |
if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) |
49 | 49 |
return AVERROR(EINVAL); |
50 | 50 |
|
51 |
+ p = strchr(uri, '?'); |
|
52 |
+ if (p) { |
|
53 |
+ if (av_find_info_tag(buf, sizeof(buf), "listen", p)) |
|
54 |
+ listen_socket = 1; |
|
55 |
+ } |
|
51 | 56 |
memset(&hints, 0, sizeof(hints)); |
52 | 57 |
hints.ai_family = AF_UNSPEC; |
53 | 58 |
hints.ai_socktype = SOCK_STREAM; |
... | ... |
@@ -66,10 +75,21 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
66 | 66 |
fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); |
67 | 67 |
if (fd < 0) |
68 | 68 |
goto fail; |
69 |
- ff_socket_nonblock(fd, 1); |
|
70 | 69 |
|
70 |
+ if (listen_socket) { |
|
71 |
+ int fd1; |
|
72 |
+ ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
|
73 |
+ listen(fd, 1); |
|
74 |
+ fd1 = accept(fd, NULL, NULL); |
|
75 |
+ closesocket(fd); |
|
76 |
+ fd = fd1; |
|
77 |
+ } else { |
|
71 | 78 |
redo: |
72 |
- ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
|
79 |
+ ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ ff_socket_nonblock(fd, 1); |
|
83 |
+ |
|
73 | 84 |
if (ret < 0) { |
74 | 85 |
struct pollfd p = {fd, POLLOUT, 0}; |
75 | 86 |
if (ff_neterrno() == AVERROR(EINTR)) { |