2 * a very simple circular buffer FIFO implementation
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4 * Copyright (c) 2006 Roman Shaposhnik
6 * This file is part of FFmpeg.
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.
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.
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
27 static AVFifoBuffer
*fifo_alloc_common(void *buffer
, size_t size
)
32 f
= av_mallocz(sizeof(AVFifoBuffer
));
38 f
->end
= f
->buffer
+ size
;
43 AVFifoBuffer
*av_fifo_alloc(unsigned int size
)
45 void *buffer
= av_malloc(size
);
46 return fifo_alloc_common(buffer
, size
);
49 AVFifoBuffer
*av_fifo_alloc_array(size_t nmemb
, size_t size
)
51 void *buffer
= av_malloc_array(nmemb
, size
);
52 return fifo_alloc_common(buffer
, nmemb
* size
);
55 void av_fifo_free(AVFifoBuffer
*f
)
63 void av_fifo_freep(AVFifoBuffer
**f
)
71 void av_fifo_reset(AVFifoBuffer
*f
)
73 f
->wptr
= f
->rptr
= f
->buffer
;
74 f
->wndx
= f
->rndx
= 0;
77 int av_fifo_size(const AVFifoBuffer
*f
)
79 return (uint32_t)(f
->wndx
- f
->rndx
);
82 int av_fifo_space(const AVFifoBuffer
*f
)
84 return f
->end
- f
->buffer
- av_fifo_size(f
);
87 int av_fifo_realloc2(AVFifoBuffer
*f
, unsigned int new_size
)
89 unsigned int old_size
= f
->end
- f
->buffer
;
91 if (old_size
< new_size
) {
92 int len
= av_fifo_size(f
);
93 AVFifoBuffer
*f2
= av_fifo_alloc(new_size
);
96 return AVERROR(ENOMEM
);
97 av_fifo_generic_read(f
, f2
->buffer
, len
, NULL
);
107 int av_fifo_grow(AVFifoBuffer
*f
, unsigned int size
)
109 unsigned int old_size
= f
->end
- f
->buffer
;
110 if(size
+ (unsigned)av_fifo_size(f
) < size
)
111 return AVERROR(EINVAL
);
113 size
+= av_fifo_size(f
);
116 return av_fifo_realloc2(f
, FFMAX(size
, 2*size
));
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))
126 uint32_t wndx
= f
->wndx
;
127 uint8_t *wptr
= f
->wptr
;
130 int len
= FFMIN(f
->end
- wptr
, size
);
132 if (func(src
, wptr
, len
) <= 0)
135 memcpy(wptr
, src
, len
);
136 src
= (uint8_t *)src
+ len
;
138 // Write memory barrier needed for SMP here in theory
150 int av_fifo_generic_read(AVFifoBuffer
*f
, void *dest
, int buf_size
,
151 void (*func
)(void *, void *, int))
153 // Read memory barrier needed for SMP here in theory
155 int len
= FFMIN(f
->end
- f
->rptr
, buf_size
);
157 func(dest
, f
->rptr
, len
);
159 memcpy(dest
, f
->rptr
, len
);
160 dest
= (uint8_t *)dest
+ len
;
162 // memory barrier needed for SMP here in theory
163 av_fifo_drain(f
, len
);
165 } while (buf_size
> 0);
169 /** Discard data from the FIFO. */
170 void av_fifo_drain(AVFifoBuffer
*f
, int size
)
172 av_assert2(av_fifo_size(f
) >= size
);
174 if (f
->rptr
>= f
->end
)
175 f
->rptr
-= f
->end
- f
->buffer
;
183 /* create a FIFO buffer */
184 AVFifoBuffer
*fifo
= av_fifo_alloc(13 * sizeof(int));
188 for (i
= 0; av_fifo_space(fifo
) >= sizeof(int); i
++)
189 av_fifo_generic_write(fifo
, &i
, sizeof(int), NULL
);
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
);
200 for (i
= 0; av_fifo_size(fifo
) >= sizeof(int); i
++) {
201 av_fifo_generic_read(fifo
, &j
, sizeof(int), NULL
);