Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread James Almer
On 3/14/2018 12:09 PM, wm4 wrote:
> On Wed, 14 Mar 2018 11:59:59 -0300
> James Almer  wrote:
> 
>> On 3/14/2018 11:35 AM, wm4 wrote:
>>> On Wed, 14 Mar 2018 11:13:52 -0300
>>> James Almer  wrote:
>>>   
 On 3/14/2018 4:14 AM, wm4 wrote:  
> On Tue, 13 Mar 2018 20:48:56 -0300
> James Almer  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 
>> ---
>> 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
>> + * clea

Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread wm4
On Wed, 14 Mar 2018 11:59:59 -0300
James Almer  wrote:

> On 3/14/2018 11:35 AM, wm4 wrote:
> > On Wed, 14 Mar 2018 11:13:52 -0300
> > James Almer  wrote:
> >   
> >> On 3/14/2018 4:14 AM, wm4 wrote:  
> >>> On Tue, 13 Mar 2018 20:48:56 -0300
> >>> James Almer  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 
>  ---
>  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.
> 

Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread James Almer
On 3/14/2018 11:35 AM, wm4 wrote:
> On Wed, 14 Mar 2018 11:13:52 -0300
> James Almer  wrote:
> 
>> On 3/14/2018 4:14 AM, wm4 wrote:
>>> On Tue, 13 Mar 2018 20:48:56 -0300
>>> James Almer  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 
 ---
 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

Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread wm4
On Wed, 14 Mar 2018 11:13:52 -0300
James Almer  wrote:

> On 3/14/2018 4:14 AM, wm4 wrote:
> > On Tue, 13 Mar 2018 20:48:56 -0300
> > James Almer  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 
> >> ---
> >> 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()
> >> + */
> >> +i

Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread James Almer
On 3/14/2018 4:14 AM, wm4 wrote:
> On Tue, 13 Mar 2018 20:48:56 -0300
> James Almer  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 
>> ---
>> 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.)

There are some d

Re: [FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-14 Thread wm4
On Tue, 13 Mar 2018 20:48:56 -0300
James Almer  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 
> ---
> 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


[FFmpeg-devel] [PATCH] avutil/buffer: add av_buffer_fast_alloc()

2018-03-13 Thread James Almer
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 
---
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);
+
 /**
  * @}
  */
-- 
2.16.2

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel