diff mbox

[FFmpeg-devel,2/4] avutil/buffer: Add av_fast_malloc equivalent

Message ID 20181120113839.4512-3-andreas.rheinhardt@googlemail.com
State Superseded
Headers show

Commit Message

Andreas Rheinhardt Nov. 20, 2018, 11:38 a.m. UTC
A new function, avpriv_buffer_fast_alloc, is added. Its distinguishing
feature is that the content of the buffer is considered expendable
for the given reference, so that no data copying is performed.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
---
 libavutil/buffer.c | 37 +++++++++++++++++++++++++++++++++++++
 libavutil/buffer.h | 19 +++++++++++++++++++
 2 files changed, 56 insertions(+)

Comments

Hendrik Leppkes Nov. 20, 2018, 12:05 p.m. UTC | #1
On Tue, Nov 20, 2018 at 12:45 PM Andreas Rheinhardt
<andreas.rheinhardt@googlemail.com> wrote:
>
> A new function, avpriv_buffer_fast_alloc, is added. Its distinguishing
> feature is that the content of the buffer is considered expendable
> for the given reference, so that no data copying is performed.
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@googlemail.com>
> ---
>  libavutil/buffer.c | 37 +++++++++++++++++++++++++++++++++++++
>  libavutil/buffer.h | 19 +++++++++++++++++++
>  2 files changed, 56 insertions(+)
>
> diff --git a/libavutil/buffer.c b/libavutil/buffer.c
> index 8d1aa5fa84..8303f2fc80 100644
> --- a/libavutil/buffer.c
> +++ b/libavutil/buffer.c
> @@ -215,6 +215,43 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size)
>      return 0;
>  }
>
> +int avpriv_buffer_fast_alloc(AVBufferRef **pbuf, int min_size)
> +{
> +    AVBufferRef *buf = *pbuf;
> +
> +    if (!buf || !av_buffer_is_writable(buf)) {
> +        av_buffer_unref(pbuf);
> +
> +        buf = av_buffer_alloc(FFMAX(min_size + (min_size >> 4) + 32,
> +                                    min_size));
> +        if (!buf)
> +            return AVERROR(ENOMEM);
> +
> +        *pbuf = buf;
> +        return 0;
> +    }
> +
> +    if (min_size <= buf->buffer->size) {
> +        buf->data = buf->buffer->data;
> +        buf->size = buf->buffer->size;
> +        return 0;
> +    }
> +
> +    min_size = FFMAX(min_size + (min_size >> 4) + 32, min_size);
> +    av_free(buf->buffer->data);
> +    buf->buffer->data = av_malloc(min_size);
> +    if (!buf->buffer->data) {
> +        av_free(buf->buffer);
> +        av_freep(pbuf);
> +        return AVERROR(ENOMEM);
> +    }
> +
> +    buf->data = buf->buffer->data;
> +    buf->size = buf->buffer->size = min_size;
> +
> +    return 0;
> +}
> +
>  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..26715275c4 100644
> --- a/libavutil/buffer.h
> +++ b/libavutil/buffer.h
> @@ -197,6 +197,25 @@ int av_buffer_make_writable(AVBufferRef **buf);
>   */
>  int av_buffer_realloc(AVBufferRef **buf, int size);
>
> +/**
> + * Create a writable buffer with given minimum size, reusing the given buffer
> + * if possible. The content of the buffer is considered expendable for the
> + * given reference and might not be preserved at all if the buffer is writable.
> + * The underlying buffer must be compatible with av_free; furthermore, only the
> + * default free callback may be used.
> + *
> + * @param buf      Pointer to NULL or a pointer to a pointer to a buffer reference.
> + *                 On success, **buf will be an AVBufferRef whose size is the
> + *                 allocated size. On failure the reference is unreferenced.
> + *                 If *buf is NULL, a new buffer is allocated.
> + * @param min_size Desired minimal buffer size in bytes.
> + * @return 0 on success, a negative AVERROR on failure.
> + *
> + * @note The function intentionally overallocates in order to reduce the need
> + * for future allocations.
> + */
> +int avpriv_buffer_fast_alloc(AVBufferRef **buf, int min_size);
> +

