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 
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 */
178  if (!data)
179  return AVERROR(ENOMEM);
180 
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 
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 
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 {
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) {
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;
332  ret->buffer->free = pool_release_buffer;
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) {
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 }
ff_mutex_init
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition: thread.h:167
av_buffer_alloc
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
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
av_buffer_realloc
int av_buffer_realloc(AVBufferRef **pbuf, int size)
Reallocate a given buffer.
Definition: buffer.c:169
AVBufferPool::mutex
AVMutex mutex
Definition: buffer_internal.h:78
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:77
thread.h
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:89
buffer_internal.h
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:91
FF_MEMORY_POISON
#define FF_MEMORY_POISON
Definition: internal.h:89
av_buffer_allocz
AVBufferRef * av_buffer_allocz(int size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition: buffer.c:83
av_buffer_create
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
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:31
ff_mutex_unlock
static int ff_mutex_unlock(AVMutex *mutex)
Definition: thread.h:169
AVBufferRef::size
int size
Size of data in bytes.
Definition: buffer.h:93
av_buffer_pool_init
AVBufferPool * av_buffer_pool_init(int size, AVBufferRef *(*alloc)(int size))
Allocate and initialize a buffer pool.
Definition: buffer.c:239
BufferPoolEntry::data
uint8_t * data
Definition: buffer_internal.h:64
AVBufferPool::size
int size
Definition: buffer_internal.h:92
AVBufferPool::refcount
atomic_uint refcount
Definition: buffer_internal.h:90
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:362
AVBuffer::flags
int flags
A combination of AV_BUFFER_FLAG_*.
Definition: buffer_internal.h:55
avassert.h
AVBufferPool::opaque
void * opaque
Definition: buffer_internal.h:93
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:337
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:113
BufferPoolEntry::pool
AVBufferPool * pool
Definition: buffer_internal.h:73
pool_release_buffer
static void pool_release_buffer(void *opaque, uint8_t *data)
Definition: buffer.c:289
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:45
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:60
buffer_pool_free
static void buffer_pool_free(AVBufferPool *pool)
Definition: buffer.c:259
AVBuffer::opaque
void * opaque
an opaque pointer, to be used by the freeing callback
Definition: buffer_internal.h:50
NULL
#define NULL
Definition: coverity.c:32
AVBufferPool::pool_free
void(* pool_free)(void *opaque)
Definition: buffer_internal.h:96
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:34
src
#define src
Definition: vp8dsp.c:254
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:276
BufferPoolEntry::free
void(* free)(void *opaque, uint8_t *data)
Definition: buffer_internal.h:71
pool_alloc_buffer
static AVBufferRef * pool_alloc_buffer(AVBufferPool *pool)
Definition: buffer.c:308
atomic_fetch_sub_explicit
#define atomic_fetch_sub_explicit(object, operand, order)
Definition: stdatomic.h:152
ff_mutex_destroy
static int ff_mutex_destroy(AVMutex *mutex)
Definition: thread.h:170
AVBuffer::size
int size
size of data in bytes
Definition: buffer_internal.h:35
AVBufferPool::alloc
AVBufferRef *(* alloc)(int size)
Definition: buffer_internal.h:94
BufferPoolEntry
Definition: buffer_internal.h:63
size
int size
Definition: twinvq_data.h:11134
atomic_fetch_add_explicit
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
AVBufferPool::alloc2
AVBufferRef *(* alloc2)(void *opaque, int 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:96
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:82
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:134
BufferPoolEntry::opaque
void * opaque
Definition: buffer_internal.h:70
AVBuffer
A reference counted buffer type.
Definition: buffer_internal.h:33
AVBufferPool::pool
BufferPoolEntry * pool
Definition: buffer_internal.h:79
common.h
uint8_t
uint8_t
Definition: audio_convert.c:194
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:237
av_buffer_pool_init2
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
BufferPoolEntry::next
struct BufferPoolEntry * next
Definition: buffer_internal.h:74
av_buffer_is_writable
int av_buffer_is_writable(const AVBufferRef *buf)
Definition: buffer.c:133
ret
ret
Definition: filter_design.txt:187
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_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:81
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:565
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:40