/src/ffmpeg/libavutil/container_fifo.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This file is part of FFmpeg. |
3 | | * |
4 | | * FFmpeg 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 | | * FFmpeg 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 FFmpeg; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | | */ |
18 | | |
19 | | #include "avassert.h" |
20 | | #include "container_fifo.h" |
21 | | #include "error.h" |
22 | | #include "fifo.h" |
23 | | #include "frame.h" |
24 | | #include "mem.h" |
25 | | #include "refstruct.h" |
26 | | |
27 | | struct AVContainerFifo { |
28 | | AVFifo *fifo; |
29 | | AVRefStructPool *pool; |
30 | | |
31 | | void *opaque; |
32 | | void* (*container_alloc)(void *opaque); |
33 | | void (*container_reset)(void *opaque, void *obj); |
34 | | void (*container_free) (void *opaque, void *obj); |
35 | | int (*fifo_transfer) (void *opaque, void *dst, void *src, unsigned flags); |
36 | | |
37 | | }; |
38 | | |
39 | | static int container_fifo_init_entry(AVRefStructOpaque opaque, void *obj) |
40 | 9.71k | { |
41 | 9.71k | AVContainerFifo *cf = opaque.nc; |
42 | 9.71k | void **pobj = obj; |
43 | | |
44 | 9.71k | *pobj = cf->container_alloc(cf->opaque); |
45 | 9.71k | if (!*pobj) |
46 | 0 | return AVERROR(ENOMEM); |
47 | | |
48 | 9.71k | return 0; |
49 | 9.71k | } |
50 | | |
51 | | static void container_fifo_reset_entry(AVRefStructOpaque opaque, void *obj) |
52 | 44.7k | { |
53 | 44.7k | AVContainerFifo *cf = opaque.nc; |
54 | 44.7k | cf->container_reset(cf->opaque, *(void**)obj); |
55 | 44.7k | } |
56 | | |
57 | | static void container_fifo_free_entry(AVRefStructOpaque opaque, void *obj) |
58 | 9.71k | { |
59 | 9.71k | AVContainerFifo *cf = opaque.nc; |
60 | 9.71k | cf->container_free(cf->opaque, *(void**)obj); |
61 | 9.71k | } |
62 | | |
63 | | AVContainerFifo* |
64 | | av_container_fifo_alloc(void *opaque, |
65 | | void* (*container_alloc)(void *opaque), |
66 | | void (*container_reset)(void *opaque, void *obj), |
67 | | void (*container_free) (void *opaque, void *obj), |
68 | | int (*fifo_transfer) (void *opaque, void *dst, void *src, unsigned flags), |
69 | | unsigned flags) |
70 | 24.6k | { |
71 | 24.6k | AVContainerFifo *cf; |
72 | | |
73 | 24.6k | cf = av_mallocz(sizeof(*cf)); |
74 | 24.6k | if (!cf) |
75 | 0 | return NULL; |
76 | | |
77 | 24.6k | cf->opaque = opaque; |
78 | 24.6k | cf->container_alloc = container_alloc; |
79 | 24.6k | cf->container_reset = container_reset; |
80 | 24.6k | cf->container_free = container_free; |
81 | 24.6k | cf->fifo_transfer = fifo_transfer; |
82 | | |
83 | 24.6k | cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW); |
84 | 24.6k | if (!cf->fifo) |
85 | 0 | goto fail; |
86 | | |
87 | 24.6k | cf->pool = av_refstruct_pool_alloc_ext(sizeof(void*), 0, cf, |
88 | 24.6k | container_fifo_init_entry, |
89 | 24.6k | container_fifo_reset_entry, |
90 | 24.6k | container_fifo_free_entry, |
91 | 24.6k | NULL); |
92 | 24.6k | if (!cf->pool) |
93 | 0 | goto fail; |
94 | | |
95 | 24.6k | return cf; |
96 | 0 | fail: |
97 | 0 | av_container_fifo_free(&cf); |
98 | 0 | return NULL; |
99 | 24.6k | } |
100 | | |
101 | | void av_container_fifo_free(AVContainerFifo **pcf) |
102 | 24.6k | { |
103 | 24.6k | AVContainerFifo *cf; |
104 | | |
105 | 24.6k | if (!*pcf) |
106 | 0 | return; |
107 | | |
108 | 24.6k | cf = *pcf; |
109 | | |
110 | 24.6k | if (cf->fifo) { |
111 | 24.6k | void *obj; |
112 | 24.7k | while (av_fifo_read(cf->fifo, &obj, 1) >= 0) |
113 | 16 | av_refstruct_unref(&obj); |
114 | 24.6k | av_fifo_freep2(&cf->fifo); |
115 | 24.6k | } |
116 | | |
117 | 24.6k | av_refstruct_pool_uninit(&cf->pool); |
118 | | |
119 | 24.6k | av_freep(pcf); |
120 | 24.6k | } |
121 | | |
122 | | int av_container_fifo_read(AVContainerFifo *cf, void *obj, unsigned flags) |
123 | 215k | { |
124 | 215k | void **psrc; |
125 | 215k | int ret; |
126 | | |
127 | 215k | ret = av_fifo_read(cf->fifo, &psrc, 1); |
128 | 215k | if (ret < 0) |
129 | 170k | return ret; |
130 | | |
131 | 44.7k | ret = cf->fifo_transfer(cf->opaque, obj, *psrc, flags); |
132 | 44.7k | av_refstruct_unref(&psrc); |
133 | | |
134 | 44.7k | return ret; |
135 | 215k | } |
136 | | |
137 | | int av_container_fifo_peek(AVContainerFifo *cf, void **pdst, size_t offset) |
138 | 0 | { |
139 | 0 | void **pobj; |
140 | 0 | int ret; |
141 | |
|
142 | 0 | ret = av_fifo_peek(cf->fifo, &pobj, 1, offset); |
143 | 0 | if (ret < 0) |
144 | 0 | return ret; |
145 | | |
146 | 0 | *pdst = *pobj; |
147 | |
|
148 | 0 | return 0; |
149 | 0 | } |
150 | | |
151 | | void av_container_fifo_drain(AVContainerFifo *cf, size_t nb_elems) |
152 | 0 | { |
153 | 0 | av_assert0(nb_elems <= av_fifo_can_read(cf->fifo)); |
154 | 0 | while (nb_elems--) { |
155 | 0 | void **pobj; |
156 | 0 | int ret = av_fifo_read(cf->fifo, &pobj, 1); |
157 | 0 | av_assert0(ret >= 0); |
158 | 0 | av_refstruct_unref(&pobj); |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | int av_container_fifo_write(AVContainerFifo *cf, void *obj, unsigned flags) |
163 | 44.7k | { |
164 | 44.7k | void **pdst; |
165 | 44.7k | int ret; |
166 | | |
167 | 44.7k | pdst = av_refstruct_pool_get(cf->pool); |
168 | 44.7k | if (!pdst) |
169 | 0 | return AVERROR(ENOMEM); |
170 | | |
171 | 44.7k | ret = cf->fifo_transfer(cf->opaque, *pdst, obj, flags); |
172 | 44.7k | if (ret < 0) |
173 | 0 | goto fail; |
174 | | |
175 | 44.7k | ret = av_fifo_write(cf->fifo, &pdst, 1); |
176 | 44.7k | if (ret < 0) |
177 | 0 | goto fail; |
178 | | |
179 | 44.7k | return 0; |
180 | 0 | fail: |
181 | 0 | av_refstruct_unref(&pdst); |
182 | 0 | return ret; |
183 | 44.7k | } |
184 | | |
185 | | size_t av_container_fifo_can_read(const AVContainerFifo *cf) |
186 | 458k | { |
187 | 458k | return av_fifo_can_read(cf->fifo); |
188 | 458k | } |
189 | | |
190 | | static void *frame_alloc(void *opaque) |
191 | 9.71k | { |
192 | 9.71k | return av_frame_alloc(); |
193 | 9.71k | } |
194 | | |
195 | | static void frame_reset(void *opaque, void *obj) |
196 | 44.7k | { |
197 | 44.7k | av_frame_unref(obj); |
198 | 44.7k | } |
199 | | |
200 | | static void frame_free(void *opaque, void *obj) |
201 | 9.71k | { |
202 | 9.71k | AVFrame *frame = obj; |
203 | 9.71k | av_frame_free(&frame); |
204 | 9.71k | } |
205 | | |
206 | | static int frame_transfer(void *opaque, void *dst, void *src, unsigned flags) |
207 | 89.5k | { |
208 | 89.5k | if (flags & AV_CONTAINER_FIFO_FLAG_REF) |
209 | 44.7k | return av_frame_ref(dst, src); |
210 | | |
211 | 44.7k | av_frame_move_ref(dst, src); |
212 | 44.7k | return 0; |
213 | 89.5k | } |
214 | | |
215 | | AVContainerFifo *av_container_fifo_alloc_avframe(unsigned flags) |
216 | 24.6k | { |
217 | 24.6k | return av_container_fifo_alloc(NULL, frame_alloc, frame_reset, frame_free, |
218 | 24.6k | frame_transfer, 0); |
219 | 24.6k | } |