Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * filter graphs | ||
3 | * Copyright (c) 2008 Vitor Sessak | ||
4 | * Copyright (c) 2007 Bobby Bingham | ||
5 | * | ||
6 | * This file is part of FFmpeg. | ||
7 | * | ||
8 | * FFmpeg is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public | ||
10 | * License as published by the Free Software Foundation; either | ||
11 | * version 2.1 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * FFmpeg is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with FFmpeg; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include "config.h" | ||
24 | |||
25 | #include <string.h> | ||
26 | |||
27 | #include "libavutil/avassert.h" | ||
28 | #include "libavutil/bprint.h" | ||
29 | #include "libavutil/channel_layout.h" | ||
30 | #include "libavutil/imgutils.h" | ||
31 | #include "libavutil/mem.h" | ||
32 | #include "libavutil/opt.h" | ||
33 | #include "libavutil/pixdesc.h" | ||
34 | |||
35 | |||
36 | #include "avfilter.h" | ||
37 | #include "avfilter_internal.h" | ||
38 | #include "buffersink.h" | ||
39 | #include "filters.h" | ||
40 | #include "formats.h" | ||
41 | #include "framequeue.h" | ||
42 | #include "video.h" | ||
43 | |||
44 | #define OFFSET(x) offsetof(AVFilterGraph, x) | ||
45 | #define F AV_OPT_FLAG_FILTERING_PARAM | ||
46 | #define V AV_OPT_FLAG_VIDEO_PARAM | ||
47 | #define A AV_OPT_FLAG_AUDIO_PARAM | ||
48 | static const AVOption filtergraph_options[] = { | ||
49 | { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, | ||
50 | { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, F|V|A, .unit = "thread_type" }, | ||
51 | { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = F|V|A, .unit = "thread_type" }, | ||
52 | { "threads", "Maximum number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, | ||
53 | { .i64 = 0 }, 0, INT_MAX, F|V|A, .unit = "threads"}, | ||
54 | {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = F|V|A, .unit = "threads"}, | ||
55 | {"scale_sws_opts" , "default scale filter options" , OFFSET(scale_sws_opts) , | ||
56 | AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, F|V }, | ||
57 | {"aresample_swr_opts" , "default aresample filter options" , OFFSET(aresample_swr_opts) , | ||
58 | AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, F|A }, | ||
59 | {"max_buffered_frames" , "maximum number of buffered frames allowed", OFFSET(max_buffered_frames), | ||
60 | AV_OPT_TYPE_UINT, {.i64 = 0}, 0, UINT_MAX, F|V|A }, | ||
61 | { NULL }, | ||
62 | }; | ||
63 | |||
64 | static const AVClass filtergraph_class = { | ||
65 | .class_name = "AVFilterGraph", | ||
66 | .item_name = av_default_item_name, | ||
67 | .version = LIBAVUTIL_VERSION_INT, | ||
68 | .option = filtergraph_options, | ||
69 | .category = AV_CLASS_CATEGORY_FILTER, | ||
70 | }; | ||
71 | |||
72 | #if !HAVE_THREADS | ||
73 | void ff_graph_thread_free(FFFilterGraph *graph) | ||
74 | { | ||
75 | } | ||
76 | |||
77 | int ff_graph_thread_init(FFFilterGraph *graph) | ||
78 | { | ||
79 | graph->p.thread_type = 0; | ||
80 | graph->p.nb_threads = 1; | ||
81 | return 0; | ||
82 | } | ||
83 | #endif | ||
84 | |||
85 | 16118 | AVFilterGraph *avfilter_graph_alloc(void) | |
86 | { | ||
87 | 16118 | FFFilterGraph *graph = av_mallocz(sizeof(*graph)); | |
88 | AVFilterGraph *ret; | ||
89 | |||
90 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16118 times.
|
16118 | if (!graph) |
91 | ✗ | return NULL; | |
92 | |||
93 | 16118 | ret = &graph->p; | |
94 | 16118 | ret->av_class = &filtergraph_class; | |
95 | 16118 | av_opt_set_defaults(ret); | |
96 | 16118 | ff_framequeue_global_init(&graph->frame_queues); | |
97 | |||
98 | 16118 | return ret; | |
99 | } | ||
100 | |||
101 | 62781 | void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter) | |
102 | { | ||
103 | int i, j; | ||
104 |
1/2✓ Branch 0 taken 62781 times.
✗ Branch 1 not taken.
|
62781 | for (i = 0; i < graph->nb_filters; i++) { |
105 |
1/2✓ Branch 0 taken 62781 times.
✗ Branch 1 not taken.
|
62781 | if (graph->filters[i] == filter) { |
106 | 62781 | FFSWAP(AVFilterContext*, graph->filters[i], | |
107 | graph->filters[graph->nb_filters - 1]); | ||
108 | 62781 | graph->nb_filters--; | |
109 | 62781 | filter->graph = NULL; | |
110 |
2/2✓ Branch 0 taken 54768 times.
✓ Branch 1 taken 62781 times.
|
117549 | for (j = 0; j<filter->nb_outputs; j++) |
111 |
2/2✓ Branch 0 taken 20719 times.
✓ Branch 1 taken 34049 times.
|
54768 | if (filter->outputs[j]) |
112 | 20719 | ff_filter_link(filter->outputs[j])->graph = NULL; | |
113 | |||
114 | 62781 | return; | |
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | 24097 | void avfilter_graph_free(AVFilterGraph **graphp) | |
120 | { | ||
121 | 24097 | AVFilterGraph *graph = *graphp; | |
122 | 24097 | FFFilterGraph *graphi = fffiltergraph(graph); | |
123 | |||
124 |
2/2✓ Branch 0 taken 7979 times.
✓ Branch 1 taken 16118 times.
|
24097 | if (!graph) |
125 | 7979 | return; | |
126 | |||
127 |
2/2✓ Branch 0 taken 62715 times.
✓ Branch 1 taken 16118 times.
|
78833 | while (graph->nb_filters) |
128 | 62715 | avfilter_free(graph->filters[0]); | |
129 | |||
130 | 16118 | ff_graph_thread_free(graphi); | |
131 | |||
132 | 16118 | av_freep(&graphi->sink_links); | |
133 | |||
134 | 16118 | av_opt_free(graph); | |
135 | |||
136 | 16118 | av_freep(&graph->filters); | |
137 | 16118 | av_freep(graphp); | |
138 | } | ||
139 | |||
140 | 19079 | int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, | |
141 | const char *name, const char *args, void *opaque, | ||
142 | AVFilterGraph *graph_ctx) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | 19079 | *filt_ctx = avfilter_graph_alloc_filter(graph_ctx, filt, name); | |
147 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19079 times.
|
19079 | if (!*filt_ctx) |
148 | ✗ | return AVERROR(ENOMEM); | |
149 | |||
150 | 19079 | ret = avfilter_init_str(*filt_ctx, args); | |
151 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19079 times.
|
19079 | if (ret < 0) |
152 | ✗ | goto fail; | |
153 | |||
154 | 19079 | return 0; | |
155 | |||
156 | ✗ | fail: | |
157 | ✗ | avfilter_free(*filt_ctx); | |
158 | ✗ | *filt_ctx = NULL; | |
159 | ✗ | return ret; | |
160 | } | ||
161 | |||
162 | 6245 | void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags) | |
163 | { | ||
164 | 6245 | fffiltergraph(graph)->disable_auto_convert = flags; | |
165 | 6245 | } | |
166 | |||
167 | 62781 | AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, | |
168 | const AVFilter *filter, | ||
169 | const char *name) | ||
170 | { | ||
171 | AVFilterContext **filters, *s; | ||
172 | 62781 | FFFilterGraph *graphi = fffiltergraph(graph); | |
173 | |||
174 |
4/4✓ Branch 0 taken 33008 times.
✓ Branch 1 taken 29773 times.
✓ Branch 2 taken 16118 times.
✓ Branch 3 taken 16890 times.
|
62781 | if (graph->thread_type && !graphi->thread_execute) { |
175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16118 times.
|
16118 | if (graph->execute) { |
176 | ✗ | graphi->thread_execute = graph->execute; | |
177 | } else { | ||
178 | 16118 | int ret = ff_graph_thread_init(graphi); | |
179 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16118 times.
|
16118 | if (ret < 0) { |
180 | ✗ | av_log(graph, AV_LOG_ERROR, "Error initializing threading: %s.\n", av_err2str(ret)); | |
181 | ✗ | return NULL; | |
182 | } | ||
183 | } | ||
184 | } | ||
185 | |||
186 | 62781 | filters = av_realloc_array(graph->filters, graph->nb_filters + 1, sizeof(*filters)); | |
187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62781 times.
|
62781 | if (!filters) |
188 | ✗ | return NULL; | |
189 | 62781 | graph->filters = filters; | |
190 | |||
191 | 62781 | s = ff_filter_alloc(filter, name); | |
192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62781 times.
|
62781 | if (!s) |
193 | ✗ | return NULL; | |
194 | |||
195 | 62781 | graph->filters[graph->nb_filters++] = s; | |
196 | |||
197 | 62781 | s->graph = graph; | |
198 | |||
199 | 62781 | return s; | |
200 | } | ||
201 | |||
202 | /** | ||
203 | * Check for the validity of graph. | ||
204 | * | ||
205 | * A graph is considered valid if all its input and output pads are | ||
206 | * connected. | ||
207 | * | ||
208 | * @return >= 0 in case of success, a negative value otherwise | ||
209 | */ | ||
210 | 8073 | static int graph_check_validity(AVFilterGraph *graph, void *log_ctx) | |
211 | { | ||
212 | AVFilterContext *filt; | ||
213 | int i, j; | ||
214 | |||
215 |
2/2✓ Branch 0 taken 43252 times.
✓ Branch 1 taken 8073 times.
|
51325 | for (i = 0; i < graph->nb_filters; i++) { |
216 | const AVFilterPad *pad; | ||
217 | 43252 | filt = graph->filters[i]; | |
218 | |||
219 |
2/2✓ Branch 0 taken 35142 times.
✓ Branch 1 taken 43252 times.
|
78394 | for (j = 0; j < filt->nb_inputs; j++) { |
220 |
2/4✓ Branch 0 taken 35142 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35142 times.
|
35142 | if (!filt->inputs[j] || !filt->inputs[j]->src) { |
221 | ✗ | pad = &filt->input_pads[j]; | |
222 | ✗ | av_log(log_ctx, AV_LOG_ERROR, | |
223 | "Input pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any source\n", | ||
224 | ✗ | pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name); | |
225 | ✗ | return AVERROR(EINVAL); | |
226 | } | ||
227 | } | ||
228 | |||
229 |
2/2✓ Branch 0 taken 35142 times.
✓ Branch 1 taken 43252 times.
|
78394 | for (j = 0; j < filt->nb_outputs; j++) { |
230 |
2/4✓ Branch 0 taken 35142 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35142 times.
|
35142 | if (!filt->outputs[j] || !filt->outputs[j]->dst) { |
231 | ✗ | pad = &filt->output_pads[j]; | |
232 | ✗ | av_log(log_ctx, AV_LOG_ERROR, | |
233 | "Output pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any destination\n", | ||
234 | ✗ | pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name); | |
235 | ✗ | return AVERROR(EINVAL); | |
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | 8073 | return 0; | |
241 | } | ||
242 | |||
243 | /** | ||
244 | * Configure all the links of graphctx. | ||
245 | * | ||
246 | * @return >= 0 in case of success, a negative value otherwise | ||
247 | */ | ||
248 | 8073 | static int graph_config_links(AVFilterGraph *graph, void *log_ctx) | |
249 | { | ||
250 | AVFilterContext *filt; | ||
251 | int i, ret; | ||
252 | |||
253 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) { |
254 | 44504 | filt = graph->filters[i]; | |
255 | |||
256 |
2/2✓ Branch 0 taken 8209 times.
✓ Branch 1 taken 36295 times.
|
44504 | if (!filt->nb_outputs) { |
257 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8209 times.
|
8209 | if ((ret = ff_filter_config_links(filt))) |
258 | ✗ | return ret; | |
259 | } | ||
260 | } | ||
261 | |||
262 | 8073 | return 0; | |
263 | } | ||
264 | |||
265 | 8073 | static int graph_check_links(AVFilterGraph *graph, void *log_ctx) | |
266 | { | ||
267 | AVFilterContext *f; | ||
268 | AVFilterLink *l; | ||
269 | unsigned i, j; | ||
270 | int ret; | ||
271 | |||
272 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) { |
273 | 44504 | f = graph->filters[i]; | |
274 |
2/2✓ Branch 0 taken 36394 times.
✓ Branch 1 taken 44504 times.
|
80898 | for (j = 0; j < f->nb_outputs; j++) { |
275 | 36394 | l = f->outputs[j]; | |
276 |
2/2✓ Branch 0 taken 30483 times.
✓ Branch 1 taken 5911 times.
|
36394 | if (l->type == AVMEDIA_TYPE_VIDEO) { |
277 | 30483 | ret = av_image_check_size2(l->w, l->h, INT64_MAX, l->format, 0, f); | |
278 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30483 times.
|
30483 | if (ret < 0) |
279 | ✗ | return ret; | |
280 | } | ||
281 | } | ||
282 | } | ||
283 | 8073 | return 0; | |
284 | } | ||
285 | |||
286 | ✗ | AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name) | |
287 | { | ||
288 | int i; | ||
289 | |||
290 | ✗ | for (i = 0; i < graph->nb_filters; i++) | |
291 | ✗ | if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name)) | |
292 | ✗ | return graph->filters[i]; | |
293 | |||
294 | ✗ | return NULL; | |
295 | } | ||
296 | |||
297 | 59372 | static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterFormatsConfig *cfg) | |
298 | { | ||
299 | int ret; | ||
300 | |||
301 |
2/3✓ Branch 0 taken 50000 times.
✓ Branch 1 taken 9372 times.
✗ Branch 2 not taken.
|
59372 | switch (link->type) { |
302 | |||
303 | 50000 | case AVMEDIA_TYPE_VIDEO: | |
304 |
2/4✓ Branch 1 taken 50000 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 50000 times.
✗ Branch 4 not taken.
|
100000 | if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0 || |
305 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 50000 times.
|
100000 | (ret = ff_formats_check_color_spaces(log, cfg->color_spaces)) < 0 || |
306 | 50000 | (ret = ff_formats_check_color_ranges(log, cfg->color_ranges)) < 0) | |
307 | ✗ | return ret; | |
308 | 50000 | break; | |
309 | |||
310 | 9372 | case AVMEDIA_TYPE_AUDIO: | |
311 |
2/4✓ Branch 1 taken 9372 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9372 times.
✗ Branch 4 not taken.
|
18744 | if ((ret = ff_formats_check_sample_formats(log, cfg->formats)) < 0 || |
312 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9372 times.
|
18744 | (ret = ff_formats_check_sample_rates(log, cfg->samplerates)) < 0 || |
313 | 9372 | (ret = ff_formats_check_channel_layouts(log, cfg->channel_layouts)) < 0) | |
314 | ✗ | return ret; | |
315 | 9372 | break; | |
316 | |||
317 | ✗ | default: | |
318 | ✗ | av_assert0(!"reached"); | |
319 | } | ||
320 | 59372 | return 0; | |
321 | } | ||
322 | |||
323 | /** | ||
324 | * Check the validity of the formats / etc. lists set by query_formats(). | ||
325 | * | ||
326 | * In particular, check they do not contain any redundant element. | ||
327 | */ | ||
328 | 37271 | static int filter_check_formats(AVFilterContext *ctx) | |
329 | { | ||
330 | unsigned i; | ||
331 | int ret; | ||
332 | |||
333 |
2/2✓ Branch 0 taken 30238 times.
✓ Branch 1 taken 37271 times.
|
67509 | for (i = 0; i < ctx->nb_inputs; i++) { |
334 | 30238 | ret = filter_link_check_formats(ctx, ctx->inputs[i], &ctx->inputs[i]->outcfg); | |
335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30238 times.
|
30238 | if (ret < 0) |
336 | ✗ | return ret; | |
337 | } | ||
338 |
2/2✓ Branch 0 taken 29134 times.
✓ Branch 1 taken 37271 times.
|
66405 | for (i = 0; i < ctx->nb_outputs; i++) { |
339 | 29134 | ret = filter_link_check_formats(ctx, ctx->outputs[i], &ctx->outputs[i]->incfg); | |
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29134 times.
|
29134 | if (ret < 0) |
341 | ✗ | return ret; | |
342 | } | ||
343 | 37271 | return 0; | |
344 | } | ||
345 | |||
346 | 44518 | static int filter_query_formats(AVFilterContext *ctx) | |
347 | { | ||
348 | 44518 | const FFFilter *const filter = fffilter(ctx->filter); | |
349 | int ret; | ||
350 | |||
351 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 44490 times.
|
44518 | if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC) { |
352 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
|
28 | if ((ret = filter->formats.query_func(ctx)) < 0) { |
353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (ret != AVERROR(EAGAIN)) |
354 | ✗ | av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n", | |
355 | ✗ | ctx->name, av_err2str(ret)); | |
356 | 14 | return ret; | |
357 | } | ||
358 |
2/2✓ Branch 0 taken 37257 times.
✓ Branch 1 taken 7233 times.
|
44490 | } else if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) { |
359 | AVFilterFormatsConfig *cfg_in_stack[64], *cfg_out_stack[64]; | ||
360 | 37257 | AVFilterFormatsConfig **cfg_in_dyn = NULL, **cfg_out_dyn = NULL; | |
361 | AVFilterFormatsConfig **cfg_in, **cfg_out; | ||
362 | |||
363 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37256 times.
|
37257 | if (ctx->nb_inputs > FF_ARRAY_ELEMS(cfg_in_stack)) { |
364 | 1 | cfg_in_dyn = av_malloc_array(ctx->nb_inputs, sizeof(*cfg_in_dyn)); | |
365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!cfg_in_dyn) |
366 | ✗ | return AVERROR(ENOMEM); | |
367 | 1 | cfg_in = cfg_in_dyn; | |
368 | } else | ||
369 |
2/2✓ Branch 0 taken 30109 times.
✓ Branch 1 taken 7147 times.
|
37256 | cfg_in = ctx->nb_inputs ? cfg_in_stack : NULL; |
370 | |||
371 |
2/2✓ Branch 0 taken 30223 times.
✓ Branch 1 taken 37257 times.
|
67480 | for (unsigned i = 0; i < ctx->nb_inputs; i++) { |
372 | 30223 | AVFilterLink *l = ctx->inputs[i]; | |
373 | 30223 | cfg_in[i] = &l->outcfg; | |
374 | } | ||
375 | |||
376 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37256 times.
|
37257 | if (ctx->nb_outputs > FF_ARRAY_ELEMS(cfg_out_stack)) { |
377 | 1 | cfg_out_dyn = av_malloc_array(ctx->nb_outputs, sizeof(*cfg_out_dyn)); | |
378 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!cfg_out_dyn) { |
379 | ✗ | av_freep(&cfg_in_dyn); | |
380 | ✗ | return AVERROR(ENOMEM); | |
381 | } | ||
382 | 1 | cfg_out = cfg_out_dyn; | |
383 | } else | ||
384 |
2/2✓ Branch 0 taken 29048 times.
✓ Branch 1 taken 8208 times.
|
37256 | cfg_out = ctx->nb_outputs ? cfg_out_stack : NULL; |
385 | |||
386 |
2/2✓ Branch 0 taken 29120 times.
✓ Branch 1 taken 37257 times.
|
66377 | for (unsigned i = 0; i < ctx->nb_outputs; i++) { |
387 | 29120 | AVFilterLink *l = ctx->outputs[i]; | |
388 | 29120 | cfg_out[i] = &l->incfg; | |
389 | } | ||
390 | |||
391 | 37257 | ret = filter->formats.query_func2(ctx, cfg_in, cfg_out); | |
392 | 37257 | av_freep(&cfg_in_dyn); | |
393 | 37257 | av_freep(&cfg_out_dyn); | |
394 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37257 times.
|
37257 | if (ret < 0) { |
395 | ✗ | if (ret != AVERROR(EAGAIN)) | |
396 | ✗ | av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n", | |
397 | ✗ | ctx->name, av_err2str(ret)); | |
398 | ✗ | return ret; | |
399 | } | ||
400 | } | ||
401 | |||
402 |
2/2✓ Branch 0 taken 44490 times.
✓ Branch 1 taken 14 times.
|
44504 | if (filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC || |
403 |
2/2✓ Branch 0 taken 37257 times.
✓ Branch 1 taken 7233 times.
|
44490 | filter->formats_state == FF_FILTER_FORMATS_QUERY_FUNC2) { |
404 | 37271 | ret = filter_check_formats(ctx); | |
405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37271 times.
|
37271 | if (ret < 0) |
406 | ✗ | return ret; | |
407 | } | ||
408 | |||
409 | 44504 | return ff_default_query_formats(ctx); | |
410 | } | ||
411 | |||
412 | 43310 | static int formats_declared(AVFilterContext *f) | |
413 | { | ||
414 | int i; | ||
415 | |||
416 |
2/2✓ Branch 0 taken 35052 times.
✓ Branch 1 taken 8291 times.
|
43343 | for (i = 0; i < f->nb_inputs; i++) { |
417 |
2/2✓ Branch 0 taken 35017 times.
✓ Branch 1 taken 35 times.
|
35052 | if (!f->inputs[i]->outcfg.formats) |
418 | 35017 | return 0; | |
419 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 2 times.
|
35 | if (f->inputs[i]->type == AVMEDIA_TYPE_VIDEO && |
420 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
|
33 | !(f->inputs[i]->outcfg.color_ranges && |
421 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | f->inputs[i]->outcfg.color_spaces)) |
422 | 2 | return 0; | |
423 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 31 times.
|
33 | if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO && |
424 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | !(f->inputs[i]->outcfg.samplerates && |
425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | f->inputs[i]->outcfg.channel_layouts)) |
426 | ✗ | return 0; | |
427 | } | ||
428 |
2/2✓ Branch 0 taken 8281 times.
✓ Branch 1 taken 44 times.
|
8325 | for (i = 0; i < f->nb_outputs; i++) { |
429 |
2/2✓ Branch 0 taken 8247 times.
✓ Branch 1 taken 34 times.
|
8281 | if (!f->outputs[i]->incfg.formats) |
430 | 8247 | return 0; | |
431 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 3 times.
|
34 | if (f->outputs[i]->type == AVMEDIA_TYPE_VIDEO && |
432 |
1/2✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
|
31 | !(f->outputs[i]->incfg.color_ranges && |
433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
|
31 | f->outputs[i]->incfg.color_spaces)) |
434 | ✗ | return 0; | |
435 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 31 times.
|
34 | if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO && |
436 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | !(f->outputs[i]->incfg.samplerates && |
437 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | f->outputs[i]->incfg.channel_layouts)) |
438 | ✗ | return 0; | |
439 | } | ||
440 | 44 | return 1; | |
441 | } | ||
442 | |||
443 | ✗ | static void print_formats(void *log_ctx, int level, enum AVMediaType type, | |
444 | const AVFilterFormats *formats) | ||
445 | { | ||
446 | AVBPrint bp; | ||
447 | ✗ | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); | |
448 | |||
449 | ✗ | switch (type) { | |
450 | ✗ | case AVMEDIA_TYPE_VIDEO: | |
451 | ✗ | for (unsigned i = 0; i < formats->nb_formats; i++) | |
452 | ✗ | av_bprintf(&bp, "%s%s", bp.len ? " " : "", av_get_pix_fmt_name(formats->formats[i])); | |
453 | ✗ | break; | |
454 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
455 | ✗ | for (unsigned i = 0; i < formats->nb_formats; i++) | |
456 | ✗ | av_bprintf(&bp, "%s%s", bp.len ? " " : "", av_get_sample_fmt_name(formats->formats[i])); | |
457 | ✗ | break; | |
458 | ✗ | default: | |
459 | ✗ | av_bprintf(&bp, "(unknown)"); | |
460 | ✗ | break; | |
461 | } | ||
462 | |||
463 | ✗ | if (av_bprint_is_complete(&bp)) { | |
464 | ✗ | av_log(log_ctx, level, "%s\n", bp.str); | |
465 | } else { | ||
466 | ✗ | av_log(log_ctx, level, "(out of memory)\n"); | |
467 | } | ||
468 | ✗ | av_bprint_finalize(&bp, NULL); | |
469 | ✗ | } | |
470 | |||
471 | ✗ | static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l) | |
472 | { | ||
473 | ✗ | if (av_log_get_level() < level) | |
474 | ✗ | return; | |
475 | |||
476 | ✗ | av_log(log_ctx, level, "Link '%s.%s' -> '%s.%s':\n" | |
477 | ✗ | " src: ", l->src->name, l->srcpad->name, l->dst->name, l->dstpad->name); | |
478 | ✗ | print_formats(log_ctx, level, l->type, l->incfg.formats); | |
479 | ✗ | av_log(log_ctx, level, " dst: "); | |
480 | ✗ | print_formats(log_ctx, level, l->type, l->outcfg.formats); | |
481 | } | ||
482 | |||
483 | 43252 | static void print_filter_formats(void *log_ctx, int level, const AVFilterContext *f) | |
484 | { | ||
485 |
1/2✓ Branch 1 taken 43252 times.
✗ Branch 2 not taken.
|
43252 | if (av_log_get_level() < level) |
486 | 43252 | return; | |
487 | |||
488 | ✗ | av_log(log_ctx, level, "Filter '%s' formats:\n", f->name); | |
489 | ✗ | for (int i = 0; i < f->nb_inputs; i++) { | |
490 | ✗ | av_log(log_ctx, level, " in[%d] '%s': ", i, f->input_pads[i].name); | |
491 | ✗ | print_formats(log_ctx, level, f->inputs[i]->type, f->inputs[i]->outcfg.formats); | |
492 | } | ||
493 | ✗ | for (int i = 0; i < f->nb_outputs; i++) { | |
494 | ✗ | av_log(log_ctx, level, " out[%d] '%s': ", i, f->output_pads[i].name); | |
495 | ✗ | print_formats(log_ctx, level, f->outputs[i]->type, f->outputs[i]->incfg.formats); | |
496 | } | ||
497 | } | ||
498 | |||
499 | /** | ||
500 | * Perform one round of query_formats() and merging formats lists on the | ||
501 | * filter graph. | ||
502 | * @return >=0 if all links formats lists could be queried and merged; | ||
503 | * AVERROR(EAGAIN) some progress was made in the queries or merging | ||
504 | * and a later call may succeed; | ||
505 | * AVERROR(EIO) (may be changed) plus a log message if no progress | ||
506 | * was made and the negotiation is stuck; | ||
507 | * a negative error code if some other error happened | ||
508 | */ | ||
509 | 8087 | static int query_formats(AVFilterGraph *graph, void *log_ctx) | |
510 | { | ||
511 | int i, j, ret; | ||
512 | 8087 | int converter_count = 0; | |
513 | 8087 | int count_queried = 0; /* successful calls to query_formats() */ | |
514 | 8087 | int count_merged = 0; /* successful merge of formats lists */ | |
515 | 8087 | int count_already_merged = 0; /* lists already merged */ | |
516 | 8087 | int count_delayed = 0; /* lists that need to be merged later */ | |
517 | |||
518 |
2/2✓ Branch 0 taken 43310 times.
✓ Branch 1 taken 8087 times.
|
51397 | for (i = 0; i < graph->nb_filters; i++) { |
519 | 43310 | AVFilterContext *f = graph->filters[i]; | |
520 |
2/2✓ Branch 1 taken 44 times.
✓ Branch 2 taken 43266 times.
|
43310 | if (formats_declared(f)) |
521 | 44 | continue; | |
522 | 43266 | ret = filter_query_formats(f); | |
523 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 43252 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
43266 | if (ret < 0 && ret != AVERROR(EAGAIN)) |
524 | ✗ | return ret; | |
525 | /* note: EAGAIN could indicate a partial success, not counted yet */ | ||
526 |
2/2✓ Branch 0 taken 43252 times.
✓ Branch 1 taken 14 times.
|
43266 | if (ret >= 0) { |
527 | 43252 | print_filter_formats(log_ctx, AV_LOG_DEBUG, f); | |
528 | 43252 | count_queried++; | |
529 | } | ||
530 | } | ||
531 | |||
532 | /* go through and merge as many format lists as possible */ | ||
533 |
2/2✓ Branch 0 taken 44562 times.
✓ Branch 1 taken 8087 times.
|
52649 | for (i = 0; i < graph->nb_filters; i++) { |
534 | 44562 | AVFilterContext *filter = graph->filters[i]; | |
535 | |||
536 |
2/2✓ Branch 0 taken 36442 times.
✓ Branch 1 taken 44562 times.
|
81004 | for (j = 0; j < filter->nb_inputs; j++) { |
537 | 36442 | AVFilterLink *link = filter->inputs[j]; | |
538 | const AVFilterNegotiation *neg; | ||
539 | unsigned neg_step; | ||
540 | 36442 | int convert_needed = 0; | |
541 | |||
542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36442 times.
|
36442 | if (!link) |
543 | ✗ | continue; | |
544 | |||
545 | 36442 | neg = ff_filter_get_negotiation(link); | |
546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36442 times.
|
36442 | av_assert0(neg); |
547 |
2/2✓ Branch 0 taken 108066 times.
✓ Branch 1 taken 35190 times.
|
143256 | for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) { |
548 | 108066 | const AVFilterFormatsMerger *m = &neg->mergers[neg_step]; | |
549 | 108066 | void *a = FF_FIELD_AT(void *, m->offset, link->incfg); | |
550 | 108066 | void *b = FF_FIELD_AT(void *, m->offset, link->outcfg); | |
551 |
8/8✓ Branch 0 taken 108024 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 107981 times.
✓ Branch 3 taken 43 times.
✓ Branch 4 taken 104153 times.
✓ Branch 5 taken 3828 times.
✓ Branch 7 taken 1252 times.
✓ Branch 8 taken 102901 times.
|
108066 | if (a && b && a != b && !m->can_merge(a, b)) { |
552 | 1252 | convert_needed = 1; | |
553 | 1252 | break; | |
554 | } | ||
555 | } | ||
556 |
2/2✓ Branch 0 taken 109326 times.
✓ Branch 1 taken 36442 times.
|
145768 | for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) { |
557 | 109326 | const AVFilterFormatsMerger *m = &neg->mergers[neg_step]; | |
558 | 109326 | void *a = FF_FIELD_AT(void *, m->offset, link->incfg); | |
559 | 109326 | void *b = FF_FIELD_AT(void *, m->offset, link->outcfg); | |
560 |
4/4✓ Branch 0 taken 109284 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 109241 times.
|
109326 | if (!(a && b)) { |
561 | 85 | count_delayed++; | |
562 |
2/2✓ Branch 0 taken 8996 times.
✓ Branch 1 taken 100245 times.
|
109241 | } else if (a == b) { |
563 | 8996 | count_already_merged++; | |
564 |
2/2✓ Branch 0 taken 97070 times.
✓ Branch 1 taken 3175 times.
|
100245 | } else if (!convert_needed) { |
565 | 97070 | count_merged++; | |
566 | 97070 | ret = m->merge(a, b); | |
567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97070 times.
|
97070 | if (ret < 0) |
568 | ✗ | return ret; | |
569 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97070 times.
|
97070 | if (!ret) |
570 | ✗ | convert_needed = 1; | |
571 | } | ||
572 | } | ||
573 | |||
574 |
2/2✓ Branch 0 taken 1252 times.
✓ Branch 1 taken 35190 times.
|
36442 | if (convert_needed) { |
575 | AVFilterContext *convert; | ||
576 | const AVFilter *filter; | ||
577 | AVFilterLink *inlink, *outlink; | ||
578 | char inst_name[30]; | ||
579 | const char *opts; | ||
580 | |||
581 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1252 times.
|
1252 | if (fffiltergraph(graph)->disable_auto_convert) { |
582 | ✗ | av_log(log_ctx, AV_LOG_ERROR, | |
583 | "The filters '%s' and '%s' do not have a common format " | ||
584 | "and automatic conversion is disabled.\n", | ||
585 | ✗ | link->src->name, link->dst->name); | |
586 | ✗ | print_link_formats(log_ctx, AV_LOG_ERROR, link); | |
587 | ✗ | return AVERROR(EINVAL); | |
588 | } | ||
589 | |||
590 | /* couldn't merge format lists. auto-insert conversion filter */ | ||
591 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1252 times.
|
1252 | if (!(filter = avfilter_get_by_name(neg->conversion_filter))) { |
592 | ✗ | av_log(log_ctx, AV_LOG_ERROR, | |
593 | "'%s' filter not present, cannot convert formats.\n", | ||
594 | ✗ | neg->conversion_filter); | |
595 | ✗ | print_link_formats(log_ctx, AV_LOG_ERROR, link); | |
596 | ✗ | return AVERROR(EINVAL); | |
597 | } | ||
598 | 1252 | snprintf(inst_name, sizeof(inst_name), "auto_%s_%d", | |
599 | 1252 | neg->conversion_filter, converter_count++); | |
600 | 1252 | opts = FF_FIELD_AT(char *, neg->conversion_opts_offset, *graph); | |
601 | 1252 | ret = avfilter_graph_create_filter(&convert, filter, inst_name, opts, NULL, graph); | |
602 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1252 times.
|
1252 | if (ret < 0) |
603 | ✗ | return ret; | |
604 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1252 times.
|
1252 | if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0) |
605 | ✗ | return ret; | |
606 | |||
607 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1252 times.
|
1252 | if ((ret = filter_query_formats(convert)) < 0) |
608 | ✗ | return ret; | |
609 | |||
610 | 1252 | inlink = convert->inputs[0]; | |
611 | 1252 | outlink = convert->outputs[0]; | |
612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1252 times.
|
1252 | av_assert0( inlink->incfg.formats->refcount > 0); |
613 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1252 times.
|
1252 | av_assert0( inlink->outcfg.formats->refcount > 0); |
614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1252 times.
|
1252 | av_assert0(outlink->incfg.formats->refcount > 0); |
615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1252 times.
|
1252 | av_assert0(outlink->outcfg.formats->refcount > 0); |
616 |
2/2✓ Branch 0 taken 622 times.
✓ Branch 1 taken 630 times.
|
1252 | if (outlink->type == AVMEDIA_TYPE_VIDEO) { |
617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0( inlink-> incfg.color_spaces->refcount > 0); |
618 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0( inlink->outcfg.color_spaces->refcount > 0); |
619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0(outlink-> incfg.color_spaces->refcount > 0); |
620 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0(outlink->outcfg.color_spaces->refcount > 0); |
621 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0( inlink-> incfg.color_ranges->refcount > 0); |
622 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0( inlink->outcfg.color_ranges->refcount > 0); |
623 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0(outlink-> incfg.color_ranges->refcount > 0); |
624 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 622 times.
|
622 | av_assert0(outlink->outcfg.color_ranges->refcount > 0); |
625 |
1/2✓ Branch 0 taken 630 times.
✗ Branch 1 not taken.
|
630 | } else if (outlink->type == AVMEDIA_TYPE_AUDIO) { |
626 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0( inlink-> incfg.samplerates->refcount > 0); |
627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0( inlink->outcfg.samplerates->refcount > 0); |
628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0(outlink-> incfg.samplerates->refcount > 0); |
629 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0(outlink->outcfg.samplerates->refcount > 0); |
630 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0( inlink-> incfg.channel_layouts->refcount > 0); |
631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0( inlink->outcfg.channel_layouts->refcount > 0); |
632 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0(outlink-> incfg.channel_layouts->refcount > 0); |
633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 630 times.
|
630 | av_assert0(outlink->outcfg.channel_layouts->refcount > 0); |
634 | } | ||
635 | #define MERGE(merger, link) \ | ||
636 | ((merger)->merge(FF_FIELD_AT(void *, (merger)->offset, (link)->incfg), \ | ||
637 | FF_FIELD_AT(void *, (merger)->offset, (link)->outcfg))) | ||
638 |
2/2✓ Branch 0 taken 3756 times.
✓ Branch 1 taken 1252 times.
|
5008 | for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) { |
639 | 3756 | const AVFilterFormatsMerger *m = &neg->mergers[neg_step]; | |
640 |
2/4✓ Branch 1 taken 3756 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3756 times.
|
7512 | if ((ret = MERGE(m, inlink)) <= 0 || |
641 | 3756 | (ret = MERGE(m, outlink)) <= 0) { | |
642 | ✗ | if (ret < 0) | |
643 | ✗ | return ret; | |
644 | ✗ | av_log(log_ctx, AV_LOG_ERROR, | |
645 | "Impossible to convert between the formats supported by the filter " | ||
646 | ✗ | "'%s' and the filter '%s'\n", link->src->name, link->dst->name); | |
647 | ✗ | print_link_formats(log_ctx, AV_LOG_ERROR, link); | |
648 | ✗ | return AVERROR(ENOSYS); | |
649 | } | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | } | ||
654 | |||
655 | 8087 | av_log(graph, AV_LOG_DEBUG, "query_formats: " | |
656 | "%d queried, %d merged, %d already done, %d delayed\n", | ||
657 | count_queried, count_merged, count_already_merged, count_delayed); | ||
658 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8073 times.
|
8087 | if (count_delayed) { |
659 | AVBPrint bp; | ||
660 | |||
661 | /* if count_queried > 0, one filter at least did set its formats, | ||
662 | that will give additional information to its neighbour; | ||
663 | if count_merged > 0, one pair of formats lists at least was merged, | ||
664 | that will give additional information to all connected filters; | ||
665 | in both cases, progress was made and a new round must be done */ | ||
666 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
14 | if (count_queried || count_merged) |
667 | 14 | return AVERROR(EAGAIN); | |
668 | ✗ | av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
669 | ✗ | for (i = 0; i < graph->nb_filters; i++) | |
670 | ✗ | if (!formats_declared(graph->filters[i])) | |
671 | ✗ | av_bprintf(&bp, "%s%s", bp.len ? ", " : "", | |
672 | ✗ | graph->filters[i]->name); | |
673 | ✗ | av_log(graph, AV_LOG_ERROR, | |
674 | "The following filters could not choose their formats: %s\n" | ||
675 | "Consider inserting the (a)format filter near their input or " | ||
676 | "output.\n", bp.str); | ||
677 | ✗ | return AVERROR(EIO); | |
678 | } | ||
679 | 8073 | return 0; | |
680 | } | ||
681 | |||
682 | 1130 | static int get_fmt_score(enum AVSampleFormat dst_fmt, enum AVSampleFormat src_fmt) | |
683 | { | ||
684 | 1130 | int score = 0; | |
685 | |||
686 |
2/2✓ Branch 2 taken 1035 times.
✓ Branch 3 taken 95 times.
|
1130 | if (av_sample_fmt_is_planar(dst_fmt) != av_sample_fmt_is_planar(src_fmt)) |
687 | 1035 | score ++; | |
688 | |||
689 |
2/2✓ Branch 2 taken 254 times.
✓ Branch 3 taken 876 times.
|
1130 | if (av_get_bytes_per_sample(dst_fmt) < av_get_bytes_per_sample(src_fmt)) { |
690 | 254 | score += 100 * (av_get_bytes_per_sample(src_fmt) - av_get_bytes_per_sample(dst_fmt)); | |
691 | }else | ||
692 | 876 | score += 10 * (av_get_bytes_per_sample(dst_fmt) - av_get_bytes_per_sample(src_fmt)); | |
693 | |||
694 |
3/4✓ Branch 1 taken 139 times.
✓ Branch 2 taken 991 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 139 times.
|
1269 | if (av_get_packed_sample_fmt(dst_fmt) == AV_SAMPLE_FMT_S32 && |
695 | 139 | av_get_packed_sample_fmt(src_fmt) == AV_SAMPLE_FMT_FLT) | |
696 | ✗ | score += 20; | |
697 | |||
698 |
3/4✓ Branch 1 taken 95 times.
✓ Branch 2 taken 1035 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 95 times.
|
1225 | if (av_get_packed_sample_fmt(dst_fmt) == AV_SAMPLE_FMT_FLT && |
699 | 95 | av_get_packed_sample_fmt(src_fmt) == AV_SAMPLE_FMT_S32) | |
700 | ✗ | score += 2; | |
701 | |||
702 | 1130 | return score; | |
703 | } | ||
704 | |||
705 | 565 | static enum AVSampleFormat find_best_sample_fmt_of_2(enum AVSampleFormat dst_fmt1, enum AVSampleFormat dst_fmt2, | |
706 | enum AVSampleFormat src_fmt) | ||
707 | { | ||
708 | int score1, score2; | ||
709 | |||
710 | 565 | score1 = get_fmt_score(dst_fmt1, src_fmt); | |
711 | 565 | score2 = get_fmt_score(dst_fmt2, src_fmt); | |
712 | |||
713 |
2/2✓ Branch 0 taken 425 times.
✓ Branch 1 taken 140 times.
|
565 | return score1 < score2 ? dst_fmt1 : dst_fmt2; |
714 | } | ||
715 | |||
716 | 36189 | int ff_fmt_is_regular_yuv(enum AVPixelFormat fmt) | |
717 | { | ||
718 | 36189 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); | |
719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36189 times.
|
36189 | if (!desc) |
720 | ✗ | return 0; | |
721 |
2/2✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 34419 times.
|
36189 | if (desc->nb_components < 3) |
722 | 1770 | return 0; /* Grayscale is explicitly full-range in swscale */ | |
723 | av_assert1(!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)); | ||
724 | 34419 | return !(desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PAL | | |
725 | AV_PIX_FMT_FLAG_XYZ | AV_PIX_FMT_FLAG_FLOAT)); | ||
726 | } | ||
727 | |||
728 | |||
729 | 25792 | int ff_fmt_is_forced_full_range(enum AVPixelFormat fmt) | |
730 | { | ||
731 |
2/2✓ Branch 0 taken 745 times.
✓ Branch 1 taken 25047 times.
|
25792 | switch (fmt) { |
732 | 745 | case AV_PIX_FMT_YUVJ420P: | |
733 | case AV_PIX_FMT_YUVJ422P: | ||
734 | case AV_PIX_FMT_YUVJ444P: | ||
735 | case AV_PIX_FMT_YUVJ440P: | ||
736 | case AV_PIX_FMT_YUVJ411P: | ||
737 | 745 | return 1; | |
738 | 25047 | default: | |
739 | 25047 | return 0; | |
740 | } | ||
741 | } | ||
742 | |||
743 | 109130 | static int pick_format(AVFilterLink *link, AVFilterLink *ref) | |
744 | { | ||
745 |
3/4✓ Branch 0 taken 109130 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72736 times.
✓ Branch 3 taken 36394 times.
|
109130 | if (!link || !link->incfg.formats) |
746 | 72736 | return 0; | |
747 | |||
748 |
2/2✓ Branch 0 taken 30483 times.
✓ Branch 1 taken 5911 times.
|
36394 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
749 |
3/4✓ Branch 0 taken 97 times.
✓ Branch 1 taken 30386 times.
✓ Branch 2 taken 97 times.
✗ Branch 3 not taken.
|
30483 | if(ref && ref->type == AVMEDIA_TYPE_VIDEO){ |
750 | //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented | ||
751 | 97 | int has_alpha= av_pix_fmt_desc_get(ref->format)->nb_components % 2 == 0; | |
752 | 97 | enum AVPixelFormat best= AV_PIX_FMT_NONE; | |
753 | int i; | ||
754 |
2/2✓ Branch 0 taken 1029 times.
✓ Branch 1 taken 97 times.
|
1126 | for (i = 0; i < link->incfg.formats->nb_formats; i++) { |
755 | 1029 | enum AVPixelFormat p = link->incfg.formats->formats[i]; | |
756 | 1029 | best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); | |
757 | } | ||
758 | 97 | av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n", | |
759 | 97 | av_get_pix_fmt_name(best), link->incfg.formats->nb_formats, | |
760 | 97 | av_get_pix_fmt_name(ref->format), has_alpha); | |
761 | 97 | link->incfg.formats->formats[0] = best; | |
762 | } | ||
763 |
1/2✓ Branch 0 taken 5911 times.
✗ Branch 1 not taken.
|
5911 | } else if (link->type == AVMEDIA_TYPE_AUDIO) { |
764 |
3/4✓ Branch 0 taken 140 times.
✓ Branch 1 taken 5771 times.
✓ Branch 2 taken 140 times.
✗ Branch 3 not taken.
|
5911 | if(ref && ref->type == AVMEDIA_TYPE_AUDIO){ |
765 | 140 | enum AVSampleFormat best= AV_SAMPLE_FMT_NONE; | |
766 | int i; | ||
767 |
2/2✓ Branch 0 taken 565 times.
✓ Branch 1 taken 140 times.
|
705 | for (i = 0; i < link->incfg.formats->nb_formats; i++) { |
768 | 565 | enum AVSampleFormat p = link->incfg.formats->formats[i]; | |
769 | 565 | best = find_best_sample_fmt_of_2(best, p, ref->format); | |
770 | } | ||
771 | 140 | av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s\n", | |
772 | 140 | av_get_sample_fmt_name(best), link->incfg.formats->nb_formats, | |
773 | 140 | av_get_sample_fmt_name(ref->format)); | |
774 | 140 | link->incfg.formats->formats[0] = best; | |
775 | } | ||
776 | } | ||
777 | |||
778 | 36394 | link->incfg.formats->nb_formats = 1; | |
779 | 36394 | link->format = link->incfg.formats->formats[0]; | |
780 | |||
781 |
2/2✓ Branch 0 taken 30483 times.
✓ Branch 1 taken 5911 times.
|
36394 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
782 | 30483 | enum AVPixelFormat swfmt = link->format; | |
783 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30483 times.
|
30483 | if (av_pix_fmt_desc_get(swfmt)->flags & AV_PIX_FMT_FLAG_HWACCEL) { |
784 | // FIXME: this is a hack - we'd like to use the sw_format of | ||
785 | // link->hw_frames_ctx here, but it is not yet available. | ||
786 | // To make this work properly we will need to either reorder | ||
787 | // things so that it is available here or somehow negotiate | ||
788 | // sw_format separately. | ||
789 | ✗ | swfmt = AV_PIX_FMT_YUV420P; | |
790 | } | ||
791 | |||
792 |
2/2✓ Branch 1 taken 9693 times.
✓ Branch 2 taken 20790 times.
|
30483 | if (!ff_fmt_is_regular_yuv(swfmt)) { |
793 | 9693 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swfmt); | |
794 | /* These fields are explicitly documented as affecting YUV only, | ||
795 | * so set them to sane values for other formats. */ | ||
796 |
2/2✓ Branch 0 taken 571 times.
✓ Branch 1 taken 9122 times.
|
9693 | if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) |
797 | 571 | link->color_range = AVCOL_RANGE_UNSPECIFIED; | |
798 | else | ||
799 | 9122 | link->color_range = AVCOL_RANGE_JPEG; | |
800 |
2/2✓ Branch 0 taken 8117 times.
✓ Branch 1 taken 1576 times.
|
9693 | if (desc->flags & (AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_XYZ)) { |
801 | 8117 | link->colorspace = AVCOL_SPC_RGB; | |
802 | } else { | ||
803 | 1576 | link->colorspace = AVCOL_SPC_UNSPECIFIED; | |
804 | } | ||
805 | } else { | ||
806 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20790 times.
|
20790 | if (!link->incfg.color_spaces->nb_formats) { |
807 | ✗ | av_log(link->src, AV_LOG_ERROR, "Cannot select color space for" | |
808 | ✗ | " the link between filters %s and %s.\n", link->src->name, | |
809 | ✗ | link->dst->name); | |
810 | ✗ | return AVERROR(EINVAL); | |
811 | } | ||
812 | 20790 | link->incfg.color_spaces->nb_formats = 1; | |
813 | 20790 | link->colorspace = link->incfg.color_spaces->formats[0]; | |
814 | |||
815 |
2/2✓ Branch 1 taken 674 times.
✓ Branch 2 taken 20116 times.
|
20790 | if (ff_fmt_is_forced_full_range(swfmt)) { |
816 | 674 | link->color_range = AVCOL_RANGE_JPEG; | |
817 | } else { | ||
818 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20116 times.
|
20116 | if (!link->incfg.color_ranges->nb_formats) { |
819 | ✗ | av_log(link->src, AV_LOG_ERROR, "Cannot select color range for" | |
820 | ✗ | " the link between filters %s and %s.\n", link->src->name, | |
821 | ✗ | link->dst->name); | |
822 | ✗ | return AVERROR(EINVAL); | |
823 | } | ||
824 | 20116 | link->incfg.color_ranges->nb_formats = 1; | |
825 | 20116 | link->color_range = link->incfg.color_ranges->formats[0]; | |
826 | } | ||
827 | } | ||
828 |
1/2✓ Branch 0 taken 5911 times.
✗ Branch 1 not taken.
|
5911 | } else if (link->type == AVMEDIA_TYPE_AUDIO) { |
829 | int ret; | ||
830 | |||
831 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5911 times.
|
5911 | if (!link->incfg.samplerates->nb_formats) { |
832 | ✗ | av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" | |
833 | ✗ | " the link between filters %s and %s.\n", link->src->name, | |
834 | ✗ | link->dst->name); | |
835 | ✗ | return AVERROR(EINVAL); | |
836 | } | ||
837 | 5911 | link->incfg.samplerates->nb_formats = 1; | |
838 | 5911 | link->sample_rate = link->incfg.samplerates->formats[0]; | |
839 | |||
840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5911 times.
|
5911 | if (link->incfg.channel_layouts->all_layouts) { |
841 | ✗ | av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for" | |
842 | ✗ | " the link between filters %s and %s.\n", link->src->name, | |
843 | ✗ | link->dst->name); | |
844 | ✗ | if (!link->incfg.channel_layouts->all_counts) | |
845 | ✗ | av_log(link->src, AV_LOG_ERROR, "Unknown channel layouts not " | |
846 | "supported, try specifying a channel layout using " | ||
847 | "'aformat=channel_layouts=something'.\n"); | ||
848 | ✗ | return AVERROR(EINVAL); | |
849 | } | ||
850 | 5911 | link->incfg.channel_layouts->nb_channel_layouts = 1; | |
851 | 5911 | ret = av_channel_layout_copy(&link->ch_layout, &link->incfg.channel_layouts->channel_layouts[0]); | |
852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5911 times.
|
5911 | if (ret < 0) |
853 | ✗ | return ret; | |
854 | } | ||
855 | |||
856 | 36394 | ff_formats_unref(&link->incfg.formats); | |
857 | 36394 | ff_formats_unref(&link->outcfg.formats); | |
858 | 36394 | ff_formats_unref(&link->incfg.samplerates); | |
859 | 36394 | ff_formats_unref(&link->outcfg.samplerates); | |
860 | 36394 | ff_channel_layouts_unref(&link->incfg.channel_layouts); | |
861 | 36394 | ff_channel_layouts_unref(&link->outcfg.channel_layouts); | |
862 | 36394 | ff_formats_unref(&link->incfg.color_spaces); | |
863 | 36394 | ff_formats_unref(&link->outcfg.color_spaces); | |
864 | 36394 | ff_formats_unref(&link->incfg.color_ranges); | |
865 | 36394 | ff_formats_unref(&link->outcfg.color_ranges); | |
866 | |||
867 | 36394 | return 0; | |
868 | } | ||
869 | |||
870 | #define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \ | ||
871 | do { \ | ||
872 | for (i = 0; i < filter->nb_inputs; i++) { \ | ||
873 | AVFilterLink *link = filter->inputs[i]; \ | ||
874 | fmt_type fmt; \ | ||
875 | \ | ||
876 | if (!link->outcfg.list || link->outcfg.list->nb != 1) \ | ||
877 | continue; \ | ||
878 | fmt = link->outcfg.list->var[0]; \ | ||
879 | \ | ||
880 | for (j = 0; j < filter->nb_outputs; j++) { \ | ||
881 | AVFilterLink *out_link = filter->outputs[j]; \ | ||
882 | list_type *fmts; \ | ||
883 | \ | ||
884 | if (link->type != out_link->type || \ | ||
885 | out_link->incfg.list->nb == 1) \ | ||
886 | continue; \ | ||
887 | fmts = out_link->incfg.list; \ | ||
888 | \ | ||
889 | if (!out_link->incfg.list->nb) { \ | ||
890 | if ((ret = add_format(&out_link->incfg.list, fmt)) < 0)\ | ||
891 | return ret; \ | ||
892 | ret = 1; \ | ||
893 | break; \ | ||
894 | } \ | ||
895 | \ | ||
896 | for (k = 0; k < out_link->incfg.list->nb; k++) \ | ||
897 | if (fmts->var[k] == fmt) { \ | ||
898 | fmts->var[0] = fmt; \ | ||
899 | fmts->nb = 1; \ | ||
900 | ret = 1; \ | ||
901 | break; \ | ||
902 | } \ | ||
903 | } \ | ||
904 | } \ | ||
905 | } while (0) | ||
906 | |||
907 | 71341 | static int reduce_formats_on_filter(AVFilterContext *filter) | |
908 | { | ||
909 | 71341 | int i, j, k, ret = 0; | |
910 | |||
911 |
16/20✓ Branch 0 taken 58621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1363 times.
✓ Branch 3 taken 57258 times.
✓ Branch 4 taken 44761 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 44213 times.
✓ Branch 7 taken 548 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 548 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 51 times.
✓ Branch 14 taken 4666 times.
✓ Branch 15 taken 4717 times.
✓ Branch 16 taken 497 times.
✓ Branch 17 taken 44773 times.
✓ Branch 18 taken 57258 times.
✓ Branch 19 taken 58621 times.
✓ Branch 20 taken 71341 times.
|
179401 | REDUCE_FORMATS(int, AVFilterFormats, formats, formats, |
912 | nb_formats, ff_add_format); | ||
913 |
18/20✓ Branch 0 taken 10708 times.
✓ Branch 1 taken 47913 times.
✓ Branch 2 taken 1173 times.
✓ Branch 3 taken 9535 times.
✓ Branch 4 taken 7728 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 6963 times.
✓ Branch 7 taken 765 times.
✓ Branch 8 taken 729 times.
✓ Branch 9 taken 36 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 729 times.
✓ Branch 13 taken 36 times.
✓ Branch 14 taken 68 times.
✓ Branch 15 taken 104 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 7734 times.
✓ Branch 18 taken 8806 times.
✓ Branch 19 taken 58621 times.
✓ Branch 20 taken 71341 times.
|
137035 | REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats, |
914 | nb_formats, ff_add_format); | ||
915 |
15/20✓ Branch 0 taken 47913 times.
✓ Branch 1 taken 10708 times.
✓ Branch 2 taken 11011 times.
✓ Branch 3 taken 36902 times.
✓ Branch 4 taken 28940 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 25032 times.
✓ Branch 7 taken 3908 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3908 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3908 times.
✓ Branch 14 taken 411 times.
✓ Branch 15 taken 4319 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 28940 times.
✓ Branch 18 taken 36902 times.
✓ Branch 19 taken 58621 times.
✓ Branch 20 taken 71341 times.
|
159313 | REDUCE_FORMATS(int, AVFilterFormats, color_spaces, formats, |
916 | nb_formats, ff_add_format); | ||
917 |
15/20✓ Branch 0 taken 47913 times.
✓ Branch 1 taken 10708 times.
✓ Branch 2 taken 8464 times.
✓ Branch 3 taken 39449 times.
✓ Branch 4 taken 30229 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 26922 times.
✓ Branch 7 taken 3307 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3307 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3307 times.
✓ Branch 14 taken 3287 times.
✓ Branch 15 taken 6594 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 30229 times.
✓ Branch 18 taken 39449 times.
✓ Branch 19 taken 58621 times.
✓ Branch 20 taken 71341 times.
|
163478 | REDUCE_FORMATS(int, AVFilterFormats, color_ranges, formats, |
918 | nb_formats, ff_add_format); | ||
919 | |||
920 | /* reduce channel layouts */ | ||
921 |
2/2✓ Branch 0 taken 58621 times.
✓ Branch 1 taken 71341 times.
|
129962 | for (i = 0; i < filter->nb_inputs; i++) { |
922 | 58621 | AVFilterLink *inlink = filter->inputs[i]; | |
923 | const AVChannelLayout *fmt; | ||
924 | |||
925 |
2/2✓ Branch 0 taken 10708 times.
✓ Branch 1 taken 47913 times.
|
58621 | if (!inlink->outcfg.channel_layouts || |
926 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 10631 times.
|
10708 | inlink->outcfg.channel_layouts->nb_channel_layouts != 1) |
927 | 47990 | continue; | |
928 | 10631 | fmt = &inlink->outcfg.channel_layouts->channel_layouts[0]; | |
929 | |||
930 |
2/2✓ Branch 0 taken 8447 times.
✓ Branch 1 taken 9790 times.
|
18237 | for (j = 0; j < filter->nb_outputs; j++) { |
931 | 8447 | AVFilterLink *outlink = filter->outputs[j]; | |
932 | AVFilterChannelLayouts *fmts; | ||
933 | |||
934 | 8447 | fmts = outlink->incfg.channel_layouts; | |
935 |
4/4✓ Branch 0 taken 8441 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7559 times.
✓ Branch 3 taken 882 times.
|
8447 | if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1) |
936 | 7565 | continue; | |
937 | |||
938 |
2/2✓ Branch 0 taken 841 times.
✓ Branch 1 taken 41 times.
|
882 | if (fmts->all_layouts && |
939 |
4/6✓ Branch 0 taken 7 times.
✓ Branch 1 taken 834 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
841 | (KNOWN(fmt) || fmts->all_counts)) { |
940 | /* Turn the infinite list into a singleton */ | ||
941 | 841 | fmts->all_layouts = fmts->all_counts = 0; | |
942 | 841 | ret = ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt); | |
943 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 841 times.
|
841 | if (ret < 0) |
944 | ✗ | return ret; | |
945 | 841 | ret = 1; | |
946 | 841 | break; | |
947 | } | ||
948 | |||
949 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 6 times.
|
128 | for (k = 0; k < outlink->incfg.channel_layouts->nb_channel_layouts; k++) { |
950 |
2/2✓ Branch 1 taken 35 times.
✓ Branch 2 taken 87 times.
|
122 | if (!av_channel_layout_compare(&fmts->channel_layouts[k], fmt)) { |
951 | 35 | ret = av_channel_layout_copy(&fmts->channel_layouts[0], fmt); | |
952 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | if (ret < 0) |
953 | ✗ | return ret; | |
954 | 35 | fmts->nb_channel_layouts = 1; | |
955 | 35 | ret = 1; | |
956 | 35 | break; | |
957 | } | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | |||
962 | 71341 | return ret; | |
963 | } | ||
964 | |||
965 | 8073 | static int reduce_formats(AVFilterGraph *graph) | |
966 | { | ||
967 | int i, reduced, ret; | ||
968 | |||
969 | do { | ||
970 | 12650 | reduced = 0; | |
971 | |||
972 |
2/2✓ Branch 0 taken 71341 times.
✓ Branch 1 taken 12650 times.
|
83991 | for (i = 0; i < graph->nb_filters; i++) { |
973 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 71341 times.
|
71341 | if ((ret = reduce_formats_on_filter(graph->filters[i])) < 0) |
974 | ✗ | return ret; | |
975 | 71341 | reduced |= ret; | |
976 | } | ||
977 |
2/2✓ Branch 0 taken 4577 times.
✓ Branch 1 taken 8073 times.
|
12650 | } while (reduced); |
978 | |||
979 | 8073 | return 0; | |
980 | } | ||
981 | |||
982 | 44504 | static void swap_samplerates_on_filter(AVFilterContext *filter) | |
983 | { | ||
984 | 44504 | AVFilterLink *link = NULL; | |
985 | int sample_rate; | ||
986 | int i, j; | ||
987 | |||
988 |
2/2✓ Branch 0 taken 36311 times.
✓ Branch 1 taken 38672 times.
|
74983 | for (i = 0; i < filter->nb_inputs; i++) { |
989 | 36311 | link = filter->inputs[i]; | |
990 | |||
991 |
2/2✓ Branch 0 taken 5832 times.
✓ Branch 1 taken 30479 times.
|
36311 | if (link->type == AVMEDIA_TYPE_AUDIO && |
992 |
1/2✓ Branch 0 taken 5832 times.
✗ Branch 1 not taken.
|
5832 | link->outcfg.samplerates->nb_formats== 1) |
993 | 5832 | break; | |
994 | } | ||
995 |
2/2✓ Branch 0 taken 38672 times.
✓ Branch 1 taken 5832 times.
|
44504 | if (i == filter->nb_inputs) |
996 | 38672 | return; | |
997 | |||
998 | 5832 | sample_rate = link->outcfg.samplerates->formats[0]; | |
999 | |||
1000 |
2/2✓ Branch 0 taken 4548 times.
✓ Branch 1 taken 5832 times.
|
10380 | for (i = 0; i < filter->nb_outputs; i++) { |
1001 | 4548 | AVFilterLink *outlink = filter->outputs[i]; | |
1002 | 4548 | int best_idx, best_diff = INT_MAX; | |
1003 | |||
1004 |
2/2✓ Branch 0 taken 4546 times.
✓ Branch 1 taken 2 times.
|
4548 | if (outlink->type != AVMEDIA_TYPE_AUDIO || |
1005 |
1/2✓ Branch 0 taken 4546 times.
✗ Branch 1 not taken.
|
4546 | outlink->incfg.samplerates->nb_formats < 2) |
1006 | 4548 | continue; | |
1007 | |||
1008 | ✗ | for (j = 0; j < outlink->incfg.samplerates->nb_formats; j++) { | |
1009 | ✗ | int diff = abs(sample_rate - outlink->incfg.samplerates->formats[j]); | |
1010 | |||
1011 | ✗ | av_assert0(diff < INT_MAX); // This would lead to the use of uninitialized best_diff but is only possible with invalid sample rates | |
1012 | |||
1013 | ✗ | if (diff < best_diff) { | |
1014 | ✗ | best_diff = diff; | |
1015 | ✗ | best_idx = j; | |
1016 | } | ||
1017 | } | ||
1018 | ✗ | FFSWAP(int, outlink->incfg.samplerates->formats[0], | |
1019 | outlink->incfg.samplerates->formats[best_idx]); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | 8073 | static void swap_samplerates(AVFilterGraph *graph) | |
1024 | { | ||
1025 | int i; | ||
1026 | |||
1027 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) |
1028 | 44504 | swap_samplerates_on_filter(graph->filters[i]); | |
1029 | 8073 | } | |
1030 | |||
1031 | #define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER) | ||
1032 | #define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) | ||
1033 | #define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT) | ||
1034 | #define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT) | ||
1035 | #define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT) | ||
1036 | #define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT) | ||
1037 | #define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT) | ||
1038 | |||
1039 | /* allowable substitutions for channel pairs when comparing layouts, | ||
1040 | * ordered by priority for both values */ | ||
1041 | static const uint64_t ch_subst[][2] = { | ||
1042 | { CH_FRONT_PAIR, CH_CENTER_PAIR }, | ||
1043 | { CH_FRONT_PAIR, CH_WIDE_PAIR }, | ||
1044 | { CH_FRONT_PAIR, AV_CH_FRONT_CENTER }, | ||
1045 | { CH_CENTER_PAIR, CH_FRONT_PAIR }, | ||
1046 | { CH_CENTER_PAIR, CH_WIDE_PAIR }, | ||
1047 | { CH_CENTER_PAIR, AV_CH_FRONT_CENTER }, | ||
1048 | { CH_WIDE_PAIR, CH_FRONT_PAIR }, | ||
1049 | { CH_WIDE_PAIR, CH_CENTER_PAIR }, | ||
1050 | { CH_WIDE_PAIR, AV_CH_FRONT_CENTER }, | ||
1051 | { AV_CH_FRONT_CENTER, CH_FRONT_PAIR }, | ||
1052 | { AV_CH_FRONT_CENTER, CH_CENTER_PAIR }, | ||
1053 | { AV_CH_FRONT_CENTER, CH_WIDE_PAIR }, | ||
1054 | { CH_SIDE_PAIR, CH_DIRECT_PAIR }, | ||
1055 | { CH_SIDE_PAIR, CH_BACK_PAIR }, | ||
1056 | { CH_SIDE_PAIR, AV_CH_BACK_CENTER }, | ||
1057 | { CH_BACK_PAIR, CH_DIRECT_PAIR }, | ||
1058 | { CH_BACK_PAIR, CH_SIDE_PAIR }, | ||
1059 | { CH_BACK_PAIR, AV_CH_BACK_CENTER }, | ||
1060 | { AV_CH_BACK_CENTER, CH_BACK_PAIR }, | ||
1061 | { AV_CH_BACK_CENTER, CH_DIRECT_PAIR }, | ||
1062 | { AV_CH_BACK_CENTER, CH_SIDE_PAIR }, | ||
1063 | }; | ||
1064 | |||
1065 | 44504 | static void swap_channel_layouts_on_filter(AVFilterContext *filter) | |
1066 | { | ||
1067 | 44504 | AVFilterLink *link = NULL; | |
1068 | int i, j, k; | ||
1069 | |||
1070 |
2/2✓ Branch 0 taken 36311 times.
✓ Branch 1 taken 38678 times.
|
74989 | for (i = 0; i < filter->nb_inputs; i++) { |
1071 | 36311 | link = filter->inputs[i]; | |
1072 | |||
1073 |
2/2✓ Branch 0 taken 5832 times.
✓ Branch 1 taken 30479 times.
|
36311 | if (link->type == AVMEDIA_TYPE_AUDIO && |
1074 |
2/2✓ Branch 0 taken 5826 times.
✓ Branch 1 taken 6 times.
|
5832 | link->outcfg.channel_layouts->nb_channel_layouts == 1) |
1075 | 5826 | break; | |
1076 | } | ||
1077 |
2/2✓ Branch 0 taken 38678 times.
✓ Branch 1 taken 5826 times.
|
44504 | if (i == filter->nb_inputs) |
1078 | 38678 | return; | |
1079 | |||
1080 |
2/2✓ Branch 0 taken 4545 times.
✓ Branch 1 taken 5826 times.
|
10371 | for (i = 0; i < filter->nb_outputs; i++) { |
1081 | 4545 | AVFilterLink *outlink = filter->outputs[i]; | |
1082 | 4545 | int best_idx = -1, best_score = INT_MIN, best_count_diff = INT_MAX; | |
1083 | |||
1084 |
2/2✓ Branch 0 taken 4543 times.
✓ Branch 1 taken 2 times.
|
4545 | if (outlink->type != AVMEDIA_TYPE_AUDIO || |
1085 |
2/2✓ Branch 0 taken 4540 times.
✓ Branch 1 taken 3 times.
|
4543 | outlink->incfg.channel_layouts->nb_channel_layouts < 2) |
1086 | 4542 | continue; | |
1087 | |||
1088 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 3 times.
|
37 | for (j = 0; j < outlink->incfg.channel_layouts->nb_channel_layouts; j++) { |
1089 | 34 | AVChannelLayout in_chlayout = { 0 }, out_chlayout = { 0 }; | |
1090 | int in_channels; | ||
1091 | int out_channels; | ||
1092 | int count_diff; | ||
1093 | int matched_channels, extra_channels; | ||
1094 | 34 | int score = 100000; | |
1095 | |||
1096 | 34 | av_channel_layout_copy(&in_chlayout, &link->outcfg.channel_layouts->channel_layouts[0]); | |
1097 | 34 | av_channel_layout_copy(&out_chlayout, &outlink->incfg.channel_layouts->channel_layouts[j]); | |
1098 | 34 | in_channels = in_chlayout.nb_channels; | |
1099 | 34 | out_channels = out_chlayout.nb_channels; | |
1100 | 34 | count_diff = out_channels - in_channels; | |
1101 |
4/8✓ Branch 0 taken 16 times.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
34 | if (!KNOWN(&in_chlayout) || !KNOWN(&out_chlayout)) { |
1102 | /* Compute score in case the input or output layout encodes | ||
1103 | a channel count; in this case the score is not altered by | ||
1104 | the computation afterwards, as in_chlayout and | ||
1105 | out_chlayout have both been set to 0 */ | ||
1106 |
2/4✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | if (!KNOWN(&in_chlayout)) |
1107 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | in_channels = FF_LAYOUT2COUNT(&in_chlayout); |
1108 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
16 | if (!KNOWN(&out_chlayout)) |
1109 | ✗ | out_channels = FF_LAYOUT2COUNT(&out_chlayout); | |
1110 | 32 | score -= 10000 + FFABS(out_channels - in_channels) + | |
1111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | (in_channels > out_channels ? 10000 : 0); |
1112 | 16 | av_channel_layout_uninit(&in_chlayout); | |
1113 | 16 | av_channel_layout_uninit(&out_chlayout); | |
1114 | /* Let the remaining computation run, even if the score | ||
1115 | value is not altered */ | ||
1116 | } | ||
1117 | |||
1118 | /* channel substitution */ | ||
1119 |
2/2✓ Branch 0 taken 714 times.
✓ Branch 1 taken 34 times.
|
748 | for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) { |
1120 | 714 | uint64_t cmp0 = ch_subst[k][0]; | |
1121 | 714 | uint64_t cmp1 = ch_subst[k][1]; | |
1122 |
4/4✓ Branch 1 taken 216 times.
✓ Branch 2 taken 498 times.
✓ Branch 3 taken 120 times.
✓ Branch 4 taken 96 times.
|
930 | if ( av_channel_layout_subset(& in_chlayout, cmp0) && |
1123 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 100 times.
|
336 | !av_channel_layout_subset(&out_chlayout, cmp0) && |
1124 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 16 times.
|
140 | av_channel_layout_subset(&out_chlayout, cmp1) && |
1125 | 20 | !av_channel_layout_subset(& in_chlayout, cmp1)) { | |
1126 | 4 | av_channel_layout_from_mask(&in_chlayout, av_channel_layout_subset(& in_chlayout, ~cmp0)); | |
1127 | 4 | av_channel_layout_from_mask(&out_chlayout, av_channel_layout_subset(&out_chlayout, ~cmp1)); | |
1128 | /* add score for channel match, minus a deduction for | ||
1129 | having to do the substitution */ | ||
1130 | 4 | score += 10 * av_popcount64(cmp1) - 2; | |
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | /* no penalty for LFE channel mismatch */ | ||
1135 |
4/4✓ Branch 1 taken 18 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 11 times.
|
52 | if (av_channel_layout_index_from_channel(&in_chlayout, AV_CHAN_LOW_FREQUENCY) >= 0 && |
1136 | 18 | av_channel_layout_index_from_channel(&out_chlayout, AV_CHAN_LOW_FREQUENCY) >= 0) | |
1137 | 7 | score += 10; | |
1138 | 34 | av_channel_layout_from_mask(&in_chlayout, av_channel_layout_subset(&in_chlayout, ~AV_CH_LOW_FREQUENCY)); | |
1139 | 34 | av_channel_layout_from_mask(&out_chlayout, av_channel_layout_subset(&out_chlayout, ~AV_CH_LOW_FREQUENCY)); | |
1140 | |||
1141 | 34 | matched_channels = av_popcount64(in_chlayout.u.mask & out_chlayout.u.mask); | |
1142 | 34 | extra_channels = av_popcount64(out_chlayout.u.mask & (~in_chlayout.u.mask)); | |
1143 | 34 | score += 10 * matched_channels - 5 * extra_channels; | |
1144 | |||
1145 |
4/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 20 times.
|
34 | if (score > best_score || |
1146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | (count_diff < best_count_diff && score == best_score)) { |
1147 | 10 | best_score = score; | |
1148 | 10 | best_idx = j; | |
1149 | 10 | best_count_diff = count_diff; | |
1150 | } | ||
1151 | } | ||
1152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | av_assert0(best_idx >= 0); |
1153 | 3 | FFSWAP(AVChannelLayout, outlink->incfg.channel_layouts->channel_layouts[0], | |
1154 | outlink->incfg.channel_layouts->channel_layouts[best_idx]); | ||
1155 | } | ||
1156 | |||
1157 | } | ||
1158 | |||
1159 | 8073 | static void swap_channel_layouts(AVFilterGraph *graph) | |
1160 | { | ||
1161 | int i; | ||
1162 | |||
1163 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) |
1164 | 44504 | swap_channel_layouts_on_filter(graph->filters[i]); | |
1165 | 8073 | } | |
1166 | |||
1167 | 44504 | static void swap_sample_fmts_on_filter(AVFilterContext *filter) | |
1168 | { | ||
1169 | 44504 | AVFilterLink *link = NULL; | |
1170 | int format, bps; | ||
1171 | int i, j; | ||
1172 | |||
1173 |
2/2✓ Branch 0 taken 36380 times.
✓ Branch 1 taken 39063 times.
|
75443 | for (i = 0; i < filter->nb_inputs; i++) { |
1174 | 36380 | link = filter->inputs[i]; | |
1175 | |||
1176 |
2/2✓ Branch 0 taken 5901 times.
✓ Branch 1 taken 30479 times.
|
36380 | if (link->type == AVMEDIA_TYPE_AUDIO && |
1177 |
2/2✓ Branch 0 taken 5441 times.
✓ Branch 1 taken 460 times.
|
5901 | link->outcfg.formats->nb_formats == 1) |
1178 | 5441 | break; | |
1179 | } | ||
1180 |
2/2✓ Branch 0 taken 39063 times.
✓ Branch 1 taken 5441 times.
|
44504 | if (i == filter->nb_inputs) |
1181 | 39063 | return; | |
1182 | |||
1183 | 5441 | format = link->outcfg.formats->formats[0]; | |
1184 | 5441 | bps = av_get_bytes_per_sample(format); | |
1185 | |||
1186 |
2/2✓ Branch 0 taken 4167 times.
✓ Branch 1 taken 5441 times.
|
9608 | for (i = 0; i < filter->nb_outputs; i++) { |
1187 | 4167 | AVFilterLink *outlink = filter->outputs[i]; | |
1188 | 4167 | int best_idx = -1, best_score = INT_MIN; | |
1189 | |||
1190 |
2/2✓ Branch 0 taken 4165 times.
✓ Branch 1 taken 2 times.
|
4167 | if (outlink->type != AVMEDIA_TYPE_AUDIO || |
1191 |
2/2✓ Branch 0 taken 4007 times.
✓ Branch 1 taken 158 times.
|
4165 | outlink->incfg.formats->nb_formats < 2) |
1192 | 4009 | continue; | |
1193 | |||
1194 |
2/2✓ Branch 0 taken 293 times.
✓ Branch 1 taken 7 times.
|
300 | for (j = 0; j < outlink->incfg.formats->nb_formats; j++) { |
1195 | 293 | int out_format = outlink->incfg.formats->formats[j]; | |
1196 | 293 | int out_bps = av_get_bytes_per_sample(out_format); | |
1197 | int score; | ||
1198 | |||
1199 |
4/4✓ Branch 1 taken 156 times.
✓ Branch 2 taken 137 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 142 times.
|
449 | if (av_get_packed_sample_fmt(out_format) == format || |
1200 | 156 | av_get_planar_sample_fmt(out_format) == format) { | |
1201 | 151 | best_idx = j; | |
1202 | 151 | break; | |
1203 | } | ||
1204 | |||
1205 | /* for s32 and float prefer double to prevent loss of information */ | ||
1206 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 138 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
142 | if (bps == 4 && out_bps == 8) { |
1207 | ✗ | best_idx = j; | |
1208 | ✗ | break; | |
1209 | } | ||
1210 | |||
1211 | /* prefer closest higher or equal bps */ | ||
1212 | 142 | score = -abs(out_bps - bps); | |
1213 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 114 times.
|
142 | if (out_bps >= bps) |
1214 | 28 | score += INT_MAX/2; | |
1215 | |||
1216 |
2/2✓ Branch 0 taken 109 times.
✓ Branch 1 taken 33 times.
|
142 | if (score > best_score) { |
1217 | 109 | best_score = score; | |
1218 | 109 | best_idx = j; | |
1219 | } | ||
1220 | } | ||
1221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
|
158 | av_assert0(best_idx >= 0); |
1222 | 158 | FFSWAP(int, outlink->incfg.formats->formats[0], | |
1223 | outlink->incfg.formats->formats[best_idx]); | ||
1224 | } | ||
1225 | } | ||
1226 | |||
1227 | 8073 | static void swap_sample_fmts(AVFilterGraph *graph) | |
1228 | { | ||
1229 | int i; | ||
1230 | |||
1231 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) |
1232 | 44504 | swap_sample_fmts_on_filter(graph->filters[i]); | |
1233 | |||
1234 | 8073 | } | |
1235 | |||
1236 | 8073 | static int pick_formats(AVFilterGraph *graph) | |
1237 | { | ||
1238 | int i, j, ret; | ||
1239 | int change; | ||
1240 | |||
1241 | do{ | ||
1242 | 16188 | change = 0; | |
1243 |
2/2✓ Branch 0 taken 89950 times.
✓ Branch 1 taken 16188 times.
|
106138 | for (i = 0; i < graph->nb_filters; i++) { |
1244 | 89950 | AVFilterContext *filter = graph->filters[i]; | |
1245 |
2/2✓ Branch 0 taken 73302 times.
✓ Branch 1 taken 16648 times.
|
89950 | if (filter->nb_inputs){ |
1246 |
2/2✓ Branch 0 taken 73651 times.
✓ Branch 1 taken 73302 times.
|
146953 | for (j = 0; j < filter->nb_inputs; j++){ |
1247 |
4/4✓ Branch 0 taken 15532 times.
✓ Branch 1 taken 58119 times.
✓ Branch 2 taken 15038 times.
✓ Branch 3 taken 494 times.
|
73651 | if (filter->inputs[j]->incfg.formats && filter->inputs[j]->incfg.formats->nb_formats == 1) { |
1248 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 15038 times.
|
15038 | if ((ret = pick_format(filter->inputs[j], NULL)) < 0) |
1249 | ✗ | return ret; | |
1250 | 15038 | change = 1; | |
1251 | } | ||
1252 | } | ||
1253 | } | ||
1254 |
2/2✓ Branch 0 taken 73383 times.
✓ Branch 1 taken 16567 times.
|
89950 | if (filter->nb_outputs){ |
1255 |
2/2✓ Branch 0 taken 73651 times.
✓ Branch 1 taken 73383 times.
|
147034 | for (j = 0; j < filter->nb_outputs; j++){ |
1256 |
4/4✓ Branch 0 taken 21665 times.
✓ Branch 1 taken 51986 times.
✓ Branch 2 taken 21067 times.
✓ Branch 3 taken 598 times.
|
73651 | if (filter->outputs[j]->incfg.formats && filter->outputs[j]->incfg.formats->nb_formats == 1) { |
1257 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 21067 times.
|
21067 | if ((ret = pick_format(filter->outputs[j], NULL)) < 0) |
1258 | ✗ | return ret; | |
1259 | 21067 | change = 1; | |
1260 | } | ||
1261 | } | ||
1262 | } | ||
1263 |
6/6✓ Branch 0 taken 73302 times.
✓ Branch 1 taken 16648 times.
✓ Branch 2 taken 56735 times.
✓ Branch 3 taken 16567 times.
✓ Branch 4 taken 56465 times.
✓ Branch 5 taken 270 times.
|
89950 | if (filter->nb_inputs && filter->nb_outputs && filter->inputs[0]->format>=0) { |
1264 |
2/2✓ Branch 0 taken 56665 times.
✓ Branch 1 taken 56465 times.
|
113130 | for (j = 0; j < filter->nb_outputs; j++) { |
1265 |
2/2✓ Branch 0 taken 237 times.
✓ Branch 1 taken 56428 times.
|
56665 | if (filter->outputs[j]->format<0) { |
1266 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 237 times.
|
237 | if ((ret = pick_format(filter->outputs[j], filter->inputs[0])) < 0) |
1267 | ✗ | return ret; | |
1268 | 237 | change = 1; | |
1269 | } | ||
1270 | } | ||
1271 | } | ||
1272 | } | ||
1273 |
2/2✓ Branch 0 taken 8115 times.
✓ Branch 1 taken 8073 times.
|
16188 | }while(change); |
1274 | |||
1275 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) { |
1276 | 44504 | AVFilterContext *filter = graph->filters[i]; | |
1277 | |||
1278 |
2/2✓ Branch 0 taken 36394 times.
✓ Branch 1 taken 44504 times.
|
80898 | for (j = 0; j < filter->nb_inputs; j++) |
1279 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36394 times.
|
36394 | if ((ret = pick_format(filter->inputs[j], NULL)) < 0) |
1280 | ✗ | return ret; | |
1281 |
2/2✓ Branch 0 taken 36394 times.
✓ Branch 1 taken 44504 times.
|
80898 | for (j = 0; j < filter->nb_outputs; j++) |
1282 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36394 times.
|
36394 | if ((ret = pick_format(filter->outputs[j], NULL)) < 0) |
1283 | ✗ | return ret; | |
1284 | } | ||
1285 | 8073 | return 0; | |
1286 | } | ||
1287 | |||
1288 | /** | ||
1289 | * Configure the formats of all the links in the graph. | ||
1290 | */ | ||
1291 | 8073 | static int graph_config_formats(AVFilterGraph *graph, void *log_ctx) | |
1292 | { | ||
1293 | int ret; | ||
1294 | |||
1295 | /* find supported formats from sub-filters, and merge along links */ | ||
1296 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 8073 times.
|
8087 | while ((ret = query_formats(graph, log_ctx)) == AVERROR(EAGAIN)) |
1297 | 14 | av_log(graph, AV_LOG_DEBUG, "query_formats not finished\n"); | |
1298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8073 times.
|
8073 | if (ret < 0) |
1299 | ✗ | return ret; | |
1300 | |||
1301 | /* Once everything is merged, it's possible that we'll still have | ||
1302 | * multiple valid media format choices. We try to minimize the amount | ||
1303 | * of format conversion inside filters */ | ||
1304 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = reduce_formats(graph)) < 0) |
1305 | ✗ | return ret; | |
1306 | |||
1307 | /* for audio filters, ensure the best format, sample rate and channel layout | ||
1308 | * is selected */ | ||
1309 | 8073 | swap_sample_fmts(graph); | |
1310 | 8073 | swap_samplerates(graph); | |
1311 | 8073 | swap_channel_layouts(graph); | |
1312 | |||
1313 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = pick_formats(graph)) < 0) |
1314 | ✗ | return ret; | |
1315 | |||
1316 | 8073 | return 0; | |
1317 | } | ||
1318 | |||
1319 | 8073 | static int graph_config_pointers(AVFilterGraph *graph, void *log_ctx) | |
1320 | { | ||
1321 | unsigned i, j; | ||
1322 | 8073 | int sink_links_count = 0, n = 0; | |
1323 | AVFilterContext *f; | ||
1324 | FilterLinkInternal **sinks; | ||
1325 | |||
1326 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) { |
1327 | 44504 | f = graph->filters[i]; | |
1328 |
2/2✓ Branch 0 taken 36394 times.
✓ Branch 1 taken 44504 times.
|
80898 | for (j = 0; j < f->nb_inputs; j++) { |
1329 | 36394 | ff_link_internal(f->inputs[j])->age_index = -1; | |
1330 | } | ||
1331 |
2/2✓ Branch 0 taken 36394 times.
✓ Branch 1 taken 44504 times.
|
80898 | for (j = 0; j < f->nb_outputs; j++) { |
1332 | 36394 | ff_link_internal(f->outputs[j])->age_index = -1; | |
1333 | } | ||
1334 |
2/2✓ Branch 0 taken 8209 times.
✓ Branch 1 taken 36295 times.
|
44504 | if (!f->nb_outputs) { |
1335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8209 times.
|
8209 | if (f->nb_inputs > INT_MAX - sink_links_count) |
1336 | ✗ | return AVERROR(EINVAL); | |
1337 | 8209 | sink_links_count += f->nb_inputs; | |
1338 | } | ||
1339 | } | ||
1340 | 8073 | sinks = av_calloc(sink_links_count, sizeof(*sinks)); | |
1341 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8073 times.
|
8073 | if (!sinks) |
1342 | ✗ | return AVERROR(ENOMEM); | |
1343 |
2/2✓ Branch 0 taken 44504 times.
✓ Branch 1 taken 8073 times.
|
52577 | for (i = 0; i < graph->nb_filters; i++) { |
1344 | 44504 | f = graph->filters[i]; | |
1345 |
2/2✓ Branch 0 taken 8209 times.
✓ Branch 1 taken 36295 times.
|
44504 | if (!f->nb_outputs) { |
1346 |
2/2✓ Branch 0 taken 8209 times.
✓ Branch 1 taken 8209 times.
|
16418 | for (j = 0; j < f->nb_inputs; j++) { |
1347 | 8209 | sinks[n] = ff_link_internal(f->inputs[j]); | |
1348 | 8209 | sinks[n]->age_index = n; | |
1349 | 8209 | n++; | |
1350 | } | ||
1351 | } | ||
1352 | } | ||
1353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8073 times.
|
8073 | av_assert0(n == sink_links_count); |
1354 | 8073 | fffiltergraph(graph)->sink_links = sinks; | |
1355 | 8073 | fffiltergraph(graph)->sink_links_count = sink_links_count; | |
1356 | 8073 | return 0; | |
1357 | } | ||
1358 | |||
1359 | 8073 | int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) | |
1360 | { | ||
1361 | int ret; | ||
1362 | |||
1363 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8072 times.
|
8073 | if (graphctx->max_buffered_frames) |
1364 | 1 | fffiltergraph(graphctx)->frame_queues.max_queued = graphctx->max_buffered_frames; | |
1365 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = graph_check_validity(graphctx, log_ctx))) |
1366 | ✗ | return ret; | |
1367 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = graph_config_formats(graphctx, log_ctx))) |
1368 | ✗ | return ret; | |
1369 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = graph_config_links(graphctx, log_ctx))) |
1370 | ✗ | return ret; | |
1371 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = graph_check_links(graphctx, log_ctx))) |
1372 | ✗ | return ret; | |
1373 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8073 times.
|
8073 | if ((ret = graph_config_pointers(graphctx, log_ctx))) |
1374 | ✗ | return ret; | |
1375 | |||
1376 | 8073 | return 0; | |
1377 | } | ||
1378 | |||
1379 | ✗ | int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags) | |
1380 | { | ||
1381 | ✗ | int i, r = AVERROR(ENOSYS); | |
1382 | |||
1383 | ✗ | if (!graph) | |
1384 | ✗ | return r; | |
1385 | |||
1386 | ✗ | if ((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) { | |
1387 | ✗ | r = avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST); | |
1388 | ✗ | if (r != AVERROR(ENOSYS)) | |
1389 | ✗ | return r; | |
1390 | } | ||
1391 | |||
1392 | ✗ | if (res_len && res) | |
1393 | ✗ | res[0] = 0; | |
1394 | |||
1395 | ✗ | for (i = 0; i < graph->nb_filters; i++) { | |
1396 | ✗ | AVFilterContext *filter = graph->filters[i]; | |
1397 | ✗ | if (!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)) { | |
1398 | ✗ | r = avfilter_process_command(filter, cmd, arg, res, res_len, flags); | |
1399 | ✗ | if (r != AVERROR(ENOSYS)) { | |
1400 | ✗ | if ((flags & AVFILTER_CMD_FLAG_ONE) || r < 0) | |
1401 | ✗ | return r; | |
1402 | } | ||
1403 | } | ||
1404 | } | ||
1405 | |||
1406 | ✗ | return r; | |
1407 | } | ||
1408 | |||
1409 | ✗ | int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts) | |
1410 | { | ||
1411 | int i; | ||
1412 | |||
1413 | ✗ | if(!graph) | |
1414 | ✗ | return 0; | |
1415 | |||
1416 | ✗ | for (i = 0; i < graph->nb_filters; i++) { | |
1417 | ✗ | AVFilterContext *filter = graph->filters[i]; | |
1418 | ✗ | FFFilterContext *ctxi = fffilterctx(filter); | |
1419 | ✗ | if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){ | |
1420 | ✗ | AVFilterCommand **queue = &ctxi->command_queue, *next; | |
1421 | ✗ | while (*queue && (*queue)->time <= ts) | |
1422 | ✗ | queue = &(*queue)->next; | |
1423 | ✗ | next = *queue; | |
1424 | ✗ | *queue = av_mallocz(sizeof(AVFilterCommand)); | |
1425 | ✗ | if (!*queue) | |
1426 | ✗ | return AVERROR(ENOMEM); | |
1427 | |||
1428 | ✗ | (*queue)->command = av_strdup(command); | |
1429 | ✗ | (*queue)->arg = av_strdup(arg); | |
1430 | ✗ | (*queue)->time = ts; | |
1431 | ✗ | (*queue)->flags = flags; | |
1432 | ✗ | (*queue)->next = next; | |
1433 | ✗ | if(flags & AVFILTER_CMD_FLAG_ONE) | |
1434 | ✗ | return 0; | |
1435 | } | ||
1436 | } | ||
1437 | |||
1438 | ✗ | return 0; | |
1439 | } | ||
1440 | |||
1441 | 409269 | static void heap_bubble_up(FFFilterGraph *graph, | |
1442 | FilterLinkInternal *li, int index) | ||
1443 | { | ||
1444 | 409269 | FilterLinkInternal **links = graph->sink_links; | |
1445 | |||
1446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409269 times.
|
409269 | av_assert0(index >= 0); |
1447 | |||
1448 |
2/2✓ Branch 0 taken 1828 times.
✓ Branch 1 taken 409269 times.
|
411097 | while (index) { |
1449 | 1828 | int parent = (index - 1) >> 1; | |
1450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1828 times.
|
1828 | if (links[parent]->l.current_pts_us >= li->l.current_pts_us) |
1451 | ✗ | break; | |
1452 | 1828 | links[index] = links[parent]; | |
1453 | 1828 | links[index]->age_index = index; | |
1454 | 1828 | index = parent; | |
1455 | } | ||
1456 | 409269 | links[index] = li; | |
1457 | 409269 | li->age_index = index; | |
1458 | 409269 | } | |
1459 | |||
1460 | 409393 | static void heap_bubble_down(FFFilterGraph *graph, | |
1461 | FilterLinkInternal *li, int index) | ||
1462 | { | ||
1463 | 409393 | FilterLinkInternal **links = graph->sink_links; | |
1464 | |||
1465 |
1/2✓ Branch 0 taken 409393 times.
✗ Branch 1 not taken.
|
409393 | av_assert0(index >= 0); |
1466 | |||
1467 | 5144 | while (1) { | |
1468 | 414537 | int child = 2 * index + 1; | |
1469 |
2/2✓ Branch 0 taken 409058 times.
✓ Branch 1 taken 5479 times.
|
414537 | if (child >= graph->sink_links_count) |
1470 | 409058 | break; | |
1471 |
2/2✓ Branch 0 taken 4082 times.
✓ Branch 1 taken 1397 times.
|
5479 | if (child + 1 < graph->sink_links_count && |
1472 |
2/2✓ Branch 0 taken 1261 times.
✓ Branch 1 taken 2821 times.
|
4082 | links[child + 1]->l.current_pts_us < links[child]->l.current_pts_us) |
1473 | 1261 | child++; | |
1474 |
2/2✓ Branch 0 taken 335 times.
✓ Branch 1 taken 5144 times.
|
5479 | if (li->l.current_pts_us < links[child]->l.current_pts_us) |
1475 | 335 | break; | |
1476 | 5144 | links[index] = links[child]; | |
1477 | 5144 | links[index]->age_index = index; | |
1478 | 5144 | index = child; | |
1479 | } | ||
1480 | 409393 | links[index] = li; | |
1481 | 409393 | li->age_index = index; | |
1482 | 409393 | } | |
1483 | |||
1484 | 409269 | void ff_avfilter_graph_update_heap(AVFilterGraph *graph, FilterLinkInternal *li) | |
1485 | { | ||
1486 | 409269 | FFFilterGraph *graphi = fffiltergraph(graph); | |
1487 | |||
1488 | 409269 | heap_bubble_up (graphi, li, li->age_index); | |
1489 | 409269 | heap_bubble_down(graphi, li, li->age_index); | |
1490 | 409269 | } | |
1491 | |||
1492 | 400093 | int avfilter_graph_request_oldest(AVFilterGraph *graph) | |
1493 | { | ||
1494 | 400093 | FFFilterGraph *graphi = fffiltergraph(graph); | |
1495 | 400093 | FilterLinkInternal *oldesti = graphi->sink_links[0]; | |
1496 | 400093 | AVFilterLink *oldest = &oldesti->l.pub; | |
1497 | int64_t frame_count; | ||
1498 | int r; | ||
1499 | |||
1500 |
2/2✓ Branch 0 taken 400223 times.
✓ Branch 1 taken 4915 times.
|
405138 | while (graphi->sink_links_count) { |
1501 | 400223 | oldesti = graphi->sink_links[0]; | |
1502 | 400223 | oldest = &oldesti->l.pub; | |
1503 |
2/2✓ Branch 1 taken 400197 times.
✓ Branch 2 taken 26 times.
|
400223 | if (fffilter(oldest->dst->filter)->activate) { |
1504 | 400197 | r = av_buffersink_get_frame_flags(oldest->dst, NULL, | |
1505 | AV_BUFFERSINK_FLAG_PEEK); | ||
1506 |
2/2✓ Branch 0 taken 395153 times.
✓ Branch 1 taken 5044 times.
|
400197 | if (r != AVERROR_EOF) |
1507 | 395153 | return r; | |
1508 | } else { | ||
1509 | 26 | r = ff_request_frame(oldest); | |
1510 | } | ||
1511 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5045 times.
|
5070 | if (r != AVERROR_EOF) |
1512 | 25 | break; | |
1513 | 5045 | av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n", | |
1514 | 5045 | oldest->dst->name, | |
1515 | 5045 | oldest->dstpad->name); | |
1516 | /* EOF: remove the link from the heap */ | ||
1517 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 4921 times.
|
5045 | if (oldesti->age_index < --graphi->sink_links_count) |
1518 | 124 | heap_bubble_down(graphi, graphi->sink_links[graphi->sink_links_count], | |
1519 | oldesti->age_index); | ||
1520 | 5045 | oldesti->age_index = -1; | |
1521 | } | ||
1522 |
2/2✓ Branch 0 taken 4915 times.
✓ Branch 1 taken 25 times.
|
4940 | if (!graphi->sink_links_count) |
1523 | 4915 | return AVERROR_EOF; | |
1524 | av_assert1(!fffilter(oldest->dst->filter)->activate); | ||
1525 | av_assert1(oldesti->age_index >= 0); | ||
1526 | 25 | frame_count = oldesti->l.frame_count_out; | |
1527 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | while (frame_count == oldesti->l.frame_count_out) { |
1528 | 100 | r = ff_filter_graph_run_once(graph); | |
1529 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 75 times.
|
100 | if (r == FFERROR_BUFFERSRC_EMPTY) |
1530 | 25 | r = 0; | |
1531 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 75 times.
|
100 | if (r == AVERROR(EAGAIN) && |
1532 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
25 | !oldesti->frame_wanted_out && !oldesti->frame_blocked_in && |
1533 | ✗ | !oldesti->status_in) | |
1534 | ✗ | (void)ff_request_frame(oldest); | |
1535 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 75 times.
|
100 | else if (r < 0) |
1536 | 25 | return r; | |
1537 | } | ||
1538 | ✗ | return 0; | |
1539 | } | ||
1540 | |||
1541 | 4456293 | int ff_filter_graph_run_once(AVFilterGraph *graph) | |
1542 | { | ||
1543 | FFFilterContext *ctxi; | ||
1544 | unsigned i; | ||
1545 | |||
1546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4456293 times.
|
4456293 | av_assert0(graph->nb_filters); |
1547 | 4456293 | ctxi = fffilterctx(graph->filters[0]); | |
1548 |
2/2✓ Branch 0 taken 18750978 times.
✓ Branch 1 taken 4456293 times.
|
23207271 | for (i = 1; i < graph->nb_filters; i++) { |
1549 | 18750978 | FFFilterContext *ctxi_other = fffilterctx(graph->filters[i]); | |
1550 | |||
1551 |
2/2✓ Branch 0 taken 2666270 times.
✓ Branch 1 taken 16084708 times.
|
18750978 | if (ctxi_other->ready > ctxi->ready) |
1552 | 2666270 | ctxi = ctxi_other; | |
1553 | } | ||
1554 | |||
1555 |
2/2✓ Branch 0 taken 739888 times.
✓ Branch 1 taken 3716405 times.
|
4456293 | if (!ctxi->ready) |
1556 | 739888 | return AVERROR(EAGAIN); | |
1557 | 3716405 | return ff_filter_activate(&ctxi->p); | |
1558 | } | ||
1559 |