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 | 4962 | 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 | 4962 | pool = av_mallocz(sizeof(FFFramePool)); | |
64 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4962 times.
|
4962 | if (!pool) |
65 | ✗ | return NULL; | |
66 | |||
67 | 4962 | pool->type = AVMEDIA_TYPE_VIDEO; | |
68 | 4962 | pool->width = width; | |
69 | 4962 | pool->height = height; | |
70 | 4962 | pool->format = format; | |
71 | 4962 | pool->align = align; | |
72 | |||
73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4962 times.
|
4962 | 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 4962 times.
✗ Branch 1 not taken.
|
4962 | if (!pool->linesize[0]) { |
78 | 4962 | ret = av_image_fill_linesizes(pool->linesize, pool->format, | |
79 | 4962 | FFALIGN(pool->width, align)); | |
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4962 times.
|
4962 | if (ret < 0) { |
81 | ✗ | goto fail; | |
82 | } | ||
83 | |||
84 |
4/4✓ Branch 0 taken 16165 times.
✓ Branch 1 taken 767 times.
✓ Branch 2 taken 11970 times.
✓ Branch 3 taken 4195 times.
|
16932 | for (i = 0; i < 4 && pool->linesize[i]; i++) { |
85 | 11970 | pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); | |
86 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11970 times.
|
11970 | if ((pool->linesize[i] & (pool->align - 1))) |
87 | ✗ | goto fail; | |
88 | } | ||
89 | } | ||
90 | |||
91 |
2/2✓ Branch 0 taken 19848 times.
✓ Branch 1 taken 4962 times.
|
24810 | for (i = 0; i < 4; i++) |
92 | 19848 | linesizes[i] = pool->linesize[i]; | |
93 | |||
94 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4962 times.
|
4962 | if (av_image_fill_plane_sizes(sizes, pool->format, |
95 | 4962 | pool->height, | |
96 | linesizes) < 0) { | ||
97 | ✗ | goto fail; | |
98 | } | ||
99 | |||
100 |
4/4✓ Branch 0 taken 16188 times.
✓ Branch 1 taken 767 times.
✓ Branch 2 taken 11993 times.
✓ Branch 3 taken 4195 times.
|
16955 | for (i = 0; i < 4 && sizes[i]; i++) { |
101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11993 times.
|
11993 | if (sizes[i] > SIZE_MAX - align) |
102 | ✗ | goto fail; | |
103 | 11993 | pool->pools[i] = av_buffer_pool_init(sizes[i] + align, alloc); | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11993 times.
|
11993 | if (!pool->pools[i]) |
105 | ✗ | goto fail; | |
106 | } | ||
107 | |||
108 | 4962 | return pool; | |
109 | |||
110 | ✗ | fail: | |
111 | ✗ | ff_frame_pool_uninit(&pool); | |
112 | ✗ | return NULL; | |
113 | } | ||
114 | |||
115 | 2957 | 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 | 2957 | pool = av_mallocz(sizeof(FFFramePool)); | |
125 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
|
2957 | if (!pool) |
126 | ✗ | return NULL; | |
127 | |||
128 | 2957 | planar = av_sample_fmt_is_planar(format); | |
129 | |||
130 | 2957 | pool->type = AVMEDIA_TYPE_AUDIO; | |
131 |
2/2✓ Branch 0 taken 960 times.
✓ Branch 1 taken 1997 times.
|
2957 | pool->planes = planar ? channels : 1; |
132 | 2957 | pool->channels = channels; | |
133 | 2957 | pool->nb_samples = nb_samples; | |
134 | 2957 | pool->format = format; | |
135 | 2957 | pool->align = align; | |
136 | |||
137 | 2957 | 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 2957 times.
|
2957 | if (ret < 0) |
140 | ✗ | goto fail; | |
141 | |||
142 | 2957 | pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL); | |
143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2957 times.
|
2957 | if (!pool->pools[0]) |
144 | ✗ | goto fail; | |
145 | |||
146 | 2957 | return pool; | |
147 | |||
148 | ✗ | fail: | |
149 | ✗ | ff_frame_pool_uninit(&pool); | |
150 | ✗ | return NULL; | |
151 | } | ||
152 | |||
153 | 50123 | int ff_frame_pool_get_video_config(FFFramePool *pool, | |
154 | int *width, | ||
155 | int *height, | ||
156 | enum AVPixelFormat *format, | ||
157 | int *align) | ||
158 | { | ||
159 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50123 times.
|
50123 | if (!pool) |
160 | ✗ | return AVERROR(EINVAL); | |
161 | |||
162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50123 times.
|
50123 | av_assert0(pool->type == AVMEDIA_TYPE_VIDEO); |
163 | |||
164 | 50123 | *width = pool->width; | |
165 | 50123 | *height = pool->height; | |
166 | 50123 | *format = pool->format; | |
167 | 50123 | *align = pool->align; | |
168 | |||
169 | 50123 | return 0; | |
170 | } | ||
171 | |||
172 | 226579 | int ff_frame_pool_get_audio_config(FFFramePool *pool, | |
173 | int *channels, | ||
174 | int *nb_samples, | ||
175 | enum AVSampleFormat *format, | ||
176 | int *align) | ||
177 | { | ||
178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 226579 times.
|
226579 | if (!pool) |
179 | ✗ | return AVERROR(EINVAL); | |
180 | |||
181 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 226579 times.
|
226579 | av_assert0(pool->type == AVMEDIA_TYPE_AUDIO); |
182 | |||
183 | 226579 | *channels = pool->channels; | |
184 | 226579 | *nb_samples = pool->nb_samples; | |
185 | 226579 | *format = pool->format; | |
186 | 226579 | *align = pool->align; | |
187 | |||
188 | 226579 | return 0; | |
189 | } | ||
190 | |||
191 | 283137 | AVFrame *ff_frame_pool_get(FFFramePool *pool) | |
192 | { | ||
193 | int i; | ||
194 | AVFrame *frame; | ||
195 | const AVPixFmtDescriptor *desc; | ||
196 | |||
197 | 283137 | frame = av_frame_alloc(); | |
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 283137 times.
|
283137 | if (!frame) { |
199 | ✗ | return NULL; | |
200 | } | ||
201 | |||
202 |
2/3✓ Branch 0 taken 55084 times.
✓ Branch 1 taken 228053 times.
✗ Branch 2 not taken.
|
283137 | switch(pool->type) { |
203 | 55084 | case AVMEDIA_TYPE_VIDEO: | |
204 | 55084 | desc = av_pix_fmt_desc_get(pool->format); | |
205 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55084 times.
|
55084 | if (!desc) { |
206 | ✗ | goto fail; | |
207 | } | ||
208 | |||
209 | 55084 | frame->width = pool->width; | |
210 | 55084 | frame->height = pool->height; | |
211 | 55084 | frame->format = pool->format; | |
212 | |||
213 |
2/2✓ Branch 0 taken 185896 times.
✓ Branch 1 taken 2678 times.
|
188574 | for (i = 0; i < 4; i++) { |
214 | 185896 | frame->linesize[i] = pool->linesize[i]; | |
215 |
2/2✓ Branch 0 taken 52406 times.
✓ Branch 1 taken 133490 times.
|
185896 | if (!pool->pools[i]) |
216 | 52406 | break; | |
217 | |||
218 | 133490 | frame->buf[i] = av_buffer_pool_get(pool->pools[i]); | |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133490 times.
|
133490 | if (!frame->buf[i]) |
220 | ✗ | goto fail; | |
221 | |||
222 | 133490 | frame->data[i] = frame->buf[i]->data; | |
223 | } | ||
224 | |||
225 |
2/2✓ Branch 0 taken 867 times.
✓ Branch 1 taken 54217 times.
|
55084 | if (desc->flags & AV_PIX_FMT_FLAG_PAL) { |
226 | 867 | enum AVPixelFormat format = | |
227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 867 times.
|
867 | pool->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : pool->format; |
228 | |||
229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 867 times.
|
867 | av_assert0(frame->data[1] != NULL); |
230 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 867 times.
|
867 | if (avpriv_set_systematic_pal2((uint32_t *)frame->data[1], format) < 0) |
231 | ✗ | goto fail; | |
232 | } | ||
233 | |||
234 | 55084 | frame->extended_data = frame->data; | |
235 | 55084 | break; | |
236 | 228053 | case AVMEDIA_TYPE_AUDIO: | |
237 | 228053 | frame->nb_samples = pool->nb_samples; | |
238 | 228053 | frame->ch_layout.nb_channels = pool->channels; | |
239 | 228053 | frame->format = pool->format; | |
240 | 228053 | frame->linesize[0] = pool->linesize[0]; | |
241 | |||
242 |
2/2✓ Branch 0 taken 312 times.
✓ Branch 1 taken 227741 times.
|
228053 | if (pool->planes > AV_NUM_DATA_POINTERS) { |
243 | 312 | frame->extended_data = av_calloc(pool->planes, | |
244 | sizeof(*frame->extended_data)); | ||
245 | 312 | frame->nb_extended_buf = pool->planes - AV_NUM_DATA_POINTERS; | |
246 | 312 | frame->extended_buf = av_calloc(frame->nb_extended_buf, | |
247 | sizeof(*frame->extended_buf)); | ||
248 |
2/4✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 312 times.
|
312 | if (!frame->extended_data || !frame->extended_buf) |
249 | ✗ | goto fail; | |
250 | } else { | ||
251 | 227741 | frame->extended_data = frame->data; | |
252 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 227741 times.
|
227741 | av_assert0(frame->nb_extended_buf == 0); |
253 | } | ||
254 | |||
255 |
2/2✓ Branch 0 taken 235578 times.
✓ Branch 1 taken 228053 times.
|
463631 | for (i = 0; i < FFMIN(pool->planes, AV_NUM_DATA_POINTERS); i++) { |
256 | 235578 | frame->buf[i] = av_buffer_pool_get(pool->pools[0]); | |
257 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 235578 times.
|
235578 | if (!frame->buf[i]) |
258 | ✗ | goto fail; | |
259 | 235578 | frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; | |
260 | } | ||
261 |
2/2✓ Branch 0 taken 960 times.
✓ Branch 1 taken 228053 times.
|
229013 | for (i = 0; i < frame->nb_extended_buf; i++) { |
262 | 960 | frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); | |
263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 960 times.
|
960 | if (!frame->extended_buf[i]) |
264 | ✗ | goto fail; | |
265 | 960 | frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; | |
266 | } | ||
267 | |||
268 | 228053 | break; | |
269 | ✗ | default: | |
270 | ✗ | av_assert0(0); | |
271 | } | ||
272 | |||
273 | 283137 | return frame; | |
274 | ✗ | fail: | |
275 | ✗ | av_frame_free(&frame); | |
276 | ✗ | return NULL; | |
277 | } | ||
278 | |||
279 | 34081 | void ff_frame_pool_uninit(FFFramePool **pool) | |
280 | { | ||
281 | int i; | ||
282 | |||
283 |
3/4✓ Branch 0 taken 34081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26162 times.
✓ Branch 3 taken 7919 times.
|
34081 | if (!pool || !*pool) |
284 | 26162 | return; | |
285 | |||
286 |
2/2✓ Branch 0 taken 31676 times.
✓ Branch 1 taken 7919 times.
|
39595 | for (i = 0; i < 4; i++) { |
287 | 31676 | av_buffer_pool_uninit(&(*pool)->pools[i]); | |
288 | } | ||
289 | |||
290 | 7919 | av_freep(pool); | |
291 | } | ||
292 |