| @@ -26,6 +26,9 @@ · 25 unmodified lines |
| 26 | 26 | #include "common.h" |
| 27 | 27 | #include "fifo.h" |
| 28 | 28 | |
| 29 | +// by default the FIFO can be auto-grown to 1MB |
| 30 | +#define AUTO_GROW_DEFAULT_BYTES (1024 * 1024) |
| 31 | + |
| 29 | 32 | struct AVFifo { |
| 30 | 33 | uint8_t *buffer; |
| 31 | 34 | |
| @@ -33,6 +36,9 @@ struct AVFifo { · 1 unmodified line |
| 33 | 36 | size_t offset_r, offset_w; |
| 34 | 37 | // distinguishes the ambiguous situation offset_r == offset_w |
| 35 | 38 | int is_empty; |
| 39 | + |
| 40 | + unsigned int flags; |
| 41 | + size_t auto_grow_limit; |
| 36 | 42 | }; |
| 37 | 43 | |
| 38 | 44 | 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, · 20 unmodified lines |
| 59 | 65 | f->elem_size = elem_size; |
| 60 | 66 | f->is_empty = 1; |
| 61 | 67 | |
| 68 | + f->flags = flags; |
| 69 | + f->auto_grow_limit = FFMAX(AUTO_GROW_DEFAULT_BYTES / elem_size, 1); |
| 70 | + |
| 62 | 71 | return f; |
| 63 | 72 | } |
| 64 | 73 | |
| 74 | +void av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems) |
| 75 | +{ |
| 76 | + f->auto_grow_limit = max_elems; |
| 77 | +} |
| 78 | + |
| 65 | 79 | size_t av_fifo_elem_size(const AVFifo *f) |
| 66 | 80 | { |
| 67 | 81 | return f->elem_size; |
| @@ -109,6 +123,26 @@ int av_fifo_grow2(AVFifo *f, size_t inc) · 41 unmodified lines |
| 109 | 123 | return 0; |
| 110 | 124 | } |
| 111 | 125 | |
| 126 | +static int fifo_check_space(AVFifo *f, size_t to_write) |
| 127 | +{ |
| 128 | + const size_t can_write = av_fifo_can_write(f); |
| 129 | + const size_t need_grow = to_write > can_write ? to_write - can_write : 0; |
| 130 | + size_t can_grow; |
| 131 | + |
| 132 | + if (!need_grow) |
| 133 | + return 0; |
| 134 | + |
| 135 | + can_grow = f->auto_grow_limit > f->nb_elems ? |
| 136 | + f->auto_grow_limit - f->nb_elems : 0; |
| 137 | + if ((f->flags & AV_FIFO_FLAG_AUTO_GROW) && need_grow <= can_grow) { |
| 138 | + // allocate a bit more than necessary, if we can |
| 139 | + const size_t inc = (need_grow < can_grow / 2 ) ? need_grow * 2 : can_grow; |
| 140 | + return av_fifo_grow2(f, inc); |
| 141 | + } |
| 142 | + |
| 143 | + return AVERROR(ENOSPC); |
| 144 | +} |
| 145 | + |
| 112 | 146 | static int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, |
| 113 | 147 | AVFifoCB read_cb, void *opaque) |
| 114 | 148 | { |
| @@ -116,8 +150,9 @@ static int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, · 1 unmodified line |
| 116 | 150 | size_t offset_w = f->offset_w; |
| 117 | 151 | int ret = 0; |
| 118 | 152 | |
| 119 | | − if (to_write > av_fifo_can_write(f)) |
| 120 | | − return AVERROR(ENOSPC); |
| 153 | + ret = fifo_check_space(f, to_write); |
| 154 | + if (ret < 0) |
| 155 | + return ret; |
| 121 | 156 | |
| 122 | 157 | while (to_write > 0) { |
| 123 | 158 | size_t len = FFMIN(f->nb_elems - offset_w, to_write); |