[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