[FFmpeg-devel] [PATCH] cache: read_buf_size

Robert Nagy ronag89 at gmail.com
Sat Sep 22 13:16:10 EEST 2018


This adds a `read_buf_size` option which can help avoid excessive seeking
when a file has e.g. badly interleaved audio and video.


---

 libavformat/cache.c | 69 +++++++++++++++++++++++++++++++++++++--------

 1 file changed, 57 insertions(+), 12 deletions(-)


diff --git a/libavformat/cache.c b/libavformat/cache.c

index 66bbbf54c9..d2fd467032 100644

--- a/libavformat/cache.c

+++ b/libavformat/cache.c

@@ -63,6 +63,8 @@ typedef struct Context {

     URLContext *inner;

     int64_t cache_hit, cache_miss;

     int read_ahead_limit;

+    int read_buf_size;

+    unsigned char* read_buf;

 } Context;



 static int cmp(const void *key, const void *node)

@@ -86,6 +88,8 @@ static int cache_open(URLContext *h, const char *arg, int
flags, AVDictionary **

     unlink(buffername);

     av_freep(&buffername);



+    c->read_buf = av_mallocz(c->read_buf_size);

+

     return ffurl_open_whitelist(&c->inner, arg, flags,
&h->interrupt_callback,

                                 options, h->protocol_whitelist,
h->protocol_blacklist, h);

 }

@@ -158,6 +162,12 @@ static int cache_read(URLContext *h, unsigned char
*buf, int size)

     Context *c= h->priv_data;

     CacheEntry *entry, *next[2] = {NULL, NULL};

     int64_t r;

+    int read_size, read_pos;

+    unsigned char* read_buf;

+

+    if (!buf) {

+        buf = c->read_buf;

+    }



     entry = av_tree_find(c->root, &c->logical_pos, cmp, (void**)next);



@@ -200,18 +210,52 @@ static int cache_read(URLContext *h, unsigned char
*buf, int size)

         c->inner_pos = r;

     }



-    r = ffurl_read(c->inner, buf, size);

-    if (r == AVERROR_EOF && size>0) {

-        c->is_true_eof = 1;

-        av_assert0(c->end >= c->logical_pos);

+    read_size = c->read_buf_size;

+    read_buf = c->read_buf;

+

+    if (size >= read_size) {

+        read_size = size;

+        read_buf = buf;

     }

-    if (r<=0)

+

+    read_pos = 0;

+    do {

+        r = ffurl_read(c->inner, read_buf + read_pos, read_size -
read_pos);

+

+        if (r == AVERROR_EOF) {

+            c->is_true_eof = 1;

+            av_assert0(c->end >= c->logical_pos);

+            break;

+        }

+

+        if (r == 0 || r == AVERROR(EAGAIN)) {

+            break;

+        }

+

+        if (r < 0) {

+            return r;

+        }

+

+        c->inner_pos += r;

+        read_pos += r;

+    } while (read_pos < read_size);

+

+    if (read_pos == 0) {

         return r;

-    c->inner_pos += r;

+    }



-    c->cache_miss ++;

+    r = read_pos;

+

+    c->cache_miss++;

+

+    add_entry(h, read_buf, r);

+

+    r = FFMIN(r, size);

+

+    if (read_buf != buf) {

+        memcpy(buf, read_buf, r);

+    }



-    add_entry(h, buf, r);

     c->logical_pos += r;

     c->end = FFMAX(c->end, c->logical_pos);



@@ -257,12 +301,11 @@ resolve_eof:

          whence == SEEK_END && pos <= 0) && ret < 0) {

         if (   (whence == SEEK_SET && c->read_ahead_limit >= pos -
c->logical_pos)

             || c->read_ahead_limit < 0) {

-            uint8_t tmp[32768];

             while (c->logical_pos < pos || whence == SEEK_END) {

-                int size = sizeof(tmp);

+                int size = c->read_buf_size;

                 if (whence == SEEK_SET)

-                    size = FFMIN(sizeof(tmp), pos - c->logical_pos);

-                ret = cache_read(h, tmp, size);

+                    size = FFMIN(c->read_buf_size, pos - c->logical_pos);

+                ret = cache_read(h, NULL, size);

                 if (ret == AVERROR_EOF && whence == SEEK_END) {

                     av_assert0(c->is_true_eof);

                     goto resolve_eof;

@@ -300,6 +343,7 @@ static int cache_close(URLContext *h)

     ffurl_close(c->inner);

     av_tree_enumerate(c->root, NULL, NULL, enu_free);

     av_tree_destroy(c->root);

+    av_free(c->read_buf);



     return 0;

 }

@@ -309,6 +353,7 @@ static int cache_close(URLContext *h)



 static const AVOption options[] = {

     { "read_ahead_limit", "Amount in bytes that may be read ahead when
seeking isn't supported, -1 for unlimited", OFFSET(read_ahead_limit),
AV_OPT_TYPE_INT, { .i64 = 65536 }, -1, INT_MAX, D },

+    { "read_buf_size", "Lowest amount of bytes that may be read at a
time.", OFFSET(read_buf_size), AV_OPT_TYPE_INT, { .i64 = 65536 }, -1,
INT_MAX, D },

     {NULL},

 };



-- 

2.18.0


More information about the ffmpeg-devel mailing list