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