diff options
author | Anton Khirnov <anton@khirnov.net> | 2022-01-06 16:32:49 +0100 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@outlook.com> | 2022-02-07 00:31:23 +0100 |
commit | 14429f8fec231e1d6e0bfdb3f646e7461d11c736 (patch) | |
tree | 2b92f07a243b9e554346c5e8eae1f1ea53f8bad2 /libavutil | |
parent | 7329b22c058cf271e9ea3aa6e8ab2bb1c462d99f (diff) | |
download | ffmpeg-14429f8fec231e1d6e0bfdb3f646e7461d11c736.tar.gz |
lavu/fifo: add a flag for automatically growing the FIFO as needed
This will not increase the FIFO beyond 1MB, unless the caller explicitly
specifies otherwise.
Diffstat (limited to 'libavutil')
-rw-r--r-- | libavutil/fifo.c | 39 | ||||
-rw-r--r-- | libavutil/fifo.h | 15 |
2 files changed, 51 insertions, 3 deletions
diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 0001ccbd43..4137ae2fd9 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -26,6 +26,9 @@ #include "common.h" #include "fifo.h" +// by default the FIFO can be auto-grown to 1MB +#define AUTO_GROW_DEFAULT_BYTES (1024 * 1024) + struct AVFifo { uint8_t *buffer; @@ -33,6 +36,9 @@ struct AVFifo { size_t offset_r, offset_w; // distinguishes the ambiguous situation offset_r == offset_w int is_empty; + + unsigned int flags; + size_t auto_grow_limit; }; AVFifo *av_fifo_alloc2(size_t nb_elems, size_t elem_size, @@ -59,9 +65,17 @@ AVFifo *av_fifo_alloc2(size_t nb_elems, size_t elem_size, f->elem_size = elem_size; f->is_empty = 1; + f->flags = flags; + f->auto_grow_limit = FFMAX(AUTO_GROW_DEFAULT_BYTES / elem_size, 1); + return f; } +void av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems) +{ + f->auto_grow_limit = max_elems; +} + size_t av_fifo_elem_size(const AVFifo *f) { return f->elem_size; @@ -109,6 +123,26 @@ int av_fifo_grow2(AVFifo *f, size_t inc) return 0; } +static int fifo_check_space(AVFifo *f, size_t to_write) +{ + const size_t can_write = av_fifo_can_write(f); + const size_t need_grow = to_write > can_write ? to_write - can_write : 0; + size_t can_grow; + + if (!need_grow) + return 0; + + can_grow = f->auto_grow_limit > f->nb_elems ? + f->auto_grow_limit - f->nb_elems : 0; + if ((f->flags & AV_FIFO_FLAG_AUTO_GROW) && need_grow <= can_grow) { + // allocate a bit more than necessary, if we can + const size_t inc = (need_grow < can_grow / 2 ) ? need_grow * 2 : can_grow; + return av_fifo_grow2(f, inc); + } + + return AVERROR(ENOSPC); +} + static int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, AVFifoCB read_cb, void *opaque) { @@ -116,8 +150,9 @@ static int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, size_t offset_w = f->offset_w; int ret = 0; - if (to_write > av_fifo_can_write(f)) - return AVERROR(ENOSPC); + ret = fifo_check_space(f, to_write); + if (ret < 0) + return ret; while (to_write > 0) { size_t len = FFMIN(f->nb_elems - offset_w, to_write); diff --git a/libavutil/fifo.h b/libavutil/fifo.h index f455022e3c..55548fbeb4 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -49,12 +49,19 @@ typedef struct AVFifo AVFifo; typedef int AVFifoCB(void *opaque, void *buf, size_t *nb_elems); /** + * Automatically resize the FIFO on writes, so that the data fits. This + * automatic resizing happens up to a limit that can be modified with + * av_fifo_auto_grow_limit(). + */ +#define AV_FIFO_FLAG_AUTO_GROW (1 << 0) + +/** * Allocate and initialize an AVFifo with a given element size. * * @param elems initial number of elements that can be stored in the FIFO * @param elem_size Size in bytes of a single element. Further operations on * the returned FIFO will implicitly use this element size. - * @param flags currently unused, must be 0 + * @param flags a combination of AV_FIFO_FLAG_* * * @return newly-allocated AVFifo on success, a negative error code on failure */ @@ -68,6 +75,12 @@ AVFifo *av_fifo_alloc2(size_t elems, size_t elem_size, size_t av_fifo_elem_size(const AVFifo *f); /** + * Set the maximum size (in elements) to which the FIFO can be resized + * automatically. Has no effect unless AV_FIFO_FLAG_AUTO_GROW is used. + */ +void av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems); + +/** * @return number of elements available for reading from the given FIFO. */ size_t av_fifo_can_read(const AVFifo *f); |