FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
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
#include "
thread.h
"
27
28
AVBufferRef
*
av_buffer_create
(
uint8_t
*
data
,
int
size
,
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
buf->
refcount
= 1;
44
45
if
(flags &
AV_BUFFER_FLAG_READONLY
)
46
buf->
flags
|=
BUFFER_FLAG_READONLY
;
47
48
ref =
av_mallocz
(
sizeof
(*ref));
49
if
(!ref) {
50
av_freep
(&buf);
51
return
NULL
;
52
}
53
54
ref->
buffer
=
buf
;
55
ref->
data
=
data
;
56
ref->
size
=
size
;
57
58
return
ref;
59
}
60
61
void
av_buffer_default_free
(
void
*opaque,
uint8_t
*data)
62
{
63
av_free
(data);
64
}
65
66
AVBufferRef
*
av_buffer_alloc
(
int
size)
67
{
68
AVBufferRef
*
ret
=
NULL
;
69
uint8_t
*data =
NULL
;
70
71
data =
av_malloc
(size);
72
if
(!data)
73
return
NULL
;
74
75
ret =
av_buffer_create
(data, size,
av_buffer_default_free
,
NULL
, 0);
76
if
(!ret)
77
av_freep
(&data);
78
79
return
ret
;
80
}
81
82
AVBufferRef
*
av_buffer_allocz
(
int
size)
83
{
84
AVBufferRef
*
ret
=
av_buffer_alloc
(size);
85
if
(!ret)
86
return
NULL
;
87
88
memset(ret->
data
, 0, size);
89
return
ret
;
90
}
91
92
AVBufferRef
*
av_buffer_ref
(
AVBufferRef
*
buf
)
93
{
94
AVBufferRef
*
ret
=
av_mallocz
(
sizeof
(*ret));
95
96
if
(!ret)
97
return
NULL
;
98
99
*ret = *
buf
;
100
101
avpriv_atomic_int_add_and_fetch
(&buf->
buffer
->
refcount
, 1);
102
103
return
ret
;
104
}
105
106
static
void
buffer_replace
(
AVBufferRef
**dst,
AVBufferRef
**
src
)
107
{
108
AVBuffer
*
b
;
109
110
b = (*dst)->buffer;
111
112
if
(src) {
113
**dst = **
src
;
114
av_freep
(src);
115
}
else
116
av_freep
(dst);
117
118
if
(!
avpriv_atomic_int_add_and_fetch
(&b->
refcount
, -1)) {
119
b->
free
(b->
opaque
, b->
data
);
120
av_freep
(&b);
121
}
122
}
123
124
void
av_buffer_unref
(
AVBufferRef
**
buf
)
125
{
126
if
(!buf || !*buf)
127
return
;
128
129
buffer_replace
(buf,
NULL
);
130
}
131
132
int
av_buffer_is_writable
(
const
AVBufferRef
*
buf
)
133
{
134
if
(buf->
buffer
->
flags
&
AV_BUFFER_FLAG_READONLY
)
135
return
0;
136
137
return
avpriv_atomic_int_get
(&buf->
buffer
->
refcount
) == 1;
138
}
139
140
void
*
av_buffer_get_opaque
(
const
AVBufferRef
*
buf
)
141
{
142
return
buf->
buffer
->
opaque
;
143
}
144
145
int
av_buffer_get_ref_count
(
const
AVBufferRef
*
buf
)
146
{
147
return
buf->
buffer
->
refcount
;
148
}
149
150
int
av_buffer_make_writable
(
AVBufferRef
**pbuf)
151
{
152
AVBufferRef
*newbuf, *
buf
= *pbuf;
153
154
if
(
av_buffer_is_writable
(buf))
155
return
0;
156
157
newbuf =
av_buffer_alloc
(buf->
size
);
158
if
(!newbuf)
159
return
AVERROR
(ENOMEM);
160
161
memcpy(newbuf->
data
, buf->
data
, buf->
size
);
162
av_buffer_unref
(pbuf);
163
*pbuf = newbuf;
164
165
return
0;
166
}
167
168
int
av_buffer_realloc
(
AVBufferRef
**pbuf,
int
size)
169
{
170
AVBufferRef
*
buf
= *pbuf;
171
uint8_t
*tmp;
172
173
if
(!buf) {
174
/* allocate a new buffer with av_realloc(), so it will be reallocatable
175
* later */
176
uint8_t
*data =
av_realloc
(
NULL
, size);
177
if
(!data)
178
return
AVERROR
(ENOMEM);
179
180
buf =
av_buffer_create
(data, size,
av_buffer_default_free
,
NULL
, 0);
181
if
(!buf) {
182
av_freep
(&data);
183
return
AVERROR
(ENOMEM);
184
}
185
186
buf->
buffer
->
flags
|=
BUFFER_FLAG_REALLOCATABLE
;
187
*pbuf =
buf
;
188
189
return
0;
190
}
else
if
(buf->
size
== size)
191
return
0;
192
193
if
(!(buf->
buffer
->
flags
&
BUFFER_FLAG_REALLOCATABLE
) ||
194
!
av_buffer_is_writable
(buf)) {
195
/* cannot realloc, allocate a new reallocable buffer and copy data */
196
AVBufferRef
*
new
=
NULL
;
197
198
av_buffer_realloc
(&
new
, size);
199
if
(!
new
)
200
return
AVERROR
(ENOMEM);
201
202
memcpy(new->data, buf->
data
,
FFMIN
(size, buf->
size
));
203
204
av_buffer_unref
(pbuf);
205
*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_init
(
int
size,
AVBufferRef
* (*alloc)(
int
size))
219
{
220
AVBufferPool
*pool =
av_mallocz
(
sizeof
(*pool));
221
if
(!pool)
222
return
NULL
;
223
224
ff_mutex_init
(&pool->
mutex
,
NULL
);
225
226
pool->
size
=
size
;
227
pool->
alloc
= alloc ? alloc :
av_buffer_alloc
;
228
229
avpriv_atomic_int_set
(&pool->
refcount
, 1);
230
231
return
pool;
232
}
233
234
/*
235
* This function gets called when the pool has been uninited and
236
* all the buffers returned to it.
237
*/
238
static
void
buffer_pool_free
(
AVBufferPool
*pool)
239
{
240
while
(pool->
pool
) {
241
BufferPoolEntry
*
buf
= pool->
pool
;
242
pool->
pool
= buf->
next
;
243
244
buf->
free
(buf->
opaque
, buf->
data
);
245
av_freep
(&buf);
246
}
247
ff_mutex_destroy
(&pool->
mutex
);
248
av_freep
(&pool);
249
}
250
251
void
av_buffer_pool_uninit
(
AVBufferPool
**ppool)
252
{
253
AVBufferPool
*pool;
254
255
if
(!ppool || !*ppool)
256
return
;
257
pool = *ppool;
258
*ppool =
NULL
;
259
260
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
261
buffer_pool_free
(pool);
262
}
263
264
#if USE_ATOMICS
265
/* remove the whole buffer list from the pool and return it */
266
static
BufferPoolEntry
*
get_pool
(
AVBufferPool
*pool)
267
{
268
BufferPoolEntry
*cur = *(
void
*
volatile
*)&pool->
pool
, *last =
NULL
;
269
270
while (cur != last) {
271
last = cur;
272
cur =
avpriv_atomic_ptr_cas
((
void
*
volatile
*)&pool->
pool
, last,
NULL
);
273
if
(!cur)
274
return
NULL
;
275
}
276
277
return
cur;
278
}
279
280
static
void
add_to_pool
(
BufferPoolEntry
*
buf
)
281
{
282
AVBufferPool
*pool;
283
BufferPoolEntry
*cur, *
end
=
buf
;
284
285
if
(!buf)
286
return
;
287
pool = buf->
pool
;
288
289
while
(end->
next
)
290
end = end->
next
;
291
292
while
(
avpriv_atomic_ptr_cas
((
void
*
volatile
*)&pool->
pool
,
NULL
, buf)) {
293
/* pool is not empty, retrieve it and append it to our list */
294
cur =
get_pool
(pool);
295
end->
next
= cur;
296
while
(end->
next
)
297
end = end->
next
;
298
}
299
}
300
#endif
301
302
static
void
pool_release_buffer
(
void
*opaque,
uint8_t
*data)
303
{
304
BufferPoolEntry
*
buf
= opaque;
305
AVBufferPool
*pool = buf->
pool
;
306
307
if
(CONFIG_MEMORY_POISONING)
308
memset(buf->
data
,
FF_MEMORY_POISON
, pool->
size
);
309
310
#if USE_ATOMICS
311
add_to_pool
(buf);
312
#else
313
ff_mutex_lock
(&pool->
mutex
);
314
buf->
next
= pool->
pool
;
315
pool->
pool
=
buf
;
316
ff_mutex_unlock
(&pool->
mutex
);
317
#endif
318
319
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
320
buffer_pool_free
(pool);
321
}
322
323
/* allocate a new buffer and override its free() callback so that
324
* it is returned to the pool on free */
325
static
AVBufferRef
*
pool_alloc_buffer
(
AVBufferPool
*pool)
326
{
327
BufferPoolEntry
*
buf
;
328
AVBufferRef
*
ret
;
329
330
ret = pool->
alloc
(pool->
size
);
331
if
(!ret)
332
return
NULL
;
333
334
buf =
av_mallocz
(
sizeof
(*buf));
335
if
(!buf) {
336
av_buffer_unref
(&ret);
337
return
NULL
;
338
}
339
340
buf->
data
= ret->
buffer
->
data
;
341
buf->
opaque
= ret->
buffer
->
opaque
;
342
buf->
free
= ret->
buffer
->
free
;
343
buf->
pool
= pool;
344
345
ret->
buffer
->
opaque
=
buf
;
346
ret->
buffer
->
free
=
pool_release_buffer
;
347
348
#if USE_ATOMICS
349
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, 1);
350
avpriv_atomic_int_add_and_fetch
(&pool->
nb_allocated
, 1);
351
#endif
352
353
return
ret
;
354
}
355
356
AVBufferRef
*
av_buffer_pool_get
(
AVBufferPool
*pool)
357
{
358
AVBufferRef
*
ret
;
359
BufferPoolEntry
*
buf
;
360
361
#if USE_ATOMICS
362
/* check whether the pool is empty */
363
buf =
get_pool
(pool);
364
if
(!buf && pool->
refcount
<= pool->
nb_allocated
) {
365
av_log
(
NULL
,
AV_LOG_DEBUG
,
"Pool race dectected, spining to avoid overallocation and eventual OOM\n"
);
366
while
(!buf &&
avpriv_atomic_int_get
(&pool->
refcount
) <=
avpriv_atomic_int_get
(&pool->
nb_allocated
))
367
buf =
get_pool
(pool);
368
}
369
370
if
(!buf)
371
return
pool_alloc_buffer
(pool);
372
373
/* keep the first entry, return the rest of the list to the pool */
374
add_to_pool
(buf->
next
);
375
buf->
next
=
NULL
;
376
377
ret =
av_buffer_create
(buf->
data
, pool->
size
,
pool_release_buffer
,
378
buf, 0);
379
if
(!ret) {
380
add_to_pool
(buf);
381
return
NULL
;
382
}
383
#else
384
ff_mutex_lock
(&pool->
mutex
);
385
buf = pool->
pool
;
386
if
(buf) {
387
ret =
av_buffer_create
(buf->
data
, pool->
size
,
pool_release_buffer
,
388
buf, 0);
389
if
(ret) {
390
pool->
pool
= buf->
next
;
391
buf->
next
=
NULL
;
392
}
393
}
else
{
394
ret =
pool_alloc_buffer
(pool);
395
}
396
ff_mutex_unlock
(&pool->
mutex
);
397
#endif
398
399
if
(ret)
400
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, 1);
401
402
return
ret
;
403
}
Generated on Sun Mar 8 2015 02:35:05 for FFmpeg by
1.8.2