FFmpeg
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 {
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 
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_sub_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_sub_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 }
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:157
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:100
atomic_uint refcount
Memory handling functions.
#define FF_MEMORY_POISON
Definition: internal.h:89
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:155
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
#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
#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:100
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 atomic_load(object)
Definition: stdatomic.h:93
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
void(* pool_free)(void *opaque)
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:156
#define b
Definition: input.c:41
#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 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:288
#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 av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:146
void * buf
Definition: avisynth_c.h:766
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
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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 *(* 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:334
void(* free)(void *opaque, uint8_t *data)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
#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:154
static uint8_t tmp[11]
Definition: aes_ctr.c:26