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