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
fifo.c
Go to the documentation of this file.
1
/*
2
* a very simple circular buffer FIFO implementation
3
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4
* Copyright (c) 2006 Roman Shaposhnik
5
*
6
* This file is part of FFmpeg.
7
*
8
* FFmpeg is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* FFmpeg is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with FFmpeg; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
#include "
avassert.h
"
24
#include "
common.h
"
25
#include "
fifo.h
"
26
27
static
AVFifoBuffer
*
fifo_alloc_common
(
void
*
buffer
,
size_t
size
)
28
{
29
AVFifoBuffer
*f;
30
if
(!buffer)
31
return
NULL;
32
f =
av_mallocz
(
sizeof
(
AVFifoBuffer
));
33
if
(!f) {
34
av_free
(buffer);
35
return
NULL;
36
}
37
f->
buffer
=
buffer
;
38
f->
end
= f->
buffer
+
size
;
39
av_fifo_reset
(f);
40
return
f;
41
}
42
43
AVFifoBuffer
*
av_fifo_alloc
(
unsigned
int
size
)
44
{
45
void
*
buffer
=
av_malloc
(size);
46
return
fifo_alloc_common
(buffer, size);
47
}
48
49
AVFifoBuffer
*
av_fifo_alloc_array
(
size_t
nmemb,
size_t
size
)
50
{
51
void
*
buffer
=
av_malloc_array
(nmemb, size);
52
return
fifo_alloc_common
(buffer, nmemb * size);
53
}
54
55
void
av_fifo_free
(
AVFifoBuffer
*f)
56
{
57
if
(f) {
58
av_freep
(&f->
buffer
);
59
av_free
(f);
60
}
61
}
62
63
void
av_fifo_freep
(
AVFifoBuffer
**f)
64
{
65
if
(f) {
66
av_fifo_free
(*f);
67
*f = NULL;
68
}
69
}
70
71
void
av_fifo_reset
(
AVFifoBuffer
*f)
72
{
73
f->
wptr
= f->
rptr
= f->
buffer
;
74
f->
wndx
= f->
rndx
= 0;
75
}
76
77
int
av_fifo_size
(
FF_CONST_AVUTIL53
AVFifoBuffer
*f)
78
{
79
return
(uint32_t)(f->wndx - f->rndx);
80
}
81
82
int
av_fifo_space
(
FF_CONST_AVUTIL53
AVFifoBuffer
*f)
83
{
84
return
f->end - f->buffer -
av_fifo_size
(f);
85
}
86
87
int
av_fifo_realloc2
(
AVFifoBuffer
*f,
unsigned
int
new_size)
88
{
89
unsigned
int
old_size = f->
end
- f->
buffer
;
90
91
if
(old_size < new_size) {
92
int
len
=
av_fifo_size
(f);
93
AVFifoBuffer
*f2 =
av_fifo_alloc
(new_size);
94
95
if
(!f2)
96
return
AVERROR
(ENOMEM);
97
av_fifo_generic_read
(f, f2->
buffer
, len, NULL);
98
f2->
wptr
+=
len
;
99
f2->
wndx
+=
len
;
100
av_free
(f->
buffer
);
101
*f = *f2;
102
av_free
(f2);
103
}
104
return
0;
105
}
106
107
int
av_fifo_grow
(
AVFifoBuffer
*f,
unsigned
int
size
)
108
{
109
unsigned
int
old_size = f->
end
- f->
buffer
;
110
if
(size + (
unsigned
)
av_fifo_size
(f) < size)
111
return
AVERROR
(EINVAL);
112
113
size +=
av_fifo_size
(f);
114
115
if
(old_size < size)
116
return
av_fifo_realloc2
(f,
FFMAX
(size, 2*size));
117
return
0;
118
}
119
120
/* src must NOT be const as it can be a context for func that may need
121
* updating (like a pointer or byte counter) */
122
int
av_fifo_generic_write
(
AVFifoBuffer
*f,
void
*
src
,
int
size
,
123
int
(*
func
)(
void
*,
void
*,
int
))
124
{
125
int
total =
size
;
126
uint32_t wndx= f->
wndx
;
127
uint8_t
*wptr= f->
wptr
;
128
129
do
{
130
int
len
=
FFMIN
(f->
end
- wptr, size);
131
if
(
func
) {
132
if
(
func
(src, wptr, len) <= 0)
133
break
;
134
}
else
{
135
memcpy(wptr, src, len);
136
src = (
uint8_t
*)src + len;
137
}
138
// Write memory barrier needed for SMP here in theory
139
wptr +=
len
;
140
if
(wptr >= f->
end
)
141
wptr = f->
buffer
;
142
wndx +=
len
;
143
size -=
len
;
144
}
while
(size > 0);
145
f->
wndx
= wndx;
146
f->
wptr
= wptr;
147
return
total -
size
;
148
}
149
150
int
av_fifo_generic_read
(
AVFifoBuffer
*f,
void
*dest,
int
buf_size,
151
void
(*
func
)(
void
*,
void
*,
int
))
152
{
153
// Read memory barrier needed for SMP here in theory
154
do
{
155
int
len
=
FFMIN
(f->
end
- f->
rptr
, buf_size);
156
if
(
func
)
157
func
(dest, f->
rptr
, len);
158
else
{
159
memcpy(dest, f->
rptr
, len);
160
dest = (
uint8_t
*)dest + len;
161
}
162
// memory barrier needed for SMP here in theory
163
av_fifo_drain
(f, len);
164
buf_size -=
len
;
165
}
while
(buf_size > 0);
166
return
0;
167
}
168
169
/** Discard data from the FIFO. */
170
void
av_fifo_drain
(
AVFifoBuffer
*f,
int
size)
171
{
172
av_assert2
(
av_fifo_size
(f) >= size);
173
f->
rptr
+=
size
;
174
if
(f->
rptr
>= f->
end
)
175
f->
rptr
-= f->
end
- f->
buffer
;
176
f->
rndx
+=
size
;
177
}
178
179
#ifdef TEST
180
181
int
main
(
void
)
182
{
183
/* create a FIFO buffer */
184
AVFifoBuffer
*fifo =
av_fifo_alloc
(13 *
sizeof
(
int
));
185
int
i, j,
n
;
186
187
/* fill data */
188
for
(i = 0;
av_fifo_space
(fifo) >=
sizeof
(int); i++)
189
av_fifo_generic_write
(fifo, &i,
sizeof
(
int
), NULL);
190
191
/* peek at FIFO */
192
n =
av_fifo_size
(fifo) /
sizeof
(int);
193
for
(i = -n + 1; i <
n
; i++) {
194
int
*
v
= (
int
*)
av_fifo_peek2
(fifo, i *
sizeof
(
int
));
195
printf(
"%d: %d\n"
, i, *v);
196
}
197
printf(
"\n"
);
198
199
/* read data */
200
for
(i = 0;
av_fifo_size
(fifo) >=
sizeof
(int); i++) {
201
av_fifo_generic_read
(fifo, &j,
sizeof
(
int
), NULL);
202
printf(
"%d "
, j);
203
}
204
printf(
"\n"
);
205
206
av_fifo_free
(fifo);
207
208
return
0;
209
}
210
211
#endif
Generated on Sun Jul 20 2014 23:06:00 for FFmpeg by
1.8.2