Directory: | ../../../ffmpeg/ |
---|---|
File: | src/fftools/ffmpeg_filter.c |
Date: | 2022-07-04 00:18:54 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 492 | 635 | 77.5% |
Branches: | 304 | 476 | 63.9% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * ffmpeg filter configuration | ||
3 | * | ||
4 | * This file is part of FFmpeg. | ||
5 | * | ||
6 | * FFmpeg is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * FFmpeg is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <stdint.h> | ||
22 | |||
23 | #include "ffmpeg.h" | ||
24 | |||
25 | #include "libavfilter/avfilter.h" | ||
26 | #include "libavfilter/buffersink.h" | ||
27 | #include "libavfilter/buffersrc.h" | ||
28 | |||
29 | #include "libavutil/avassert.h" | ||
30 | #include "libavutil/avstring.h" | ||
31 | #include "libavutil/bprint.h" | ||
32 | #include "libavutil/channel_layout.h" | ||
33 | #include "libavutil/display.h" | ||
34 | #include "libavutil/opt.h" | ||
35 | #include "libavutil/pixdesc.h" | ||
36 | #include "libavutil/pixfmt.h" | ||
37 | #include "libavutil/imgutils.h" | ||
38 | #include "libavutil/samplefmt.h" | ||
39 | |||
40 | // FIXME: YUV420P etc. are actually supported with full color range, | ||
41 | // yet the latter information isn't available here. | ||
42 | 544 | static const enum AVPixelFormat *get_compliance_normal_pix_fmts(const AVCodec *codec, const enum AVPixelFormat default_formats[]) | |
43 | { | ||
44 | static const enum AVPixelFormat mjpeg_formats[] = | ||
45 | { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, | ||
46 | AV_PIX_FMT_NONE }; | ||
47 | |||
48 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 517 times.
|
544 | if (!strcmp(codec->name, "mjpeg")) { |
49 | 27 | return mjpeg_formats; | |
50 | } else { | ||
51 | 517 | return default_formats; | |
52 | } | ||
53 | } | ||
54 | |||
55 | 3530 | static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, | |
56 | const AVCodec *codec, enum AVPixelFormat target) | ||
57 | { | ||
58 |
3/4✓ Branch 0 taken 3530 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 292 times.
✓ Branch 3 taken 3238 times.
|
3530 | if (codec && codec->pix_fmts) { |
59 | 292 | const enum AVPixelFormat *p = codec->pix_fmts; | |
60 | 292 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); | |
61 | //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented | ||
62 |
3/4✓ Branch 0 taken 292 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 273 times.
|
292 | int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; |
63 | 292 | enum AVPixelFormat best= AV_PIX_FMT_NONE; | |
64 | |||
65 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 45 times.
|
292 | if (enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { |
66 | 247 | p = get_compliance_normal_pix_fmts(codec, p); | |
67 | } | ||
68 |
2/2✓ Branch 0 taken 1416 times.
✓ Branch 1 taken 11 times.
|
1427 | for (; *p != AV_PIX_FMT_NONE; p++) { |
69 | 1416 | best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); | |
70 |
2/2✓ Branch 0 taken 281 times.
✓ Branch 1 taken 1135 times.
|
1416 | if (*p == target) |
71 | 281 | break; | |
72 | } | ||
73 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 281 times.
|
292 | if (*p == AV_PIX_FMT_NONE) { |
74 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | if (target != AV_PIX_FMT_NONE) |
75 | 22 | av_log(NULL, AV_LOG_WARNING, | |
76 | "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", | ||
77 | av_get_pix_fmt_name(target), | ||
78 | 11 | codec->name, | |
79 | av_get_pix_fmt_name(best)); | ||
80 | 11 | return best; | |
81 | } | ||
82 | } | ||
83 | 3519 | return target; | |
84 | } | ||
85 | |||
86 | /* May return NULL (no pixel format found), a static string or a string | ||
87 | * backed by the bprint. Nothing has been written to the AVBPrint in case | ||
88 | * NULL is returned. The AVBPrint provided should be clean. */ | ||
89 | 4908 | static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) | |
90 | { | ||
91 | 4908 | OutputStream *ost = ofilter->ost; | |
92 | 4908 | const AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); | |
93 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4844 times.
|
4908 | if (strict_dict) |
94 | // used by choose_pixel_fmt() and below | ||
95 | 64 | av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); | |
96 | |||
97 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4908 times.
|
4908 | if (ost->keep_pix_fmt) { |
98 | ✗ | avfilter_graph_set_auto_convert(ofilter->graph->graph, | |
99 | AVFILTER_AUTO_CONVERT_NONE); | ||
100 | ✗ | if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) | |
101 | ✗ | return NULL; | |
102 | ✗ | return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); | |
103 | } | ||
104 |
2/2✓ Branch 0 taken 3530 times.
✓ Branch 1 taken 1378 times.
|
4908 | if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { |
105 | 3530 | return av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)); | |
106 |
3/4✓ Branch 0 taken 1378 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
✓ Branch 3 taken 1062 times.
|
1378 | } else if (ost->enc && ost->enc->pix_fmts) { |
107 | const enum AVPixelFormat *p; | ||
108 | |||
109 | 316 | p = ost->enc->pix_fmts; | |
110 |
2/2✓ Branch 0 taken 297 times.
✓ Branch 1 taken 19 times.
|
316 | if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { |
111 | 297 | p = get_compliance_normal_pix_fmts(ost->enc, p); | |
112 | } | ||
113 | |||
114 |
2/2✓ Branch 0 taken 1747 times.
✓ Branch 1 taken 316 times.
|
2063 | for (; *p != AV_PIX_FMT_NONE; p++) { |
115 | 1747 | const char *name = av_get_pix_fmt_name(*p); | |
116 |
2/2✓ Branch 0 taken 316 times.
✓ Branch 1 taken 1431 times.
|
1747 | av_bprintf(bprint, "%s%c", name, p[1] == AV_PIX_FMT_NONE ? '\0' : '|'); |
117 | } | ||
118 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 316 times.
|
316 | if (!av_bprint_is_complete(bprint)) |
119 | ✗ | exit_program(1); | |
120 | 316 | return bprint->str; | |
121 | } else | ||
122 | 1062 | return NULL; | |
123 | } | ||
124 | |||
125 | /* Define a function for appending a list of allowed formats | ||
126 | * to an AVBPrint. If nonempty, the list will have a header. */ | ||
127 | #define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \ | ||
128 | static void choose_ ## name (OutputFilter *ofilter, AVBPrint *bprint) \ | ||
129 | { \ | ||
130 | if (ofilter->var == none && !ofilter->supported_list) \ | ||
131 | return; \ | ||
132 | av_bprintf(bprint, #name "="); \ | ||
133 | if (ofilter->var != none) { \ | ||
134 | av_bprintf(bprint, printf_format, get_name(ofilter->var)); \ | ||
135 | } else { \ | ||
136 | const type *p; \ | ||
137 | \ | ||
138 | for (p = ofilter->supported_list; *p != none; p++) { \ | ||
139 | av_bprintf(bprint, printf_format "|", get_name(*p)); \ | ||
140 | } \ | ||
141 | if (bprint->len > 0) \ | ||
142 | bprint->str[--bprint->len] = '\0'; \ | ||
143 | } \ | ||
144 | av_bprint_chars(bprint, ':', 1); \ | ||
145 | } | ||
146 | |||
147 | //DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats, AV_PIX_FMT_NONE, | ||
148 | // GET_PIX_FMT_NAME) | ||
149 | |||
150 |
8/10✓ Branch 0 taken 1147 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1147 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1147 times.
✓ Branch 11 taken 1185 times.
✓ Branch 12 taken 1147 times.
✓ Branch 13 taken 1147 times.
✗ Branch 14 not taken.
|
2333 | DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, |
151 | AV_SAMPLE_FMT_NONE, "%s", av_get_sample_fmt_name) | ||
152 | |||
153 |
9/10✓ Branch 0 taken 1122 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 1083 times.
✓ Branch 3 taken 39 times.
✓ Branch 5 taken 26 times.
✓ Branch 6 taken 39 times.
✓ Branch 9 taken 282 times.
✓ Branch 10 taken 39 times.
✓ Branch 11 taken 39 times.
✗ Branch 12 not taken.
|
1430 | DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, |
154 | "%d", ) | ||
155 | |||
156 | 1148 | static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) | |
157 | { | ||
158 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 1135 times.
|
1148 | if (av_channel_layout_check(&ofilter->ch_layout)) { |
159 | 13 | av_bprintf(bprint, "channel_layouts="); | |
160 | 13 | av_channel_layout_describe_bprint(&ofilter->ch_layout, bprint); | |
161 |
2/2✓ Branch 0 taken 65 times.
✓ Branch 1 taken 1070 times.
|
1135 | } else if (ofilter->ch_layouts) { |
162 | const AVChannelLayout *p; | ||
163 | |||
164 | 65 | av_bprintf(bprint, "channel_layouts="); | |
165 |
2/2✓ Branch 0 taken 326 times.
✓ Branch 1 taken 65 times.
|
391 | for (p = ofilter->ch_layouts; p->nb_channels; p++) { |
166 | 326 | av_channel_layout_describe_bprint(p, bprint); | |
167 | 326 | av_bprintf(bprint, "|"); | |
168 | } | ||
169 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | if (bprint->len > 0) |
170 | 65 | bprint->str[--bprint->len] = '\0'; | |
171 | } else | ||
172 | 1070 | return; | |
173 | 78 | av_bprint_chars(bprint, ':', 1); | |
174 | } | ||
175 | |||
176 | 5910 | int init_simple_filtergraph(InputStream *ist, OutputStream *ost) | |
177 | { | ||
178 | 5910 | FilterGraph *fg = av_mallocz(sizeof(*fg)); | |
179 | OutputFilter *ofilter; | ||
180 | InputFilter *ifilter; | ||
181 | |||
182 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5910 times.
|
5910 | if (!fg) |
183 | ✗ | exit_program(1); | |
184 | 5910 | fg->index = nb_filtergraphs; | |
185 | |||
186 | 5910 | ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); | |
187 | 5910 | ofilter->ost = ost; | |
188 | 5910 | ofilter->graph = fg; | |
189 | 5910 | ofilter->format = -1; | |
190 | |||
191 | 5910 | ost->filter = ofilter; | |
192 | |||
193 | 5910 | ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); | |
194 | 5910 | ifilter->ist = ist; | |
195 | 5910 | ifilter->graph = fg; | |
196 | 5910 | ifilter->format = -1; | |
197 | |||
198 | 5910 | ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); | |
199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5910 times.
|
5910 | if (!ifilter->frame_queue) |
200 | ✗ | exit_program(1); | |
201 | |||
202 | 5910 | GROW_ARRAY(ist->filters, ist->nb_filters); | |
203 | 5910 | ist->filters[ist->nb_filters - 1] = ifilter; | |
204 | |||
205 | 5910 | GROW_ARRAY(filtergraphs, nb_filtergraphs); | |
206 | 5910 | filtergraphs[nb_filtergraphs - 1] = fg; | |
207 | |||
208 | 5910 | return 0; | |
209 | } | ||
210 | |||
211 | 191 | static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) | |
212 | { | ||
213 | 191 | AVFilterContext *ctx = inout->filter_ctx; | |
214 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 107 times.
|
191 | AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; |
215 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 107 times.
|
191 | int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; |
216 | char *res; | ||
217 | |||
218 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 138 times.
|
191 | if (nb_pads > 1) |
219 | 53 | res = av_strdup(ctx->filter->name); | |
220 | else | ||
221 | 138 | res = av_asprintf("%s:%s", ctx->filter->name, | |
222 | avfilter_pad_get_name(pads, inout->pad_idx)); | ||
223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 191 times.
|
191 | if (!res) |
224 | ✗ | exit_program(1); | |
225 | 191 | return res; | |
226 | } | ||
227 | |||
228 | 84 | static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) | |
229 | { | ||
230 | 84 | InputStream *ist = NULL; | |
231 | 84 | enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); | |
232 | InputFilter *ifilter; | ||
233 | int i; | ||
234 | |||
235 | // TODO: support other filter types | ||
236 |
3/4✓ Branch 0 taken 32 times.
✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
84 | if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { |
237 | ✗ | av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported " | |
238 | "currently.\n"); | ||
239 | ✗ | exit_program(1); | |
240 | } | ||
241 | |||
242 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 50 times.
|
84 | if (in->name) { |
243 | AVFormatContext *s; | ||
244 | 34 | AVStream *st = NULL; | |
245 | char *p; | ||
246 | 34 | int file_idx = strtol(in->name, &p, 0); | |
247 | |||
248 |
2/4✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
|
34 | if (file_idx < 0 || file_idx >= nb_input_files) { |
249 | ✗ | av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", | |
250 | file_idx, fg->graph_desc); | ||
251 | ✗ | exit_program(1); | |
252 | } | ||
253 | 34 | s = input_files[file_idx]->ctx; | |
254 | |||
255 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | for (i = 0; i < s->nb_streams; i++) { |
256 | 39 | enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type; | |
257 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
|
39 | if (stream_type != type && |
258 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | !(stream_type == AVMEDIA_TYPE_SUBTITLE && |
259 | type == AVMEDIA_TYPE_VIDEO /* sub2video hack */)) | ||
260 | 3 | continue; | |
261 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 34 times.
✓ Branch 4 taken 2 times.
|
36 | if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { |
262 | 34 | st = s->streams[i]; | |
263 | 34 | break; | |
264 | } | ||
265 | } | ||
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (!st) { |
267 | ✗ | av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " | |
268 | "matches no streams.\n", p, fg->graph_desc); | ||
269 | ✗ | exit_program(1); | |
270 | } | ||
271 | 34 | ist = input_streams[input_files[file_idx]->ist_index + st->index]; | |
272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (ist->user_set_discard == AVDISCARD_ALL) { |
273 | ✗ | av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " | |
274 | "matches a disabled input stream.\n", p, fg->graph_desc); | ||
275 | ✗ | exit_program(1); | |
276 | } | ||
277 | } else { | ||
278 | /* find the first unused stream of corresponding type */ | ||
279 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | for (i = 0; i < nb_input_streams; i++) { |
280 | 69 | ist = input_streams[i]; | |
281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | if (ist->user_set_discard == AVDISCARD_ALL) |
282 | ✗ | continue; | |
283 |
4/4✓ Branch 0 taken 68 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 18 times.
|
69 | if (ist->dec_ctx->codec_type == type && ist->discard) |
284 | 50 | break; | |
285 | } | ||
286 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
|
50 | if (i == nb_input_streams) { |
287 | ✗ | av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " | |
288 | "unlabeled input pad %d on filter %s\n", in->pad_idx, | ||
289 | ✗ | in->filter_ctx->name); | |
290 | ✗ | exit_program(1); | |
291 | } | ||
292 | } | ||
293 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | av_assert0(ist); |
294 | |||
295 | 84 | ist->discard = 0; | |
296 | 84 | ist->decoding_needed |= DECODING_FOR_FILTER; | |
297 | 84 | ist->processing_needed = 1; | |
298 | 84 | ist->st->discard = AVDISCARD_NONE; | |
299 | |||
300 | 84 | ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); | |
301 | 84 | ifilter->ist = ist; | |
302 | 84 | ifilter->graph = fg; | |
303 | 84 | ifilter->format = -1; | |
304 | 84 | ifilter->type = ist->st->codecpar->codec_type; | |
305 | 84 | ifilter->name = describe_filter_link(fg, in, 1); | |
306 | |||
307 | 84 | ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); | |
308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (!ifilter->frame_queue) |
309 | ✗ | exit_program(1); | |
310 | |||
311 | 84 | GROW_ARRAY(ist->filters, ist->nb_filters); | |
312 | 84 | ist->filters[ist->nb_filters - 1] = ifilter; | |
313 | 84 | } | |
314 | |||
315 | 97 | int init_complex_filtergraph(FilterGraph *fg) | |
316 | { | ||
317 | AVFilterInOut *inputs, *outputs, *cur; | ||
318 | AVFilterGraph *graph; | ||
319 | 97 | int ret = 0; | |
320 | |||
321 | /* this graph is only used for determining the kinds of inputs | ||
322 | * and outputs we have, and is discarded on exit from this function */ | ||
323 | 97 | graph = avfilter_graph_alloc(); | |
324 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
|
97 | if (!graph) |
325 | ✗ | return AVERROR(ENOMEM); | |
326 | 97 | graph->nb_threads = 1; | |
327 | |||
328 | 97 | ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); | |
329 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
|
97 | if (ret < 0) |
330 | ✗ | goto fail; | |
331 | |||
332 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 97 times.
|
181 | for (cur = inputs; cur; cur = cur->next) |
333 | 84 | init_input_filter(fg, cur); | |
334 | |||
335 |
2/2✓ Branch 0 taken 107 times.
✓ Branch 1 taken 97 times.
|
204 | for (cur = outputs; cur;) { |
336 | 107 | OutputFilter *const ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); | |
337 | |||
338 | 107 | ofilter->graph = fg; | |
339 | 107 | ofilter->out_tmp = cur; | |
340 | 107 | ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, | |
341 | cur->pad_idx); | ||
342 | 107 | ofilter->name = describe_filter_link(fg, cur, 0); | |
343 | 107 | cur = cur->next; | |
344 | 107 | ofilter->out_tmp->next = NULL; | |
345 | } | ||
346 | |||
347 | 97 | fail: | |
348 | 97 | avfilter_inout_free(&inputs); | |
349 | 97 | avfilter_graph_free(&graph); | |
350 | 97 | return ret; | |
351 | } | ||
352 | |||
353 | 12089 | static int insert_trim(int64_t start_time, int64_t duration, | |
354 | AVFilterContext **last_filter, int *pad_idx, | ||
355 | const char *filter_name) | ||
356 | { | ||
357 | 12089 | AVFilterGraph *graph = (*last_filter)->graph; | |
358 | AVFilterContext *ctx; | ||
359 | const AVFilter *trim; | ||
360 | 12089 | enum AVMediaType type = avfilter_pad_get_type((*last_filter)->output_pads, *pad_idx); | |
361 |
2/2✓ Branch 0 taken 9787 times.
✓ Branch 1 taken 2302 times.
|
12089 | const char *name = (type == AVMEDIA_TYPE_VIDEO) ? "trim" : "atrim"; |
362 | 12089 | int ret = 0; | |
363 | |||
364 |
4/4✓ Branch 0 taken 11928 times.
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 11911 times.
✓ Branch 3 taken 17 times.
|
12089 | if (duration == INT64_MAX && start_time == AV_NOPTS_VALUE) |
365 | 11911 | return 0; | |
366 | |||
367 | 178 | trim = avfilter_get_by_name(name); | |
368 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (!trim) { |
369 | ✗ | av_log(NULL, AV_LOG_ERROR, "%s filter not present, cannot limit " | |
370 | "recording time.\n", name); | ||
371 | ✗ | return AVERROR_FILTER_NOT_FOUND; | |
372 | } | ||
373 | |||
374 | 178 | ctx = avfilter_graph_alloc_filter(graph, trim, filter_name); | |
375 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (!ctx) |
376 | ✗ | return AVERROR(ENOMEM); | |
377 | |||
378 |
2/2✓ Branch 0 taken 161 times.
✓ Branch 1 taken 17 times.
|
178 | if (duration != INT64_MAX) { |
379 | 161 | ret = av_opt_set_int(ctx, "durationi", duration, | |
380 | AV_OPT_SEARCH_CHILDREN); | ||
381 | } | ||
382 |
3/4✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 161 times.
|
178 | if (ret >= 0 && start_time != AV_NOPTS_VALUE) { |
383 | 17 | ret = av_opt_set_int(ctx, "starti", start_time, | |
384 | AV_OPT_SEARCH_CHILDREN); | ||
385 | } | ||
386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (ret < 0) { |
387 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error configuring the %s filter", name); | |
388 | ✗ | return ret; | |
389 | } | ||
390 | |||
391 | 178 | ret = avfilter_init_str(ctx, NULL); | |
392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (ret < 0) |
393 | ✗ | return ret; | |
394 | |||
395 | 178 | ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); | |
396 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 178 times.
|
178 | if (ret < 0) |
397 | ✗ | return ret; | |
398 | |||
399 | 178 | *last_filter = ctx; | |
400 | 178 | *pad_idx = 0; | |
401 | 178 | return 0; | |
402 | } | ||
403 | |||
404 | 1 | static int insert_filter(AVFilterContext **last_filter, int *pad_idx, | |
405 | const char *filter_name, const char *args) | ||
406 | { | ||
407 | 1 | AVFilterGraph *graph = (*last_filter)->graph; | |
408 | AVFilterContext *ctx; | ||
409 | int ret; | ||
410 | |||
411 | 1 | ret = avfilter_graph_create_filter(&ctx, | |
412 | avfilter_get_by_name(filter_name), | ||
413 | filter_name, args, NULL, graph); | ||
414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
415 | ✗ | return ret; | |
416 | |||
417 | 1 | ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); | |
418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
419 | ✗ | return ret; | |
420 | |||
421 | 1 | *last_filter = ctx; | |
422 | 1 | *pad_idx = 0; | |
423 | 1 | return 0; | |
424 | } | ||
425 | |||
426 | 4908 | static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |
427 | { | ||
428 | 4908 | OutputStream *ost = ofilter->ost; | |
429 | 4908 | OutputFile *of = output_files[ost->file_index]; | |
430 | 4908 | AVFilterContext *last_filter = out->filter_ctx; | |
431 | AVBPrint bprint; | ||
432 | 4908 | int pad_idx = out->pad_idx; | |
433 | int ret; | ||
434 | const char *pix_fmts; | ||
435 | char name[255]; | ||
436 | |||
437 | 4908 | snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); | |
438 | 4908 | ret = avfilter_graph_create_filter(&ofilter->filter, | |
439 | avfilter_get_by_name("buffersink"), | ||
440 | name, NULL, NULL, fg->graph); | ||
441 | |||
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4908 times.
|
4908 | if (ret < 0) |
443 | ✗ | return ret; | |
444 | |||
445 |
4/6✓ Branch 0 taken 4639 times.
✓ Branch 1 taken 269 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4639 times.
✓ Branch 4 taken 269 times.
✗ Branch 5 not taken.
|
4908 | if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) { |
446 | char args[255]; | ||
447 | AVFilterContext *filter; | ||
448 | 269 | const AVDictionaryEntry *e = NULL; | |
449 | |||
450 | 269 | snprintf(args, sizeof(args), "%d:%d", | |
451 | ofilter->width, ofilter->height); | ||
452 | |||
453 |
2/2✓ Branch 1 taken 256 times.
✓ Branch 2 taken 269 times.
|
525 | while ((e = av_dict_get(ost->sws_dict, "", e, |
454 | AV_DICT_IGNORE_SUFFIX))) { | ||
455 | 256 | av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); | |
456 | } | ||
457 | |||
458 | 269 | snprintf(name, sizeof(name), "scaler_out_%d_%d", | |
459 | ost->file_index, ost->index); | ||
460 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 269 times.
|
269 | if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), |
461 | name, args, NULL, fg->graph)) < 0) | ||
462 | ✗ | return ret; | |
463 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 269 times.
|
269 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) |
464 | ✗ | return ret; | |
465 | |||
466 | 269 | last_filter = filter; | |
467 | 269 | pad_idx = 0; | |
468 | } | ||
469 | |||
470 | 4908 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
471 |
2/2✓ Branch 1 taken 3846 times.
✓ Branch 2 taken 1062 times.
|
4908 | if ((pix_fmts = choose_pix_fmts(ofilter, &bprint))) { |
472 | AVFilterContext *filter; | ||
473 | |||
474 | 3846 | ret = avfilter_graph_create_filter(&filter, | |
475 | avfilter_get_by_name("format"), | ||
476 | "format", pix_fmts, NULL, fg->graph); | ||
477 | 3846 | av_bprint_finalize(&bprint, NULL); | |
478 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3846 times.
|
3846 | if (ret < 0) |
479 | ✗ | return ret; | |
480 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3846 times.
|
3846 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) |
481 | ✗ | return ret; | |
482 | |||
483 | 3846 | last_filter = filter; | |
484 | 3846 | pad_idx = 0; | |
485 | } | ||
486 | |||
487 | if (ost->frame_rate.num && 0) { | ||
488 | AVFilterContext *fps; | ||
489 | char args[255]; | ||
490 | |||
491 | snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, | ||
492 | ost->frame_rate.den); | ||
493 | snprintf(name, sizeof(name), "fps_out_%d_%d", | ||
494 | ost->file_index, ost->index); | ||
495 | ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), | ||
496 | name, args, NULL, fg->graph); | ||
497 | if (ret < 0) | ||
498 | return ret; | ||
499 | |||
500 | ret = avfilter_link(last_filter, pad_idx, fps, 0); | ||
501 | if (ret < 0) | ||
502 | return ret; | ||
503 | last_filter = fps; | ||
504 | pad_idx = 0; | ||
505 | } | ||
506 | |||
507 | 4908 | snprintf(name, sizeof(name), "trim_out_%d_%d", | |
508 | ost->file_index, ost->index); | ||
509 | 4908 | ret = insert_trim(of->start_time, of->recording_time, | |
510 | &last_filter, &pad_idx, name); | ||
511 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4908 times.
|
4908 | if (ret < 0) |
512 | ✗ | return ret; | |
513 | |||
514 | |||
515 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4908 times.
|
4908 | if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) |
516 | ✗ | return ret; | |
517 | |||
518 | 4908 | return 0; | |
519 | } | ||
520 | |||
521 | 1148 | static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |
522 | { | ||
523 | 1148 | OutputStream *ost = ofilter->ost; | |
524 | 1148 | OutputFile *of = output_files[ost->file_index]; | |
525 | 1148 | AVCodecContext *codec = ost->enc_ctx; | |
526 | 1148 | AVFilterContext *last_filter = out->filter_ctx; | |
527 | 1148 | int pad_idx = out->pad_idx; | |
528 | AVBPrint args; | ||
529 | char name[255]; | ||
530 | int ret; | ||
531 | |||
532 | 1148 | snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); | |
533 | 1148 | ret = avfilter_graph_create_filter(&ofilter->filter, | |
534 | avfilter_get_by_name("abuffersink"), | ||
535 | name, NULL, NULL, fg->graph); | ||
536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1148 times.
|
1148 | if (ret < 0) |
537 | ✗ | return ret; | |
538 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1148 times.
|
1148 | if ((ret = av_opt_set_int(ofilter->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0) |
539 | ✗ | return ret; | |
540 | |||
541 | #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ | ||
542 | AVFilterContext *filt_ctx; \ | ||
543 | \ | ||
544 | av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | ||
545 | "similarly to -af " filter_name "=%s.\n", arg); \ | ||
546 | \ | ||
547 | ret = avfilter_graph_create_filter(&filt_ctx, \ | ||
548 | avfilter_get_by_name(filter_name), \ | ||
549 | filter_name, arg, NULL, fg->graph); \ | ||
550 | if (ret < 0) \ | ||
551 | goto fail; \ | ||
552 | \ | ||
553 | ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \ | ||
554 | if (ret < 0) \ | ||
555 | goto fail; \ | ||
556 | \ | ||
557 | last_filter = filt_ctx; \ | ||
558 | pad_idx = 0; \ | ||
559 | } while (0) | ||
560 | 1148 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_UNLIMITED); | |
561 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1142 times.
|
1148 | if (ost->audio_channels_mapped) { |
562 | 6 | AVChannelLayout mapped_layout = { 0 }; | |
563 | int i; | ||
564 | 6 | av_channel_layout_default(&mapped_layout, ost->audio_channels_mapped); | |
565 | 6 | av_channel_layout_describe_bprint(&mapped_layout, &args); | |
566 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
|
16 | for (i = 0; i < ost->audio_channels_mapped; i++) |
567 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
|
10 | if (ost->audio_channels_map[i] != -1) |
568 | 9 | av_bprintf(&args, "|c%d=c%d", i, ost->audio_channels_map[i]); | |
569 | |||
570 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
|
6 | AUTO_INSERT_FILTER("-map_channel", "pan", args.str); |
571 | 6 | av_bprint_clear(&args); | |
572 | } | ||
573 | |||
574 |
2/2✓ Branch 0 taken 1146 times.
✓ Branch 1 taken 2 times.
|
1148 | if (codec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) |
575 | 1146 | av_channel_layout_default(&codec->ch_layout, codec->ch_layout.nb_channels); | |
576 | |||
577 | 1148 | choose_sample_fmts(ofilter, &args); | |
578 | 1148 | choose_sample_rates(ofilter, &args); | |
579 | 1148 | choose_channel_layouts(ofilter, &args); | |
580 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1148 times.
|
1148 | if (!av_bprint_is_complete(&args)) { |
581 | ✗ | ret = AVERROR(ENOMEM); | |
582 | ✗ | goto fail; | |
583 | } | ||
584 |
1/2✓ Branch 0 taken 1148 times.
✗ Branch 1 not taken.
|
1148 | if (args.len) { |
585 | AVFilterContext *format; | ||
586 | |||
587 | 1148 | snprintf(name, sizeof(name), "format_out_%d_%d", | |
588 | ost->file_index, ost->index); | ||
589 | 1148 | ret = avfilter_graph_create_filter(&format, | |
590 | avfilter_get_by_name("aformat"), | ||
591 | 1148 | name, args.str, NULL, fg->graph); | |
592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1148 times.
|
1148 | if (ret < 0) |
593 | ✗ | goto fail; | |
594 | |||
595 | 1148 | ret = avfilter_link(last_filter, pad_idx, format, 0); | |
596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1148 times.
|
1148 | if (ret < 0) |
597 | ✗ | goto fail; | |
598 | |||
599 | 1148 | last_filter = format; | |
600 | 1148 | pad_idx = 0; | |
601 | } | ||
602 | |||
603 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1148 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1148 | if (ost->apad && of->shortest) { |
604 | int i; | ||
605 | |||
606 | ✗ | for (i=0; i<of->ctx->nb_streams; i++) | |
607 | ✗ | if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) | |
608 | ✗ | break; | |
609 | |||
610 | ✗ | if (i<of->ctx->nb_streams) { | |
611 | ✗ | AUTO_INSERT_FILTER("-apad", "apad", ost->apad); | |
612 | } | ||
613 | } | ||
614 | |||
615 | 1148 | snprintf(name, sizeof(name), "trim for output stream %d:%d", | |
616 | ost->file_index, ost->index); | ||
617 | 1148 | ret = insert_trim(of->start_time, of->recording_time, | |
618 | &last_filter, &pad_idx, name); | ||
619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1148 times.
|
1148 | if (ret < 0) |
620 | ✗ | goto fail; | |
621 | |||
622 |
1/2✓ Branch 1 taken 1148 times.
✗ Branch 2 not taken.
|
1148 | if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) |
623 | ✗ | goto fail; | |
624 | 1148 | fail: | |
625 | 1148 | av_bprint_finalize(&args, NULL); | |
626 | |||
627 | 1148 | return ret; | |
628 | } | ||
629 | |||
630 | 6056 | static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, | |
631 | AVFilterInOut *out) | ||
632 | { | ||
633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6056 times.
|
6056 | if (!ofilter->ost) { |
634 | ✗ | av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name); | |
635 | ✗ | exit_program(1); | |
636 | } | ||
637 | |||
638 |
2/3✓ Branch 1 taken 4908 times.
✓ Branch 2 taken 1148 times.
✗ Branch 3 not taken.
|
6056 | switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { |
639 | 4908 | case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out); | |
640 | 1148 | case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out); | |
641 | ✗ | default: av_assert0(0); return 0; | |
642 | } | ||
643 | } | ||
644 | |||
645 | 6248 | void check_filter_outputs(void) | |
646 | { | ||
647 | int i; | ||
648 |
2/2✓ Branch 0 taken 6007 times.
✓ Branch 1 taken 6248 times.
|
12255 | for (i = 0; i < nb_filtergraphs; i++) { |
649 | int n; | ||
650 |
2/2✓ Branch 0 taken 6017 times.
✓ Branch 1 taken 6007 times.
|
12024 | for (n = 0; n < filtergraphs[i]->nb_outputs; n++) { |
651 | 6017 | OutputFilter *output = filtergraphs[i]->outputs[n]; | |
652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6017 times.
|
6017 | if (!output->ost) { |
653 | ✗ | av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", output->name); | |
654 | ✗ | exit_program(1); | |
655 | } | ||
656 | } | ||
657 | } | ||
658 | 6248 | } | |
659 | |||
660 | 4 | static int sub2video_prepare(InputStream *ist, InputFilter *ifilter) | |
661 | { | ||
662 | 4 | AVFormatContext *avf = input_files[ist->file_index]->ctx; | |
663 | int i, w, h; | ||
664 | |||
665 | /* Compute the size of the canvas for the subtitles stream. | ||
666 | If the subtitles codecpar has set a size, use it. Otherwise use the | ||
667 | maximum dimensions of the video streams in the same file. */ | ||
668 | 4 | w = ifilter->width; | |
669 | 4 | h = ifilter->height; | |
670 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4 | if (!(w && h)) { |
671 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
|
12 | for (i = 0; i < avf->nb_streams; i++) { |
672 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
673 | 1 | w = FFMAX(w, avf->streams[i]->codecpar->width); | |
674 | 1 | h = FFMAX(h, avf->streams[i]->codecpar->height); | |
675 | } | ||
676 | } | ||
677 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
4 | if (!(w && h)) { |
678 | 3 | w = FFMAX(w, 720); | |
679 | 3 | h = FFMAX(h, 576); | |
680 | } | ||
681 | 4 | av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); | |
682 | } | ||
683 | 4 | ist->sub2video.w = ifilter->width = w; | |
684 | 4 | ist->sub2video.h = ifilter->height = h; | |
685 | |||
686 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ifilter->width = ist->dec_ctx->width ? ist->dec_ctx->width : ist->sub2video.w; |
687 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | ifilter->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h; |
688 | |||
689 | /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the | ||
690 | palettes for all rectangles are identical or compatible */ | ||
691 | 4 | ifilter->format = AV_PIX_FMT_RGB32; | |
692 | |||
693 | 4 | ist->sub2video.frame = av_frame_alloc(); | |
694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!ist->sub2video.frame) |
695 | ✗ | return AVERROR(ENOMEM); | |
696 | 4 | ist->sub2video.last_pts = INT64_MIN; | |
697 | 4 | ist->sub2video.end_pts = INT64_MIN; | |
698 | |||
699 | /* sub2video structure has been (re-)initialized. | ||
700 | Mark it as such so that the system will be | ||
701 | initialized with the first received heartbeat. */ | ||
702 | 4 | ist->sub2video.initialize = 1; | |
703 | |||
704 | 4 | return 0; | |
705 | } | ||
706 | |||
707 | 4879 | static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, | |
708 | AVFilterInOut *in) | ||
709 | { | ||
710 | AVFilterContext *last_filter; | ||
711 | 4879 | const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); | |
712 | const AVPixFmtDescriptor *desc; | ||
713 | 4879 | InputStream *ist = ifilter->ist; | |
714 | 4879 | InputFile *f = input_files[ist->file_index]; | |
715 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4855 times.
|
4879 | AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : |
716 | 4855 | ist->st->time_base; | |
717 | 4879 | AVRational fr = ist->framerate; | |
718 | AVRational sar; | ||
719 | AVBPrint args; | ||
720 | char name[255]; | ||
721 | 4879 | int ret, pad_idx = 0; | |
722 | 4879 | int64_t tsoffset = 0; | |
723 | 4879 | AVBufferSrcParameters *par = av_buffersrc_parameters_alloc(); | |
724 | |||
725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (!par) |
726 | ✗ | return AVERROR(ENOMEM); | |
727 | 4879 | memset(par, 0, sizeof(*par)); | |
728 | 4879 | par->format = AV_PIX_FMT_NONE; | |
729 | |||
730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { |
731 | ✗ | av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); | |
732 | ✗ | ret = AVERROR(EINVAL); | |
733 | ✗ | goto fail; | |
734 | } | ||
735 | |||
736 |
2/2✓ Branch 0 taken 4855 times.
✓ Branch 1 taken 24 times.
|
4879 | if (!fr.num) |
737 | 4855 | fr = av_guess_frame_rate(input_files[ist->file_index]->ctx, ist->st, NULL); | |
738 | |||
739 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4875 times.
|
4879 | if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { |
740 | 4 | ret = sub2video_prepare(ist, ifilter); | |
741 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ret < 0) |
742 | ✗ | goto fail; | |
743 | } | ||
744 | |||
745 | 4879 | sar = ifilter->sample_aspect_ratio; | |
746 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4875 times.
|
4879 | if(!sar.den) |
747 | 4 | sar = (AVRational){0,1}; | |
748 | 4879 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
749 | 4879 | av_bprintf(&args, | |
750 | "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" | ||
751 | "pixel_aspect=%d/%d", | ||
752 | ifilter->width, ifilter->height, ifilter->format, | ||
753 | tb.num, tb.den, sar.num, sar.den); | ||
754 |
3/4✓ Branch 0 taken 4875 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4875 times.
✗ Branch 3 not taken.
|
4879 | if (fr.num && fr.den) |
755 | 4875 | av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); | |
756 | 4879 | snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |
757 | 4879 | ist->file_index, ist->st->index); | |
758 | |||
759 | |||
760 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, |
761 | 4879 | args.str, NULL, fg->graph)) < 0) | |
762 | ✗ | goto fail; | |
763 | 4879 | par->hw_frames_ctx = ifilter->hw_frames_ctx; | |
764 | 4879 | ret = av_buffersrc_parameters_set(ifilter->filter, par); | |
765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (ret < 0) |
766 | ✗ | goto fail; | |
767 | 4879 | av_freep(&par); | |
768 | 4879 | last_filter = ifilter->filter; | |
769 | |||
770 | 4879 | desc = av_pix_fmt_desc_get(ifilter->format); | |
771 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | av_assert0(desc); |
772 | |||
773 | // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph | ||
774 |
2/4✓ Branch 0 taken 4879 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4879 times.
✗ Branch 3 not taken.
|
4879 | if (ist->autorotate && !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { |
775 | 4879 | int32_t *displaymatrix = ifilter->displaymatrix; | |
776 | double theta; | ||
777 | |||
778 |
1/2✓ Branch 0 taken 4879 times.
✗ Branch 1 not taken.
|
4879 | if (!displaymatrix) |
779 | 4879 | displaymatrix = (int32_t *)av_stream_get_side_data(ist->st, AV_PKT_DATA_DISPLAYMATRIX, NULL); | |
780 | 4879 | theta = get_rotation(displaymatrix); | |
781 | |||
782 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4878 times.
|
4879 | if (fabs(theta - 90) < 1.0) { |
783 | 1 | ret = insert_filter(&last_filter, &pad_idx, "transpose", | |
784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | displaymatrix[3] > 0 ? "cclock_flip" : "clock"); |
785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4878 times.
|
4878 | } else if (fabs(theta - 180) < 1.0) { |
786 | ✗ | if (displaymatrix[0] < 0) { | |
787 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); | |
788 | ✗ | if (ret < 0) | |
789 | ✗ | return ret; | |
790 | } | ||
791 | ✗ | if (displaymatrix[4] < 0) { | |
792 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); | |
793 | } | ||
794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4878 times.
|
4878 | } else if (fabs(theta - 270) < 1.0) { |
795 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "transpose", | |
796 | ✗ | displaymatrix[3] < 0 ? "clock_flip" : "cclock"); | |
797 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4878 times.
|
4878 | } else if (fabs(theta) > 1.0) { |
798 | char rotate_buf[64]; | ||
799 | ✗ | snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta); | |
800 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf); | |
801 |
1/2✓ Branch 0 taken 4878 times.
✗ Branch 1 not taken.
|
4878 | } else if (fabs(theta) < 1.0) { |
802 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4878 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4878 | if (displaymatrix && displaymatrix[4] < 0) { |
803 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); | |
804 | } | ||
805 | } | ||
806 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (ret < 0) |
807 | ✗ | return ret; | |
808 | } | ||
809 | |||
810 | 4879 | snprintf(name, sizeof(name), "trim_in_%d_%d", | |
811 | 4879 | ist->file_index, ist->st->index); | |
812 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4877 times.
|
4879 | if (copy_ts) { |
813 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time; |
814 |
3/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE) |
815 | 1 | tsoffset += f->ctx->start_time; | |
816 | } | ||
817 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4878 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
4879 | ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ? |
818 | AV_NOPTS_VALUE : tsoffset, f->recording_time, | ||
819 | &last_filter, &pad_idx, name); | ||
820 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4879 times.
|
4879 | if (ret < 0) |
821 | ✗ | return ret; | |
822 | |||
823 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4879 times.
|
4879 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) |
824 | ✗ | return ret; | |
825 | 4879 | return 0; | |
826 | ✗ | fail: | |
827 | ✗ | av_freep(&par); | |
828 | |||
829 | ✗ | return ret; | |
830 | } | ||
831 | |||
832 | 1154 | static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, | |
833 | AVFilterInOut *in) | ||
834 | { | ||
835 | AVFilterContext *last_filter; | ||
836 | 1154 | const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); | |
837 | 1154 | InputStream *ist = ifilter->ist; | |
838 | 1154 | InputFile *f = input_files[ist->file_index]; | |
839 | AVBPrint args; | ||
840 | char name[255]; | ||
841 | 1154 | int ret, pad_idx = 0; | |
842 | 1154 | int64_t tsoffset = 0; | |
843 | |||
844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) { |
845 | ✗ | av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n"); | |
846 | ✗ | return AVERROR(EINVAL); | |
847 | } | ||
848 | |||
849 | 1154 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
850 | 1154 | av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", | |
851 | 1, ifilter->sample_rate, | ||
852 | ifilter->sample_rate, | ||
853 | 1154 | av_get_sample_fmt_name(ifilter->format)); | |
854 |
1/2✓ Branch 1 taken 1154 times.
✗ Branch 2 not taken.
|
1154 | if (av_channel_layout_check(&ifilter->ch_layout) && |
855 |
2/2✓ Branch 0 taken 1145 times.
✓ Branch 1 taken 9 times.
|
1154 | ifilter->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { |
856 | 1145 | av_bprintf(&args, ":channel_layout="); | |
857 | 1145 | av_channel_layout_describe_bprint(&ifilter->ch_layout, &args); | |
858 | } else | ||
859 | 9 | av_bprintf(&args, ":channels=%d", ifilter->ch_layout.nb_channels); | |
860 | 1154 | snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, | |
861 | 1154 | ist->file_index, ist->st->index); | |
862 | |||
863 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, |
864 | 1154 | name, args.str, NULL, | |
865 | fg->graph)) < 0) | ||
866 | ✗ | return ret; | |
867 | 1154 | last_filter = ifilter->filter; | |
868 | |||
869 | #define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do { \ | ||
870 | AVFilterContext *filt_ctx; \ | ||
871 | \ | ||
872 | av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | ||
873 | "similarly to -af " filter_name "=%s.\n", arg); \ | ||
874 | \ | ||
875 | snprintf(name, sizeof(name), "graph_%d_%s_in_%d_%d", \ | ||
876 | fg->index, filter_name, ist->file_index, ist->st->index); \ | ||
877 | ret = avfilter_graph_create_filter(&filt_ctx, \ | ||
878 | avfilter_get_by_name(filter_name), \ | ||
879 | name, arg, NULL, fg->graph); \ | ||
880 | if (ret < 0) \ | ||
881 | return ret; \ | ||
882 | \ | ||
883 | ret = avfilter_link(last_filter, 0, filt_ctx, 0); \ | ||
884 | if (ret < 0) \ | ||
885 | return ret; \ | ||
886 | \ | ||
887 | last_filter = filt_ctx; \ | ||
888 | } while (0) | ||
889 | |||
890 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if (audio_sync_method > 0) { |
891 | ✗ | char args[256] = {0}; | |
892 | |||
893 | ✗ | av_strlcatf(args, sizeof(args), "async=%d", audio_sync_method); | |
894 | ✗ | if (audio_drift_threshold != 0.1) | |
895 | ✗ | av_strlcatf(args, sizeof(args), ":min_hard_comp=%f", audio_drift_threshold); | |
896 | ✗ | if (!fg->reconfiguration) | |
897 | ✗ | av_strlcatf(args, sizeof(args), ":first_pts=0"); | |
898 | ✗ | AUTO_INSERT_FILTER_INPUT("-async", "aresample", args); | |
899 | } | ||
900 | |||
901 | // if (ost->audio_channels_mapped) { | ||
902 | // int i; | ||
903 | // AVBPrint pan_buf; | ||
904 | // av_bprint_init(&pan_buf, 256, 8192); | ||
905 | // av_bprintf(&pan_buf, "0x%"PRIx64, | ||
906 | // av_get_default_channel_layout(ost->audio_channels_mapped)); | ||
907 | // for (i = 0; i < ost->audio_channels_mapped; i++) | ||
908 | // if (ost->audio_channels_map[i] != -1) | ||
909 | // av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); | ||
910 | // AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str); | ||
911 | // av_bprint_finalize(&pan_buf, NULL); | ||
912 | // } | ||
913 | |||
914 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if (audio_volume != 256) { |
915 | char args[256]; | ||
916 | |||
917 | ✗ | av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Use the volume " | |
918 | "audio filter instead.\n"); | ||
919 | |||
920 | ✗ | snprintf(args, sizeof(args), "%f", audio_volume / 256.); | |
921 | ✗ | AUTO_INSERT_FILTER_INPUT("-vol", "volume", args); | |
922 | } | ||
923 | |||
924 | 1154 | snprintf(name, sizeof(name), "trim for input stream %d:%d", | |
925 | 1154 | ist->file_index, ist->st->index); | |
926 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if (copy_ts) { |
927 | ✗ | tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time; | |
928 | ✗ | if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE) | |
929 | ✗ | tsoffset += f->ctx->start_time; | |
930 | } | ||
931 |
3/4✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1139 times.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
1154 | ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ? |
932 | AV_NOPTS_VALUE : tsoffset, f->recording_time, | ||
933 | &last_filter, &pad_idx, name); | ||
934 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1154 times.
|
1154 | if (ret < 0) |
935 | ✗ | return ret; | |
936 | |||
937 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1154 times.
|
1154 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) |
938 | ✗ | return ret; | |
939 | |||
940 | 1154 | return 0; | |
941 | } | ||
942 | |||
943 | 6033 | static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, | |
944 | AVFilterInOut *in) | ||
945 | { | ||
946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6033 times.
|
6033 | if (!ifilter->ist->dec) { |
947 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
948 | "No decoder for stream #%d:%d, filtering impossible\n", | ||
949 | ✗ | ifilter->ist->file_index, ifilter->ist->st->index); | |
950 | ✗ | return AVERROR_DECODER_NOT_FOUND; | |
951 | } | ||
952 |
2/3✓ Branch 1 taken 4879 times.
✓ Branch 2 taken 1154 times.
✗ Branch 3 not taken.
|
6033 | switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { |
953 | 4879 | case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); | |
954 | 1154 | case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); | |
955 | ✗ | default: av_assert0(0); return 0; | |
956 | } | ||
957 | } | ||
958 | |||
959 | 6046 | static void cleanup_filtergraph(FilterGraph *fg) | |
960 | { | ||
961 | int i; | ||
962 |
2/2✓ Branch 0 taken 6056 times.
✓ Branch 1 taken 6046 times.
|
12102 | for (i = 0; i < fg->nb_outputs; i++) |
963 | 6056 | fg->outputs[i]->filter = (AVFilterContext *)NULL; | |
964 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 6046 times.
|
12079 | for (i = 0; i < fg->nb_inputs; i++) |
965 | 6033 | fg->inputs[i]->filter = (AVFilterContext *)NULL; | |
966 | 6046 | avfilter_graph_free(&fg->graph); | |
967 | 6046 | } | |
968 | |||
969 | 7190 | static int filter_is_buffersrc(const AVFilterContext *f) | |
970 | { | ||
971 |
2/2✓ Branch 0 taken 2851 times.
✓ Branch 1 taken 4339 times.
|
10041 | return f->nb_inputs == 0 && |
972 |
2/2✓ Branch 0 taken 637 times.
✓ Branch 1 taken 2214 times.
|
2851 | (!strcmp(f->filter->name, "buffer") || |
973 |
2/2✓ Branch 0 taken 586 times.
✓ Branch 1 taken 51 times.
|
637 | !strcmp(f->filter->name, "abuffer")); |
974 | } | ||
975 | |||
976 | 6046 | static int graph_is_meta(AVFilterGraph *graph) | |
977 | { | ||
978 |
2/2✓ Branch 0 taken 15054 times.
✓ Branch 1 taken 1656 times.
|
16710 | for (unsigned i = 0; i < graph->nb_filters; i++) { |
979 | 15054 | const AVFilterContext *f = graph->filters[i]; | |
980 | |||
981 | /* in addition to filters flagged as meta, also | ||
982 | * disregard sinks and buffersources (but not other sources, | ||
983 | * since they introduce data we are not aware of) | ||
984 | */ | ||
985 |
4/4✓ Branch 0 taken 9985 times.
✓ Branch 1 taken 5069 times.
✓ Branch 2 taken 4390 times.
✓ Branch 3 taken 2800 times.
|
22244 | if (!((f->filter->flags & AVFILTER_FLAG_METADATA_ONLY) || |
986 |
2/2✓ Branch 0 taken 7190 times.
✓ Branch 1 taken 2795 times.
|
9985 | f->nb_outputs == 0 || |
987 | 7190 | filter_is_buffersrc(f))) | |
988 | 4390 | return 0; | |
989 | } | ||
990 | 1656 | return 1; | |
991 | } | ||
992 | |||
993 | 6046 | int configure_filtergraph(FilterGraph *fg) | |
994 | { | ||
995 | AVFilterInOut *inputs, *outputs, *cur; | ||
996 | 6046 | int ret, i, simple = filtergraph_is_simple(fg); | |
997 |
2/2✓ Branch 0 taken 5949 times.
✓ Branch 1 taken 97 times.
|
6046 | const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : |
998 | fg->graph_desc; | ||
999 | |||
1000 | 6046 | cleanup_filtergraph(fg); | |
1001 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6046 times.
|
6046 | if (!(fg->graph = avfilter_graph_alloc())) |
1002 | ✗ | return AVERROR(ENOMEM); | |
1003 | |||
1004 |
2/2✓ Branch 0 taken 5949 times.
✓ Branch 1 taken 97 times.
|
6046 | if (simple) { |
1005 | 5949 | OutputStream *ost = fg->outputs[0]->ost; | |
1006 | char args[512]; | ||
1007 | 5949 | const AVDictionaryEntry *e = NULL; | |
1008 | |||
1009 |
2/2✓ Branch 0 taken 343 times.
✓ Branch 1 taken 5606 times.
|
5949 | if (filter_nbthreads) { |
1010 | 343 | ret = av_opt_set(fg->graph, "threads", filter_nbthreads, 0); | |
1011 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 343 times.
|
343 | if (ret < 0) |
1012 | ✗ | goto fail; | |
1013 | } else { | ||
1014 | 5606 | e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); | |
1015 |
2/2✓ Branch 0 taken 3310 times.
✓ Branch 1 taken 2296 times.
|
5606 | if (e) |
1016 | 3310 | av_opt_set(fg->graph, "threads", e->value, 0); | |
1017 | } | ||
1018 | |||
1019 | 5949 | args[0] = 0; | |
1020 | 5949 | e = NULL; | |
1021 |
2/2✓ Branch 1 taken 3633 times.
✓ Branch 2 taken 5949 times.
|
9582 | while ((e = av_dict_get(ost->sws_dict, "", e, |
1022 | AV_DICT_IGNORE_SUFFIX))) { | ||
1023 | 3633 | av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); | |
1024 | } | ||
1025 |
2/2✓ Branch 0 taken 3633 times.
✓ Branch 1 taken 2316 times.
|
5949 | if (strlen(args)) { |
1026 | 3633 | args[strlen(args)-1] = 0; | |
1027 | 3633 | fg->graph->scale_sws_opts = av_strdup(args); | |
1028 | } | ||
1029 | |||
1030 | 5949 | args[0] = 0; | |
1031 | 5949 | e = NULL; | |
1032 |
2/2✓ Branch 1 taken 54 times.
✓ Branch 2 taken 5949 times.
|
6003 | while ((e = av_dict_get(ost->swr_opts, "", e, |
1033 | AV_DICT_IGNORE_SUFFIX))) { | ||
1034 | 54 | av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); | |
1035 | } | ||
1036 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 5895 times.
|
5949 | if (strlen(args)) |
1037 | 54 | args[strlen(args)-1] = 0; | |
1038 | 5949 | av_opt_set(fg->graph, "aresample_swr_opts", args, 0); | |
1039 | } else { | ||
1040 | 97 | fg->graph->nb_threads = filter_complex_nbthreads; | |
1041 | } | ||
1042 | |||
1043 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6046 times.
|
6046 | if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) |
1044 | ✗ | goto fail; | |
1045 | |||
1046 | 6046 | ret = hw_device_setup_for_filter(fg); | |
1047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6046 times.
|
6046 | if (ret < 0) |
1048 | ✗ | goto fail; | |
1049 | |||
1050 |
6/10✓ Branch 0 taken 5949 times.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 5949 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5949 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5949 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5949 times.
|
6046 | if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { |
1051 | const char *num_inputs; | ||
1052 | const char *num_outputs; | ||
1053 | ✗ | if (!outputs) { | |
1054 | ✗ | num_outputs = "0"; | |
1055 | ✗ | } else if (outputs->next) { | |
1056 | ✗ | num_outputs = ">1"; | |
1057 | } else { | ||
1058 | ✗ | num_outputs = "1"; | |
1059 | } | ||
1060 | ✗ | if (!inputs) { | |
1061 | ✗ | num_inputs = "0"; | |
1062 | ✗ | } else if (inputs->next) { | |
1063 | ✗ | num_inputs = ">1"; | |
1064 | } else { | ||
1065 | ✗ | num_inputs = "1"; | |
1066 | } | ||
1067 | ✗ | av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " | |
1068 | "to have exactly 1 input and 1 output." | ||
1069 | " However, it had %s input(s) and %s output(s)." | ||
1070 | " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", | ||
1071 | graph_desc, num_inputs, num_outputs); | ||
1072 | ✗ | ret = AVERROR(EINVAL); | |
1073 | ✗ | goto fail; | |
1074 | } | ||
1075 | |||
1076 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 6046 times.
|
12079 | for (cur = inputs, i = 0; cur; cur = cur->next, i++) |
1077 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6033 times.
|
6033 | if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { |
1078 | ✗ | avfilter_inout_free(&inputs); | |
1079 | ✗ | avfilter_inout_free(&outputs); | |
1080 | ✗ | goto fail; | |
1081 | } | ||
1082 | 6046 | avfilter_inout_free(&inputs); | |
1083 | |||
1084 |
2/2✓ Branch 0 taken 6056 times.
✓ Branch 1 taken 6046 times.
|
12102 | for (cur = outputs, i = 0; cur; cur = cur->next, i++) |
1085 | 6056 | configure_output_filter(fg, fg->outputs[i], cur); | |
1086 | 6046 | avfilter_inout_free(&outputs); | |
1087 | |||
1088 |
2/2✓ Branch 0 taken 4366 times.
✓ Branch 1 taken 1680 times.
|
6046 | if (!auto_conversion_filters) |
1089 | 4366 | avfilter_graph_set_auto_convert(fg->graph, AVFILTER_AUTO_CONVERT_NONE); | |
1090 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6046 times.
|
6046 | if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) |
1091 | ✗ | goto fail; | |
1092 | |||
1093 | 6046 | fg->is_meta = graph_is_meta(fg->graph); | |
1094 | |||
1095 | /* limit the lists of allowed formats to the ones selected, to | ||
1096 | * make sure they stay the same if the filtergraph is reconfigured later */ | ||
1097 |
2/2✓ Branch 0 taken 6056 times.
✓ Branch 1 taken 6046 times.
|
12102 | for (i = 0; i < fg->nb_outputs; i++) { |
1098 | 6056 | OutputFilter *ofilter = fg->outputs[i]; | |
1099 | 6056 | AVFilterContext *sink = ofilter->filter; | |
1100 | |||
1101 | 6056 | ofilter->format = av_buffersink_get_format(sink); | |
1102 | |||
1103 | 6056 | ofilter->width = av_buffersink_get_w(sink); | |
1104 | 6056 | ofilter->height = av_buffersink_get_h(sink); | |
1105 | |||
1106 | 6056 | ofilter->sample_rate = av_buffersink_get_sample_rate(sink); | |
1107 | 6056 | av_channel_layout_uninit(&ofilter->ch_layout); | |
1108 | 6056 | ret = av_buffersink_get_ch_layout(sink, &ofilter->ch_layout); | |
1109 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6056 times.
|
6056 | if (ret < 0) |
1110 | ✗ | goto fail; | |
1111 | } | ||
1112 | |||
1113 | 6046 | fg->reconfiguration = 1; | |
1114 | |||
1115 |
2/2✓ Branch 0 taken 6056 times.
✓ Branch 1 taken 6046 times.
|
12102 | for (i = 0; i < fg->nb_outputs; i++) { |
1116 | 6056 | OutputStream *ost = fg->outputs[i]->ost; | |
1117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6056 times.
|
6056 | if (!ost->enc) { |
1118 | /* identical to the same check in ffmpeg.c, needed because | ||
1119 | complex filter graphs are initialized earlier */ | ||
1120 | ✗ | av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n", | |
1121 | ✗ | avcodec_get_name(ost->st->codecpar->codec_id), ost->file_index, ost->index); | |
1122 | ✗ | ret = AVERROR(EINVAL); | |
1123 | ✗ | goto fail; | |
1124 | } | ||
1125 |
2/2✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 4908 times.
|
6056 | if (ost->enc->type == AVMEDIA_TYPE_AUDIO && |
1126 |
2/2✓ Branch 0 taken 106 times.
✓ Branch 1 taken 1042 times.
|
1148 | !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) |
1127 | 106 | av_buffersink_set_frame_size(ost->filter->filter, | |
1128 | 106 | ost->enc_ctx->frame_size); | |
1129 | } | ||
1130 | |||
1131 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 6046 times.
|
12079 | for (i = 0; i < fg->nb_inputs; i++) { |
1132 | AVFrame *tmp; | ||
1133 |
2/2✓ Branch 1 taken 34 times.
✓ Branch 2 taken 6033 times.
|
6067 | while (av_fifo_read(fg->inputs[i]->frame_queue, &tmp, 1) >= 0) { |
1134 | 34 | ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); | |
1135 | 34 | av_frame_free(&tmp); | |
1136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if (ret < 0) |
1137 | ✗ | goto fail; | |
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | /* send the EOFs for the finished inputs */ | ||
1142 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 6046 times.
|
12079 | for (i = 0; i < fg->nb_inputs; i++) { |
1143 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6032 times.
|
6033 | if (fg->inputs[i]->eof) { |
1144 | 1 | ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL); | |
1145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
1146 | ✗ | goto fail; | |
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | /* process queued up subtitle packets */ | ||
1151 |
2/2✓ Branch 0 taken 6033 times.
✓ Branch 1 taken 6046 times.
|
12079 | for (i = 0; i < fg->nb_inputs; i++) { |
1152 | 6033 | InputStream *ist = fg->inputs[i]->ist; | |
1153 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 6033 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6033 | if (ist->sub2video.sub_queue && ist->sub2video.frame) { |
1154 | AVSubtitle tmp; | ||
1155 | ✗ | while (av_fifo_read(ist->sub2video.sub_queue, &tmp, 1) >= 0) { | |
1156 | ✗ | sub2video_update(ist, INT64_MIN, &tmp); | |
1157 | ✗ | avsubtitle_free(&tmp); | |
1158 | } | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | 6046 | return 0; | |
1163 | |||
1164 | ✗ | fail: | |
1165 | ✗ | cleanup_filtergraph(fg); | |
1166 | ✗ | return ret; | |
1167 | } | ||
1168 | |||
1169 | 6028 | int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) | |
1170 | { | ||
1171 | AVFrameSideData *sd; | ||
1172 | int ret; | ||
1173 | |||
1174 | 6028 | av_buffer_unref(&ifilter->hw_frames_ctx); | |
1175 | |||
1176 | 6028 | ifilter->format = frame->format; | |
1177 | |||
1178 | 6028 | ifilter->width = frame->width; | |
1179 | 6028 | ifilter->height = frame->height; | |
1180 | 6028 | ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; | |
1181 | |||
1182 | 6028 | ifilter->sample_rate = frame->sample_rate; | |
1183 | 6028 | ret = av_channel_layout_copy(&ifilter->ch_layout, &frame->ch_layout); | |
1184 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6028 times.
|
6028 | if (ret < 0) |
1185 | ✗ | return ret; | |
1186 | |||
1187 | 6028 | av_freep(&ifilter->displaymatrix); | |
1188 | 6028 | sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); | |
1189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6028 times.
|
6028 | if (sd) |
1190 | ✗ | ifilter->displaymatrix = av_memdup(sd->data, sizeof(int32_t) * 9); | |
1191 | |||
1192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6028 times.
|
6028 | if (frame->hw_frames_ctx) { |
1193 | ✗ | ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx); | |
1194 | ✗ | if (!ifilter->hw_frames_ctx) | |
1195 | ✗ | return AVERROR(ENOMEM); | |
1196 | } | ||
1197 | |||
1198 | 6028 | return 0; | |
1199 | } | ||
1200 | |||
1201 | 18057 | int filtergraph_is_simple(FilterGraph *fg) | |
1202 | { | ||
1203 | 18057 | return !fg->graph_desc; | |
1204 | } | ||
1205 |