[FFmpeg-devel] [PATCH 1/2] file: operate in blocks, check for interrupts

Andrey Utkin andrey.krieger.utkin at gmail.com
Sun Jul 7 19:56:35 CEST 2013


Interruptibility of file operations is strongly desirable in case of
slow storage access, e.g. mounted network share.
Note that file I/O operation still may block (or even freeze) inside of
single read(2) or write(2) operation. There is no API for
asynchronous file I/O, but hopefully it will appear in future.
---
 libavformat/file.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/libavformat/file.c b/libavformat/file.c
index e09a64b..640fbdd 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -49,10 +49,12 @@ typedef struct FileContext {
     const AVClass *class;
     int fd;
     int trunc;
+    int blocksize;
 } FileContext;
 
 static const AVOption file_options[] = {
     { "truncate", "Truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
+    { "blocksize", "set I/O operation block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = 4*1024 }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
     { NULL }
 };
 
@@ -66,15 +68,41 @@ static const AVClass file_class = {
 static int file_read(URLContext *h, unsigned char *buf, int size)
 {
     FileContext *c = h->priv_data;
-    int r = read(c->fd, buf, size);
-    return (-1 == r)?AVERROR(errno):r;
+    int to_read = size;
+    int blocksize;
+    int r;
+    while (to_read) {
+      if (ff_check_interrupt(&h->interrupt_callback))
+        return AVERROR_EXIT;
+      blocksize = (c->blocksize < size) ? c->blocksize : size;
+      r = read(c->fd, buf, blocksize);
+      if (r == -1)
+        return AVERROR(errno);
+      if (r == 0)
+        return AVERROR_EOF;
+      to_read -= r;
+    }
+    return size;
 }
 
 static int file_write(URLContext *h, const unsigned char *buf, int size)
 {
     FileContext *c = h->priv_data;
-    int r = write(c->fd, buf, size);
-    return (-1 == r)?AVERROR(errno):r;
+    int to_write = size;
+    int blocksize;
+    int r;
+    while (to_write) {
+      if (ff_check_interrupt(&h->interrupt_callback))
+        return AVERROR_EXIT;
+      blocksize = (c->blocksize < size) ? c->blocksize : size;
+      r = write(c->fd, buf, blocksize);
+      if (r == -1)
+        return AVERROR(errno);
+      if (r == 0)
+        return AVERROR_EOF;
+      to_write -= r;
+    }
+    return size;
 }
 
 static int file_get_handle(URLContext *h)
-- 
1.8.1.5



More information about the ffmpeg-devel mailing list