Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * This file is part of FFmpeg. | ||
3 | * | ||
4 | * Copyright (c) 2015 Matthieu Bouron <matthieu.bouron stupeflix.com> | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include "framepool.h" | ||
22 | #include "libavutil/avassert.h" | ||
23 | #include "libavutil/avutil.h" | ||
24 | #include "libavutil/buffer.h" | ||
25 | #include "libavutil/frame.h" | ||
26 | #include "libavutil/imgutils.h" | ||
27 | #include "libavutil/imgutils_internal.h" | ||
28 | #include "libavutil/mem.h" | ||
29 | #include "libavutil/pixfmt.h" | ||
30 | |||
31 | struct FFFramePool { | ||
32 | |||
33 | enum AVMediaType type; | ||
34 | |||
35 | /* video */ | ||
36 | int width; | ||
37 | int height; | ||
38 | |||
39 | /* audio */ | ||
40 | int planes; | ||
41 | int channels; | ||
42 | int nb_samples; | ||
43 | |||
44 | /* common */ | ||
45 | int format; | ||
46 | int align; | ||
47 | int linesize[4]; | ||
48 | AVBufferPool *pools[4]; | ||
49 | |||
50 | }; | ||
51 | |||
52 | 7662 | FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(size_t size), | |
53 | int width, | ||
54 | int height, | ||
55 | enum AVPixelFormat format, | ||
56 | int align) | ||
57 | { | ||
58 | int i, ret; | ||
59 | FFFramePool *pool; | ||
60 | ptrdiff_t linesizes[4]; | ||
61 | size_t sizes[4]; | ||
62 | |||
63 | 7662 | pool = av_mallocz(sizeof(FFFramePool)); | |
64 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7662 times.
|
7662 | if (!pool) |
65 | ✗ | return NULL; | |
66 | |||
67 | 7662 | pool->type = AVMEDIA_TYPE_VIDEO; | |
68 | 7662 | pool->width = width; | |
69 | 7662 | pool->height = height; | |
70 | 7662 | pool->format = format; | |
71 | 7662 | pool->align = align; | |
72 | |||
73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7662 times.
|
7662 | if ((ret = av_image_check_size2(width, height, INT64_MAX, format, 0, NULL)) < 0) { |
74 | ✗ | goto fail; | |
75 | } | ||
76 | |||
77 |
1/2✓ Branch 0 taken 7662 times.
✗ Branch 1 not taken.
|
7662 | if (!pool->linesize[0]) { |
78 | 7662 | ret = av_image_fill_linesizes(pool->linesize, pool->format, | |
79 | 7662 | FFALIGN(pool->width, align)); | |
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7662 times.
|
7662 | if (ret < 0) { |
81 | ✗ | goto fail; | |
82 | } | ||
83 | |||
84 |
4/4✓ Branch 0 taken 24993 times.
✓ Branch 1 taken 799 times.
✓ Branch 2 taken 18130 times.
✓ Branch 3 taken 6863 times.
|
25792 | for (i = 0; i < 4 && pool->linesize[i]; i++) { |
85 | 18130 | pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); | |
86 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18130 times.
|
18130 | if ((pool->linesize[i] & (pool->align - 1))) |
87 | ✗ | goto fail; | |
88 | } | ||
89 | } | ||
90 | |||
91 |
2/2✓ Branch 0 taken 30648 times.
✓ Branch 1 taken 7662 times.
|
38310 | for (i = 0; i < 4; i++) |
92 | 30648 | linesizes[i] = pool->linesize[i]; | |
93 | |||
94 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7662 times.
|
7662 | if (av_image_fill_plane_sizes(sizes, pool->format, |
95 | 7662 | pool->height, | |
96 | linesizes) < 0) { | ||
97 | ✗ | goto fail; | |
98 | } | ||
99 | |||
100 |
4/4✓ Branch 0 taken 25016 times.
✓ Branch 1 taken 799 times.
✓ Branch 2 taken 18153 times.
✓ Branch 3 taken 6863 times.
|
25815 | for (i = 0; i < 4 && sizes[i]; i++) { |
101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18153 times.
|
18153 | if (sizes[i] > SIZE_MAX - align) |
102 | ✗ | goto fail; | |
103 | 18153 | pool->pools[i] = av_buffer_pool_init(sizes[i] + align, alloc); | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18153 times.
|
18153 | if (!pool->pools[i]) |
105 | ✗ | goto fail; | |
106 | } | ||
107 | |||
108 | 7662 | return pool; | |
109 | |||
110 | ✗ | fail: | |
111 | ✗ | ff_frame_pool_uninit(&pool); | |
112 | ✗ | return NULL; | |
113 | } | ||
114 | |||
115 | 3243 | FFFramePool *ff_frame_pool_audio_init(AVBufferRef* (*alloc)(size_t size), | |
116 | int channels, | ||
117 | int nb_samples, | ||
118 | enum AVSampleFormat format, | ||
119 | int align) | ||
120 | { | ||
121 | int ret, planar; | ||
122 | FFFramePool *pool; | ||
123 | |||
124 | 3243 | pool = av_mallocz(sizeof(FFFramePool)); | |
125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3243 times.
|
3243 | if (!pool) |
126 | ✗ | return NULL; | |
127 | |||
128 | 3243 | planar = av_sample_fmt_is_planar(format); | |
129 | |||
130 | 3243 | pool->type = AVMEDIA_TYPE_AUDIO; | |
131 |
2/2✓ Branch 0 taken 1033 times.
✓ Branch 1 taken 2210 times.
|
3243 | pool->planes = planar ? channels : 1; |
132 | 3243 | pool->channels = channels; | |
133 | 3243 | pool->nb_samples = nb_samples; | |
134 | 3243 | pool->format = format; | |
135 | 3243 | pool->align = align; | |
136 | |||
137 | 3243 | ret = av_samples_get_buffer_size(&pool->linesize[0], channels, | |
138 | nb_samples, format, 0); | ||
139 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3243 times.
|
3243 | if (ret < 0) |
140 | ✗ | goto fail; | |
141 | |||
142 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3243 times.
|
3243 | if (pool->linesize[0] > SIZE_MAX - align) |
143 | ✗ | goto fail; | |
144 | 3243 | pool->pools[0] = av_buffer_pool_init(pool->linesize[0] + align, NULL); | |
145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3243 times.
|
3243 | if (!pool->pools[0]) |
146 | ✗ | goto fail; | |
147 | |||
148 | 3243 | return pool; | |
149 | |||
150 | ✗ | fail: | |
151 | ✗ | ff_frame_pool_uninit(&pool); | |
152 | ✗ | return NULL; | |
153 | } | ||
154 | |||
155 | 90353 | int ff_frame_pool_get_video_config(FFFramePool *pool, | |
156 | int *width, | ||
157 | int *height, | ||
158 | enum AVPixelFormat *format, | ||
159 | int *align) | ||
160 | { | ||
161 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90353 times.
|
90353 | if (!pool) |
162 | ✗ | return AVERROR(EINVAL); | |
163 | |||
164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90353 times.
|
90353 | av_assert0(pool->type == AVMEDIA_TYPE_VIDEO); |
165 | |||
166 | 90353 | *width = pool->width; | |
167 | 90353 | *height = pool->height; | |
168 | 90353 | *format = pool->format; | |
169 | 90353 | *align = pool->align; | |
170 | |||
171 | 90353 | return 0; | |
172 | } | ||
173 | |||
174 | 230876 | int ff_frame_pool_get_audio_config(FFFramePool *pool, | |
175 | int *channels, | ||
176 | int *nb_samples, | ||
177 | enum AVSampleFormat *format, | ||
178 | int *align) | ||
179 | { | ||
180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 230876 times.
|
230876 | if (!pool) |
181 | ✗ | return AVERROR(EINVAL); | |
182 | |||
183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 230876 times.
|
230876 | av_assert0(pool->type == AVMEDIA_TYPE_AUDIO); |
184 | |||
185 | 230876 | *channels = pool->channels; | |
186 | 230876 | *nb_samples = pool->nb_samples; | |
187 | 230876 | *format = pool->format; | |
188 | 230876 | *align = pool->align; | |
189 | |||
190 | 230876 | return 0; | |
191 | } | ||
192 | |||
193 | 330579 | AVFrame *ff_frame_pool_get(FFFramePool *pool) | |
194 | { | ||
195 | int i; | ||
196 | AVFrame *frame; | ||
197 | const AVPixFmtDescriptor *desc; | ||
198 | |||
199 | 330579 | frame = av_frame_alloc(); | |
200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 330579 times.
|
330579 | if (!frame) { |
201 | ✗ | return NULL; | |
202 | } | ||
203 | |||
204 |
2/3✓ Branch 0 taken 98014 times.
✓ Branch 1 taken 232565 times.
✗ Branch 2 not taken.
|
330579 | switch(pool->type) { |
205 | 98014 | case AVMEDIA_TYPE_VIDEO: | |
206 | 98014 | desc = av_pix_fmt_desc_get(pool->format); | |
207 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 98014 times.
|
98014 | if (!desc) { |
208 | ✗ | goto fail; | |
209 | } | ||
210 | |||
211 | 98014 | frame->width = pool->width; | |
212 | 98014 | frame->height = pool->height; | |
213 | 98014 | frame->format = pool->format; | |
214 | |||
215 |
2/2✓ Branch 0 taken 326783 times.
✓ Branch 1 taken 2655 times.
|
329438 | for (i = 0; i < 4; i++) { |
216 | 326783 | frame->linesize[i] = pool->linesize[i]; | |
217 |
2/2✓ Branch 0 taken 95359 times.
✓ Branch 1 taken 231424 times.
|
326783 | if (!pool->pools[i]) |
218 | 95359 | break; | |
219 | |||
220 | 231424 | frame->buf[i] = av_buffer_pool_get(pool->pools[i]); | |
221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231424 times.
|
231424 | if (!frame->buf[i]) |
222 | ✗ | goto fail; | |
223 | |||
224 | 231424 | frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align); | |
225 | } | ||
226 | |||
227 |
2/2✓ Branch 0 taken 867 times.
✓ Branch 1 taken 97147 times.
|
98014 | if (desc->flags & AV_PIX_FMT_FLAG_PAL) { |
228 | 867 | enum AVPixelFormat format = | |
229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 867 times.
|
867 | pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; |
230 | |||
231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 867 times.
|
867 | av_assert0(frame->data[1] != NULL); |
232 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 867 times.
|
867 | if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0) |
233 | ✗ | goto fail; | |
234 | } | ||
235 | |||
236 | 98014 | frame->extended_data = frame->data; | |
237 | 98014 | break; | |
238 | 232565 | case AVMEDIA_TYPE_AUDIO: | |
239 | 232565 | frame->nb_samples = pool->nb_samples; | |
240 | 232565 | frame->ch_layout.nb_channels = pool->channels; | |
241 | 232565 | frame->format = pool->format; | |
242 | 232565 | frame->linesize[0] = pool->linesize[0]; | |
243 | |||
244 |
2/2✓ Branch 0 taken 396 times.
✓ Branch 1 taken 232169 times.
|
232565 | if (pool->planes > AV_NUM_DATA_POINTERS) { |
245 | 396 | frame->extended_data = av_calloc(pool->planes, | |
246 | sizeof(*frame->extended_data)); | ||
247 | 396 | frame->nb_extended_buf = pool->planes - AV_NUM_DATA_POINTERS; | |
248 | 396 | frame->extended_buf = av_calloc(frame->nb_extended_buf, | |
249 | sizeof(*frame->extended_buf)); | ||
250 |
2/4✓ Branch 0 taken 396 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 396 times.
|
396 | if (!frame->extended_data || !frame->extended_buf) |
251 | ✗ | goto fail; | |
252 | } else { | ||
253 | 232169 | frame->extended_data = frame->data; | |
254 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 232169 times.
|
232169 | av_assert0(frame->nb_extended_buf == 0); |
255 | } | ||
256 | |||
257 |
2/2✓ Branch 0 taken 240679 times.
✓ Branch 1 taken 232565 times.
|
473244 | for (i = 0; i < FFMIN(pool->planes, AV_NUM_DATA_POINTERS); i++) { |
258 | 240679 | frame->buf[i] = av_buffer_pool_get(pool->pools[0]); | |
259 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240679 times.
|
240679 | if (!frame->buf[i]) |
260 | ✗ | goto fail; | |
261 | 240679 | frame->extended_data[i] = frame->data[i] = | |
262 | 240679 | (uint8_t *)FFALIGN((uintptr_t)frame->buf[i]->data, pool->align); | |
263 | } | ||
264 |
2/2✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 232565 times.
|
233861 | for (i = 0; i < frame->nb_extended_buf; i++) { |
265 | 1296 | frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); | |
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1296 times.
|
1296 | if (!frame->extended_buf[i]) |
267 | ✗ | goto fail; | |
268 | 1296 | frame->extended_data[i + AV_NUM_DATA_POINTERS] = | |
269 | 1296 | (uint8_t *)FFALIGN((uintptr_t)frame->extended_buf[i]->data, pool->align); | |
270 | } | ||
271 | |||
272 | 232565 | break; | |
273 | ✗ | default: | |
274 | ✗ | av_assert0(0); | |
275 | } | ||
276 | |||
277 | 330579 | return frame; | |
278 | ✗ | fail: | |
279 | ✗ | av_frame_free(&frame); | |
280 | ✗ | return NULL; | |
281 | } | ||
282 | |||
283 | 44316 | void ff_frame_pool_uninit(FFFramePool **pool) | |
284 | { | ||
285 | int i; | ||
286 | |||
287 |
3/4✓ Branch 0 taken 44316 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33411 times.
✓ Branch 3 taken 10905 times.
|
44316 | if (!pool || !*pool) |
288 | 33411 | return; | |
289 | |||
290 |
2/2✓ Branch 0 taken 43620 times.
✓ Branch 1 taken 10905 times.
|
54525 | for (i = 0; i < 4; i++) { |
291 | 43620 | av_buffer_pool_uninit(&(*pool)->pools[i]); | |
292 | } | ||
293 | |||
294 | 10905 | av_freep(pool); | |
295 | } | ||
296 |