@@ -219,26 +219,38 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size)
int av_buffer_replace(AVBufferRef **pdst, AVBufferRef *src)
{
AVBufferRef *dst = *pdst;
- AVBufferRef *tmp;
+ AVBuffer *b;
if (!src) {
av_buffer_unref(pdst);
return 0;
}
- if (dst && dst->buffer == src->buffer) {
+ if (!dst) {
+ *pdst = av_buffer_ref(src);
+ if (!*pdst)
+ return AVERROR(ENOMEM);
+
+ return 0;
+ }
+
+ if (dst->buffer == src->buffer) {
/* make sure the data pointers match */
dst->data = src->data;
dst->size = src->size;
return 0;
}
- tmp = av_buffer_ref(src);
- if (!tmp)
- return AVERROR(ENOMEM);
+ b = dst->buffer;
+
+ atomic_fetch_add_explicit(&src->buffer->refcount, 1, memory_order_relaxed);
+
+ if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
+ b->free(b->opaque, b->data);
+ av_freep(&b);
+ }
- av_buffer_unref(pdst);
- *pdst = tmp;
+ *dst = *src;
return 0;
}
This is an optimization to av_buffer_replace() to avoid a redundant allocation when the src and dst are non-NULL. Instead of doing a unref + ref, the dst buffer is reused and buffer counters updated accordingly. Signed-off-by: Gil Pedersen <git@gpost.dk> --- libavutil/buffer.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)