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
#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
void
av_buffer_unref
(
AVBufferRef
**buf)
107
{
108
AVBuffer
*
b
;
109
110
if
(!buf || !*buf)
111
return
;
112
b = (*buf)->buffer;
113
av_freep
(buf);
114
115
if
(!
avpriv_atomic_int_add_and_fetch
(&b->
refcount
, -1)) {
116
b->
free
(b->
opaque
, b->
data
);
117
av_freep
(&b);
118
}
119
}
120
121
int
av_buffer_is_writable
(
const
AVBufferRef
*buf)
122
{
123
if
(buf->
buffer
->
flags
&
AV_BUFFER_FLAG_READONLY
)
124
return
0;
125
126
return
avpriv_atomic_int_add_and_fetch
(&buf->
buffer
->
refcount
, 0) == 1;
127
}
128
129
int
av_buffer_make_writable
(
AVBufferRef
**pbuf)
130
{
131
AVBufferRef
*newbuf, *buf = *pbuf;
132
133
if
(
av_buffer_is_writable
(buf))
134
return
0;
135
136
newbuf =
av_buffer_alloc
(buf->
size
);
137
if
(!newbuf)
138
return
AVERROR
(ENOMEM);
139
140
memcpy(newbuf->
data
, buf->
data
, buf->
size
);
141
av_buffer_unref
(pbuf);
142
*pbuf = newbuf;
143
144
return
0;
145
}
146
147
int
av_buffer_realloc
(
AVBufferRef
**pbuf,
int
size)
148
{
149
AVBufferRef
*buf = *pbuf;
150
uint8_t
*tmp;
151
152
if
(!buf) {
153
/* allocate a new buffer with av_realloc(), so it will be reallocatable
154
* later */
155
uint8_t
*data =
av_realloc
(
NULL
, size);
156
if
(!data)
157
return
AVERROR
(ENOMEM);
158
159
buf =
av_buffer_create
(data, size,
av_buffer_default_free
,
NULL
, 0);
160
if
(!buf) {
161
av_freep
(&data);
162
return
AVERROR
(ENOMEM);
163
}
164
165
buf->
buffer
->
flags
|=
BUFFER_FLAG_REALLOCATABLE
;
166
*pbuf = buf;
167
168
return
0;
169
}
else
if
(buf->
size
== size)
170
return
0;
171
172
if
(!(buf->
buffer
->
flags
&
BUFFER_FLAG_REALLOCATABLE
) ||
173
!
av_buffer_is_writable
(buf)) {
174
/* cannot realloc, allocate a new reallocable buffer and copy data */
175
AVBufferRef
*
new
=
NULL
;
176
177
av_buffer_realloc
(&
new
, size);
178
if
(!
new
)
179
return
AVERROR
(ENOMEM);
180
181
memcpy(new->data, buf->
data
,
FFMIN
(size, buf->
size
));
182
183
av_buffer_unref
(pbuf);
184
*pbuf =
new
;
185
return
0;
186
}
187
188
tmp =
av_realloc
(buf->
buffer
->
data
, size);
189
if
(!tmp)
190
return
AVERROR
(ENOMEM);
191
192
buf->
buffer
->
data
= buf->
data
= tmp;
193
buf->
buffer
->
size
= buf->
size
=
size
;
194
return
0;
195
}
196
197
AVBufferPool
*
av_buffer_pool_init
(
int
size,
AVBufferRef
* (*alloc)(
int
size))
198
{
199
AVBufferPool
*pool =
av_mallocz
(
sizeof
(*pool));
200
if
(!pool)
201
return
NULL
;
202
203
ff_mutex_init
(&pool->
mutex
,
NULL
);
204
205
pool->
size
=
size
;
206
pool->
alloc
= alloc ? alloc :
av_buffer_alloc
;
207
208
avpriv_atomic_int_set
(&pool->
refcount
, 1);
209
210
return
pool;
211
}
212
213
/*
214
* This function gets called when the pool has been uninited and
215
* all the buffers returned to it.
216
*/
217
static
void
buffer_pool_free
(
AVBufferPool
*pool)
218
{
219
while
(pool->
pool
) {
220
BufferPoolEntry
*buf = pool->
pool
;
221
pool->
pool
= buf->
next
;
222
223
buf->
free
(buf->
opaque
, buf->
data
);
224
av_freep
(&buf);
225
}
226
ff_mutex_destroy
(&pool->
mutex
);
227
av_freep
(&pool);
228
}
229
230
void
av_buffer_pool_uninit
(
AVBufferPool
**ppool)
231
{
232
AVBufferPool
*pool;
233
234
if
(!ppool || !*ppool)
235
return
;
236
pool = *ppool;
237
*ppool =
NULL
;
238
239
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
240
buffer_pool_free
(pool);
241
}
242
243
static
void
pool_release_buffer
(
void
*opaque,
uint8_t
*data)
244
{
245
BufferPoolEntry
*buf = opaque;
246
AVBufferPool
*pool = buf->
pool
;
247
248
ff_mutex_lock
(&pool->
mutex
);
249
buf->
next
= pool->
pool
;
250
pool->
pool
= buf;
251
ff_mutex_unlock
(&pool->
mutex
);
252
253
if
(!
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, -1))
254
buffer_pool_free
(pool);
255
}
256
257
/* allocate a new buffer and override its free() callback so that
258
* it is returned to the pool on free */
259
static
AVBufferRef
*
pool_alloc_buffer
(
AVBufferPool
*pool)
260
{
261
BufferPoolEntry
*buf;
262
AVBufferRef
*ret;
263
264
ret = pool->
alloc
(pool->
size
);
265
if
(!ret)
266
return
NULL
;
267
268
buf =
av_mallocz
(
sizeof
(*buf));
269
if
(!buf) {
270
av_buffer_unref
(&ret);
271
return
NULL
;
272
}
273
274
buf->
data
= ret->
buffer
->
data
;
275
buf->
opaque
= ret->
buffer
->
opaque
;
276
buf->
free
= ret->
buffer
->
free
;
277
buf->
pool
= pool;
278
279
ret->
buffer
->
opaque
= buf;
280
ret->
buffer
->
free
=
pool_release_buffer
;
281
282
return
ret;
283
}
284
285
AVBufferRef
*
av_buffer_pool_get
(
AVBufferPool
*pool)
286
{
287
AVBufferRef
*ret;
288
BufferPoolEntry
*buf;
289
290
ff_mutex_lock
(&pool->
mutex
);
291
buf = pool->
pool
;
292
if
(buf) {
293
ret =
av_buffer_create
(buf->
data
, pool->
size
,
pool_release_buffer
,
294
buf, 0);
295
if
(ret) {
296
pool->
pool
= buf->
next
;
297
buf->
next
=
NULL
;
298
}
299
}
else
{
300
ret =
pool_alloc_buffer
(pool);
301
}
302
ff_mutex_unlock
(&pool->
mutex
);
303
304
if
(ret)
305
avpriv_atomic_int_add_and_fetch
(&pool->
refcount
, 1);
306
307
return
ret;
308
}
Generated on Tue Mar 1 2016 21:14:48 for Libav by
1.8.4