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 Sep 14 2014 18:56:09 for FFmpeg by
1.8.2