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 "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  if (flags & AV_BUFFER_FLAG_READONLY)
49 
50  ref = av_mallocz(sizeof(*ref));
51  if (!ref) {
52  av_freep(&buf);
53  return NULL;
54  }
55 
56  ref->buffer = buf;
57  ref->data = data;
58  ref->size = size;
59 
60  return ref;
61 }
62 
63 void av_buffer_default_free(void *opaque, uint8_t *data)
64 {
65  av_free(data);
66 }
67 
69 {
70  AVBufferRef *ret = NULL;
71  uint8_t *data = NULL;
72 
73  data = av_malloc(size);
74  if (!data)
75  return NULL;
76 
77  ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
78  if (!ret)
79  av_freep(&data);
80 
81  return ret;
82 }
83 
85 {
87  if (!ret)
88  return NULL;
89 
90  memset(ret->data, 0, size);
91  return ret;
92 }
93 
95 {
96  AVBufferRef *ret = av_mallocz(sizeof(*ret));
97 
98  if (!ret)
99  return NULL;
100 
101  *ret = *buf;
102 
103  atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
104 
105  return ret;
106 }
107 
109 {
110  AVBuffer *b;
111 
112  b = (*dst)->buffer;
113 
114  if (src) {
115  **dst = **src;
116  av_freep(src);
117  } else
118  av_freep(dst);
119 
120  if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
121  b->free(b->opaque, b->data);
122  av_freep(&b);
123  }
124 }
125 
127 {
128  if (!buf || !*buf)
129  return;
130 
131  buffer_replace(buf, NULL);
132 }
133 
135 {
137  return 0;
138 
139  return atomic_load(&buf->buffer->refcount) == 1;
140 }
141 
143 {
144  return buf->buffer->opaque;
145 }
146 
148 {
149  return atomic_load(&buf->buffer->refcount);
150 }
151 
153 {
154  AVBufferRef *newbuf, *buf = *pbuf;
155 
156  if (av_buffer_is_writable(buf))
157  return 0;
158 
159  newbuf = av_buffer_alloc(buf->size);
160  if (!newbuf)
161  return AVERROR(ENOMEM);
162 
163  memcpy(newbuf->data, buf->data, buf->size);
164 
165  buffer_replace(pbuf, &newbuf);
166 
167  return 0;
168 }
169 
170 int av_buffer_realloc(AVBufferRef **pbuf, int size)
171 {
172  AVBufferRef *buf = *pbuf;
173  uint8_t *tmp;
174 
175  if (!buf) {
176  /* allocate a new buffer with av_realloc(), so it will be reallocatable
177  * later */
178  uint8_t *data = av_realloc(NULL, size);
179  if (!data)
180  return AVERROR(ENOMEM);
181 
182  buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
183  if (!buf) {
184  av_freep(&data);
185  return AVERROR(ENOMEM);
186  }
187 
189  *pbuf = buf;
190 
191  return 0;
192  } else if (buf->size == size)
193  return 0;
194 
195  if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) ||
196  !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {
197  /* cannot realloc, allocate a new reallocable buffer and copy data */
198  AVBufferRef *new = NULL;
199 
200  av_buffer_realloc(&new, size);
201  if (!new)
202  return AVERROR(ENOMEM);
203 
204  memcpy(new->data, buf->data, FFMIN(size, buf->size));
205 
206  buffer_replace(pbuf, &new);
207  return 0;
208  }
209 
210  tmp = av_realloc(buf->buffer->data, size);
211  if (!tmp)
212  return AVERROR(ENOMEM);
213 
214  buf->buffer->data = buf->data = tmp;
215  buf->buffer->size = buf->size = size;
216  return 0;
217 }
218 
219 AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
220  AVBufferRef* (*alloc)(void *opaque, int size),
221  void (*pool_free)(void *opaque))
222 {
223  AVBufferPool *pool = av_mallocz(sizeof(*pool));
224  if (!pool)
225  return NULL;
226 
227  ff_mutex_init(&pool->mutex, NULL);
228 
229  pool->size = size;
230  pool->opaque = opaque;
231  pool->alloc2 = alloc;
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 
294  if(CONFIG_MEMORY_POISONING)
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 {
311  AVBufferRef *ret;
312 
313  ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
314  pool->alloc(pool->size);
315  if (!ret)
316  return NULL;
317 
318  buf = av_mallocz(sizeof(*buf));
319  if (!buf) {
320  av_buffer_unref(&ret);
321  return NULL;
322  }
323 
324  buf->data = ret->buffer->data;
325  buf->opaque = ret->buffer->opaque;
326  buf->free = ret->buffer->free;
327  buf->pool = pool;
328 
329  ret->buffer->opaque = buf;
331 
332  return ret;
333 }
334 
336 {
337  AVBufferRef *ret;
339 
340  ff_mutex_lock(&pool->mutex);
341  buf = pool->pool;
342  if (buf) {
343  ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
344  buf, 0);
345  if (ret) {
346  pool->pool = buf->next;
347  buf->next = NULL;
348  }
349  } else {
350  ret = pool_alloc_buffer(pool);
351  }
352  ff_mutex_unlock(&pool->mutex);
353 
354  if (ret)
355  atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
356 
357  return ret;
358 }
359 
361 {
362  BufferPoolEntry *buf = ref->buffer->opaque;
363  av_assert0(buf);
364  return buf->opaque;
365 }
int av_buffer_make_writable(AVBufferRef **pbuf)
Create a writable reference from a given buffer reference, avoiding data copy if possible.
Definition: buffer.c:152
#define NULL
Definition: coverity.c:32
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:157
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:360
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:126
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: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)
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:63
#define atomic_load(object)
Definition: stdatomic.h:93
simple assert() macros that are a bit more flexible than ISO C assert().
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:170
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:134
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:219
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: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:68
uint8_t * data
The data buffer.
Definition: buffer.h:89
int av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:147
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:84
AVBuffer * buffer
Definition: buffer.h:82
void * av_buffer_get_opaque(const AVBufferRef *buf)
Definition: buffer.c:142
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
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
Definition: buffer.c:108
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:94
#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:335
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