[FFmpeg-devel] [PATCH] avformat/file: fd, pipe and file input/output now honor rw_timeout
Davy Durham
ddurham at davyandbeth.com
Fri Mar 17 08:32:11 EET 2023
File descriptors, pipes or even filenames (that may be fifos or
reference other non-regular files) may have upstream or downstream
processess that stall out just like any network channel. Hence ffmpeg
should respect -rw_timeout for these types too. This is necessary
when, for example, input from a pipe has stalled and we want ffmpeg
to timeout in order to have a pipeline tear down.
---
doc/protocols.texi | 4 ++--
libavformat/file.c | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/doc/protocols.texi b/doc/protocols.texi
index 21ae6181a0..d75521ced2 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -45,8 +45,8 @@ All protocols accept the following options:
@table @option
@item rw_timeout
-Maximum time to wait for (network) read/write operations to complete,
-in microseconds.
+Maximum time to wait for (network, file, fd, and pipe) read/write
operations
+to complete, in microseconds.
@end table
A description of the currently available protocols follows.
diff --git a/libavformat/file.c b/libavformat/file.c
index cbdf48de0a..fc1d15a672 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -40,6 +40,7 @@
#include <stdlib.h>
#include "os_support.h"
#include "url.h"
+#include "network.h"
/* Some systems may not have S_ISFIFO */
#ifndef S_ISFIFO
@@ -140,6 +141,11 @@ static int file_read(URLContext *h, unsigned char
*buf, int size)
FileContext *c = h->priv_data;
int ret;
size = FFMIN(size, c->blocksize);
+ if (h->rw_timeout > 0) { /* wait for something, anything to read */
+ ret = ff_network_wait_fd_timeout(c->fd, 0, h->rw_timeout, NULL);
+ if (ret)
+ return ret;
+ }
ret = read(c->fd, buf, size);
if (ret == 0 && c->follow)
return AVERROR(EAGAIN);
@@ -152,6 +158,11 @@ static int file_write(URLContext *h, const unsigned
char *buf, int size)
{
FileContext *c = h->priv_data;
int ret;
+ if (h->rw_timeout > 0) { /* wait for something, anything to read */
+ ret = ff_network_wait_fd_timeout(c->fd, 1, h->rw_timeout, NULL);
+ if (ret)
+ return ret;
+ }
size = FFMIN(size, c->blocksize);
ret = write(c->fd, buf, size);
return (ret == -1) ? AVERROR(errno) : ret;
@@ -304,6 +315,9 @@ static int file_open(URLContext *h, const char
*filename, int flags)
if (fd == -1)
return AVERROR(errno);
c->fd = fd;
+ if (h->rw_timeout > 0) { /* if we'll be doing reads w/ timeout,
mark non-blocking */
+ fcntl(c->fd, F_SETFL, fcntl(c->fd, F_GETFL, 0) | O_NONBLOCK);
+ }
h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);
@@ -448,6 +462,9 @@ static int pipe_open(URLContext *h, const char
*filename, int flags)
c->fd = fd_dup(h, c->fd);
if (c->fd == -1)
return AVERROR(errno);
+ if (h->rw_timeout > 0) { /* if we'll be doing reads w/ timeout,
mark non-blocking */
+ fcntl(c->fd, F_SETFL, fcntl(c->fd, F_GETFL, 0) | O_NONBLOCK);
+ }
h->is_streamed = 1;
return 0;
}
@@ -493,6 +510,9 @@ static int fd_open(URLContext *h, const char
*filename, int flags)
c->fd = fd_dup(h, c->fd);
if (c->fd == -1)
return AVERROR(errno);
+ if (h->rw_timeout > 0) { /* if we'll be doing reads w/ timeout,
mark non-blocking */
+ fcntl(c->fd, F_SETFL, fcntl(c->fd, F_GETFL, 0) | O_NONBLOCK);
+ }
return 0;
}
--
2.25.1
More information about the ffmpeg-devel
mailing list