FFmpeg  4.3
buffer.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdatomic.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include "avassert.h"
24 #include "buffer_internal.h"
25 #include "common.h"
26 #include "mem.h"
27 #include "thread.h"
28 
30  void (*free)(void *opaque, uint8_t *data),
31  void *opaque, int flags)
32 {
33  AVBufferRef *ref = NULL;
34  AVBuffer *buf = NULL;
35 
36  buf = av_mallocz(sizeof(*buf));
37  if (!buf)
38  return NULL;
39 
40  buf->data = data;
41  buf->size = size;
42  buf->free = free ? free : av_buffer_default_free;
43  buf->opaque = opaque;
44 
45  atomic_init(&buf->refcount, 1);
46 
47  buf->flags = flags;
48 
49  ref = av_mallocz(sizeof(*ref));
50  if (!ref) {
51  av_freep(&buf);
52  return NULL;
53  }
54 
55  ref->buffer = buf;
56  ref->data = data;
57  ref->size = size;
58 
59  return ref;
60 }
61 
62 void av_buffer_default_free(void *opaque, uint8_t *data)
63 {
64  av_free(data);
65 }
66 
68 {
69  AVBufferRef *ret = NULL;
70  uint8_t *data = NULL;
71 
72  data = av_malloc(size);
73  if (!data)
74  return NULL;
75 
76  ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
77  if (!ret)
78  av_freep(&data);
79 
80  return ret;
81 }
82 
84 {
85  AVBufferRef *ret = av_buffer_alloc(size);
86  if (!ret)
87  return NULL;
88 
89  memset(ret->data, 0, size);
90  return ret;
91 }
92 
94 {
95  AVBufferRef *ret = av_mallocz(sizeof(*ret));
96 
97  if (!ret)
98  return NULL;
99 
100  *ret = *buf;
101 
102  atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
103 
104  return ret;
105 }
106 
108 {
109  AVBuffer *b;
110 
111  b = (*dst)->buffer;
112 
113  if (src) {
114  **dst = **src;
115  av_freep(src);
116  } else
117  av_freep(dst);
118 
119  if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
120  b->free(b->opaque, b->data);
121  av_freep(&b);
122  }
123 }
124 
126 {
127  if (!buf || !*buf)
128  return;
129 
130  buffer_replace(buf, NULL);
131 }
132 
134 {
136  return 0;
137 
138  return atomic_load(&buf->buffer->refcount) == 1;
139 }
140 
142 {
143  return buf->buffer->opaque;
144 }
145 
147 {
148  return atomic_load(&buf->buffer->refcount);
149 }
150 
152 {
153  AVBufferRef *newbuf, *buf = *pbuf;
154 
155  if (av_buffer_is_writable(buf))
156  return 0;
157 
158  newbuf = av_buffer_alloc(buf->size);
159  if (!newbuf)
160  return AVERROR(ENOMEM);
161 
162  memcpy(newbuf->data, buf->data, buf->size);
163 
164  buffer_replace(pbuf, &newbuf);
165 
166  return 0;
167 }
168 
169 int av_buffer_realloc(AVBufferRef **pbuf, int size)
170 {
171  AVBufferRef *buf = *pbuf;
172  uint8_t *tmp;
173 
174  if (!buf) {
175  /* allocate a new buffer with av_realloc(), so it will be reallocatable
176  * later */
177  uint8_t *data = av_realloc(NULL, size);
178  if (!data)
179  return AVERROR(ENOMEM);
180 
181  buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
182  if (!buf) {
183  av_freep(&data);
184  return AVERROR(ENOMEM);
185  }
186 
188  *pbuf = buf;
189 
190  return 0;
191  } else if (buf->size == size)
192  return 0;
193 
195  !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {
196  /* cannot realloc, allocate a new reallocable buffer and copy data */
197  AVBufferRef *new = NULL;
198 
199  av_buffer_realloc(&new, size);
200  if (!new)
201  return AVERROR(ENOMEM);
202 
203  memcpy(new->data, buf->data, FFMIN(size, buf->size));
204 
205  buffer_replace(pbuf, &new);
206  return 0;
207  }
208 
209  tmp = av_realloc(buf->buffer->data, size);
210  if (!tmp)
211  return AVERROR(ENOMEM);
212 
213  buf->buffer->data = buf->data = tmp;
214  buf->buffer->size = buf->size = size;
215  return 0;
216 }
217 
218 AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
219  AVBufferRef* (*alloc)(void *opaque, int size),
220  void (*pool_free)(void *opaque))
221 {
222  AVBufferPool *pool = av_mallocz(sizeof(*pool));
223  if (!pool)
224  return NULL;
225 
226  ff_mutex_init(&pool->mutex, NULL);
227 
228  pool->size = size;
229  pool->opaque = opaque;
230  pool->alloc2 = alloc;
231  pool->alloc = av_buffer_alloc; // fallback
232  pool->pool_free = pool_free;
233 
234  atomic_init(&pool->refcount, 1);
235 
236  return pool;
237 }
238 
239 AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
240 {
241  AVBufferPool *pool = av_mallocz(sizeof(*pool));
242  if (!pool)
243  return NULL;
244 
245  ff_mutex_init(&pool->mutex, NULL);
246 
247  pool->size = size;
248  pool->alloc = alloc ? alloc : av_buffer_alloc;
249 
250  atomic_init(&pool->refcount, 1);
251 
252  return pool;
253 }
254 
255 /*
256  * This function gets called when the pool has been uninited and
257  * all the buffers returned to it.
258  */
259 static void buffer_pool_free(AVBufferPool *pool)
260 {
261  while (pool->pool) {
262  BufferPoolEntry *buf = pool->pool;
263  pool->pool = buf->next;
264 
265  buf->free(buf->opaque, buf->data);
266  av_freep(&buf);
267  }
268  ff_mutex_destroy(&pool->mutex);
269 
270  if (pool->pool_free)
271  pool->pool_free(pool->opaque);
272 
273  av_freep(&pool);
274 }
275 
277 {
278  AVBufferPool *pool;
279 
280  if (!ppool || !*ppool)
281  return;
282  pool = *ppool;
283  *ppool = NULL;
284 
285  if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
286  buffer_pool_free(pool);
287 }
288 
289 static void pool_release_buffer(void *opaque, uint8_t *data)
290 {
291  BufferPoolEntry *buf = opaque;
292  AVBufferPool *pool = buf->pool;
293 
295  memset(buf->data, FF_MEMORY_POISON, pool->size);
296 
297  ff_mutex_lock(&pool->mutex);
298  buf->next = pool->pool;
299  pool->pool = buf;
300  ff_mutex_unlock(&pool->mutex);
301 
302  if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
303  buffer_pool_free(pool);
304 }
305 
306 /* allocate a new buffer and override its free() callback so that
307  * it is returned to the pool on free */
309 {
310  BufferPoolEntry *buf;
311  AVBufferRef *ret;
312 
313  av_assert0(pool->alloc || pool->alloc2);
314 
315  ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
316  pool->alloc(pool->size);
317  if (!ret)
318  return NULL;
319 
320  buf = av_mallocz(sizeof(*buf));
321  if (!buf) {
322  av_buffer_unref(&ret);
323  return NULL;
324  }
325 
326  buf->data = ret->buffer->data;
327  buf->opaque = ret->buffer->opaque;
328  buf->free = ret->buffer->free;
329  buf->pool = pool;
330 
331  ret->buffer->opaque = buf;
333 
334  return ret;
335 }
336 
338 {
339  AVBufferRef *ret;
340  BufferPoolEntry *buf;
341 
342  ff_mutex_lock(&pool->mutex);
343  buf = pool->pool;
344  if (buf) {
345  ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
346  buf, 0);
347  if (ret) {
348  pool->pool = buf->next;
349  buf->next = NULL;
350  }
351  } else {
352  ret = pool_alloc_buffer(pool);
353  }
354  ff_mutex_unlock(&pool->mutex);
355 
356  if (ret)
357  atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
358 
359  return ret;
360 }
361 
363 {
364  BufferPoolEntry *buf = ref->buffer->opaque;
365  av_assert0(buf);
366  return buf->opaque;
367 }
int av_buffer_make_writable(AVBufferRef **pbuf)
Create a writable reference from a given buffer reference, avoiding data copy if possible.
Definition: buffer.c:151
#define NULL
Definition: coverity.c:32
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:170
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:362
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
int size
atomic_uint refcount
Memory handling functions.
#define FF_MEMORY_POISON
Definition: internal.h:89
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:168
const char * b
Definition: vf_curves.c:116
struct BufferPoolEntry * next
static AVBufferRef * pool_alloc_buffer(AVBufferPool *pool)
Definition: buffer.c:308
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t * data
data described by this buffer
uint8_t
#define av_malloc(s)
const char data[16]
Definition: mxf.c:91
atomic_uint refcount
number of existing AVBufferRef instances referring to this buffer
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
The buffer pool.
void av_buffer_default_free(void *opaque, uint8_t *data)
Default free callback, which calls av_free() on the buffer data.
Definition: buffer.c:62
#define src
Definition: vp8dsp.c:254
#define atomic_load(object)
Definition: stdatomic.h:93
#define AVERROR(e)
Definition: error.h:43
simple assert() macros that are a bit more flexible than ISO C assert().
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:239
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
int av_buffer_realloc(AVBufferRef **pbuf, int size)
Reallocate a given buffer.
Definition: buffer.c:169
void(* pool_free)(void *opaque)
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:169
#define FFMIN(a, b)
Definition: common.h:96
int av_buffer_is_writable(const AVBufferRef *buf)
Definition: buffer.c:133
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:218
int flags
A combination of AV_BUFFER_FLAG_*.
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
void(* free)(void *opaque, uint8_t *data)
a callback for freeing the data
static void pool_release_buffer(void *opaque, uint8_t *data)
Definition: buffer.c:289
#define atomic_fetch_sub_explicit(object, operand, order)
Definition: stdatomic.h:152
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
uint8_t * data
The data buffer.
Definition: buffer.h:89
int flags_internal
A combination of BUFFER_FLAG_*.
int av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:146
AVBufferRef * av_buffer_allocz(int size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition: buffer.c:83
AVBuffer * buffer
Definition: buffer.h:82
void * av_buffer_get_opaque(const AVBufferRef *buf)
Definition: buffer.c:141
static void buffer_pool_free(AVBufferPool *pool)
Definition: buffer.c:259
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:276
#define CONFIG_MEMORY_POISONING
Definition: config.h:589
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
Definition: buffer.c:107
A reference counted buffer type.
int size
Size of data in bytes.
Definition: buffer.h:93
#define flags(name, subs,...)
Definition: cbs_av1.c:564
void * opaque
an opaque pointer, to be used by the freeing callback
A reference to a data buffer.
Definition: buffer.h:81
common internal and external API header
AVBufferPool * pool
AVBufferPool * av_buffer_pool_init(int size, AVBufferRef *(*alloc)(int size))
Allocate and initialize a buffer pool.
Definition: buffer.c:239
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
#define av_free(p)
int size
size of data in bytes
BufferPoolEntry * pool
#define atomic_init(obj, value)
Definition: stdatomic.h:33
#define av_freep(p)
AVBufferRef *(* alloc)(int size)
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:337
void(* free)(void *opaque, uint8_t *data)
#define BUFFER_FLAG_REALLOCATABLE
The buffer was av_realloc()ed, so it is reallocatable.
AVBufferRef *(* alloc2)(void *opaque, int size)
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition: thread.h:167
static uint8_t tmp[11]
Definition: aes_ctr.c:26