avpriv functions don't really belong in public headers. Either the
function is deemed to be useful for external callers as well, and
should be av_, or its not and it should be hidden from public headers.
Although I would argue that a key component like the buffer function
really shouldn't have  avpriv functions. If something is so specific
to one component that its not universally useful, then it should
probably be local to that component.

- Hendrik
Andreas Rheinhardt Nov. 21, 2018, 6:34 p.m. UTC | #2
> If something is so specific to one component that its not universally
> useful, then it should probably be local to that component.

Ok, I have completely removed the changes to buffer.c and buffer.h and
incorporated them into a static function in h2645_parse.c.

Thank you.

- Andreas

Andreas Rheinhardt (3):
  cbs_h2645: Avoid memcpy when splitting fragment
  h2645_parse: Make ff_h2645_packet_split reference-compatible
  cbs_h2645: Avoid memcpy when splitting fragment #2

 libavcodec/cbs_h2645.c             | 45 +++++++++++++++---------------
 libavcodec/cbs_h2645.h             |  2 ++
 libavcodec/extract_extradata_bsf.c |  4 +--
 libavcodec/h2645_parse.c           | 43 +++++++++++++++++++++++++---
 libavcodec/h2645_parse.h           | 15 ++++++++--
 libavcodec/h264_parse.c            |  4 +--
 libavcodec/h264dec.c               |  6 ++--
 libavcodec/hevc_parse.c            |  5 ++--
 libavcodec/hevc_parser.c           |  4 +--
 libavcodec/hevcdec.c               |  4 +--
 10 files changed, 90 insertions(+), 42 deletions(-)
diff mbox

Patch

diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index 8d1aa5fa84..8303f2fc80 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -215,6 +215,43 @@  int av_buffer_realloc(AVBufferRef **pbuf, int size)
     return 0;
 }
 
+int avpriv_buffer_fast_alloc(AVBufferRef **pbuf, int min_size)
+{
+    AVBufferRef *buf = *pbuf;
+
+    if (!buf || !av_buffer_is_writable(buf)) {
+        av_buffer_unref(pbuf);
+
+        buf = av_buffer_alloc(FFMAX(min_size + (min_size >> 4) + 32,
+                                    min_size));
+        if (!buf)
+            return AVERROR(ENOMEM);
+
+        *pbuf = buf;
+        return 0;
+    }
+
+    if (min_size <= buf->buffer->size) {
+        buf->data = buf->buffer->data;
+        buf->size = buf->buffer->size;
+        return 0;
+    }
+
+    min_size = FFMAX(min_size + (min_size >> 4) + 32, min_size);
+    av_free(buf->buffer->data);
+    buf->buffer->data = av_malloc(min_size);
+    if (!buf->buffer->data) {
+        av_free(buf->buffer);
+        av_freep(pbuf);
+        return AVERROR(ENOMEM);
+    }
+
+    buf->data = buf->buffer->data;
+    buf->size = buf->buffer->size = min_size;
+
+    return 0;
+}
+
 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..26715275c4 100644
--- a/libavutil/buffer.h
+++ b/libavutil/buffer.h
@@ -197,6 +197,25 @@  int av_buffer_make_writable(AVBufferRef **buf);
  */
 int av_buffer_realloc(AVBufferRef **buf, int size);
 
+/**
+ * Create a writable buffer with given minimum size, reusing the given buffer
+ * if possible. The content of the buffer is considered expendable for the
+ * given reference and might not be preserved at all if the buffer is writable.
+ * The underlying buffer must be compatible with av_free; furthermore, only the
+ * default free callback may be used.
+ *
+ * @param buf      Pointer to NULL or a pointer to a pointer to a buffer reference.
+ *                 On success, **buf will be an AVBufferRef whose size is the
+ *                 allocated size. On failure the reference is unreferenced.
+ *                 If *buf is NULL, a new buffer is allocated.
+ * @param min_size Desired minimal buffer size in bytes.
+ * @return 0 on success, a negative AVERROR on failure.
+ *
+ * @note The function intentionally overallocates in order to reduce the need
+ * for future allocations.
+ */
+int avpriv_buffer_fast_alloc(AVBufferRef **buf, int min_size);
+
 /**
  * @}
  */