Line | Branch | Exec | Source |
---|---|---|---|
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 "libavutil/error.h" | ||
20 | #include "libavutil/fifo.h" | ||
21 | #include "libavutil/frame.h" | ||
22 | #include "libavutil/mem.h" | ||
23 | |||
24 | #include "container_fifo.h" | ||
25 | #include "refstruct.h" | ||
26 | |||
27 | struct ContainerFifo { | ||
28 | AVFifo *fifo; | ||
29 | FFRefStructPool *pool; | ||
30 | |||
31 | void* (*container_alloc)(void); | ||
32 | void (*container_reset)(void *obj); | ||
33 | void (*container_free) (void *obj); | ||
34 | int (*fifo_write) (void *dst, void *src); | ||
35 | int (*fifo_read) (void *dst, void *src); | ||
36 | |||
37 | }; | ||
38 | |||
39 | 494 | static int container_fifo_init_entry(FFRefStructOpaque opaque, void *obj) | |
40 | { | ||
41 | 494 | ContainerFifo *cf = opaque.nc; | |
42 | 494 | void **pobj = obj; | |
43 | |||
44 | 494 | *pobj = cf->container_alloc(); | |
45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
|
494 | if (!*pobj) |
46 | ✗ | return AVERROR(ENOMEM); | |
47 | |||
48 | 494 | return 0; | |
49 | } | ||
50 | |||
51 | 10006 | static void container_fifo_reset_entry(FFRefStructOpaque opaque, void *obj) | |
52 | { | ||
53 | 10006 | ContainerFifo *cf = opaque.nc; | |
54 | 10006 | cf->container_reset(*(void**)obj); | |
55 | 10006 | } | |
56 | |||
57 | 494 | static void container_fifo_free_entry(FFRefStructOpaque opaque, void *obj) | |
58 | { | ||
59 | 494 | ContainerFifo *cf = opaque.nc; | |
60 | 494 | cf->container_free(*(void**)obj); | |
61 | 494 | } | |
62 | |||
63 | ContainerFifo* | ||
64 | 456 | ff_container_fifo_alloc(void* (*container_alloc)(void), | |
65 | void (*container_reset)(void *obj), | ||
66 | void (*container_free) (void *obj), | ||
67 | int (*fifo_write) (void *dst, void *src), | ||
68 | int (*fifo_read) (void *dst, void *src)) | ||
69 | { | ||
70 | ContainerFifo *cf; | ||
71 | |||
72 | 456 | cf = av_mallocz(sizeof(*cf)); | |
73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
|
456 | if (!cf) |
74 | ✗ | return NULL; | |
75 | |||
76 | 456 | cf->container_alloc = container_alloc; | |
77 | 456 | cf->container_reset = container_reset; | |
78 | 456 | cf->container_free = container_free; | |
79 | 456 | cf->fifo_write = fifo_write; | |
80 | 456 | cf->fifo_read = fifo_read; | |
81 | |||
82 | 456 | cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW); | |
83 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
|
456 | if (!cf->fifo) |
84 | ✗ | goto fail; | |
85 | |||
86 | 456 | cf->pool = ff_refstruct_pool_alloc_ext(sizeof(void*), 0, cf, | |
87 | container_fifo_init_entry, | ||
88 | container_fifo_reset_entry, | ||
89 | container_fifo_free_entry, | ||
90 | NULL); | ||
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
|
456 | if (!cf->pool) |
92 | ✗ | goto fail; | |
93 | |||
94 | 456 | return cf; | |
95 | ✗ | fail: | |
96 | ✗ | ff_container_fifo_free(&cf); | |
97 | ✗ | return NULL; | |
98 | } | ||
99 | |||
100 | 456 | void ff_container_fifo_free(ContainerFifo **pcf) | |
101 | { | ||
102 | ContainerFifo *cf; | ||
103 | |||
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
|
456 | if (!*pcf) |
105 | ✗ | return; | |
106 | |||
107 | 456 | cf = *pcf; | |
108 | |||
109 |
1/2✓ Branch 0 taken 456 times.
✗ Branch 1 not taken.
|
456 | if (cf->fifo) { |
110 | void *obj; | ||
111 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 456 times.
|
456 | while (av_fifo_read(cf->fifo, &obj, 1) >= 0) |
112 | ✗ | ff_refstruct_unref(&obj); | |
113 | 456 | av_fifo_freep2(&cf->fifo); | |
114 | } | ||
115 | |||
116 | 456 | ff_refstruct_pool_uninit(&cf->pool); | |
117 | |||
118 | 456 | av_freep(pcf); | |
119 | } | ||
120 | |||
121 | 11222 | int ff_container_fifo_read(ContainerFifo *cf, void *obj) | |
122 | { | ||
123 | void **psrc; | ||
124 | int ret; | ||
125 | |||
126 | 11222 | ret = av_fifo_read(cf->fifo, &psrc, 1); | |
127 |
2/2✓ Branch 0 taken 1216 times.
✓ Branch 1 taken 10006 times.
|
11222 | if (ret < 0) |
128 | 1216 | return ret; | |
129 | |||
130 | 10006 | ret = cf->fifo_read(obj, *psrc); | |
131 | 10006 | ff_refstruct_unref(&psrc); | |
132 | |||
133 | 10006 | return ret; | |
134 | } | ||
135 | |||
136 | 10006 | int ff_container_fifo_write(ContainerFifo *cf, void *obj) | |
137 | { | ||
138 | void **pdst; | ||
139 | int ret; | ||
140 | |||
141 | 10006 | pdst = ff_refstruct_pool_get(cf->pool); | |
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10006 times.
|
10006 | if (!pdst) |
143 | ✗ | return AVERROR(ENOMEM); | |
144 | |||
145 | 10006 | ret = cf->fifo_write(*pdst, obj); | |
146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10006 times.
|
10006 | if (ret < 0) |
147 | ✗ | goto fail; | |
148 | |||
149 | 10006 | ret = av_fifo_write(cf->fifo, &pdst, 1); | |
150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10006 times.
|
10006 | if (ret < 0) |
151 | ✗ | goto fail; | |
152 | |||
153 | 10006 | return 0; | |
154 | ✗ | fail: | |
155 | ✗ | ff_refstruct_unref(&pdst); | |
156 | ✗ | return ret; | |
157 | } | ||
158 | |||
159 | 21117 | size_t ff_container_fifo_can_read(ContainerFifo *cf) | |
160 | { | ||
161 | 21117 | return av_fifo_can_read(cf->fifo); | |
162 | } | ||
163 | |||
164 | 494 | static void *frame_alloc(void) | |
165 | { | ||
166 | 494 | return av_frame_alloc(); | |
167 | } | ||
168 | |||
169 | 10006 | static void frame_reset(void *obj) | |
170 | { | ||
171 | 10006 | av_frame_unref(obj); | |
172 | 10006 | } | |
173 | |||
174 | 494 | static void frame_free(void *obj) | |
175 | { | ||
176 | 494 | AVFrame *frame = obj; | |
177 | 494 | av_frame_free(&frame); | |
178 | 494 | } | |
179 | |||
180 | 10006 | static int frame_ref(void *dst, void *src) | |
181 | { | ||
182 | 10006 | return av_frame_ref(dst, src); | |
183 | } | ||
184 | |||
185 | 10006 | static int frame_move_ref(void *dst, void *src) | |
186 | { | ||
187 | 10006 | av_frame_move_ref(dst, src); | |
188 | 10006 | return 0; | |
189 | } | ||
190 | |||
191 | 456 | ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags) | |
192 | { | ||
193 | 456 | return ff_container_fifo_alloc(frame_alloc, frame_reset, frame_free, | |
194 | frame_ref, frame_move_ref); | ||
195 | } | ||
196 |