Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavutil
buffer.c
Go to the documentation of this file.
1
/*
2
* This file is part of Libav.
3
*
4
* Libav 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
* Libav 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 Libav; 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
27
AVBufferRef
*
av_buffer_create
(
uint8_t
*
data
,
int
size
,
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
;
40
buf->
free
= free ? free :
av_buffer_default_free
;
41
buf->
opaque
= opaque;
42
buf->
refcount
= 1;
43
44
if
(flags &
AV_BUFFER_FLAG_READONLY
)
45
buf->
flags
|=
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
65
AVBufferRef
*
av_buffer_alloc
(
int
size)
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
81
AVBufferRef
*
av_buffer_allocz
(
int
size)
82
{
83
AVBufferRef
*ret =
av_buffer_alloc
(size);
84
if
(!ret)
85
return
NULL
;
86
87
memset(ret->
data
, 0, size);
88
return
ret;
89
}
90
91
AVBufferRef
*
av_buffer_ref
(
AVBufferRef
*buf)
92
{
93
AVBufferRef
*ret =
av_mallocz
(
sizeof
(*ret));
94
95
if
(!ret)
96
return
NULL
;
97
98
*ret = *buf;
99
100
avpriv_atomic_int_add_and_fetch
(&buf->
buffer
->
refcount
, 1);
101
102
return
ret;
103
}
104
105
void
av_buffer_unref
(
AVBufferRef
**buf)
106
{
107
AVBuffer
*
b
;
108
109
if
(!buf || !*buf)
110
return
;
111
b = (*buf)->buffer;
112
av_freep
(buf);
113
114
if
(!
avpriv_atomic_int_add_and_fetch
(&b->
refcount
, -1)) {
115
b->
free
(b->
opaque
, b->
data
);
116
av_freep
(&b);
117
}
118
}
119
120
int
av_buffer_is_writable
(
const
AVBufferRef
*buf)
121
{
122
if
(buf->
buffer
->
flags
&
AV_BUFFER_FLAG_READONLY
)
123
return
0;
124
125
return
avpriv_atomic_int_add_and_fetch
(&buf->
buffer
->
refcount
, 0) == 1;
126
}
127
128
int
av_buffer_make_writable
(
AVBufferRef
**pbuf)
129
{
130
AVBufferRef
*newbuf, *buf = *pbuf;
131
132
if
(
av_buffer_is_writable
(buf))
133
return
0;
134
135
newbuf =
av_buffer_alloc
(buf->
size
);
136
if
(!newbuf)
137
return
AVERROR
(ENOMEM);
138
139
memcpy(newbuf->
data
, buf->
data
, buf->
size
);
140
av_buffer_unref
(pbuf);
141
*pbuf = newbuf;
142
143
return
0;
144
}
145
146
int
av_buffer_realloc
(
AVBufferRef
**pbuf,
int
size)
147
{
148
AVBufferRef
*buf = *pbuf;
149
uint8_t
*tmp;
150
151
if
(!buf) {
152
/* allocate a new buffer with av_realloc(), so it will be reallocatable
153
* later */
154
uint8_t
*data =
av_realloc
(
NULL
, size);
155
if
(!data)
156
return
AVERROR
(ENOMEM);
157
158
buf =
av_buffer_create
(data, size,
av_buffer_default_free
,
NULL
, 0);
159
if
(!buf) {
160
av_freep
(&data);
161
return
AVERROR
(ENOMEM);
162
}
163
164
buf->
buffer
->
flags
|=
BUFFER_FLAG_REALLOCATABLE
;
165
*pbuf = buf;
166
167
return
0;
168
}
else
if
(buf->
size
== size)
169
return
0;
170
171
if
(!(buf->
buffer
->
flags
&
BUFFER_FLAG_REALLOCATABLE
) ||
172
!
av_buffer_is_writable
(buf)) {
173
/* cannot realloc, allocate a new reallocable buffer and copy data */
174
AVBufferRef
*
new
=
NULL
;
175
176
av_buffer_realloc
(&
new
, size);
177
if
(!
new
)
178
return
AVERROR
(ENOMEM);
179
180
memcpy(new->data, buf->
data
,
FFMIN
(size, buf->
size
));
181
182
av_buffer_unref
(pbuf);
183
*pbuf =
new
;
184
return
0;
185
}
186
187
tmp =
av_realloc
(buf->
buffer
->
data
, size);
188
if
(!tmp)
189
return
AVERROR
(ENOMEM);
190
191
buf->
buffer
->
data
= buf->
data
= tmp;
192
buf->
buffer
->
size
= buf->
size
=
size
;
193
return
0;
194
}
195
196
AVBufferPool
*
av_buffer_pool_init
(
int
size,
AVBufferRef
* (*alloc)(
int
size))
197
{
198
AVBufferPool
*pool =
av_mallocz
(
sizeof
(*pool));
199
if
(!pool)
200
return
NULL
;
201
202
pool->
size
=
size
;
203
pool->
alloc
= alloc ? alloc :
av_buffer_alloc
;
204
205
avpriv_atomic_int_set
(&pool->
refcount
, 1);
206
207
return
pool;
208
}
209
210
/*
211
* This function gets called when the pool has been uninited and
212
* all the buffers returned to it.
213
*/
214
static
void
buffer_pool_free
(
AVBufferPool
*pool)
215
{
216
while
(pool->
pool
) {
217
BufferPoolEntry
*buf = pool->
pool
;
218
pool->
pool
= buf->
next
;
219
220
buf->
free
(buf->
opaque
, buf->
data
);
221
av_freep
(&buf);
222
}
223
av_freep
(&pool);
224
}
225
226
void
av_buffer_pool_uninit
(
AVBufferPool
**ppool)
227
{
228
AVBufferPool
*pool;
229
230
if
(!ppool || !*ppool)
231
return
;
232
pool = *ppool;
233
*ppool =
NULL
;
234
235
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
236
buffer_pool_free
(pool);
237
}
238
239
/* remove the whole buffer list from the pool and return it */
240
static
BufferPoolEntry
*
get_pool
(
AVBufferPool
*pool)
241
{
242
BufferPoolEntry
*cur =
NULL
, *last =
NULL
;
243
244
do
{
245
FFSWAP
(
BufferPoolEntry
*, cur, last);
246
cur =
avpriv_atomic_ptr_cas
((
void
*
volatile
*)&pool->
pool
, last,
NULL
);
247
if
(!cur)
248
return
NULL
;
249
}
while
(cur != last);
250
251
return
cur;
252
}
253
254
static
void
add_to_pool
(
BufferPoolEntry
*buf)
255
{
256
AVBufferPool
*pool;
257
BufferPoolEntry
*cur, *end = buf;
258
259
if
(!buf)
260
return
;
261
pool = buf->
pool
;
262
263
while
(end->
next
)
264
end = end->
next
;
265
266
while
((cur =
avpriv_atomic_ptr_cas
((
void
*
volatile
*)&pool->
pool
,
NULL
, buf))) {
267
/* pool is not empty, retrieve it and append it to our list */
268
cur =
get_pool
(pool);
269
end->
next
= cur;
270
while
(end->
next
)
271
end = end->
next
;
272
}
273
}
274
275
static
void
pool_release_buffer
(
void
*opaque,
uint8_t
*data)
276
{
277
BufferPoolEntry
*buf = opaque;
278
AVBufferPool
*pool = buf->
pool
;
279
add_to_pool
(buf);
280
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
281
buffer_pool_free
(pool);
282
}
283
284
/* allocate a new buffer and override its free() callback so that
285
* it is returned to the pool on free */
286
static
AVBufferRef
*
pool_alloc_buffer
(
AVBufferPool
*pool)
287
{
288
BufferPoolEntry
*buf;
289
AVBufferRef
*ret;
290
291
ret = pool->
alloc
(pool->
size
);
292
if
(!ret)
293
return
NULL
;
294
295
buf =
av_mallocz
(
sizeof
(*buf));
296
if
(!buf) {
297
av_buffer_unref
(&ret);
298
return
NULL
;
299
}
300
301
buf->
data
= ret->
buffer
->
data
;
302
buf->
opaque
= ret->
buffer
->
opaque
;
303
buf->
free
= ret->
buffer
->
free
;
304
buf->
pool
= pool;
305
306
ret->
buffer
->
opaque
= buf;
307
ret->
buffer
->
free
=
pool_release_buffer
;
308
309
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, 1);
310
311
return
ret;
312
}
313
314
AVBufferRef
*
av_buffer_pool_get
(
AVBufferPool
*pool)
315
{
316
AVBufferRef
*ret;
317
BufferPoolEntry
*buf;
318
319
/* check whether the pool is empty */
320
buf =
get_pool
(pool);
321
if
(!buf)
322
return
pool_alloc_buffer
(pool);
323
324
/* keep the first entry, return the rest of the list to the pool */
325
add_to_pool
(buf->
next
);
326
buf->
next
=
NULL
;
327
328
ret =
av_buffer_create
(buf->
data
, pool->
size
,
pool_release_buffer
,
329
buf, 0);
330
if
(!ret) {
331
add_to_pool
(buf);
332
return
NULL
;
333
}
334
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, 1);
335
336
return
ret;
337
}
Generated on Sun Jun 1 2014 17:55:35 for Libav by
1.8.1.2