On Tue, 13 Mar 2018 20:48:56 -0300 James Almer <jamr...@gmail.com> wrote:
> Same concept as av_fast_malloc(). If the buffer passed to it is writable > and big enough it will be reused, otherwise a new one will be allocated > instead. > > Signed-off-by: James Almer <jamr...@gmail.com> > --- > TODO: Changelog and APIChanges entries, version bump. > > libavutil/buffer.c | 63 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > libavutil/buffer.h | 42 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 105 insertions(+) > > diff --git a/libavutil/buffer.c b/libavutil/buffer.c > index 8d1aa5fa84..16ce1b82e2 100644 > --- a/libavutil/buffer.c > +++ b/libavutil/buffer.c > @@ -215,6 +215,69 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size) > return 0; > } > > +static av_always_inline int buffer_fast_alloc(AVBufferRef **pbuf, int size, > int zero_alloc) > +{ > + AVBufferRef *buf = *pbuf; > + AVBuffer *b; > + uint8_t *data; > + > + if (!buf || !av_buffer_is_writable(buf) || buf->data != > buf->buffer->data) { > + /* Buffer can't be reused, and neither can the entire AVBufferRef. > + * Unref the latter and alloc a new one. */ > + av_buffer_unref(pbuf); > + > + buf = av_buffer_alloc(size); > + if (!buf) > + return AVERROR(ENOMEM); > + > + if (zero_alloc) > + memset(buf->data, 0, size); > + > + *pbuf = buf; > + return 0; > + } > + b = buf->buffer; > + > + if (size <= b->size) { > + /* Buffer can be reused. Update the size of AVBufferRef but leave the > + * AVBuffer untouched. */ > + buf->size = FFMAX(0, size); > + return 0; > + } > + > + /* Buffer can't be reused, but there's no need to alloc new AVBuffer and > + * AVBufferRef structs. Free the existing buffer, allocate a new one, and > + * reset AVBuffer and AVBufferRef to default values. */ > + b->free(b->opaque, b->data); > + b->free = av_buffer_default_free; > + b->opaque = NULL; > + b->flags = 0; > + > + data = av_malloc(size); > + if (!data) { > + av_buffer_unref(pbuf); > + return AVERROR(ENOMEM); > + } > + > + if (zero_alloc) > + memset(data, 0, size); > + > + b->data = buf->data = data; > + b->size = buf->size = size; > + > + return 0; > +} > + > +int av_buffer_fast_alloc(AVBufferRef **pbuf, int size) > +{ > + return buffer_fast_alloc(pbuf, size, 0); > +} > + > +int av_buffer_fast_allocz(AVBufferRef **pbuf, int size) > +{ > + return buffer_fast_alloc(pbuf, size, 1); > +} > + > AVBufferPool *av_buffer_pool_init2(int size, void *opaque, > AVBufferRef* (*alloc)(void *opaque, int > size), > void (*pool_free)(void *opaque)) > diff --git a/libavutil/buffer.h b/libavutil/buffer.h > index 73b6bd0b14..1166017d22 100644 > --- a/libavutil/buffer.h > +++ b/libavutil/buffer.h > @@ -197,6 +197,48 @@ int av_buffer_make_writable(AVBufferRef **buf); > */ > int av_buffer_realloc(AVBufferRef **buf, int size); > > +/** > + * Allocate a buffer, reusing the given one if writable and large enough. > + * > + * @code{.c} > + * AVBufferRef *buf = ...; > + * int ret = av_buffer_fast_alloc(&buf, size); > + * if (ret < 0) { > + * // Allocation failed; buf already freed > + * return ret; > + * } > + * @endcode > + * > + * @param buf A buffer reference. *buf may be NULL. On success, a new buffer > + * reference will be written in its place. On failure, it will be > + * unreferenced and set to NULL. > + * @param size Required buffer size. > + * > + * @return 0 on success, a negative AVERROR on failure. > + * > + * @see av_buffer_realloc() > + * @see av_buffer_fast_allocz() > + */ > +int av_buffer_fast_alloc(AVBufferRef **buf, int size); > + > +/** > + * Allocate and clear a buffer, reusing the given one if writable and large > + * enough. > + * > + * Like av_buffer_fast_alloc(), but all newly allocated space is initially > + * cleared. Reused buffer is not cleared. > + * > + * @param buf A buffer reference. *buf may be NULL. On success, a new buffer > + * reference will be written in its place. On failure, it will be > + * unreferenced and set to NULL. > + * @param size Required buffer size. > + * > + * @return 0 on success, a negative AVERROR on failure. > + * > + * @see av_buffer_fast_alloc() > + */ > +int av_buffer_fast_allocz(AVBufferRef **buf, int size); > + > /** > * @} > */ Wouldn't it be better to avoid writing a lot of new allocation code (with possibly subtle problems), and just use av_buffer_realloc() to handle reallocation? (Possibly it could be moved to an internal function to avoid the memcpy() required by realloc.) _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel