1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*
* a very simple circular buffer FIFO implementation
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
* Copyright (c) 2006 Roman Shaposhnik
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "common.h"
#include "fifo.h"
int av_fifo_init(AVFifoBuffer *f, unsigned int size)
{
f->wptr = f->rptr =
f->buffer = av_malloc(size);
f->end = f->buffer + size;
f->rndx = f->wndx = 0;
if (!f->buffer)
return -1;
return 0;
}
void av_fifo_free(AVFifoBuffer *f)
{
av_free(f->buffer);
}
int av_fifo_size(AVFifoBuffer *f)
{
return (uint32_t)(f->wndx - f->rndx);
}
int av_fifo_read(AVFifoBuffer *f, uint8_t *buf, int buf_size)
{
return av_fifo_generic_read(f, buf_size, NULL, buf);
}
#if LIBAVUTIL_VERSION_MAJOR < 50
void av_fifo_realloc(AVFifoBuffer *f, unsigned int new_size) {
av_fifo_realloc2(f, new_size);
}
#endif
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) {
unsigned int old_size= f->end - f->buffer;
if(old_size < new_size){
int len= av_fifo_size(f);
AVFifoBuffer f2;
if (av_fifo_init(&f2, new_size) < 0)
return -1;
av_fifo_read(f, f2.buffer, len);
f2.wptr += len;
f2.wndx += len;
av_free(f->buffer);
*f= f2;
}
return 0;
}
#if LIBAVUTIL_VERSION_MAJOR < 50
void av_fifo_write(AVFifoBuffer *f, const uint8_t *buf, int size)
{
av_fifo_generic_write(f, (void *)buf, size, NULL);
}
#endif
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int))
{
int total = size;
do {
int len = FFMIN(f->end - f->wptr, size);
if(func) {
if(func(src, f->wptr, len) <= 0)
break;
} else {
memcpy(f->wptr, src, len);
src = (uint8_t*)src + len;
}
// Write memory barrier needed for SMP here in theory
f->wptr += len;
if (f->wptr >= f->end)
f->wptr = f->buffer;
f->wndx += len;
size -= len;
} while (size > 0);
return total - size;
}
int av_fifo_generic_read(AVFifoBuffer *f, int buf_size, void (*func)(void*, void*, int), void* dest)
{
// Read memory barrier needed for SMP here in theory
do {
int len = FFMIN(f->end - f->rptr, buf_size);
if(func) func(dest, f->rptr, len);
else{
memcpy(dest, f->rptr, len);
dest = (uint8_t*)dest + len;
}
// memory barrier needed for SMP here in theory
av_fifo_drain(f, len);
buf_size -= len;
} while (buf_size > 0);
return 0;
}
/** Discard data from the FIFO. */
void av_fifo_drain(AVFifoBuffer *f, int size)
{
f->rptr += size;
if (f->rptr >= f->end)
f->rptr -= f->end - f->buffer;
f->rndx += size;
}
|