GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
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/avstring.h" |
||
29 |
#include "libavutil/bprint.h" |
||
30 |
#include "libavutil/channel_layout.h" |
||
31 |
#include "libavutil/imgutils.h" |
||
32 |
#include "libavutil/internal.h" |
||
33 |
#include "libavutil/opt.h" |
||
34 |
#include "libavutil/pixdesc.h" |
||
35 |
|||
36 |
#define FF_INTERNAL_FIELDS 1 |
||
37 |
#include "framequeue.h" |
||
38 |
|||
39 |
#include "avfilter.h" |
||
40 |
#include "buffersink.h" |
||
41 |
#include "formats.h" |
||
42 |
#include "internal.h" |
||
43 |
#include "thread.h" |
||
44 |
|||
45 |
#define OFFSET(x) offsetof(AVFilterGraph, x) |
||
46 |
#define F AV_OPT_FLAG_FILTERING_PARAM |
||
47 |
#define V AV_OPT_FLAG_VIDEO_PARAM |
||
48 |
#define A AV_OPT_FLAG_AUDIO_PARAM |
||
49 |
static const AVOption filtergraph_options[] = { |
||
50 |
{ "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, |
||
51 |
{ .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, F|V|A, "thread_type" }, |
||
52 |
{ "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = F|V|A, .unit = "thread_type" }, |
||
53 |
{ "threads", "Maximum number of threads", OFFSET(nb_threads), |
||
54 |
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, F|V|A }, |
||
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 |
{ NULL }, |
||
60 |
}; |
||
61 |
|||
62 |
static const AVClass filtergraph_class = { |
||
63 |
.class_name = "AVFilterGraph", |
||
64 |
.item_name = av_default_item_name, |
||
65 |
.version = LIBAVUTIL_VERSION_INT, |
||
66 |
.option = filtergraph_options, |
||
67 |
.category = AV_CLASS_CATEGORY_FILTER, |
||
68 |
}; |
||
69 |
|||
70 |
#if !HAVE_THREADS |
||
71 |
void ff_graph_thread_free(AVFilterGraph *graph) |
||
72 |
{ |
||
73 |
} |
||
74 |
|||
75 |
int ff_graph_thread_init(AVFilterGraph *graph) |
||
76 |
{ |
||
77 |
graph->thread_type = 0; |
||
78 |
graph->nb_threads = 1; |
||
79 |
return 0; |
||
80 |
} |
||
81 |
#endif |
||
82 |
|||
83 |
6011 |
AVFilterGraph *avfilter_graph_alloc(void) |
|
84 |
{ |
||
85 |
6011 |
AVFilterGraph *ret = av_mallocz(sizeof(*ret)); |
|
86 |
✗✓ | 6011 |
if (!ret) |
87 |
return NULL; |
||
88 |
|||
89 |
6011 |
ret->internal = av_mallocz(sizeof(*ret->internal)); |
|
90 |
✗✓ | 6011 |
if (!ret->internal) { |
91 |
av_freep(&ret); |
||
92 |
return NULL; |
||
93 |
} |
||
94 |
|||
95 |
6011 |
ret->av_class = &filtergraph_class; |
|
96 |
6011 |
av_opt_set_defaults(ret); |
|
97 |
6011 |
ff_framequeue_global_init(&ret->internal->frame_queues); |
|
98 |
|||
99 |
6011 |
return ret; |
|
100 |
} |
||
101 |
|||
102 |
29783 |
void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter) |
|
103 |
{ |
||
104 |
int i, j; |
||
105 |
✓✗ | 29783 |
for (i = 0; i < graph->nb_filters; i++) { |
106 |
✓✗ | 29783 |
if (graph->filters[i] == filter) { |
107 |
29783 |
FFSWAP(AVFilterContext*, graph->filters[i], |
|
108 |
graph->filters[graph->nb_filters - 1]); |
||
109 |
29783 |
graph->nb_filters--; |
|
110 |
29783 |
filter->graph = NULL; |
|
111 |
✓✓ | 53736 |
for (j = 0; j<filter->nb_outputs; j++) |
112 |
✓✓ | 23953 |
if (filter->outputs[j]) |
113 |
11493 |
filter->outputs[j]->graph = NULL; |
|
114 |
|||
115 |
29783 |
return; |
|
116 |
} |
||
117 |
} |
||
118 |
} |
||
119 |
|||
120 |
11810 |
void avfilter_graph_free(AVFilterGraph **graph) |
|
121 |
{ |
||
122 |
✓✓ | 11810 |
if (!*graph) |
123 |
5799 |
return; |
|
124 |
|||
125 |
✓✓ | 35728 |
while ((*graph)->nb_filters) |
126 |
29717 |
avfilter_free((*graph)->filters[0]); |
|
127 |
|||
128 |
6011 |
ff_graph_thread_free(*graph); |
|
129 |
|||
130 |
6011 |
av_freep(&(*graph)->sink_links); |
|
131 |
|||
132 |
6011 |
av_freep(&(*graph)->scale_sws_opts); |
|
133 |
6011 |
av_freep(&(*graph)->aresample_swr_opts); |
|
134 |
#if FF_API_LAVR_OPTS |
||
135 |
6011 |
av_freep(&(*graph)->resample_lavr_opts); |
|
136 |
#endif |
||
137 |
6011 |
av_freep(&(*graph)->filters); |
|
138 |
6011 |
av_freep(&(*graph)->internal); |
|
139 |
6011 |
av_freep(graph); |
|
140 |
} |
||
141 |
|||
142 |
17841 |
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, |
|
143 |
const char *name, const char *args, void *opaque, |
||
144 |
AVFilterGraph *graph_ctx) |
||
145 |
{ |
||
146 |
int ret; |
||
147 |
|||
148 |
17841 |
*filt_ctx = avfilter_graph_alloc_filter(graph_ctx, filt, name); |
|
149 |
✗✓ | 17841 |
if (!*filt_ctx) |
150 |
return AVERROR(ENOMEM); |
||
151 |
|||
152 |
17841 |
ret = avfilter_init_str(*filt_ctx, args); |
|
153 |
✗✓ | 17841 |
if (ret < 0) |
154 |
goto fail; |
||
155 |
|||
156 |
17841 |
return 0; |
|
157 |
|||
158 |
fail: |
||
159 |
if (*filt_ctx) |
||
160 |
avfilter_free(*filt_ctx); |
||
161 |
*filt_ctx = NULL; |
||
162 |
return ret; |
||
163 |
} |
||
164 |
|||
165 |
4209 |
void avfilter_graph_set_auto_convert(AVFilterGraph *graph, unsigned flags) |
|
166 |
{ |
||
167 |
4209 |
graph->disable_auto_convert = flags; |
|
168 |
4209 |
} |
|
169 |
|||
170 |
29783 |
AVFilterContext *avfilter_graph_alloc_filter(AVFilterGraph *graph, |
|
171 |
const AVFilter *filter, |
||
172 |
const char *name) |
||
173 |
{ |
||
174 |
AVFilterContext **filters, *s; |
||
175 |
|||
176 |
✓✓✓✓ |
29783 |
if (graph->thread_type && !graph->internal->thread_execute) { |
177 |
✗✓ | 6011 |
if (graph->execute) { |
178 |
graph->internal->thread_execute = graph->execute; |
||
179 |
} else { |
||
180 |
6011 |
int ret = ff_graph_thread_init(graph); |
|
181 |
✗✓ | 6011 |
if (ret < 0) { |
182 |
av_log(graph, AV_LOG_ERROR, "Error initializing threading: %s.\n", av_err2str(ret)); |
||
183 |
return NULL; |
||
184 |
} |
||
185 |
} |
||
186 |
} |
||
187 |
|||
188 |
29783 |
s = ff_filter_alloc(filter, name); |
|
189 |
✗✓ | 29783 |
if (!s) |
190 |
return NULL; |
||
191 |
|||
192 |
29783 |
filters = av_realloc(graph->filters, sizeof(*filters) * (graph->nb_filters + 1)); |
|
193 |
✗✓ | 29783 |
if (!filters) { |
194 |
avfilter_free(s); |
||
195 |
return NULL; |
||
196 |
} |
||
197 |
|||
198 |
29783 |
graph->filters = filters; |
|
199 |
29783 |
graph->filters[graph->nb_filters++] = s; |
|
200 |
|||
201 |
29783 |
s->graph = graph; |
|
202 |
|||
203 |
29783 |
return s; |
|
204 |
} |
||
205 |
|||
206 |
/** |
||
207 |
* Check for the validity of graph. |
||
208 |
* |
||
209 |
* A graph is considered valid if all its input and output pads are |
||
210 |
* connected. |
||
211 |
* |
||
212 |
* @return >= 0 in case of success, a negative value otherwise |
||
213 |
*/ |
||
214 |
5865 |
static int graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx) |
|
215 |
{ |
||
216 |
AVFilterContext *filt; |
||
217 |
int i, j; |
||
218 |
|||
219 |
✓✓ | 34695 |
for (i = 0; i < graph->nb_filters; i++) { |
220 |
const AVFilterPad *pad; |
||
221 |
28830 |
filt = graph->filters[i]; |
|
222 |
|||
223 |
✓✓ | 51811 |
for (j = 0; j < filt->nb_inputs; j++) { |
224 |
✓✗✗✓ |
22981 |
if (!filt->inputs[j] || !filt->inputs[j]->src) { |
225 |
pad = &filt->input_pads[j]; |
||
226 |
av_log(log_ctx, AV_LOG_ERROR, |
||
227 |
"Input pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any source\n", |
||
228 |
pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name); |
||
229 |
return AVERROR(EINVAL); |
||
230 |
} |
||
231 |
} |
||
232 |
|||
233 |
✓✓ | 51811 |
for (j = 0; j < filt->nb_outputs; j++) { |
234 |
✓✗✗✓ |
22981 |
if (!filt->outputs[j] || !filt->outputs[j]->dst) { |
235 |
pad = &filt->output_pads[j]; |
||
236 |
av_log(log_ctx, AV_LOG_ERROR, |
||
237 |
"Output pad \"%s\" with type %s of the filter instance \"%s\" of %s not connected to any destination\n", |
||
238 |
pad->name, av_get_media_type_string(pad->type), filt->name, filt->filter->name); |
||
239 |
return AVERROR(EINVAL); |
||
240 |
} |
||
241 |
} |
||
242 |
} |
||
243 |
|||
244 |
5865 |
return 0; |
|
245 |
} |
||
246 |
|||
247 |
/** |
||
248 |
* Configure all the links of graphctx. |
||
249 |
* |
||
250 |
* @return >= 0 in case of success, a negative value otherwise |
||
251 |
*/ |
||
252 |
5861 |
static int graph_config_links(AVFilterGraph *graph, AVClass *log_ctx) |
|
253 |
{ |
||
254 |
AVFilterContext *filt; |
||
255 |
int i, ret; |
||
256 |
|||
257 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) { |
258 |
29495 |
filt = graph->filters[i]; |
|
259 |
|||
260 |
✓✓ | 29495 |
if (!filt->nb_outputs) { |
261 |
✗✓ | 5867 |
if ((ret = avfilter_config_links(filt))) |
262 |
return ret; |
||
263 |
} |
||
264 |
} |
||
265 |
|||
266 |
5861 |
return 0; |
|
267 |
} |
||
268 |
|||
269 |
5861 |
static int graph_check_links(AVFilterGraph *graph, AVClass *log_ctx) |
|
270 |
{ |
||
271 |
AVFilterContext *f; |
||
272 |
AVFilterLink *l; |
||
273 |
unsigned i, j; |
||
274 |
int ret; |
||
275 |
|||
276 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) { |
277 |
29495 |
f = graph->filters[i]; |
|
278 |
✓✓ | 53141 |
for (j = 0; j < f->nb_outputs; j++) { |
279 |
23646 |
l = f->outputs[j]; |
|
280 |
✓✓ | 23646 |
if (l->type == AVMEDIA_TYPE_VIDEO) { |
281 |
18737 |
ret = av_image_check_size2(l->w, l->h, INT64_MAX, l->format, 0, f); |
|
282 |
✗✓ | 18737 |
if (ret < 0) |
283 |
return ret; |
||
284 |
} |
||
285 |
} |
||
286 |
} |
||
287 |
5861 |
return 0; |
|
288 |
} |
||
289 |
|||
290 |
AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, const char *name) |
||
291 |
{ |
||
292 |
int i; |
||
293 |
|||
294 |
for (i = 0; i < graph->nb_filters; i++) |
||
295 |
if (graph->filters[i]->name && !strcmp(name, graph->filters[i]->name)) |
||
296 |
return graph->filters[i]; |
||
297 |
|||
298 |
return NULL; |
||
299 |
} |
||
300 |
|||
301 |
39165 |
static void sanitize_channel_layouts(void *log, AVFilterChannelLayouts *l) |
|
302 |
{ |
||
303 |
✓✓ | 39165 |
if (!l) |
304 |
31419 |
return; |
|
305 |
✓✓ | 7746 |
if (l->nb_channel_layouts) { |
306 |
✓✗✗✓ |
1330 |
if (l->all_layouts || l->all_counts) |
307 |
av_log(log, AV_LOG_WARNING, "All layouts set on non-empty list\n"); |
||
308 |
1330 |
l->all_layouts = l->all_counts = 0; |
|
309 |
} else { |
||
310 |
✓✓✗✓ |
6416 |
if (l->all_counts && !l->all_layouts) |
311 |
av_log(log, AV_LOG_WARNING, "All counts without all layouts\n"); |
||
312 |
6416 |
l->all_layouts = 1; |
|
313 |
} |
||
314 |
} |
||
315 |
|||
316 |
39165 |
static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterFormatsConfig *cfg) |
|
317 |
{ |
||
318 |
int ret; |
||
319 |
|||
320 |
✓✓✗ | 39165 |
switch (link->type) { |
321 |
|||
322 |
31417 |
case AVMEDIA_TYPE_VIDEO: |
|
323 |
✗✓ | 31417 |
if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0) |
324 |
return ret; |
||
325 |
31417 |
break; |
|
326 |
|||
327 |
7748 |
case AVMEDIA_TYPE_AUDIO: |
|
328 |
✓✗✓✗ |
15496 |
if ((ret = ff_formats_check_sample_formats(log, cfg->formats)) < 0 || |
329 |
✗✓ | 15496 |
(ret = ff_formats_check_sample_rates(log, cfg->samplerates)) < 0 || |
330 |
7748 |
(ret = ff_formats_check_channel_layouts(log, cfg->channel_layouts)) < 0) |
|
331 |
return ret; |
||
332 |
7748 |
break; |
|
333 |
|||
334 |
default: |
||
335 |
av_assert0(!"reached"); |
||
336 |
} |
||
337 |
39165 |
return 0; |
|
338 |
} |
||
339 |
|||
340 |
/** |
||
341 |
* Check the validity of the formats / etc. lists set by query_formats(). |
||
342 |
* |
||
343 |
* In particular, check they do not contain any redundant element. |
||
344 |
*/ |
||
345 |
25440 |
static int filter_check_formats(AVFilterContext *ctx) |
|
346 |
{ |
||
347 |
unsigned i; |
||
348 |
int ret; |
||
349 |
|||
350 |
✓✓ | 45031 |
for (i = 0; i < ctx->nb_inputs; i++) { |
351 |
19591 |
ret = filter_link_check_formats(ctx, ctx->inputs[i], &ctx->inputs[i]->outcfg); |
|
352 |
✗✓ | 19591 |
if (ret < 0) |
353 |
return ret; |
||
354 |
} |
||
355 |
✓✓ | 45014 |
for (i = 0; i < ctx->nb_outputs; i++) { |
356 |
19574 |
ret = filter_link_check_formats(ctx, ctx->outputs[i], &ctx->outputs[i]->incfg); |
|
357 |
✗✓ | 19574 |
if (ret < 0) |
358 |
return ret; |
||
359 |
} |
||
360 |
25440 |
return 0; |
|
361 |
} |
||
362 |
|||
363 |
25454 |
static int filter_query_formats(AVFilterContext *ctx) |
|
364 |
{ |
||
365 |
int ret, i; |
||
366 |
AVFilterFormats *formats; |
||
367 |
AVFilterChannelLayouts *chlayouts; |
||
368 |
AVFilterFormats *samplerates; |
||
369 |
✓✓✓✗ |
31364 |
enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type : |
370 |
✓✗✓✗ |
5910 |
ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type : |
371 |
AVMEDIA_TYPE_VIDEO; |
||
372 |
|||
373 |
✓✓ | 25454 |
if ((ret = ctx->filter->query_formats(ctx)) < 0) { |
374 |
✗✓ | 14 |
if (ret != AVERROR(EAGAIN)) |
375 |
av_log(ctx, AV_LOG_ERROR, "Query format failed for '%s': %s\n", |
||
376 |
ctx->name, av_err2str(ret)); |
||
377 |
14 |
return ret; |
|
378 |
} |
||
379 |
25440 |
ret = filter_check_formats(ctx); |
|
380 |
✗✓ | 25440 |
if (ret < 0) |
381 |
return ret; |
||
382 |
|||
383 |
✓✓ | 45031 |
for (i = 0; i < ctx->nb_inputs; i++) |
384 |
19591 |
sanitize_channel_layouts(ctx, ctx->inputs[i]->outcfg.channel_layouts); |
|
385 |
✓✓ | 45014 |
for (i = 0; i < ctx->nb_outputs; i++) |
386 |
19574 |
sanitize_channel_layouts(ctx, ctx->outputs[i]->incfg.channel_layouts); |
|
387 |
|||
388 |
25440 |
formats = ff_all_formats(type); |
|
389 |
✗✓ | 25440 |
if ((ret = ff_set_common_formats(ctx, formats)) < 0) |
390 |
return ret; |
||
391 |
✓✓ | 25440 |
if (type == AVMEDIA_TYPE_AUDIO) { |
392 |
5011 |
samplerates = ff_all_samplerates(); |
|
393 |
✗✓ | 5011 |
if ((ret = ff_set_common_samplerates(ctx, samplerates)) < 0) |
394 |
return ret; |
||
395 |
5011 |
chlayouts = ff_all_channel_layouts(); |
|
396 |
✗✓ | 5011 |
if ((ret = ff_set_common_channel_layouts(ctx, chlayouts)) < 0) |
397 |
return ret; |
||
398 |
} |
||
399 |
25440 |
return 0; |
|
400 |
} |
||
401 |
|||
402 |
28888 |
static int formats_declared(AVFilterContext *f) |
|
403 |
{ |
||
404 |
int i; |
||
405 |
|||
406 |
✓✓ | 28923 |
for (i = 0; i < f->nb_inputs; i++) { |
407 |
✓✓ | 22967 |
if (!f->inputs[i]->outcfg.formats) |
408 |
22932 |
return 0; |
|
409 |
✓✓ | 35 |
if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO && |
410 |
✓✗ | 2 |
!(f->inputs[i]->outcfg.samplerates && |
411 |
✗✓ | 2 |
f->inputs[i]->outcfg.channel_layouts)) |
412 |
return 0; |
||
413 |
} |
||
414 |
✓✓ | 5990 |
for (i = 0; i < f->nb_outputs; i++) { |
415 |
✓✓ | 5946 |
if (!f->outputs[i]->incfg.formats) |
416 |
5912 |
return 0; |
|
417 |
✓✓ | 34 |
if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO && |
418 |
✓✗ | 3 |
!(f->outputs[i]->incfg.samplerates && |
419 |
✗✓ | 3 |
f->outputs[i]->incfg.channel_layouts)) |
420 |
return 0; |
||
421 |
} |
||
422 |
44 |
return 1; |
|
423 |
} |
||
424 |
|||
425 |
/** |
||
426 |
* Perform one round of query_formats() and merging formats lists on the |
||
427 |
* filter graph. |
||
428 |
* @return >=0 if all links formats lists could be queried and merged; |
||
429 |
* AVERROR(EAGAIN) some progress was made in the queries or merging |
||
430 |
* and a later call may succeed; |
||
431 |
* AVERROR(EIO) (may be changed) plus a log message if no progress |
||
432 |
* was made and the negotiation is stuck; |
||
433 |
* a negative error code if some other error happened |
||
434 |
*/ |
||
435 |
5879 |
static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) |
|
436 |
{ |
||
437 |
int i, j, ret; |
||
438 |
5879 |
int scaler_count = 0, resampler_count = 0; |
|
439 |
5879 |
int count_queried = 0; /* successful calls to query_formats() */ |
|
440 |
5879 |
int count_merged = 0; /* successful merge of formats lists */ |
|
441 |
5879 |
int count_already_merged = 0; /* lists already merged */ |
|
442 |
5879 |
int count_delayed = 0; /* lists that need to be merged later */ |
|
443 |
|||
444 |
✓✓ | 34767 |
for (i = 0; i < graph->nb_filters; i++) { |
445 |
28888 |
AVFilterContext *f = graph->filters[i]; |
|
446 |
✓✓ | 28888 |
if (formats_declared(f)) |
447 |
44 |
continue; |
|
448 |
✓✓ | 28844 |
if (f->filter->query_formats) |
449 |
24761 |
ret = filter_query_formats(f); |
|
450 |
else |
||
451 |
4083 |
ret = ff_default_query_formats(f); |
|
452 |
✓✓✗✓ |
28844 |
if (ret < 0 && ret != AVERROR(EAGAIN)) |
453 |
return ret; |
||
454 |
/* note: EAGAIN could indicate a partial success, not counted yet */ |
||
455 |
28844 |
count_queried += ret >= 0; |
|
456 |
} |
||
457 |
|||
458 |
/* go through and merge as many format lists as possible */ |
||
459 |
✓✓ | 35444 |
for (i = 0; i < graph->nb_filters; i++) { |
460 |
29569 |
AVFilterContext *filter = graph->filters[i]; |
|
461 |
|||
462 |
✓✓ | 53271 |
for (j = 0; j < filter->nb_inputs; j++) { |
463 |
23706 |
AVFilterLink *link = filter->inputs[j]; |
|
464 |
23706 |
int convert_needed = 0; |
|
465 |
|||
466 |
✗✓ | 23706 |
if (!link) |
467 |
continue; |
||
468 |
|||
469 |
✓✓ | 23706 |
if (link->incfg.formats != link->outcfg.formats |
470 |
✓✓✓✓ |
22990 |
&& link->incfg.formats && link->outcfg.formats) |
471 |
✓✓ | 22963 |
if (!ff_can_merge_formats(link->incfg.formats, link->outcfg.formats, |
472 |
link->type)) |
||
473 |
685 |
convert_needed = 1; |
|
474 |
✓✓ | 23706 |
if (link->type == AVMEDIA_TYPE_AUDIO) { |
475 |
✓✓ | 4913 |
if (link->incfg.samplerates != link->outcfg.samplerates |
476 |
✓✓✓✓ |
4517 |
&& link->incfg.samplerates && link->outcfg.samplerates) |
477 |
✓✓ | 4514 |
if (!ff_can_merge_samplerates(link->incfg.samplerates, |
478 |
4514 |
link->outcfg.samplerates)) |
|
479 |
17 |
convert_needed = 1; |
|
480 |
} |
||
481 |
|||
482 |
#define CHECKED_MERGE(field, ...) ((ret = ff_merge_ ## field(__VA_ARGS__)) <= 0) |
||
483 |
#define MERGE_DISPATCH(field, ...) \ |
||
484 |
if (!(link->incfg.field && link->outcfg.field)) { \ |
||
485 |
count_delayed++; \ |
||
486 |
} else if (link->incfg.field == link->outcfg.field) { \ |
||
487 |
count_already_merged++; \ |
||
488 |
} else if (!convert_needed) { \ |
||
489 |
count_merged++; \ |
||
490 |
if (CHECKED_MERGE(field, __VA_ARGS__)) { \ |
||
491 |
if (ret < 0) \ |
||
492 |
return ret; \ |
||
493 |
convert_needed = 1; \ |
||
494 |
} \ |
||
495 |
} |
||
496 |
|||
497 |
✓✓ | 23706 |
if (link->type == AVMEDIA_TYPE_AUDIO) { |
498 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✓ |
4913 |
MERGE_DISPATCH(channel_layouts, link->incfg.channel_layouts, |
499 |
link->outcfg.channel_layouts) |
||
500 |
✓✓✓✓ ✓✓✓✓ ✗✓✗✗ |
4913 |
MERGE_DISPATCH(samplerates, link->incfg.samplerates, |
501 |
link->outcfg.samplerates) |
||
502 |
} |
||
503 |
✓✓✓✓ ✓✓✓✓ ✗✓✗✗ |
23706 |
MERGE_DISPATCH(formats, link->incfg.formats, |
504 |
link->outcfg.formats, link->type) |
||
505 |
#undef MERGE_DISPATCH |
||
506 |
|||
507 |
✓✓ | 23706 |
if (convert_needed) { |
508 |
AVFilterContext *convert; |
||
509 |
const AVFilter *filter; |
||
510 |
AVFilterLink *inlink, *outlink; |
||
511 |
char inst_name[30]; |
||
512 |
|||
513 |
✓✓ | 697 |
if (graph->disable_auto_convert) { |
514 |
4 |
av_log(log_ctx, AV_LOG_ERROR, |
|
515 |
"The filters '%s' and '%s' do not have a common format " |
||
516 |
"and automatic conversion is disabled.\n", |
||
517 |
4 |
link->src->name, link->dst->name); |
|
518 |
4 |
return AVERROR(EINVAL); |
|
519 |
} |
||
520 |
|||
521 |
/* couldn't merge format lists. auto-insert conversion filter */ |
||
522 |
✓✓✗ | 693 |
switch (link->type) { |
523 |
298 |
case AVMEDIA_TYPE_VIDEO: |
|
524 |
✗✓ | 298 |
if (!(filter = avfilter_get_by_name("scale"))) { |
525 |
av_log(log_ctx, AV_LOG_ERROR, "'scale' filter " |
||
526 |
"not present, cannot convert pixel formats.\n"); |
||
527 |
return AVERROR(EINVAL); |
||
528 |
} |
||
529 |
|||
530 |
298 |
snprintf(inst_name, sizeof(inst_name), "auto_scaler_%d", |
|
531 |
scaler_count++); |
||
532 |
|||
533 |
✗✓ | 298 |
if ((ret = avfilter_graph_create_filter(&convert, filter, |
534 |
298 |
inst_name, graph->scale_sws_opts, NULL, |
|
535 |
graph)) < 0) |
||
536 |
return ret; |
||
537 |
298 |
break; |
|
538 |
395 |
case AVMEDIA_TYPE_AUDIO: |
|
539 |
✗✓ | 395 |
if (!(filter = avfilter_get_by_name("aresample"))) { |
540 |
av_log(log_ctx, AV_LOG_ERROR, "'aresample' filter " |
||
541 |
"not present, cannot convert audio formats.\n"); |
||
542 |
return AVERROR(EINVAL); |
||
543 |
} |
||
544 |
|||
545 |
395 |
snprintf(inst_name, sizeof(inst_name), "auto_resampler_%d", |
|
546 |
resampler_count++); |
||
547 |
✗✓ | 395 |
if ((ret = avfilter_graph_create_filter(&convert, filter, |
548 |
395 |
inst_name, graph->aresample_swr_opts, |
|
549 |
NULL, graph)) < 0) |
||
550 |
return ret; |
||
551 |
395 |
break; |
|
552 |
default: |
||
553 |
return AVERROR(EINVAL); |
||
554 |
} |
||
555 |
|||
556 |
✗✓ | 693 |
if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0) |
557 |
return ret; |
||
558 |
|||
559 |
✗✓ | 693 |
if ((ret = filter_query_formats(convert)) < 0) |
560 |
return ret; |
||
561 |
|||
562 |
693 |
inlink = convert->inputs[0]; |
|
563 |
693 |
outlink = convert->outputs[0]; |
|
564 |
✗✓ | 693 |
av_assert0( inlink->incfg.formats->refcount > 0); |
565 |
✗✓ | 693 |
av_assert0( inlink->outcfg.formats->refcount > 0); |
566 |
✗✓ | 693 |
av_assert0(outlink->incfg.formats->refcount > 0); |
567 |
✗✓ | 693 |
av_assert0(outlink->outcfg.formats->refcount > 0); |
568 |
✓✓ | 693 |
if (outlink->type == AVMEDIA_TYPE_AUDIO) { |
569 |
✗✓ | 395 |
av_assert0( inlink-> incfg.samplerates->refcount > 0); |
570 |
✗✓ | 395 |
av_assert0( inlink->outcfg.samplerates->refcount > 0); |
571 |
✗✓ | 395 |
av_assert0(outlink-> incfg.samplerates->refcount > 0); |
572 |
✗✓ | 395 |
av_assert0(outlink->outcfg.samplerates->refcount > 0); |
573 |
✗✓ | 395 |
av_assert0( inlink-> incfg.channel_layouts->refcount > 0); |
574 |
✗✓ | 395 |
av_assert0( inlink->outcfg.channel_layouts->refcount > 0); |
575 |
✗✓ | 395 |
av_assert0(outlink-> incfg.channel_layouts->refcount > 0); |
576 |
✗✓ | 395 |
av_assert0(outlink->outcfg.channel_layouts->refcount > 0); |
577 |
} |
||
578 |
✓✗ | 693 |
if (CHECKED_MERGE(formats, inlink->incfg.formats, |
579 |
✓✗ | 693 |
inlink->outcfg.formats, inlink->type) || |
580 |
693 |
CHECKED_MERGE(formats, outlink->incfg.formats, |
|
581 |
693 |
outlink->outcfg.formats, outlink->type) || |
|
582 |
✓✓✓✗ |
1088 |
inlink->type == AVMEDIA_TYPE_AUDIO && |
583 |
395 |
(CHECKED_MERGE(samplerates, inlink->incfg.samplerates, |
|
584 |
✓✗ | 395 |
inlink->outcfg.samplerates) || |
585 |
395 |
CHECKED_MERGE(channel_layouts, inlink->incfg.channel_layouts, |
|
586 |
693 |
inlink->outcfg.channel_layouts)) || |
|
587 |
✓✓✓✗ |
1088 |
outlink->type == AVMEDIA_TYPE_AUDIO && |
588 |
395 |
(CHECKED_MERGE(samplerates, outlink->incfg.samplerates, |
|
589 |
✗✓ | 395 |
outlink->outcfg.samplerates) || |
590 |
395 |
CHECKED_MERGE(channel_layouts, outlink->incfg.channel_layouts, |
|
591 |
outlink->outcfg.channel_layouts))) { |
||
592 |
if (ret < 0) |
||
593 |
return ret; |
||
594 |
av_log(log_ctx, AV_LOG_ERROR, |
||
595 |
"Impossible to convert between the formats supported by the filter " |
||
596 |
"'%s' and the filter '%s'\n", link->src->name, link->dst->name); |
||
597 |
return AVERROR(ENOSYS); |
||
598 |
} |
||
599 |
} |
||
600 |
} |
||
601 |
} |
||
602 |
|||
603 |
5875 |
av_log(graph, AV_LOG_DEBUG, "query_formats: " |
|
604 |
"%d queried, %d merged, %d already done, %d delayed\n", |
||
605 |
count_queried, count_merged, count_already_merged, count_delayed); |
||
606 |
✓✓ | 5875 |
if (count_delayed) { |
607 |
AVBPrint bp; |
||
608 |
|||
609 |
/* if count_queried > 0, one filter at least did set its formats, |
||
610 |
that will give additional information to its neighbour; |
||
611 |
if count_merged > 0, one pair of formats lists at least was merged, |
||
612 |
that will give additional information to all connected filters; |
||
613 |
in both cases, progress was made and a new round must be done */ |
||
614 |
✗✓✗✗ |
14 |
if (count_queried || count_merged) |
615 |
14 |
return AVERROR(EAGAIN); |
|
616 |
av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); |
||
617 |
for (i = 0; i < graph->nb_filters; i++) |
||
618 |
if (!formats_declared(graph->filters[i])) |
||
619 |
av_bprintf(&bp, "%s%s", bp.len ? ", " : "", |
||
620 |
graph->filters[i]->name); |
||
621 |
av_log(graph, AV_LOG_ERROR, |
||
622 |
"The following filters could not choose their formats: %s\n" |
||
623 |
"Consider inserting the (a)format filter near their input or " |
||
624 |
"output.\n", bp.str); |
||
625 |
return AVERROR(EIO); |
||
626 |
} |
||
627 |
5861 |
return 0; |
|
628 |
} |
||
629 |
|||
630 |
238 |
static int get_fmt_score(enum AVSampleFormat dst_fmt, enum AVSampleFormat src_fmt) |
|
631 |
{ |
||
632 |
238 |
int score = 0; |
|
633 |
|||
634 |
✓✓ | 238 |
if (av_sample_fmt_is_planar(dst_fmt) != av_sample_fmt_is_planar(src_fmt)) |
635 |
221 |
score ++; |
|
636 |
|||
637 |
✓✓ | 238 |
if (av_get_bytes_per_sample(dst_fmt) < av_get_bytes_per_sample(src_fmt)) { |
638 |
88 |
score += 100 * (av_get_bytes_per_sample(src_fmt) - av_get_bytes_per_sample(dst_fmt)); |
|
639 |
}else |
||
640 |
150 |
score += 10 * (av_get_bytes_per_sample(dst_fmt) - av_get_bytes_per_sample(src_fmt)); |
|
641 |
|||
642 |
✓✓✗✓ |
271 |
if (av_get_packed_sample_fmt(dst_fmt) == AV_SAMPLE_FMT_S32 && |
643 |
33 |
av_get_packed_sample_fmt(src_fmt) == AV_SAMPLE_FMT_FLT) |
|
644 |
score += 20; |
||
645 |
|||
646 |
✓✓✗✓ |
258 |
if (av_get_packed_sample_fmt(dst_fmt) == AV_SAMPLE_FMT_FLT && |
647 |
20 |
av_get_packed_sample_fmt(src_fmt) == AV_SAMPLE_FMT_S32) |
|
648 |
score += 2; |
||
649 |
|||
650 |
238 |
return score; |
|
651 |
} |
||
652 |
|||
653 |
119 |
static enum AVSampleFormat find_best_sample_fmt_of_2(enum AVSampleFormat dst_fmt1, enum AVSampleFormat dst_fmt2, |
|
654 |
enum AVSampleFormat src_fmt) |
||
655 |
{ |
||
656 |
int score1, score2; |
||
657 |
|||
658 |
119 |
score1 = get_fmt_score(dst_fmt1, src_fmt); |
|
659 |
119 |
score2 = get_fmt_score(dst_fmt2, src_fmt); |
|
660 |
|||
661 |
✓✓ | 119 |
return score1 < score2 ? dst_fmt1 : dst_fmt2; |
662 |
} |
||
663 |
|||
664 |
70900 |
static int pick_format(AVFilterLink *link, AVFilterLink *ref) |
|
665 |
{ |
||
666 |
✓✗✓✓ |
70900 |
if (!link || !link->incfg.formats) |
667 |
47254 |
return 0; |
|
668 |
|||
669 |
✓✓ | 23646 |
if (link->type == AVMEDIA_TYPE_VIDEO) { |
670 |
✓✓✓✗ |
18737 |
if(ref && ref->type == AVMEDIA_TYPE_VIDEO){ |
671 |
//FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented |
||
672 |
82 |
int has_alpha= av_pix_fmt_desc_get(ref->format)->nb_components % 2 == 0; |
|
673 |
82 |
enum AVPixelFormat best= AV_PIX_FMT_NONE; |
|
674 |
int i; |
||
675 |
✓✓ | 576 |
for (i = 0; i < link->incfg.formats->nb_formats; i++) { |
676 |
494 |
enum AVPixelFormat p = link->incfg.formats->formats[i]; |
|
677 |
494 |
best= av_find_best_pix_fmt_of_2(best, p, ref->format, has_alpha, NULL); |
|
678 |
} |
||
679 |
82 |
av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s alpha:%d\n", |
|
680 |
82 |
av_get_pix_fmt_name(best), link->incfg.formats->nb_formats, |
|
681 |
82 |
av_get_pix_fmt_name(ref->format), has_alpha); |
|
682 |
82 |
link->incfg.formats->formats[0] = best; |
|
683 |
} |
||
684 |
✓✗ | 4909 |
} else if (link->type == AVMEDIA_TYPE_AUDIO) { |
685 |
✓✓✓✗ |
4909 |
if(ref && ref->type == AVMEDIA_TYPE_AUDIO){ |
686 |
29 |
enum AVSampleFormat best= AV_SAMPLE_FMT_NONE; |
|
687 |
int i; |
||
688 |
✓✓ | 148 |
for (i = 0; i < link->incfg.formats->nb_formats; i++) { |
689 |
119 |
enum AVSampleFormat p = link->incfg.formats->formats[i]; |
|
690 |
119 |
best = find_best_sample_fmt_of_2(best, p, ref->format); |
|
691 |
} |
||
692 |
29 |
av_log(link->src,AV_LOG_DEBUG, "picking %s out of %d ref:%s\n", |
|
693 |
29 |
av_get_sample_fmt_name(best), link->incfg.formats->nb_formats, |
|
694 |
29 |
av_get_sample_fmt_name(ref->format)); |
|
695 |
29 |
link->incfg.formats->formats[0] = best; |
|
696 |
} |
||
697 |
} |
||
698 |
|||
699 |
23646 |
link->incfg.formats->nb_formats = 1; |
|
700 |
23646 |
link->format = link->incfg.formats->formats[0]; |
|
701 |
|||
702 |
✓✓ | 23646 |
if (link->type == AVMEDIA_TYPE_AUDIO) { |
703 |
✗✓ | 4909 |
if (!link->incfg.samplerates->nb_formats) { |
704 |
av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" |
||
705 |
" the link between filters %s and %s.\n", link->src->name, |
||
706 |
link->dst->name); |
||
707 |
return AVERROR(EINVAL); |
||
708 |
} |
||
709 |
4909 |
link->incfg.samplerates->nb_formats = 1; |
|
710 |
4909 |
link->sample_rate = link->incfg.samplerates->formats[0]; |
|
711 |
|||
712 |
✗✓ | 4909 |
if (link->incfg.channel_layouts->all_layouts) { |
713 |
av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for" |
||
714 |
" the link between filters %s and %s.\n", link->src->name, |
||
715 |
link->dst->name); |
||
716 |
if (!link->incfg.channel_layouts->all_counts) |
||
717 |
av_log(link->src, AV_LOG_ERROR, "Unknown channel layouts not " |
||
718 |
"supported, try specifying a channel layout using " |
||
719 |
"'aformat=channel_layouts=something'.\n"); |
||
720 |
return AVERROR(EINVAL); |
||
721 |
} |
||
722 |
4909 |
link->incfg.channel_layouts->nb_channel_layouts = 1; |
|
723 |
4909 |
link->channel_layout = link->incfg.channel_layouts->channel_layouts[0]; |
|
724 |
✓✓✓✓ |
4909 |
if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout))) |
725 |
29 |
link->channel_layout = 0; |
|
726 |
else |
||
727 |
4880 |
link->channels = av_get_channel_layout_nb_channels(link->channel_layout); |
|
728 |
} |
||
729 |
|||
730 |
23646 |
ff_formats_unref(&link->incfg.formats); |
|
731 |
23646 |
ff_formats_unref(&link->outcfg.formats); |
|
732 |
23646 |
ff_formats_unref(&link->incfg.samplerates); |
|
733 |
23646 |
ff_formats_unref(&link->outcfg.samplerates); |
|
734 |
23646 |
ff_channel_layouts_unref(&link->incfg.channel_layouts); |
|
735 |
23646 |
ff_channel_layouts_unref(&link->outcfg.channel_layouts); |
|
736 |
|||
737 |
23646 |
return 0; |
|
738 |
} |
||
739 |
|||
740 |
#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \ |
||
741 |
do { \ |
||
742 |
for (i = 0; i < filter->nb_inputs; i++) { \ |
||
743 |
AVFilterLink *link = filter->inputs[i]; \ |
||
744 |
fmt_type fmt; \ |
||
745 |
\ |
||
746 |
if (!link->outcfg.list || link->outcfg.list->nb != 1) \ |
||
747 |
continue; \ |
||
748 |
fmt = link->outcfg.list->var[0]; \ |
||
749 |
\ |
||
750 |
for (j = 0; j < filter->nb_outputs; j++) { \ |
||
751 |
AVFilterLink *out_link = filter->outputs[j]; \ |
||
752 |
list_type *fmts; \ |
||
753 |
\ |
||
754 |
if (link->type != out_link->type || \ |
||
755 |
out_link->incfg.list->nb == 1) \ |
||
756 |
continue; \ |
||
757 |
fmts = out_link->incfg.list; \ |
||
758 |
\ |
||
759 |
if (!out_link->incfg.list->nb) { \ |
||
760 |
if ((ret = add_format(&out_link->incfg.list, fmt)) < 0)\ |
||
761 |
return ret; \ |
||
762 |
ret = 1; \ |
||
763 |
break; \ |
||
764 |
} \ |
||
765 |
\ |
||
766 |
for (k = 0; k < out_link->incfg.list->nb; k++) \ |
||
767 |
if (fmts->var[k] == fmt) { \ |
||
768 |
fmts->var[0] = fmt; \ |
||
769 |
fmts->nb = 1; \ |
||
770 |
ret = 1; \ |
||
771 |
break; \ |
||
772 |
} \ |
||
773 |
} \ |
||
774 |
} \ |
||
775 |
} while (0) |
||
776 |
|||
777 |
32455 |
static int reduce_formats_on_filter(AVFilterContext *filter) |
|
778 |
{ |
||
779 |
32455 |
int i, j, k, ret = 0; |
|
780 |
|||
781 |
✓✗✓✓ ✓✓✓✓ ✗✓✗✗ ✓✓✓✓ ✓✓✓✓ |
80773 |
REDUCE_FORMATS(int, AVFilterFormats, formats, formats, |
782 |
nb_formats, ff_add_format); |
||
783 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓✓✓✗ ✓✓✓✓ |
62831 |
REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats, |
784 |
nb_formats, ff_add_format); |
||
785 |
|||
786 |
/* reduce channel layouts */ |
||
787 |
✓✓ | 58432 |
for (i = 0; i < filter->nb_inputs; i++) { |
788 |
25977 |
AVFilterLink *inlink = filter->inputs[i]; |
|
789 |
uint64_t fmt; |
||
790 |
|||
791 |
✓✓ | 25977 |
if (!inlink->outcfg.channel_layouts || |
792 |
✓✓ | 6909 |
inlink->outcfg.channel_layouts->nb_channel_layouts != 1) |
793 |
19828 |
continue; |
|
794 |
6149 |
fmt = inlink->outcfg.channel_layouts->channel_layouts[0]; |
|
795 |
|||
796 |
✓✓ | 9849 |
for (j = 0; j < filter->nb_outputs; j++) { |
797 |
4855 |
AVFilterLink *outlink = filter->outputs[j]; |
|
798 |
AVFilterChannelLayouts *fmts; |
||
799 |
|||
800 |
4855 |
fmts = outlink->incfg.channel_layouts; |
|
801 |
✓✓✓✓ |
4855 |
if (inlink->type != outlink->type || fmts->nb_channel_layouts == 1) |
802 |
3671 |
continue; |
|
803 |
|||
804 |
✓✓ | 1184 |
if (fmts->all_layouts && |
805 |
✓✓✓✗ ✓✗ |
1155 |
(!FF_LAYOUT2COUNT(fmt) || fmts->all_counts)) { |
806 |
/* Turn the infinite list into a singleton */ |
||
807 |
1155 |
fmts->all_layouts = fmts->all_counts = 0; |
|
808 |
✗✓ | 1155 |
if (ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt) < 0) |
809 |
ret = 1; |
||
810 |
1155 |
break; |
|
811 |
} |
||
812 |
|||
813 |
✓✓ | 79 |
for (k = 0; k < outlink->incfg.channel_layouts->nb_channel_layouts; k++) { |
814 |
✓✓ | 77 |
if (fmts->channel_layouts[k] == fmt) { |
815 |
27 |
fmts->channel_layouts[0] = fmt; |
|
816 |
27 |
fmts->nb_channel_layouts = 1; |
|
817 |
27 |
ret = 1; |
|
818 |
27 |
break; |
|
819 |
} |
||
820 |
} |
||
821 |
} |
||
822 |
} |
||
823 |
|||
824 |
32455 |
return ret; |
|
825 |
} |
||
826 |
|||
827 |
6490 |
static int reduce_formats(AVFilterGraph *graph) |
|
828 |
{ |
||
829 |
int i, reduced, ret; |
||
830 |
|||
831 |
do { |
||
832 |
6490 |
reduced = 0; |
|
833 |
|||
834 |
✓✓ | 38945 |
for (i = 0; i < graph->nb_filters; i++) { |
835 |
✗✓ | 32455 |
if ((ret = reduce_formats_on_filter(graph->filters[i])) < 0) |
836 |
return ret; |
||
837 |
32455 |
reduced |= ret; |
|
838 |
} |
||
839 |
✓✓ | 6490 |
} while (reduced); |
840 |
|||
841 |
5861 |
return 0; |
|
842 |
} |
||
843 |
|||
844 |
29495 |
static void swap_samplerates_on_filter(AVFilterContext *filter) |
|
845 |
{ |
||
846 |
29495 |
AVFilterLink *link = NULL; |
|
847 |
int sample_rate; |
||
848 |
int i, j; |
||
849 |
|||
850 |
✓✓ | 48228 |
for (i = 0; i < filter->nb_inputs; i++) { |
851 |
23631 |
link = filter->inputs[i]; |
|
852 |
|||
853 |
✓✓ | 23631 |
if (link->type == AVMEDIA_TYPE_AUDIO && |
854 |
✓✗ | 4898 |
link->outcfg.samplerates->nb_formats== 1) |
855 |
4898 |
break; |
|
856 |
} |
||
857 |
✓✓ | 29495 |
if (i == filter->nb_inputs) |
858 |
24597 |
return; |
|
859 |
|||
860 |
4898 |
sample_rate = link->outcfg.samplerates->formats[0]; |
|
861 |
|||
862 |
✓✓ | 8659 |
for (i = 0; i < filter->nb_outputs; i++) { |
863 |
3761 |
AVFilterLink *outlink = filter->outputs[i]; |
|
864 |
3761 |
int best_idx, best_diff = INT_MAX; |
|
865 |
|||
866 |
✓✓ | 3761 |
if (outlink->type != AVMEDIA_TYPE_AUDIO || |
867 |
✓✗ | 3759 |
outlink->incfg.samplerates->nb_formats < 2) |
868 |
3761 |
continue; |
|
869 |
|||
870 |
for (j = 0; j < outlink->incfg.samplerates->nb_formats; j++) { |
||
871 |
int diff = abs(sample_rate - outlink->incfg.samplerates->formats[j]); |
||
872 |
|||
873 |
av_assert0(diff < INT_MAX); // This would lead to the use of uninitialized best_diff but is only possible with invalid sample rates |
||
874 |
|||
875 |
if (diff < best_diff) { |
||
876 |
best_diff = diff; |
||
877 |
best_idx = j; |
||
878 |
} |
||
879 |
} |
||
880 |
FFSWAP(int, outlink->incfg.samplerates->formats[0], |
||
881 |
outlink->incfg.samplerates->formats[best_idx]); |
||
882 |
} |
||
883 |
} |
||
884 |
|||
885 |
5861 |
static void swap_samplerates(AVFilterGraph *graph) |
|
886 |
{ |
||
887 |
int i; |
||
888 |
|||
889 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) |
890 |
29495 |
swap_samplerates_on_filter(graph->filters[i]); |
|
891 |
5861 |
} |
|
892 |
|||
893 |
#define CH_CENTER_PAIR (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER) |
||
894 |
#define CH_FRONT_PAIR (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) |
||
895 |
#define CH_STEREO_PAIR (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT) |
||
896 |
#define CH_WIDE_PAIR (AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT) |
||
897 |
#define CH_SIDE_PAIR (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT) |
||
898 |
#define CH_DIRECT_PAIR (AV_CH_SURROUND_DIRECT_LEFT | AV_CH_SURROUND_DIRECT_RIGHT) |
||
899 |
#define CH_BACK_PAIR (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT) |
||
900 |
|||
901 |
/* allowable substitutions for channel pairs when comparing layouts, |
||
902 |
* ordered by priority for both values */ |
||
903 |
static const uint64_t ch_subst[][2] = { |
||
904 |
{ CH_FRONT_PAIR, CH_CENTER_PAIR }, |
||
905 |
{ CH_FRONT_PAIR, CH_WIDE_PAIR }, |
||
906 |
{ CH_FRONT_PAIR, AV_CH_FRONT_CENTER }, |
||
907 |
{ CH_CENTER_PAIR, CH_FRONT_PAIR }, |
||
908 |
{ CH_CENTER_PAIR, CH_WIDE_PAIR }, |
||
909 |
{ CH_CENTER_PAIR, AV_CH_FRONT_CENTER }, |
||
910 |
{ CH_WIDE_PAIR, CH_FRONT_PAIR }, |
||
911 |
{ CH_WIDE_PAIR, CH_CENTER_PAIR }, |
||
912 |
{ CH_WIDE_PAIR, AV_CH_FRONT_CENTER }, |
||
913 |
{ AV_CH_FRONT_CENTER, CH_FRONT_PAIR }, |
||
914 |
{ AV_CH_FRONT_CENTER, CH_CENTER_PAIR }, |
||
915 |
{ AV_CH_FRONT_CENTER, CH_WIDE_PAIR }, |
||
916 |
{ CH_SIDE_PAIR, CH_DIRECT_PAIR }, |
||
917 |
{ CH_SIDE_PAIR, CH_BACK_PAIR }, |
||
918 |
{ CH_SIDE_PAIR, AV_CH_BACK_CENTER }, |
||
919 |
{ CH_BACK_PAIR, CH_DIRECT_PAIR }, |
||
920 |
{ CH_BACK_PAIR, CH_SIDE_PAIR }, |
||
921 |
{ CH_BACK_PAIR, AV_CH_BACK_CENTER }, |
||
922 |
{ AV_CH_BACK_CENTER, CH_BACK_PAIR }, |
||
923 |
{ AV_CH_BACK_CENTER, CH_DIRECT_PAIR }, |
||
924 |
{ AV_CH_BACK_CENTER, CH_SIDE_PAIR }, |
||
925 |
}; |
||
926 |
|||
927 |
29495 |
static void swap_channel_layouts_on_filter(AVFilterContext *filter) |
|
928 |
{ |
||
929 |
29495 |
AVFilterLink *link = NULL; |
|
930 |
int i, j, k; |
||
931 |
|||
932 |
✓✓ | 48230 |
for (i = 0; i < filter->nb_inputs; i++) { |
933 |
23631 |
link = filter->inputs[i]; |
|
934 |
|||
935 |
✓✓ | 23631 |
if (link->type == AVMEDIA_TYPE_AUDIO && |
936 |
✓✓ | 4898 |
link->outcfg.channel_layouts->nb_channel_layouts == 1) |
937 |
4896 |
break; |
|
938 |
} |
||
939 |
✓✓ | 29495 |
if (i == filter->nb_inputs) |
940 |
24599 |
return; |
|
941 |
|||
942 |
✓✓ | 8656 |
for (i = 0; i < filter->nb_outputs; i++) { |
943 |
3760 |
AVFilterLink *outlink = filter->outputs[i]; |
|
944 |
3760 |
int best_idx = -1, best_score = INT_MIN, best_count_diff = INT_MAX; |
|
945 |
|||
946 |
✓✓ | 3760 |
if (outlink->type != AVMEDIA_TYPE_AUDIO || |
947 |
✓✓ | 3758 |
outlink->incfg.channel_layouts->nb_channel_layouts < 2) |
948 |
3759 |
continue; |
|
949 |
|||
950 |
✓✓ | 19 |
for (j = 0; j < outlink->incfg.channel_layouts->nb_channel_layouts; j++) { |
951 |
18 |
uint64_t in_chlayout = link->outcfg.channel_layouts->channel_layouts[0]; |
|
952 |
18 |
uint64_t out_chlayout = outlink->incfg.channel_layouts->channel_layouts[j]; |
|
953 |
18 |
int in_channels = av_get_channel_layout_nb_channels(in_chlayout); |
|
954 |
18 |
int out_channels = av_get_channel_layout_nb_channels(out_chlayout); |
|
955 |
18 |
int count_diff = out_channels - in_channels; |
|
956 |
int matched_channels, extra_channels; |
||
957 |
18 |
int score = 100000; |
|
958 |
|||
959 |
✓✗✗✓ ✗✗✗✗ |
18 |
if (FF_LAYOUT2COUNT(in_chlayout) || FF_LAYOUT2COUNT(out_chlayout)) { |
960 |
/* Compute score in case the input or output layout encodes |
||
961 |
a channel count; in this case the score is not altered by |
||
962 |
the computation afterwards, as in_chlayout and |
||
963 |
out_chlayout have both been set to 0 */ |
||
964 |
✓✗✓✗ |
18 |
if (FF_LAYOUT2COUNT(in_chlayout)) |
965 |
✓✗ | 18 |
in_channels = FF_LAYOUT2COUNT(in_chlayout); |
966 |
✗✓✗✗ |
18 |
if (FF_LAYOUT2COUNT(out_chlayout)) |
967 |
out_channels = FF_LAYOUT2COUNT(out_chlayout); |
||
968 |
36 |
score -= 10000 + FFABS(out_channels - in_channels) + |
|
969 |
✗✓ | 18 |
(in_channels > out_channels ? 10000 : 0); |
970 |
18 |
in_chlayout = out_chlayout = 0; |
|
971 |
/* Let the remaining computation run, even if the score |
||
972 |
value is not altered */ |
||
973 |
} |
||
974 |
|||
975 |
/* channel substitution */ |
||
976 |
✓✓ | 396 |
for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) { |
977 |
378 |
uint64_t cmp0 = ch_subst[k][0]; |
|
978 |
378 |
uint64_t cmp1 = ch_subst[k][1]; |
|
979 |
✗✓✗✗ |
378 |
if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) && |
980 |
(out_chlayout & cmp1) && (!( in_chlayout & cmp1))) { |
||
981 |
in_chlayout &= ~cmp0; |
||
982 |
out_chlayout &= ~cmp1; |
||
983 |
/* add score for channel match, minus a deduction for |
||
984 |
having to do the substitution */ |
||
985 |
score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2; |
||
986 |
} |
||
987 |
} |
||
988 |
|||
989 |
/* no penalty for LFE channel mismatch */ |
||
990 |
✗✓ | 18 |
if ( (in_chlayout & AV_CH_LOW_FREQUENCY) && |
991 |
(out_chlayout & AV_CH_LOW_FREQUENCY)) |
||
992 |
score += 10; |
||
993 |
18 |
in_chlayout &= ~AV_CH_LOW_FREQUENCY; |
|
994 |
18 |
out_chlayout &= ~AV_CH_LOW_FREQUENCY; |
|
995 |
|||
996 |
18 |
matched_channels = av_get_channel_layout_nb_channels(in_chlayout & |
|
997 |
out_chlayout); |
||
998 |
18 |
extra_channels = av_get_channel_layout_nb_channels(out_chlayout & |
|
999 |
18 |
(~in_chlayout)); |
|
1000 |
18 |
score += 10 * matched_channels - 5 * extra_channels; |
|
1001 |
|||
1002 |
✓✓✗✓ |
18 |
if (score > best_score || |
1003 |
(count_diff < best_count_diff && score == best_score)) { |
||
1004 |
1 |
best_score = score; |
|
1005 |
1 |
best_idx = j; |
|
1006 |
1 |
best_count_diff = count_diff; |
|
1007 |
} |
||
1008 |
} |
||
1009 |
✗✓ | 1 |
av_assert0(best_idx >= 0); |
1010 |
1 |
FFSWAP(uint64_t, outlink->incfg.channel_layouts->channel_layouts[0], |
|
1011 |
outlink->incfg.channel_layouts->channel_layouts[best_idx]); |
||
1012 |
} |
||
1013 |
|||
1014 |
} |
||
1015 |
|||
1016 |
5861 |
static void swap_channel_layouts(AVFilterGraph *graph) |
|
1017 |
{ |
||
1018 |
int i; |
||
1019 |
|||
1020 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) |
1021 |
29495 |
swap_channel_layouts_on_filter(graph->filters[i]); |
|
1022 |
5861 |
} |
|
1023 |
|||
1024 |
29495 |
static void swap_sample_fmts_on_filter(AVFilterContext *filter) |
|
1025 |
{ |
||
1026 |
29495 |
AVFilterLink *link = NULL; |
|
1027 |
int format, bps; |
||
1028 |
int i, j; |
||
1029 |
|||
1030 |
✓✓ | 48277 |
for (i = 0; i < filter->nb_inputs; i++) { |
1031 |
23632 |
link = filter->inputs[i]; |
|
1032 |
|||
1033 |
✓✓ | 23632 |
if (link->type == AVMEDIA_TYPE_AUDIO && |
1034 |
✓✓ | 4899 |
link->outcfg.formats->nb_formats == 1) |
1035 |
4850 |
break; |
|
1036 |
} |
||
1037 |
✓✓ | 29495 |
if (i == filter->nb_inputs) |
1038 |
24645 |
return; |
|
1039 |
|||
1040 |
4850 |
format = link->outcfg.formats->formats[0]; |
|
1041 |
4850 |
bps = av_get_bytes_per_sample(format); |
|
1042 |
|||
1043 |
✓✓ | 8585 |
for (i = 0; i < filter->nb_outputs; i++) { |
1044 |
3735 |
AVFilterLink *outlink = filter->outputs[i]; |
|
1045 |
3735 |
int best_idx = -1, best_score = INT_MIN; |
|
1046 |
|||
1047 |
✓✓ | 3735 |
if (outlink->type != AVMEDIA_TYPE_AUDIO || |
1048 |
✓✓ | 3733 |
outlink->incfg.formats->nb_formats < 2) |
1049 |
3705 |
continue; |
|
1050 |
|||
1051 |
✓✗ | 89 |
for (j = 0; j < outlink->incfg.formats->nb_formats; j++) { |
1052 |
89 |
int out_format = outlink->incfg.formats->formats[j]; |
|
1053 |
89 |
int out_bps = av_get_bytes_per_sample(out_format); |
|
1054 |
int score; |
||
1055 |
|||
1056 |
✓✓✓✓ |
160 |
if (av_get_packed_sample_fmt(out_format) == format || |
1057 |
71 |
av_get_planar_sample_fmt(out_format) == format) { |
|
1058 |
30 |
best_idx = j; |
|
1059 |
30 |
break; |
|
1060 |
} |
||
1061 |
|||
1062 |
/* for s32 and float prefer double to prevent loss of information */ |
||
1063 |
✓✓✗✓ |
59 |
if (bps == 4 && out_bps == 8) { |
1064 |
best_idx = j; |
||
1065 |
break; |
||
1066 |
} |
||
1067 |
|||
1068 |
/* prefer closest higher or equal bps */ |
||
1069 |
59 |
score = -abs(out_bps - bps); |
|
1070 |
✗✓ | 59 |
if (out_bps >= bps) |
1071 |
score += INT_MAX/2; |
||
1072 |
|||
1073 |
✓✓ | 59 |
if (score > best_score) { |
1074 |
47 |
best_score = score; |
|
1075 |
47 |
best_idx = j; |
|
1076 |
} |
||
1077 |
} |
||
1078 |
✗✓ | 30 |
av_assert0(best_idx >= 0); |
1079 |
30 |
FFSWAP(int, outlink->incfg.formats->formats[0], |
|
1080 |
outlink->incfg.formats->formats[best_idx]); |
||
1081 |
} |
||
1082 |
} |
||
1083 |
|||
1084 |
5861 |
static void swap_sample_fmts(AVFilterGraph *graph) |
|
1085 |
{ |
||
1086 |
int i; |
||
1087 |
|||
1088 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) |
1089 |
29495 |
swap_sample_fmts_on_filter(graph->filters[i]); |
|
1090 |
|||
1091 |
5861 |
} |
|
1092 |
|||
1093 |
11755 |
static int pick_formats(AVFilterGraph *graph) |
|
1094 |
{ |
||
1095 |
int i, j, ret; |
||
1096 |
int change; |
||
1097 |
|||
1098 |
do{ |
||
1099 |
11755 |
change = 0; |
|
1100 |
✓✓ | 70952 |
for (i = 0; i < graph->nb_filters; i++) { |
1101 |
59197 |
AVFilterContext *filter = graph->filters[i]; |
|
1102 |
✓✓ | 59197 |
if (filter->nb_inputs){ |
1103 |
✓✓ | 94821 |
for (j = 0; j < filter->nb_inputs; j++){ |
1104 |
✓✓✓✓ |
47469 |
if (filter->inputs[j]->incfg.formats && filter->inputs[j]->incfg.formats->nb_formats == 1) { |
1105 |
✗✓ | 11243 |
if ((ret = pick_format(filter->inputs[j], NULL)) < 0) |
1106 |
return ret; |
||
1107 |
11243 |
change = 1; |
|
1108 |
} |
||
1109 |
} |
||
1110 |
} |
||
1111 |
✓✓ | 59197 |
if (filter->nb_outputs){ |
1112 |
✓✓ | 94899 |
for (j = 0; j < filter->nb_outputs; j++){ |
1113 |
✓✓✓✓ |
47469 |
if (filter->outputs[j]->incfg.formats && filter->outputs[j]->incfg.formats->nb_formats == 1) { |
1114 |
✗✓ | 12254 |
if ((ret = pick_format(filter->outputs[j], NULL)) < 0) |
1115 |
return ret; |
||
1116 |
12254 |
change = 1; |
|
1117 |
} |
||
1118 |
} |
||
1119 |
} |
||
1120 |
✓✓✓✓ ✓✓ |
59197 |
if (filter->nb_inputs && filter->nb_outputs && filter->inputs[0]->format>=0) { |
1121 |
✓✓ | 71039 |
for (j = 0; j < filter->nb_outputs; j++) { |
1122 |
✓✓ | 35538 |
if (filter->outputs[j]->format<0) { |
1123 |
✗✓ | 111 |
if ((ret = pick_format(filter->outputs[j], filter->inputs[0])) < 0) |
1124 |
return ret; |
||
1125 |
111 |
change = 1; |
|
1126 |
} |
||
1127 |
} |
||
1128 |
} |
||
1129 |
} |
||
1130 |
✓✓ | 11755 |
}while(change); |
1131 |
|||
1132 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) { |
1133 |
29495 |
AVFilterContext *filter = graph->filters[i]; |
|
1134 |
|||
1135 |
✓✓ | 53141 |
for (j = 0; j < filter->nb_inputs; j++) |
1136 |
✗✓ | 23646 |
if ((ret = pick_format(filter->inputs[j], NULL)) < 0) |
1137 |
return ret; |
||
1138 |
✓✓ | 53141 |
for (j = 0; j < filter->nb_outputs; j++) |
1139 |
✗✓ | 23646 |
if ((ret = pick_format(filter->outputs[j], NULL)) < 0) |
1140 |
return ret; |
||
1141 |
} |
||
1142 |
5861 |
return 0; |
|
1143 |
} |
||
1144 |
|||
1145 |
/** |
||
1146 |
* Configure the formats of all the links in the graph. |
||
1147 |
*/ |
||
1148 |
5865 |
static int graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx) |
|
1149 |
{ |
||
1150 |
int ret; |
||
1151 |
|||
1152 |
/* find supported formats from sub-filters, and merge along links */ |
||
1153 |
✓✓ | 5879 |
while ((ret = query_formats(graph, log_ctx)) == AVERROR(EAGAIN)) |
1154 |
14 |
av_log(graph, AV_LOG_DEBUG, "query_formats not finished\n"); |
|
1155 |
✓✓ | 5865 |
if (ret < 0) |
1156 |
4 |
return ret; |
|
1157 |
|||
1158 |
/* Once everything is merged, it's possible that we'll still have |
||
1159 |
* multiple valid media format choices. We try to minimize the amount |
||
1160 |
* of format conversion inside filters */ |
||
1161 |
✗✓ | 5861 |
if ((ret = reduce_formats(graph)) < 0) |
1162 |
return ret; |
||
1163 |
|||
1164 |
/* for audio filters, ensure the best format, sample rate and channel layout |
||
1165 |
* is selected */ |
||
1166 |
5861 |
swap_sample_fmts(graph); |
|
1167 |
5861 |
swap_samplerates(graph); |
|
1168 |
5861 |
swap_channel_layouts(graph); |
|
1169 |
|||
1170 |
✗✓ | 5861 |
if ((ret = pick_formats(graph)) < 0) |
1171 |
return ret; |
||
1172 |
|||
1173 |
5861 |
return 0; |
|
1174 |
} |
||
1175 |
|||
1176 |
5861 |
static int graph_config_pointers(AVFilterGraph *graph, |
|
1177 |
AVClass *log_ctx) |
||
1178 |
{ |
||
1179 |
unsigned i, j; |
||
1180 |
5861 |
int sink_links_count = 0, n = 0; |
|
1181 |
AVFilterContext *f; |
||
1182 |
AVFilterLink **sinks; |
||
1183 |
|||
1184 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) { |
1185 |
29495 |
f = graph->filters[i]; |
|
1186 |
✓✓ | 53141 |
for (j = 0; j < f->nb_inputs; j++) { |
1187 |
23646 |
f->inputs[j]->graph = graph; |
|
1188 |
23646 |
f->inputs[j]->age_index = -1; |
|
1189 |
} |
||
1190 |
✓✓ | 53141 |
for (j = 0; j < f->nb_outputs; j++) { |
1191 |
23646 |
f->outputs[j]->graph = graph; |
|
1192 |
23646 |
f->outputs[j]->age_index= -1; |
|
1193 |
} |
||
1194 |
✓✓ | 29495 |
if (!f->nb_outputs) { |
1195 |
✗✓ | 5867 |
if (f->nb_inputs > INT_MAX - sink_links_count) |
1196 |
return AVERROR(EINVAL); |
||
1197 |
5867 |
sink_links_count += f->nb_inputs; |
|
1198 |
} |
||
1199 |
} |
||
1200 |
5861 |
sinks = av_calloc(sink_links_count, sizeof(*sinks)); |
|
1201 |
✗✓ | 5861 |
if (!sinks) |
1202 |
return AVERROR(ENOMEM); |
||
1203 |
✓✓ | 35356 |
for (i = 0; i < graph->nb_filters; i++) { |
1204 |
29495 |
f = graph->filters[i]; |
|
1205 |
✓✓ | 29495 |
if (!f->nb_outputs) { |
1206 |
✓✓ | 11734 |
for (j = 0; j < f->nb_inputs; j++) { |
1207 |
5867 |
sinks[n] = f->inputs[j]; |
|
1208 |
5867 |
f->inputs[j]->age_index = n++; |
|
1209 |
} |
||
1210 |
} |
||
1211 |
} |
||
1212 |
✗✓ | 5861 |
av_assert0(n == sink_links_count); |
1213 |
5861 |
graph->sink_links = sinks; |
|
1214 |
5861 |
graph->sink_links_count = sink_links_count; |
|
1215 |
5861 |
return 0; |
|
1216 |
} |
||
1217 |
|||
1218 |
5865 |
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) |
|
1219 |
{ |
||
1220 |
int ret; |
||
1221 |
|||
1222 |
✗✓ | 5865 |
if ((ret = graph_check_validity(graphctx, log_ctx))) |
1223 |
return ret; |
||
1224 |
✓✓ | 5865 |
if ((ret = graph_config_formats(graphctx, log_ctx))) |
1225 |
4 |
return ret; |
|
1226 |
✗✓ | 5861 |
if ((ret = graph_config_links(graphctx, log_ctx))) |
1227 |
return ret; |
||
1228 |
✗✓ | 5861 |
if ((ret = graph_check_links(graphctx, log_ctx))) |
1229 |
return ret; |
||
1230 |
✗✓ | 5861 |
if ((ret = graph_config_pointers(graphctx, log_ctx))) |
1231 |
return ret; |
||
1232 |
|||
1233 |
5861 |
return 0; |
|
1234 |
} |
||
1235 |
|||
1236 |
int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags) |
||
1237 |
{ |
||
1238 |
int i, r = AVERROR(ENOSYS); |
||
1239 |
|||
1240 |
if (!graph) |
||
1241 |
return r; |
||
1242 |
|||
1243 |
if ((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) { |
||
1244 |
r = avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST); |
||
1245 |
if (r != AVERROR(ENOSYS)) |
||
1246 |
return r; |
||
1247 |
} |
||
1248 |
|||
1249 |
if (res_len && res) |
||
1250 |
res[0] = 0; |
||
1251 |
|||
1252 |
for (i = 0; i < graph->nb_filters; i++) { |
||
1253 |
AVFilterContext *filter = graph->filters[i]; |
||
1254 |
if (!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)) { |
||
1255 |
r = avfilter_process_command(filter, cmd, arg, res, res_len, flags); |
||
1256 |
if (r != AVERROR(ENOSYS)) { |
||
1257 |
if ((flags & AVFILTER_CMD_FLAG_ONE) || r < 0) |
||
1258 |
return r; |
||
1259 |
} |
||
1260 |
} |
||
1261 |
} |
||
1262 |
|||
1263 |
return r; |
||
1264 |
} |
||
1265 |
|||
1266 |
int avfilter_graph_queue_command(AVFilterGraph *graph, const char *target, const char *command, const char *arg, int flags, double ts) |
||
1267 |
{ |
||
1268 |
int i; |
||
1269 |
|||
1270 |
if(!graph) |
||
1271 |
return 0; |
||
1272 |
|||
1273 |
for (i = 0; i < graph->nb_filters; i++) { |
||
1274 |
AVFilterContext *filter = graph->filters[i]; |
||
1275 |
if(filter && (!strcmp(target, "all") || !strcmp(target, filter->name) || !strcmp(target, filter->filter->name))){ |
||
1276 |
AVFilterCommand **queue = &filter->command_queue, *next; |
||
1277 |
while (*queue && (*queue)->time <= ts) |
||
1278 |
queue = &(*queue)->next; |
||
1279 |
next = *queue; |
||
1280 |
*queue = av_mallocz(sizeof(AVFilterCommand)); |
||
1281 |
if (!*queue) |
||
1282 |
return AVERROR(ENOMEM); |
||
1283 |
|||
1284 |
(*queue)->command = av_strdup(command); |
||
1285 |
(*queue)->arg = av_strdup(arg); |
||
1286 |
(*queue)->time = ts; |
||
1287 |
(*queue)->flags = flags; |
||
1288 |
(*queue)->next = next; |
||
1289 |
if(flags & AVFILTER_CMD_FLAG_ONE) |
||
1290 |
return 0; |
||
1291 |
} |
||
1292 |
} |
||
1293 |
|||
1294 |
return 0; |
||
1295 |
} |
||
1296 |
|||
1297 |
413468 |
static void heap_bubble_up(AVFilterGraph *graph, |
|
1298 |
AVFilterLink *link, int index) |
||
1299 |
{ |
||
1300 |
413468 |
AVFilterLink **links = graph->sink_links; |
|
1301 |
|||
1302 |
✗✓ | 413468 |
av_assert0(index >= 0); |
1303 |
|||
1304 |
✓✓ | 413478 |
while (index) { |
1305 |
10 |
int parent = (index - 1) >> 1; |
|
1306 |
✗✓ | 10 |
if (links[parent]->current_pts_us >= link->current_pts_us) |
1307 |
break; |
||
1308 |
10 |
links[index] = links[parent]; |
|
1309 |
10 |
links[index]->age_index = index; |
|
1310 |
10 |
index = parent; |
|
1311 |
} |
||
1312 |
413468 |
links[index] = link; |
|
1313 |
413468 |
link->age_index = index; |
|
1314 |
413468 |
} |
|
1315 |
|||
1316 |
413470 |
static void heap_bubble_down(AVFilterGraph *graph, |
|
1317 |
AVFilterLink *link, int index) |
||
1318 |
{ |
||
1319 |
413470 |
AVFilterLink **links = graph->sink_links; |
|
1320 |
|||
1321 |
✗✓ | 413470 |
av_assert0(index >= 0); |
1322 |
|||
1323 |
642 |
while (1) { |
|
1324 |
414112 |
int child = 2 * index + 1; |
|
1325 |
✓✓ | 414112 |
if (child >= graph->sink_links_count) |
1326 |
413164 |
break; |
|
1327 |
✓✓ | 948 |
if (child + 1 < graph->sink_links_count && |
1328 |
✓✓ | 17 |
links[child + 1]->current_pts_us < links[child]->current_pts_us) |
1329 |
5 |
child++; |
|
1330 |
✓✓ | 948 |
if (link->current_pts_us < links[child]->current_pts_us) |
1331 |
306 |
break; |
|
1332 |
642 |
links[index] = links[child]; |
|
1333 |
642 |
links[index]->age_index = index; |
|
1334 |
642 |
index = child; |
|
1335 |
} |
||
1336 |
413470 |
links[index] = link; |
|
1337 |
413470 |
link->age_index = index; |
|
1338 |
413470 |
} |
|
1339 |
|||
1340 |
413468 |
void ff_avfilter_graph_update_heap(AVFilterGraph *graph, AVFilterLink *link) |
|
1341 |
{ |
||
1342 |
413468 |
heap_bubble_up (graph, link, link->age_index); |
|
1343 |
413468 |
heap_bubble_down(graph, link, link->age_index); |
|
1344 |
413468 |
} |
|
1345 |
|||
1346 |
365604 |
int avfilter_graph_request_oldest(AVFilterGraph *graph) |
|
1347 |
{ |
||
1348 |
365604 |
AVFilterLink *oldest = graph->sink_links[0]; |
|
1349 |
int64_t frame_count; |
||
1350 |
int r; |
||
1351 |
|||
1352 |
✓✓ | 369040 |
while (graph->sink_links_count) { |
1353 |
365607 |
oldest = graph->sink_links[0]; |
|
1354 |
✓✓ | 365607 |
if (oldest->dst->filter->activate) { |
1355 |
/* For now, buffersink is the only filter implementing activate. */ |
||
1356 |
365602 |
r = av_buffersink_get_frame_flags(oldest->dst, NULL, |
|
1357 |
AV_BUFFERSINK_FLAG_PEEK); |
||
1358 |
✓✓ | 365602 |
if (r != AVERROR_EOF) |
1359 |
362166 |
return r; |
|
1360 |
} else { |
||
1361 |
5 |
r = ff_request_frame(oldest); |
|
1362 |
} |
||
1363 |
✓✓ | 3441 |
if (r != AVERROR_EOF) |
1364 |
5 |
break; |
|
1365 |
3436 |
av_log(oldest->dst, AV_LOG_DEBUG, "EOF on sink link %s:%s.\n", |
|
1366 |
✓✗ | 3436 |
oldest->dst ? oldest->dst->name : "unknown", |
1367 |
✓✗ | 3436 |
oldest->dstpad ? oldest->dstpad->name : "unknown"); |
1368 |
/* EOF: remove the link from the heap */ |
||
1369 |
✓✓ | 3436 |
if (oldest->age_index < --graph->sink_links_count) |
1370 |
2 |
heap_bubble_down(graph, graph->sink_links[graph->sink_links_count], |
|
1371 |
oldest->age_index); |
||
1372 |
3436 |
oldest->age_index = -1; |
|
1373 |
} |
||
1374 |
✓✓ | 3438 |
if (!graph->sink_links_count) |
1375 |
3433 |
return AVERROR_EOF; |
|
1376 |
av_assert1(!oldest->dst->filter->activate); |
||
1377 |
av_assert1(oldest->age_index >= 0); |
||
1378 |
5 |
frame_count = oldest->frame_count_out; |
|
1379 |
✓✓ | 34 |
while (frame_count == oldest->frame_count_out) { |
1380 |
29 |
r = ff_filter_graph_run_once(graph); |
|
1381 |
✗✓ | 29 |
if (r == AVERROR(EAGAIN) && |
1382 |
!oldest->frame_wanted_out && !oldest->frame_blocked_in && |
||
1383 |
!oldest->status_in) |
||
1384 |
ff_request_frame(oldest); |
||
1385 |
✗✓ | 29 |
else if (r < 0) |
1386 |
return r; |
||
1387 |
} |
||
1388 |
5 |
return 0; |
|
1389 |
} |
||
1390 |
|||
1391 |
3990418 |
int ff_filter_graph_run_once(AVFilterGraph *graph) |
|
1392 |
{ |
||
1393 |
AVFilterContext *filter; |
||
1394 |
unsigned i; |
||
1395 |
|||
1396 |
✗✓ | 3990418 |
av_assert0(graph->nb_filters); |
1397 |
3990418 |
filter = graph->filters[0]; |
|
1398 |
✓✓ | 18677208 |
for (i = 1; i < graph->nb_filters; i++) |
1399 |
✓✓ | 14686790 |
if (graph->filters[i]->ready > filter->ready) |
1400 |
2465897 |
filter = graph->filters[i]; |
|
1401 |
✓✓ | 3990418 |
if (!filter->ready) |
1402 |
398603 |
return AVERROR(EAGAIN); |
|
1403 |
3591815 |
return ff_filter_activate(filter); |
|
1404 |
} |
Generated by: GCOVR (Version 4.2) |