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  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 
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, size_t size)
170 {
171  AVBufferRef *buf = *pbuf;
172  uint8_t *tmp;
173  int ret;
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 
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 
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  ret = av_buffer_realloc(&new, size);
201  if (ret < 0)
202  return ret;
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 
220 {
221  AVBufferRef *dst = *pdst;
222  AVBufferRef *tmp;
223 
224  if (!src) {
225  av_buffer_unref(pdst);
226  return 0;
227  }
228 
229  if (dst && dst->buffer == src->buffer) {
230  /* make sure the data pointers match */
231  dst->data = src->data;
232  dst->size = src->size;
233  return 0;
234  }
235 
236  tmp = av_buffer_ref(src);
237  if (!tmp)
238  return AVERROR(ENOMEM);
239 
240  av_buffer_unref(pdst);
241  *pdst = tmp;
242  return 0;
243 }
244 
245 AVBufferPool *av_buffer_pool_init2(size_t size, void *opaque,
246  AVBufferRef* (*alloc)(void *opaque, size_t size),
247  void (*pool_free)(void *opaque))
248 {
249  AVBufferPool *pool = av_mallocz(sizeof(*pool));
250  if (!pool)
251  return NULL;
252 
253  ff_mutex_init(&pool->mutex, NULL);
254 
255  pool->size = size;
256  pool->opaque = opaque;
257  pool->alloc2 = alloc;
258  pool->alloc = av_buffer_alloc; // fallback
259  pool->pool_free = pool_free;
260 
261  atomic_init(&pool->refcount, 1);
262 
263  return pool;
264 }
265 
267 {
268  AVBufferPool *pool = av_mallocz(sizeof(*pool));
269  if (!pool)
270  return NULL;
271 
272  ff_mutex_init(&pool->mutex, NULL);
273 
274  pool->size = size;
275  pool->alloc = alloc ? alloc : av_buffer_alloc;
276 
277  atomic_init(&pool->refcount, 1);
278 
279  return pool;
280 }
281 
282 static void buffer_pool_flush(AVBufferPool *pool)
283 {
284  while (pool->pool) {
285  BufferPoolEntry *buf = pool->pool;
286  pool->pool = buf->next;
287 
288  buf->free(buf->opaque, buf->data);
289  av_freep(&buf);
290  }
291 }
292 
293 /*
294  * This function gets called when the pool has been uninited and
295  * all the buffers returned to it.
296  */
297 static void buffer_pool_free(AVBufferPool *pool)
298 {
299  buffer_pool_flush(pool);
300  ff_mutex_destroy(&pool->mutex);
301 
302  if (pool->pool_free)
303  pool->pool_free(pool->opaque);
304 
305  av_freep(&pool);
306 }
307 
309 {
310  AVBufferPool *pool;
311 
312  if (!ppool || !*ppool)
313  return;
314  pool = *ppool;
315  *ppool = NULL;
316 
317  ff_mutex_lock(&pool->mutex);
318  buffer_pool_flush(pool);
319  ff_mutex_unlock(&pool->mutex);
320 
321  if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
322  buffer_pool_free(pool);
323 }
324 
325 static void pool_release_buffer(void *opaque, uint8_t *data)
326 {
327  BufferPoolEntry *buf = opaque;
328  AVBufferPool *pool = buf->pool;
329 
330  if(CONFIG_MEMORY_POISONING)
331  memset(buf->data, FF_MEMORY_POISON, pool->size);
332 
333  ff_mutex_lock(&pool->mutex);
334  buf->next = pool->pool;
335  pool->pool = buf;
336  ff_mutex_unlock(&pool->mutex);
337 
338  if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
339  buffer_pool_free(pool);
340 }
341 
342 /* allocate a new buffer and override its free() callback so that
343  * it is returned to the pool on free */
345 {
346  BufferPoolEntry *buf;
347  AVBufferRef *ret;
348 
349  av_assert0(pool->alloc || pool->alloc2);
350 
351  ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
352  pool->alloc(pool->size);
353  if (!ret)
354  return NULL;
355 
356  buf = av_mallocz(sizeof(*buf));
357  if (!buf) {
359  return NULL;
360  }
361 
362  buf->data = ret->buffer->data;
363  buf->opaque = ret->buffer->opaque;
364  buf->free = ret->buffer->free;
365  buf->pool = pool;
366 
367  ret->buffer->opaque = buf;
368  ret->buffer->free = pool_release_buffer;
369 
370  return ret;
371 }
372 
374 {
375  AVBufferRef *ret;
376  BufferPoolEntry *buf;
377 
378  ff_mutex_lock(&pool->mutex);
379  buf = pool->pool;
380  if (buf) {
382  buf, 0);
383  if (ret) {
384  pool->pool = buf->next;
385  buf->next = NULL;
386  }
387  } else {
388  ret = pool_alloc_buffer(pool);
389  }
390  ff_mutex_unlock(&pool->mutex);
391 
392  if (ret)
393  atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
394 
395  return ret;
396 }
397 
399 {
400  BufferPoolEntry *buf = ref->buffer->opaque;
401  av_assert0(buf);
402  return buf->opaque;
403 }
av_buffer_pool_init
AVBufferPool * av_buffer_pool_init(size_t size, AVBufferRef *(*alloc)(size_t size))
Allocate and initialize a buffer pool.
Definition: buffer.c:266
ff_mutex_init
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition: thread.h:167
AVERROR
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
AVBufferPool::mutex
AVMutex mutex
Definition: buffer_internal.h:79
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:78
thread.h
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:92
buffer_internal.h
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:27
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:142
FF_MEMORY_POISON
#define FF_MEMORY_POISON
Definition: internal.h:88
AVBufferPool::size
size_t size
Definition: buffer_internal.h:93
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
BUFFER_FLAG_REALLOCATABLE
#define BUFFER_FLAG_REALLOCATABLE
The buffer was av_realloc()ed, so it is reallocatable.
Definition: buffer_internal.h:32
ff_mutex_unlock
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:169
BufferPoolEntry::data
uint8_t * data
Definition: buffer_internal.h:65
AVBufferPool::refcount
atomic_uint refcount
Definition: buffer_internal.h:91
av_buffer_pool_buffer_get_opaque
void * av_buffer_pool_buffer_get_opaque(AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:398
AVBuffer::flags
int flags
A combination of AV_BUFFER_FLAG_*.
Definition: buffer_internal.h:56
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:245
avassert.h
AVBufferPool::opaque
void * opaque
Definition: buffer_internal.h:94
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:373
buffer_replace
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
Definition: buffer.c:107
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:116
BufferPoolEntry::pool
AVBufferPool * pool
Definition: buffer_internal.h:74
pool_release_buffer
static void pool_release_buffer(void *opaque, uint8_t *data)
Definition: buffer.c:325
av_buffer_default_free
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
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVBuffer::free
void(* free)(void *opaque, uint8_t *data)
a callback for freeing the data
Definition: buffer_internal.h:46
AVBuffer::size
size_t size
size of data in bytes
Definition: buffer_internal.h:36
atomic_load
#define atomic_load(object)
Definition: stdatomic.h:93
AVBuffer::flags_internal
int flags_internal
A combination of BUFFER_FLAG_*.
Definition: buffer_internal.h:61
buffer_pool_free
static void buffer_pool_free(AVBufferPool *pool)
Definition: buffer.c:297
AVBuffer::opaque
void * opaque
an opaque pointer, to be used by the freeing callback
Definition: buffer_internal.h:51
NULL
#define NULL
Definition: coverity.c:32
AVBufferPool::pool_free
void(* pool_free)(void *opaque)
Definition: buffer_internal.h:97
av_buffer_unref
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
AVBuffer::data
uint8_t * data
data described by this buffer
Definition: buffer_internal.h:35
src
#define src
Definition: vp8dsp.c:255
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:308
BufferPoolEntry::free
void(* free)(void *opaque, uint8_t *data)
Definition: buffer_internal.h:72
pool_alloc_buffer
static AVBufferRef * pool_alloc_buffer(AVBufferPool *pool)
Definition: buffer.c:344
atomic_fetch_sub_explicit
#define atomic_fetch_sub_explicit(object, operand, order)
Definition: stdatomic.h:152
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
ff_mutex_destroy
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:170
BufferPoolEntry
Definition: buffer_internal.h:64
size
int size
Definition: twinvq_data.h:10344
atomic_fetch_add_explicit
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
AVBufferPool::alloc
AVBufferRef *(* alloc)(size_t size)
Definition: buffer_internal.h:95
av_buffer_make_writable
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
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
av_buffer_get_ref_count
int av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:146
ff_mutex_lock
static int ff_mutex_lock(AVMutex *mutex)
Definition: thread.h:168
AVBufferRef::buffer
AVBuffer * buffer
Definition: buffer.h:85
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
AVBufferRef::size
size_t size
Size of data in bytes.
Definition: buffer.h:96
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
BufferPoolEntry::opaque
void * opaque
Definition: buffer_internal.h:71
AVBuffer
A reference counted buffer type.
Definition: buffer_internal.h:34
AVBufferPool::pool
BufferPoolEntry * pool
Definition: buffer_internal.h:80
common.h
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:244
BufferPoolEntry::next
struct BufferPoolEntry * next
Definition: buffer_internal.h:75
av_buffer_is_writable
int av_buffer_is_writable(const AVBufferRef *buf)
Definition: buffer.c:133
av_buffer_allocz
AVBufferRef * av_buffer_allocz(size_t size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition: buffer.c:83
ret
ret
Definition: filter_design.txt:187
buffer_pool_flush
static void buffer_pool_flush(AVBufferPool *pool)
Definition: buffer.c:282
av_buffer_replace
int av_buffer_replace(AVBufferRef **pdst, AVBufferRef *src)
Ensure dst refers to the same data as src.
Definition: buffer.c:219
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
av_buffer_ref
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
av_buffer_realloc
int av_buffer_realloc(AVBufferRef **pbuf, size_t size)
Reallocate a given buffer.
Definition: buffer.c:169
av_buffer_get_opaque
void * av_buffer_get_opaque(const AVBufferRef *buf)
Definition: buffer.c:141
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:84
AVBufferPool::alloc2
AVBufferRef *(* alloc2)(void *opaque, size_t size)
Definition: buffer_internal.h:96
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
atomic_init
#define atomic_init(obj, value)
Definition: stdatomic.h:33
AVBuffer::refcount
atomic_uint refcount
number of existing AVBufferRef instances referring to this buffer
Definition: buffer_internal.h:41