FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 "buffer_internal.h"
24 #include "common.h"
25 #include "mem.h"
26 #include "thread.h"
27 
29  void (*free)(void *opaque, uint8_t *data),
30  void *opaque, int flags)
31 {
32  AVBufferRef *ref = NULL;
33  AVBuffer *buf = NULL;
34 
35  buf = av_mallocz(sizeof(*buf));
36  if (!buf)
37  return NULL;
38 
39  buf->data = data;
40  buf->size = size;
41  buf->free = free ? free : av_buffer_default_free;
42  buf->opaque = opaque;
43 
44  atomic_init(&buf->refcount, 1);
45 
46  if (flags & AV_BUFFER_FLAG_READONLY)
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_add_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 
194  if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) ||
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->pool_free = pool_free;
232 
233  atomic_init(&pool->refcount, 1);
234 
235  return pool;
236 }
237 
238 AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
239 {
240  AVBufferPool *pool = av_mallocz(sizeof(*pool));
241  if (!pool)
242  return NULL;
243 
244  ff_mutex_init(&pool->mutex, NULL);
245 
246  pool->size = size;
247  pool->alloc = alloc ? alloc : av_buffer_alloc;
248 
249  atomic_init(&pool->refcount, 1);
250 
251  return pool;
252 }
253 
254 /*
255  * This function gets called when the pool has been uninited and
256  * all the buffers returned to it.
257  */
258 static void buffer_pool_free(AVBufferPool *pool)
259 {
260  while (pool->pool) {
261  BufferPoolEntry *buf = pool->pool;
262  pool->pool = buf->next;
263 
264  buf->free(buf->opaque, buf->data);
265  av_freep(&buf);
266  }
267  ff_mutex_destroy(&pool->mutex);
268 
269  if (pool->pool_free)
270  pool->pool_free(pool->opaque);
271 
272  av_freep(&pool);
273 }
274 
276 {
277  AVBufferPool *pool;
278 
279  if (!ppool || !*ppool)
280  return;
281  pool = *ppool;
282  *ppool = NULL;
283 
284  if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
285  buffer_pool_free(pool);
286 }
287 
288 static void pool_release_buffer(void *opaque, uint8_t *data)
289 {
290  BufferPoolEntry *buf = opaque;
291  AVBufferPool *pool = buf->pool;
292 
293  if(CONFIG_MEMORY_POISONING)
294  memset(buf->data, FF_MEMORY_POISON, pool->size);
295 
296  ff_mutex_lock(&pool->mutex);
297  buf->next = pool->pool;
298  pool->pool = buf;
299  ff_mutex_unlock(&pool->mutex);
300 
301  if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
302  buffer_pool_free(pool);
303 }
304 
305 /* allocate a new buffer and override its free() callback so that
306  * it is returned to the pool on free */
308 {
310  AVBufferRef *ret;
311 
312  ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
313  pool->alloc(pool->size);
314  if (!ret)
315  return NULL;
316 
317  buf = av_mallocz(sizeof(*buf));
318  if (!buf) {
319  av_buffer_unref(&ret);
320  return NULL;
321  }
322 
323  buf->data = ret->buffer->data;
324  buf->opaque = ret->buffer->opaque;
325  buf->free = ret->buffer->free;
326  buf->pool = pool;
327 
328  ret->buffer->opaque = buf;
330 
331  return ret;
332 }
333 
335 {
336  AVBufferRef *ret;
338 
339  ff_mutex_lock(&pool->mutex);
340  buf = pool->pool;
341  if (buf) {
342  ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
343  buf, 0);
344  if (ret) {
345  pool->pool = buf->next;
346  buf->next = NULL;
347  }
348  } else {
349  ret = pool_alloc_buffer(pool);
350  }
351  ff_mutex_unlock(&pool->mutex);
352 
353  if (ret)
354  atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
355 
356  return ret;
357 }
AVBufferRef *(* alloc2)(void *opaque, int size)
void(* free)(void *opaque, uint8_t *data)
a callback for freeing the data
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
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
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
atomic_uint refcount
Memory handling functions.
#define ff_mutex_unlock(mutex)
Definition: thread.h:151
#define FF_MEMORY_POISON
Definition: internal.h:89
const char * b
Definition: vf_curves.c:113
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
#define BUFFER_FLAG_READONLY
The buffer is always treated as read-only.
#define src
Definition: vp8dsp.c:254
struct BufferPoolEntry * next
static AVBufferRef * pool_alloc_buffer(AVBufferPool *pool)
Definition: buffer.c:307
uint8_t * data
data described by this buffer
uint8_t
#define av_malloc(s)
atomic_uint refcount
number of existing AVBufferRef instances referring to this buffer
static int flags
Definition: log.c:57
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
ptrdiff_t size
Definition: opengl_enc.c:101
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
void(* pool_free)(void *opaque)
#define atomic_load(object)
Definition: stdatomic.h:93
#define AVERROR(e)
Definition: error.h:43
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:28
int av_buffer_realloc(AVBufferRef **pbuf, int size)
Reallocate a given buffer.
Definition: buffer.c:169
#define ff_mutex_destroy(mutex)
Definition: thread.h:152
#define FFMIN(a, b)
Definition: common.h:96
int av_buffer_is_writable(const AVBufferRef *buf)
Definition: buffer.c:133
#define ff_mutex_lock(mutex)
Definition: thread.h:150
void(* free)(void *opaque, uint8_t *data)
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 BUFFER_FLAG_*.
#define ff_mutex_init(mutex, attr)
Definition: thread.h:149
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
static void pool_release_buffer(void *opaque, uint8_t *data)
Definition: buffer.c:288
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 av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:146
void * buf
Definition: avisynth_c.h:690
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:258
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:275
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
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:238
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 * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:334
#define BUFFER_FLAG_REALLOCATABLE
The buffer was av_realloc()ed, so it is reallocatable.
AVBufferRef *(* alloc)(int size)
static uint8_t tmp[11]
Definition: aes_ctr.c:26