libavutil/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 <stdint.h>
20 #include <string.h>
21 
22 #include "atomic.h"
23 #include "buffer_internal.h"
24 #include "common.h"
25 #include "mem.h"
26 
28  void (*free)(void *opaque, uint8_t *data),
29  void *opaque, int flags)
30 {
31  AVBufferRef *ref = NULL;
32  AVBuffer *buf = NULL;
33 
34  buf = av_mallocz(sizeof(*buf));
35  if (!buf)
36  return NULL;
37 
38  buf->data = data;
39  buf->size = size;
41  buf->opaque = opaque;
42  buf->refcount = 1;
43 
44  if (flags & AV_BUFFER_FLAG_READONLY)
46 
47  ref = av_mallocz(sizeof(*ref));
48  if (!ref) {
49  av_freep(&buf);
50  return NULL;
51  }
52 
53  ref->buffer = buf;
54  ref->data = data;
55  ref->size = size;
56 
57  return ref;
58 }
59 
60 void av_buffer_default_free(void *opaque, uint8_t *data)
61 {
62  av_free(data);
63 }
64 
66 {
67  AVBufferRef *ret = NULL;
68  uint8_t *data = NULL;
69 
70  data = av_malloc(size);
71  if (!data)
72  return NULL;
73 
74  ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
75  if (!ret)
76  av_freep(&data);
77 
78  return ret;
79 }
80 
82 {
84  if (!ret)
85  return NULL;
86 
87  memset(ret->data, 0, size);
88  return ret;
89 }
90 
92 {
93  AVBufferRef *ret = av_mallocz(sizeof(*ret));
94 
95  if (!ret)
96  return NULL;
97 
98  *ret = *buf;
99 
101 
102  return ret;
103 }
104 
106 {
107  AVBuffer *b;
108 
109  if (!buf || !*buf)
110  return;
111  b = (*buf)->buffer;
112  av_freep(buf);
113 
115  b->free(b->opaque, b->data);
116  av_freep(&b);
117  }
118 }
119 
121 {
123  return 0;
124 
125  return avpriv_atomic_int_get(&buf->buffer->refcount) == 1;
126 }
127 
129 {
130  return buf->buffer->opaque;
131 }
132 
134 {
135  return buf->buffer->refcount;
136 }
137 
139 {
140  AVBufferRef *newbuf, *buf = *pbuf;
141 
142  if (av_buffer_is_writable(buf))
143  return 0;
144 
145  newbuf = av_buffer_alloc(buf->size);
146  if (!newbuf)
147  return AVERROR(ENOMEM);
148 
149  memcpy(newbuf->data, buf->data, buf->size);
150  av_buffer_unref(pbuf);
151  *pbuf = newbuf;
152 
153  return 0;
154 }
155 
156 int av_buffer_realloc(AVBufferRef **pbuf, int size)
157 {
158  AVBufferRef *buf = *pbuf;
159  uint8_t *tmp;
160 
161  if (!buf) {
162  /* allocate a new buffer with av_realloc(), so it will be reallocatable
163  * later */
164  uint8_t *data = av_realloc(NULL, size);
165  if (!data)
166  return AVERROR(ENOMEM);
167 
168  buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
169  if (!buf) {
170  av_freep(&data);
171  return AVERROR(ENOMEM);
172  }
173 
175  *pbuf = buf;
176 
177  return 0;
178  } else if (buf->size == size)
179  return 0;
180 
181  if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) ||
182  !av_buffer_is_writable(buf)) {
183  /* cannot realloc, allocate a new reallocable buffer and copy data */
184  AVBufferRef *new = NULL;
185 
186  av_buffer_realloc(&new, size);
187  if (!new)
188  return AVERROR(ENOMEM);
189 
190  memcpy(new->data, buf->data, FFMIN(size, buf->size));
191 
192  av_buffer_unref(pbuf);
193  *pbuf = new;
194  return 0;
195  }
196 
197  tmp = av_realloc(buf->buffer->data, size);
198  if (!tmp)
199  return AVERROR(ENOMEM);
200 
201  buf->buffer->data = buf->data = tmp;
202  buf->buffer->size = buf->size = size;
203  return 0;
204 }
205 
206 AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
207 {
208  AVBufferPool *pool = av_mallocz(sizeof(*pool));
209  if (!pool)
210  return NULL;
211 
212  pool->size = size;
213  pool->alloc = alloc ? alloc : av_buffer_alloc;
214 
215  avpriv_atomic_int_set(&pool->refcount, 1);
216 
217  return pool;
218 }
219 
220 /*
221  * This function gets called when the pool has been uninited and
222  * all the buffers returned to it.
223  */
224 static void buffer_pool_free(AVBufferPool *pool)
225 {
226  while (pool->pool) {
227  BufferPoolEntry *buf = pool->pool;
228  pool->pool = buf->next;
229 
230  buf->free(buf->opaque, buf->data);
231  av_freep(&buf);
232  }
233  av_freep(&pool);
234 }
235 
237 {
238  AVBufferPool *pool;
239 
240  if (!ppool || !*ppool)
241  return;
242  pool = *ppool;
243  *ppool = NULL;
244 
245  if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
246  buffer_pool_free(pool);
247 }
248 
249 /* remove the whole buffer list from the pool and return it */
251 {
252  BufferPoolEntry *cur = *(void * volatile *)&pool->pool, *last = NULL;
253 
254  while (cur != last) {
255  last = cur;
256  cur = avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, last, NULL);
257  if (!cur)
258  return NULL;
259  }
260 
261  return cur;
262 }
263 
265 {
266  AVBufferPool *pool;
267  BufferPoolEntry *cur, *end = buf;
268 
269  if (!buf)
270  return;
271  pool = buf->pool;
272 
273  while (end->next)
274  end = end->next;
275 
276  while (avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, NULL, buf)) {
277  /* pool is not empty, retrieve it and append it to our list */
278  cur = get_pool(pool);
279  end->next = cur;
280  while (end->next)
281  end = end->next;
282  }
283 }
284 
285 static void pool_release_buffer(void *opaque, uint8_t *data)
286 {
287  BufferPoolEntry *buf = opaque;
288  AVBufferPool *pool = buf->pool;
289 
291  memset(buf->data, 0x2a, pool->size);
292 
293  add_to_pool(buf);
294  if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
295  buffer_pool_free(pool);
296 }
297 
298 /* allocate a new buffer and override its free() callback so that
299  * it is returned to the pool on free */
301 {
303  AVBufferRef *ret;
304 
305  ret = pool->alloc(pool->size);
306  if (!ret)
307  return NULL;
308 
309  buf = av_mallocz(sizeof(*buf));
310  if (!buf) {
311  av_buffer_unref(&ret);
312  return NULL;
313  }
314 
315  buf->data = ret->buffer->data;
316  buf->opaque = ret->buffer->opaque;
317  buf->free = ret->buffer->free;
318  buf->pool = pool;
319 
320  ret->buffer->opaque = buf;
322 
325 
326  return ret;
327 }
328 
330 {
331  AVBufferRef *ret;
333 
334  /* check whether the pool is empty */
335  buf = get_pool(pool);
336  if (!buf && pool->refcount <= pool->nb_allocated) {
337  av_log(NULL, AV_LOG_DEBUG, "Pool race dectected, spining to avoid overallocation and eventual OOM\n");
338  while (!buf && avpriv_atomic_int_get(&pool->refcount) <= avpriv_atomic_int_get(&pool->nb_allocated))
339  buf = get_pool(pool);
340  }
341 
342  if (!buf)
343  return pool_alloc_buffer(pool);
344 
345  /* keep the first entry, return the rest of the list to the pool */
346  add_to_pool(buf->next);
347  buf->next = NULL;
348 
349  ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
350  buf, 0);
351  if (!ret) {
352  add_to_pool(buf);
353  return NULL;
354  }
356 
357  return ret;
358 }
int av_buffer_make_writable(AVBufferRef **pbuf)
Create a writable reference from a given buffer reference, avoiding data copy if possible.
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
#define avpriv_atomic_int_add_and_fetch
Definition: atomic_gcc.h:42
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
FIXME Range Coding of cr are ref
Definition: snow.txt:367
struct BufferPoolEntry *volatile next
memory handling functions
static void add_to_pool(BufferPoolEntry *buf)
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:141
#define BUFFER_FLAG_READONLY
The buffer is always treated as read-only.
BufferPoolEntry *volatile pool
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
volatile int refcount
number of existing AVBufferRef instances referring to this buffer
uint8_t * data
data described by this buffer
uint8_t
#define b
Definition: input.c:42
end end
#define avpriv_atomic_int_set
Definition: atomic_gcc.h:35
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
void av_buffer_default_free(void *opaque, uint8_t *data)
Default free callback, which calls av_free() on the buffer data.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define avpriv_atomic_ptr_cas
Definition: atomic_gcc.h:48
#define avpriv_atomic_int_get
Definition: atomic_gcc.h:28
Spectrum Plot time data
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
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.
int av_buffer_realloc(AVBufferRef **pbuf, int size)
Reallocate a given buffer.
static AVBufferRef * pool_alloc_buffer(AVBufferPool *pool)
int size
#define FFMIN(a, b)
Definition: common.h:58
ret
Definition: avfilter.c:821
int av_buffer_is_writable(const AVBufferRef *buf)
static void pool_release_buffer(void *opaque, uint8_t *data)
int flags
A combination of BUFFER_FLAG_*.
NULL
Definition: eval.c:55
void(* free)(void *opaque, uint8_t *data)
a callback for freeing the data
static void buffer_pool_free(AVBufferPool *pool)
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
volatile int nb_allocated
uint8_t * data
The data buffer.
Definition: buffer.h:89
int av_buffer_get_ref_count(const AVBufferRef *buf)
void * buf
Definition: avisynth_c.h:594
AVBufferRef * av_buffer_allocz(int size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
AVBuffer * buffer
Definition: buffer.h:82
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
void * av_buffer_get_opaque(const AVBufferRef *buf)
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
#define CONFIG_MEMORY_POISONING
Definition: config.h:383
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
int size
Size of data in bytes.
Definition: buffer.h:93
static int flags
Definition: cpu.c:23
volatile int refcount
void * opaque
an opaque pointer, to be used by the freeing callback
Synth Windw Norm while(pin< pend)%Until the end...%---Analysis x_w
A reference to a data buffer.
Definition: buffer.h:81
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:162
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.
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
int size
size of data in bytes
AVBufferRef *(* alloc)(int size)
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
void(* free)(void *opaque, uint8_t *data)
#define BUFFER_FLAG_REALLOCATABLE
The buffer was av_realloc()ed, so it is reallocatable.
MUSIC TECHNOLOGY GROUP UNIVERSITAT POMPEU FABRA Free Non Commercial Binary License Agreement UNIVERSITAT POMPEU OR INDICATING ACCEPTANCE BY SELECTING THE ACCEPT BUTTON ON ANY DOWNLOAD OR INSTALL YOU ACCEPT THE TERMS OF THE LICENSE SUMMARY TABLE Software MELODIA Melody Extraction vamp plug in Licensor Music Technology Group Universitat Pompeu Plaça de la Spain Permitted purposes Non commercial internal research and validation and educational purposes only All commercial uses in a production either internal or are prohibited by this license and require an additional commercial exploitation license TERMS AND CONDITIONS SOFTWARE Software means the software programs identified herein in binary any other machine readable any updates or error corrections provided by and any user programming guides and other documentation provided to you by UPF under this Agreement LICENSE Subject to the terms and conditions of this UPF grants you a royalty free
static BufferPoolEntry * get_pool(AVBufferPool *pool)