Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 | ||
28 | #include "libavresample/avresample.h" | |
29 | ||
30 | #include "libavutil/avassert.h" | |
31 | #include "libavutil/avstring.h" | |
32 | #include "libavutil/bprint.h" | |
33 | #include "libavutil/channel_layout.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 | enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx, AVCodec *codec, enum AVPixelFormat target) | |
41 | { | |
42 | if (codec && codec->pix_fmts) { | |
43 | const enum AVPixelFormat *p = codec->pix_fmts; | |
44 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target); | |
45 | int has_alpha = desc ? desc->nb_components % 2 == 0 : 0; | |
46 | enum AVPixelFormat best= AV_PIX_FMT_NONE; | |
47 | static const enum AVPixelFormat mjpeg_formats[] = | |
48 | { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }; | |
49 | static const enum AVPixelFormat ljpeg_formats[] = | |
50 | { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, | |
51 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; | |
52 | ||
53 | if (enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { | |
54 | if (enc_ctx->codec_id == AV_CODEC_ID_MJPEG) { | |
55 | p = mjpeg_formats; | |
56 | } else if (enc_ctx->codec_id == AV_CODEC_ID_LJPEG) { | |
57 | p =ljpeg_formats; | |
58 | } | |
59 | } | |
60 | for (; *p != AV_PIX_FMT_NONE; p++) { | |
61 | best= avcodec_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL); | |
62 | if (*p == target) | |
63 | break; | |
64 | } | |
65 | if (*p == AV_PIX_FMT_NONE) { | |
66 | if (target != AV_PIX_FMT_NONE) | |
67 | av_log(NULL, AV_LOG_WARNING, | |
68 | "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", | |
69 | av_get_pix_fmt_name(target), | |
70 | codec->name, | |
71 | av_get_pix_fmt_name(best)); | |
72 | return best; | |
73 | } | |
74 | } | |
75 | return target; | |
76 | } | |
77 | ||
78 | void choose_sample_fmt(AVStream *st, AVCodec *codec) | |
79 | { | |
80 | if (codec && codec->sample_fmts) { | |
81 | const enum AVSampleFormat *p = codec->sample_fmts; | |
82 | for (; *p != -1; p++) { | |
83 | if (*p == st->codec->sample_fmt) | |
84 | break; | |
85 | } | |
86 | if (*p == -1) { | |
87 | if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0])) | |
88 | av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n"); | |
89 | if(av_get_sample_fmt_name(st->codec->sample_fmt)) | |
90 | av_log(NULL, AV_LOG_WARNING, | |
91 | "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n", | |
92 | av_get_sample_fmt_name(st->codec->sample_fmt), | |
93 | codec->name, | |
94 | av_get_sample_fmt_name(codec->sample_fmts[0])); | |
95 | st->codec->sample_fmt = codec->sample_fmts[0]; | |
96 | } | |
97 | } | |
98 | } | |
99 | ||
100 | static char *choose_pix_fmts(OutputStream *ost) | |
101 | { | |
102 | AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); | |
103 | if (strict_dict) | |
104 | // used by choose_pixel_fmt() and below | |
105 | av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); | |
106 | ||
107 | if (ost->keep_pix_fmt) { | |
108 | if (ost->filter) | |
109 | avfilter_graph_set_auto_convert(ost->filter->graph->graph, | |
110 | AVFILTER_AUTO_CONVERT_NONE); | |
111 | if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) | |
112 | return NULL; | |
113 | return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt)); | |
114 | } | |
115 | if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { | |
116 | return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt))); | |
117 | } else if (ost->enc && ost->enc->pix_fmts) { | |
118 | const enum AVPixelFormat *p; | |
119 | AVIOContext *s = NULL; | |
120 | uint8_t *ret; | |
121 | int len; | |
122 | ||
123 | if (avio_open_dyn_buf(&s) < 0) | |
124 | exit_program(1); | |
125 | ||
126 | p = ost->enc->pix_fmts; | |
127 | if (ost->enc_ctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { | |
128 | if (ost->enc_ctx->codec_id == AV_CODEC_ID_MJPEG) { | |
129 | p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }; | |
130 | } else if (ost->enc_ctx->codec_id == AV_CODEC_ID_LJPEG) { | |
131 | p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, | |
132 | AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE }; | |
133 | } | |
134 | } | |
135 | ||
136 | for (; *p != AV_PIX_FMT_NONE; p++) { | |
137 | const char *name = av_get_pix_fmt_name(*p); | |
138 | avio_printf(s, "%s|", name); | |
139 | } | |
140 | len = avio_close_dyn_buf(s, &ret); | |
141 | ret[len - 1] = 0; | |
142 | return ret; | |
143 | } else | |
144 | return NULL; | |
145 | } | |
146 | ||
147 | /* Define a function for building a string containing a list of | |
148 | * allowed formats. */ | |
149 | #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name) \ | |
150 | static char *choose_ ## var ## s(OutputStream *ost) \ | |
151 | { \ | |
152 | if (ost->enc_ctx->var != none) { \ | |
153 | get_name(ost->enc_ctx->var); \ | |
154 | return av_strdup(name); \ | |
155 | } else if (ost->enc && ost->enc->supported_list) { \ | |
156 | const type *p; \ | |
157 | AVIOContext *s = NULL; \ | |
158 | uint8_t *ret; \ | |
159 | int len; \ | |
160 | \ | |
161 | if (avio_open_dyn_buf(&s) < 0) \ | |
162 | exit_program(1); \ | |
163 | \ | |
164 | for (p = ost->enc->supported_list; *p != none; p++) { \ | |
165 | get_name(*p); \ | |
166 | avio_printf(s, "%s|", name); \ | |
167 | } \ | |
168 | len = avio_close_dyn_buf(s, &ret); \ | |
169 | ret[len - 1] = 0; \ | |
170 | return ret; \ | |
171 | } else \ | |
172 | return NULL; \ | |
173 | } | |
174 | ||
175 | // DEF_CHOOSE_FORMAT(enum AVPixelFormat, pix_fmt, pix_fmts, AV_PIX_FMT_NONE, | |
176 | // GET_PIX_FMT_NAME) | |
177 | ||
178 | DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts, | |
179 | AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME) | |
180 | ||
181 | DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0, | |
182 | GET_SAMPLE_RATE_NAME) | |
183 | ||
184 | DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0, | |
185 | GET_CH_LAYOUT_NAME) | |
186 | ||
187 | FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) | |
188 | { | |
189 | FilterGraph *fg = av_mallocz(sizeof(*fg)); | |
190 | ||
191 | if (!fg) | |
192 | exit_program(1); | |
193 | fg->index = nb_filtergraphs; | |
194 | ||
195 | GROW_ARRAY(fg->outputs, fg->nb_outputs); | |
196 | if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0])))) | |
197 | exit_program(1); | |
198 | fg->outputs[0]->ost = ost; | |
199 | fg->outputs[0]->graph = fg; | |
200 | ||
201 | ost->filter = fg->outputs[0]; | |
202 | ||
203 | GROW_ARRAY(fg->inputs, fg->nb_inputs); | |
204 | if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0])))) | |
205 | exit_program(1); | |
206 | fg->inputs[0]->ist = ist; | |
207 | fg->inputs[0]->graph = fg; | |
208 | ||
209 | GROW_ARRAY(ist->filters, ist->nb_filters); | |
210 | ist->filters[ist->nb_filters - 1] = fg->inputs[0]; | |
211 | ||
212 | GROW_ARRAY(filtergraphs, nb_filtergraphs); | |
213 | filtergraphs[nb_filtergraphs - 1] = fg; | |
214 | ||
215 | return fg; | |
216 | } | |
217 | ||
218 | static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) | |
219 | { | |
220 | InputStream *ist = NULL; | |
221 | enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); | |
222 | int i; | |
223 | ||
224 | // TODO: support other filter types | |
225 | if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { | |
226 | av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported " | |
227 | "currently.\n"); | |
228 | exit_program(1); | |
229 | } | |
230 | ||
231 | if (in->name) { | |
232 | AVFormatContext *s; | |
233 | AVStream *st = NULL; | |
234 | char *p; | |
235 | int file_idx = strtol(in->name, &p, 0); | |
236 | ||
237 | if (file_idx < 0 || file_idx >= nb_input_files) { | |
238 | av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", | |
239 | file_idx, fg->graph_desc); | |
240 | exit_program(1); | |
241 | } | |
242 | s = input_files[file_idx]->ctx; | |
243 | ||
244 | for (i = 0; i < s->nb_streams; i++) { | |
245 | enum AVMediaType stream_type = s->streams[i]->codec->codec_type; | |
246 | if (stream_type != type && | |
247 | !(stream_type == AVMEDIA_TYPE_SUBTITLE && | |
248 | type == AVMEDIA_TYPE_VIDEO /* sub2video hack */)) | |
249 | continue; | |
250 | if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { | |
251 | st = s->streams[i]; | |
252 | break; | |
253 | } | |
254 | } | |
255 | if (!st) { | |
256 | av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " | |
257 | "matches no streams.\n", p, fg->graph_desc); | |
258 | exit_program(1); | |
259 | } | |
260 | ist = input_streams[input_files[file_idx]->ist_index + st->index]; | |
261 | } else { | |
262 | /* find the first unused stream of corresponding type */ | |
263 | for (i = 0; i < nb_input_streams; i++) { | |
264 | ist = input_streams[i]; | |
265 | if (ist->dec_ctx->codec_type == type && ist->discard) | |
266 | break; | |
267 | } | |
268 | if (i == nb_input_streams) { | |
269 | av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " | |
270 | "unlabeled input pad %d on filter %s\n", in->pad_idx, | |
271 | in->filter_ctx->name); | |
272 | exit_program(1); | |
273 | } | |
274 | } | |
275 | av_assert0(ist); | |
276 | ||
277 | ist->discard = 0; | |
278 | ist->decoding_needed |= DECODING_FOR_FILTER; | |
279 | ist->st->discard = AVDISCARD_NONE; | |
280 | ||
281 | GROW_ARRAY(fg->inputs, fg->nb_inputs); | |
282 | if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0])))) | |
283 | exit_program(1); | |
284 | fg->inputs[fg->nb_inputs - 1]->ist = ist; | |
285 | fg->inputs[fg->nb_inputs - 1]->graph = fg; | |
286 | ||
287 | GROW_ARRAY(ist->filters, ist->nb_filters); | |
288 | ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; | |
289 | } | |
290 | ||
291 | static int insert_trim(int64_t start_time, int64_t duration, | |
292 | AVFilterContext **last_filter, int *pad_idx, | |
293 | const char *filter_name) | |
294 | { | |
295 | AVFilterGraph *graph = (*last_filter)->graph; | |
296 | AVFilterContext *ctx; | |
297 | const AVFilter *trim; | |
298 | enum AVMediaType type = avfilter_pad_get_type((*last_filter)->output_pads, *pad_idx); | |
299 | const char *name = (type == AVMEDIA_TYPE_VIDEO) ? "trim" : "atrim"; | |
300 | int ret = 0; | |
301 | ||
302 | if (duration == INT64_MAX && start_time == AV_NOPTS_VALUE) | |
303 | return 0; | |
304 | ||
305 | trim = avfilter_get_by_name(name); | |
306 | if (!trim) { | |
307 | av_log(NULL, AV_LOG_ERROR, "%s filter not present, cannot limit " | |
308 | "recording time.\n", name); | |
309 | return AVERROR_FILTER_NOT_FOUND; | |
310 | } | |
311 | ||
312 | ctx = avfilter_graph_alloc_filter(graph, trim, filter_name); | |
313 | if (!ctx) | |
314 | return AVERROR(ENOMEM); | |
315 | ||
316 | if (duration != INT64_MAX) { | |
317 | ret = av_opt_set_int(ctx, "durationi", duration, | |
318 | AV_OPT_SEARCH_CHILDREN); | |
319 | } | |
320 | if (ret >= 0 && start_time != AV_NOPTS_VALUE) { | |
321 | ret = av_opt_set_int(ctx, "starti", start_time, | |
322 | AV_OPT_SEARCH_CHILDREN); | |
323 | } | |
324 | if (ret < 0) { | |
325 | av_log(ctx, AV_LOG_ERROR, "Error configuring the %s filter", name); | |
326 | return ret; | |
327 | } | |
328 | ||
329 | ret = avfilter_init_str(ctx, NULL); | |
330 | if (ret < 0) | |
331 | return ret; | |
332 | ||
333 | ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); | |
334 | if (ret < 0) | |
335 | return ret; | |
336 | ||
337 | *last_filter = ctx; | |
338 | *pad_idx = 0; | |
339 | return 0; | |
340 | } | |
341 | ||
342 | static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |
343 | { | |
344 | char *pix_fmts; | |
345 | OutputStream *ost = ofilter->ost; | |
346 | OutputFile *of = output_files[ost->file_index]; | |
347 | AVCodecContext *codec = ost->enc_ctx; | |
348 | AVFilterContext *last_filter = out->filter_ctx; | |
349 | int pad_idx = out->pad_idx; | |
350 | int ret; | |
351 | char name[255]; | |
352 | ||
353 | snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); | |
354 | ret = avfilter_graph_create_filter(&ofilter->filter, | |
355 | avfilter_get_by_name("buffersink"), | |
356 | name, NULL, NULL, fg->graph); | |
357 | ||
358 | if (ret < 0) | |
359 | return ret; | |
360 | ||
361 | if (codec->width || codec->height) { | |
362 | char args[255]; | |
363 | AVFilterContext *filter; | |
364 | ||
365 | snprintf(args, sizeof(args), "%d:%d:0x%X", | |
366 | codec->width, | |
367 | codec->height, | |
368 | (unsigned)ost->sws_flags); | |
369 | snprintf(name, sizeof(name), "scaler for output stream %d:%d", | |
370 | ost->file_index, ost->index); | |
371 | if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), | |
372 | name, args, NULL, fg->graph)) < 0) | |
373 | return ret; | |
374 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) | |
375 | return ret; | |
376 | ||
377 | last_filter = filter; | |
378 | pad_idx = 0; | |
379 | } | |
380 | ||
381 | if ((pix_fmts = choose_pix_fmts(ost))) { | |
382 | AVFilterContext *filter; | |
383 | snprintf(name, sizeof(name), "pixel format for output stream %d:%d", | |
384 | ost->file_index, ost->index); | |
385 | ret = avfilter_graph_create_filter(&filter, | |
386 | avfilter_get_by_name("format"), | |
387 | "format", pix_fmts, NULL, | |
388 | fg->graph); | |
389 | av_freep(&pix_fmts); | |
390 | if (ret < 0) | |
391 | return ret; | |
392 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) | |
393 | return ret; | |
394 | ||
395 | last_filter = filter; | |
396 | pad_idx = 0; | |
397 | } | |
398 | ||
399 | if (ost->frame_rate.num && 0) { | |
400 | AVFilterContext *fps; | |
401 | char args[255]; | |
402 | ||
403 | snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, | |
404 | ost->frame_rate.den); | |
405 | snprintf(name, sizeof(name), "fps for output stream %d:%d", | |
406 | ost->file_index, ost->index); | |
407 | ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), | |
408 | name, args, NULL, fg->graph); | |
409 | if (ret < 0) | |
410 | return ret; | |
411 | ||
412 | ret = avfilter_link(last_filter, pad_idx, fps, 0); | |
413 | if (ret < 0) | |
414 | return ret; | |
415 | last_filter = fps; | |
416 | pad_idx = 0; | |
417 | } | |
418 | ||
419 | snprintf(name, sizeof(name), "trim for output stream %d:%d", | |
420 | ost->file_index, ost->index); | |
421 | ret = insert_trim(of->start_time, of->recording_time, | |
422 | &last_filter, &pad_idx, name); | |
423 | if (ret < 0) | |
424 | return ret; | |
425 | ||
426 | ||
427 | if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) | |
428 | return ret; | |
429 | ||
430 | return 0; | |
431 | } | |
432 | ||
433 | static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |
434 | { | |
435 | OutputStream *ost = ofilter->ost; | |
436 | OutputFile *of = output_files[ost->file_index]; | |
437 | AVCodecContext *codec = ost->enc_ctx; | |
438 | AVFilterContext *last_filter = out->filter_ctx; | |
439 | int pad_idx = out->pad_idx; | |
440 | char *sample_fmts, *sample_rates, *channel_layouts; | |
441 | char name[255]; | |
442 | int ret; | |
443 | ||
444 | snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); | |
445 | ret = avfilter_graph_create_filter(&ofilter->filter, | |
446 | avfilter_get_by_name("abuffersink"), | |
447 | name, NULL, NULL, fg->graph); | |
448 | if (ret < 0) | |
449 | return ret; | |
450 | if ((ret = av_opt_set_int(ofilter->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0) | |
451 | return ret; | |
452 | ||
453 | #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ | |
454 | AVFilterContext *filt_ctx; \ | |
455 | \ | |
456 | av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | |
457 | "similarly to -af " filter_name "=%s.\n", arg); \ | |
458 | \ | |
459 | ret = avfilter_graph_create_filter(&filt_ctx, \ | |
460 | avfilter_get_by_name(filter_name), \ | |
461 | filter_name, arg, NULL, fg->graph); \ | |
462 | if (ret < 0) \ | |
463 | return ret; \ | |
464 | \ | |
465 | ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \ | |
466 | if (ret < 0) \ | |
467 | return ret; \ | |
468 | \ | |
469 | last_filter = filt_ctx; \ | |
470 | pad_idx = 0; \ | |
471 | } while (0) | |
472 | if (ost->audio_channels_mapped) { | |
473 | int i; | |
474 | AVBPrint pan_buf; | |
475 | av_bprint_init(&pan_buf, 256, 8192); | |
476 | av_bprintf(&pan_buf, "0x%"PRIx64, | |
477 | av_get_default_channel_layout(ost->audio_channels_mapped)); | |
478 | for (i = 0; i < ost->audio_channels_mapped; i++) | |
479 | if (ost->audio_channels_map[i] != -1) | |
480 | av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); | |
481 | ||
482 | AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str); | |
483 | av_bprint_finalize(&pan_buf, NULL); | |
484 | } | |
485 | ||
486 | if (codec->channels && !codec->channel_layout) | |
487 | codec->channel_layout = av_get_default_channel_layout(codec->channels); | |
488 | ||
489 | sample_fmts = choose_sample_fmts(ost); | |
490 | sample_rates = choose_sample_rates(ost); | |
491 | channel_layouts = choose_channel_layouts(ost); | |
492 | if (sample_fmts || sample_rates || channel_layouts) { | |
493 | AVFilterContext *format; | |
494 | char args[256]; | |
495 | args[0] = 0; | |
496 | ||
497 | if (sample_fmts) | |
498 | av_strlcatf(args, sizeof(args), "sample_fmts=%s:", | |
499 | sample_fmts); | |
500 | if (sample_rates) | |
501 | av_strlcatf(args, sizeof(args), "sample_rates=%s:", | |
502 | sample_rates); | |
503 | if (channel_layouts) | |
504 | av_strlcatf(args, sizeof(args), "channel_layouts=%s:", | |
505 | channel_layouts); | |
506 | ||
507 | av_freep(&sample_fmts); | |
508 | av_freep(&sample_rates); | |
509 | av_freep(&channel_layouts); | |
510 | ||
511 | snprintf(name, sizeof(name), "audio format for output stream %d:%d", | |
512 | ost->file_index, ost->index); | |
513 | ret = avfilter_graph_create_filter(&format, | |
514 | avfilter_get_by_name("aformat"), | |
515 | name, args, NULL, fg->graph); | |
516 | if (ret < 0) | |
517 | return ret; | |
518 | ||
519 | ret = avfilter_link(last_filter, pad_idx, format, 0); | |
520 | if (ret < 0) | |
521 | return ret; | |
522 | ||
523 | last_filter = format; | |
524 | pad_idx = 0; | |
525 | } | |
526 | ||
527 | if (audio_volume != 256 && 0) { | |
528 | char args[256]; | |
529 | ||
530 | snprintf(args, sizeof(args), "%f", audio_volume / 256.); | |
531 | AUTO_INSERT_FILTER("-vol", "volume", args); | |
532 | } | |
533 | ||
534 | if (ost->apad && of->shortest) { | |
535 | char args[256]; | |
536 | int i; | |
537 | ||
538 | for (i=0; i<of->ctx->nb_streams; i++) | |
539 | if (of->ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) | |
540 | break; | |
541 | ||
542 | if (i<of->ctx->nb_streams) { | |
543 | snprintf(args, sizeof(args), "%s", ost->apad); | |
544 | AUTO_INSERT_FILTER("-apad", "apad", args); | |
545 | } | |
546 | } | |
547 | ||
548 | snprintf(name, sizeof(name), "trim for output stream %d:%d", | |
549 | ost->file_index, ost->index); | |
550 | ret = insert_trim(of->start_time, of->recording_time, | |
551 | &last_filter, &pad_idx, name); | |
552 | if (ret < 0) | |
553 | return ret; | |
554 | ||
555 | if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) | |
556 | return ret; | |
557 | ||
558 | return 0; | |
559 | } | |
560 | ||
561 | #define DESCRIBE_FILTER_LINK(f, inout, in) \ | |
562 | { \ | |
563 | AVFilterContext *ctx = inout->filter_ctx; \ | |
564 | AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \ | |
565 | int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; \ | |
566 | AVIOContext *pb; \ | |
567 | \ | |
568 | if (avio_open_dyn_buf(&pb) < 0) \ | |
569 | exit_program(1); \ | |
570 | \ | |
571 | avio_printf(pb, "%s", ctx->filter->name); \ | |
572 | if (nb_pads > 1) \ | |
573 | avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\ | |
574 | avio_w8(pb, 0); \ | |
575 | avio_close_dyn_buf(pb, &f->name); \ | |
576 | } | |
577 | ||
578 | int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |
579 | { | |
580 | av_freep(&ofilter->name); | |
581 | DESCRIBE_FILTER_LINK(ofilter, out, 0); | |
582 | ||
583 | switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { | |
584 | case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out); | |
585 | case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out); | |
586 | default: av_assert0(0); | |
587 | } | |
588 | } | |
589 | ||
590 | static int sub2video_prepare(InputStream *ist) | |
591 | { | |
592 | AVFormatContext *avf = input_files[ist->file_index]->ctx; | |
593 | int i, w, h; | |
594 | ||
595 | /* Compute the size of the canvas for the subtitles stream. | |
596 | If the subtitles codec has set a size, use it. Otherwise use the | |
597 | maximum dimensions of the video streams in the same file. */ | |
598 | w = ist->dec_ctx->width; | |
599 | h = ist->dec_ctx->height; | |
600 | if (!(w && h)) { | |
601 | for (i = 0; i < avf->nb_streams; i++) { | |
602 | if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { | |
603 | w = FFMAX(w, avf->streams[i]->codec->width); | |
604 | h = FFMAX(h, avf->streams[i]->codec->height); | |
605 | } | |
606 | } | |
607 | if (!(w && h)) { | |
608 | w = FFMAX(w, 720); | |
609 | h = FFMAX(h, 576); | |
610 | } | |
611 | av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); | |
612 | } | |
613 | ist->sub2video.w = ist->dec_ctx->width = ist->resample_width = w; | |
614 | ist->sub2video.h = ist->dec_ctx->height = ist->resample_height = h; | |
615 | ||
616 | /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the | |
617 | palettes for all rectangles are identical or compatible */ | |
618 | ist->resample_pix_fmt = ist->dec_ctx->pix_fmt = AV_PIX_FMT_RGB32; | |
619 | ||
620 | ist->sub2video.frame = av_frame_alloc(); | |
621 | if (!ist->sub2video.frame) | |
622 | return AVERROR(ENOMEM); | |
623 | return 0; | |
624 | } | |
625 | ||
626 | static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, | |
627 | AVFilterInOut *in) | |
628 | { | |
629 | AVFilterContext *last_filter; | |
630 | const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); | |
631 | InputStream *ist = ifilter->ist; | |
632 | InputFile *f = input_files[ist->file_index]; | |
633 | AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : | |
634 | ist->st->time_base; | |
635 | AVRational fr = ist->framerate; | |
636 | AVRational sar; | |
637 | AVBPrint args; | |
638 | char name[255]; | |
639 | int ret, pad_idx = 0; | |
640 | ||
641 | if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { | |
642 | av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n"); | |
643 | return AVERROR(EINVAL); | |
644 | } | |
645 | ||
646 | if (!fr.num) | |
647 | fr = av_guess_frame_rate(input_files[ist->file_index]->ctx, ist->st, NULL); | |
648 | ||
649 | if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) { | |
650 | ret = sub2video_prepare(ist); | |
651 | if (ret < 0) | |
652 | return ret; | |
653 | } | |
654 | ||
655 | sar = ist->st->sample_aspect_ratio.num ? | |
656 | ist->st->sample_aspect_ratio : | |
657 | ist->dec_ctx->sample_aspect_ratio; | |
658 | if(!sar.den) | |
659 | sar = (AVRational){0,1}; | |
660 | av_bprint_init(&args, 0, 1); | |
661 | av_bprintf(&args, | |
662 | "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" | |
663 | "pixel_aspect=%d/%d:sws_param=flags=%d", ist->resample_width, | |
664 | ist->resample_height, | |
665 | ist->hwaccel_retrieve_data ? ist->hwaccel_retrieved_pix_fmt : ist->resample_pix_fmt, | |
666 | tb.num, tb.den, sar.num, sar.den, | |
667 | SWS_BILINEAR + ((ist->dec_ctx->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); | |
668 | if (fr.num && fr.den) | |
669 | av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); | |
670 | snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |
671 | ist->file_index, ist->st->index); | |
672 | ||
673 | if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name, | |
674 | args.str, NULL, fg->graph)) < 0) | |
675 | return ret; | |
676 | last_filter = ifilter->filter; | |
677 | ||
678 | if (ist->framerate.num) { | |
679 | AVFilterContext *setpts; | |
680 | ||
681 | snprintf(name, sizeof(name), "force CFR for input from stream %d:%d", | |
682 | ist->file_index, ist->st->index); | |
683 | if ((ret = avfilter_graph_create_filter(&setpts, | |
684 | avfilter_get_by_name("setpts"), | |
685 | name, "N", NULL, | |
686 | fg->graph)) < 0) | |
687 | return ret; | |
688 | ||
689 | if ((ret = avfilter_link(last_filter, 0, setpts, 0)) < 0) | |
690 | return ret; | |
691 | ||
692 | last_filter = setpts; | |
693 | } | |
694 | ||
695 | if (do_deinterlace) { | |
696 | AVFilterContext *yadif; | |
697 | ||
698 | snprintf(name, sizeof(name), "deinterlace input from stream %d:%d", | |
699 | ist->file_index, ist->st->index); | |
700 | if ((ret = avfilter_graph_create_filter(&yadif, | |
701 | avfilter_get_by_name("yadif"), | |
702 | name, "", NULL, | |
703 | fg->graph)) < 0) | |
704 | return ret; | |
705 | ||
706 | if ((ret = avfilter_link(last_filter, 0, yadif, 0)) < 0) | |
707 | return ret; | |
708 | ||
709 | last_filter = yadif; | |
710 | } | |
711 | ||
712 | snprintf(name, sizeof(name), "trim for input stream %d:%d", | |
713 | ist->file_index, ist->st->index); | |
714 | ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ? | |
715 | AV_NOPTS_VALUE : 0, f->recording_time, &last_filter, &pad_idx, name); | |
716 | if (ret < 0) | |
717 | return ret; | |
718 | ||
719 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) | |
720 | return ret; | |
721 | return 0; | |
722 | } | |
723 | ||
724 | static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, | |
725 | AVFilterInOut *in) | |
726 | { | |
727 | AVFilterContext *last_filter; | |
728 | const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); | |
729 | InputStream *ist = ifilter->ist; | |
730 | InputFile *f = input_files[ist->file_index]; | |
731 | AVBPrint args; | |
732 | char name[255]; | |
733 | int ret, pad_idx = 0; | |
734 | ||
735 | if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) { | |
736 | av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n"); | |
737 | return AVERROR(EINVAL); | |
738 | } | |
739 | ||
740 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
741 | av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", | |
742 | 1, ist->dec_ctx->sample_rate, | |
743 | ist->dec_ctx->sample_rate, | |
744 | av_get_sample_fmt_name(ist->dec_ctx->sample_fmt)); | |
745 | if (ist->dec_ctx->channel_layout) | |
746 | av_bprintf(&args, ":channel_layout=0x%"PRIx64, | |
747 | ist->dec_ctx->channel_layout); | |
748 | else | |
749 | av_bprintf(&args, ":channels=%d", ist->dec_ctx->channels); | |
750 | snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |
751 | ist->file_index, ist->st->index); | |
752 | ||
753 | if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt, | |
754 | name, args.str, NULL, | |
755 | fg->graph)) < 0) | |
756 | return ret; | |
757 | last_filter = ifilter->filter; | |
758 | ||
759 | #define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do { \ | |
760 | AVFilterContext *filt_ctx; \ | |
761 | \ | |
762 | av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | |
763 | "similarly to -af " filter_name "=%s.\n", arg); \ | |
764 | \ | |
765 | snprintf(name, sizeof(name), "graph %d %s for input stream %d:%d", \ | |
766 | fg->index, filter_name, ist->file_index, ist->st->index); \ | |
767 | ret = avfilter_graph_create_filter(&filt_ctx, \ | |
768 | avfilter_get_by_name(filter_name), \ | |
769 | name, arg, NULL, fg->graph); \ | |
770 | if (ret < 0) \ | |
771 | return ret; \ | |
772 | \ | |
773 | ret = avfilter_link(last_filter, 0, filt_ctx, 0); \ | |
774 | if (ret < 0) \ | |
775 | return ret; \ | |
776 | \ | |
777 | last_filter = filt_ctx; \ | |
778 | } while (0) | |
779 | ||
780 | if (audio_sync_method > 0) { | |
781 | char args[256] = {0}; | |
782 | ||
783 | av_strlcatf(args, sizeof(args), "async=%d", audio_sync_method); | |
784 | if (audio_drift_threshold != 0.1) | |
785 | av_strlcatf(args, sizeof(args), ":min_hard_comp=%f", audio_drift_threshold); | |
786 | if (!fg->reconfiguration) | |
787 | av_strlcatf(args, sizeof(args), ":first_pts=0"); | |
788 | AUTO_INSERT_FILTER_INPUT("-async", "aresample", args); | |
789 | } | |
790 | ||
791 | // if (ost->audio_channels_mapped) { | |
792 | // int i; | |
793 | // AVBPrint pan_buf; | |
794 | // av_bprint_init(&pan_buf, 256, 8192); | |
795 | // av_bprintf(&pan_buf, "0x%"PRIx64, | |
796 | // av_get_default_channel_layout(ost->audio_channels_mapped)); | |
797 | // for (i = 0; i < ost->audio_channels_mapped; i++) | |
798 | // if (ost->audio_channels_map[i] != -1) | |
799 | // av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); | |
800 | // AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str); | |
801 | // av_bprint_finalize(&pan_buf, NULL); | |
802 | // } | |
803 | ||
804 | if (audio_volume != 256) { | |
805 | char args[256]; | |
806 | ||
807 | av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Use the volume " | |
808 | "audio filter instead.\n"); | |
809 | ||
810 | snprintf(args, sizeof(args), "%f", audio_volume / 256.); | |
811 | AUTO_INSERT_FILTER_INPUT("-vol", "volume", args); | |
812 | } | |
813 | ||
814 | snprintf(name, sizeof(name), "trim for input stream %d:%d", | |
815 | ist->file_index, ist->st->index); | |
816 | ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ? | |
817 | AV_NOPTS_VALUE : 0, f->recording_time, &last_filter, &pad_idx, name); | |
818 | if (ret < 0) | |
819 | return ret; | |
820 | ||
821 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) | |
822 | return ret; | |
823 | ||
824 | return 0; | |
825 | } | |
826 | ||
827 | static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, | |
828 | AVFilterInOut *in) | |
829 | { | |
830 | av_freep(&ifilter->name); | |
831 | DESCRIBE_FILTER_LINK(ifilter, in, 1); | |
832 | ||
833 | if (!ifilter->ist->dec) { | |
834 | av_log(NULL, AV_LOG_ERROR, | |
835 | "No decoder for stream #%d:%d, filtering impossible\n", | |
836 | ifilter->ist->file_index, ifilter->ist->st->index); | |
837 | return AVERROR_DECODER_NOT_FOUND; | |
838 | } | |
839 | switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { | |
840 | case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); | |
841 | case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); | |
842 | default: av_assert0(0); | |
843 | } | |
844 | } | |
845 | ||
846 | int configure_filtergraph(FilterGraph *fg) | |
847 | { | |
848 | AVFilterInOut *inputs, *outputs, *cur; | |
849 | int ret, i, init = !fg->graph, simple = !fg->graph_desc; | |
850 | const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : | |
851 | fg->graph_desc; | |
852 | ||
853 | avfilter_graph_free(&fg->graph); | |
854 | if (!(fg->graph = avfilter_graph_alloc())) | |
855 | return AVERROR(ENOMEM); | |
856 | ||
857 | if (simple) { | |
858 | OutputStream *ost = fg->outputs[0]->ost; | |
859 | char args[512]; | |
860 | AVDictionaryEntry *e = NULL; | |
861 | ||
862 | snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); | |
863 | fg->graph->scale_sws_opts = av_strdup(args); | |
864 | ||
865 | args[0] = 0; | |
866 | while ((e = av_dict_get(ost->swr_opts, "", e, | |
867 | AV_DICT_IGNORE_SUFFIX))) { | |
868 | av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); | |
869 | } | |
870 | if (strlen(args)) | |
871 | args[strlen(args)-1] = 0; | |
872 | av_opt_set(fg->graph, "aresample_swr_opts", args, 0); | |
873 | ||
874 | args[0] = '\0'; | |
875 | while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, | |
876 | AV_DICT_IGNORE_SUFFIX))) { | |
877 | av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); | |
878 | } | |
879 | if (strlen(args)) | |
880 | args[strlen(args) - 1] = '\0'; | |
881 | fg->graph->resample_lavr_opts = av_strdup(args); | |
882 | ||
883 | e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); | |
884 | if (e) | |
885 | av_opt_set(fg->graph, "threads", e->value, 0); | |
886 | } | |
887 | ||
888 | if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) | |
889 | return ret; | |
890 | ||
891 | if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { | |
892 | av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " | |
893 | "exactly one input and output.\n", graph_desc); | |
894 | return AVERROR(EINVAL); | |
895 | } | |
896 | ||
897 | for (cur = inputs; !simple && init && cur; cur = cur->next) | |
898 | init_input_filter(fg, cur); | |
899 | ||
900 | for (cur = inputs, i = 0; cur; cur = cur->next, i++) | |
901 | if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { | |
902 | avfilter_inout_free(&inputs); | |
903 | avfilter_inout_free(&outputs); | |
904 | return ret; | |
905 | } | |
906 | avfilter_inout_free(&inputs); | |
907 | ||
908 | if (!init || simple) { | |
909 | /* we already know the mappings between lavfi outputs and output streams, | |
910 | * so we can finish the setup */ | |
911 | for (cur = outputs, i = 0; cur; cur = cur->next, i++) | |
912 | configure_output_filter(fg, fg->outputs[i], cur); | |
913 | avfilter_inout_free(&outputs); | |
914 | ||
915 | if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) | |
916 | return ret; | |
917 | } else { | |
918 | /* wait until output mappings are processed */ | |
919 | for (cur = outputs; cur;) { | |
920 | GROW_ARRAY(fg->outputs, fg->nb_outputs); | |
921 | if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])))) | |
922 | exit_program(1); | |
923 | fg->outputs[fg->nb_outputs - 1]->graph = fg; | |
924 | fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; | |
925 | cur = cur->next; | |
926 | fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; | |
927 | } | |
928 | } | |
929 | ||
930 | fg->reconfiguration = 1; | |
931 | ||
932 | for (i = 0; i < fg->nb_outputs; i++) { | |
933 | OutputStream *ost = fg->outputs[i]->ost; | |
934 | if (ost && | |
935 | ost->enc->type == AVMEDIA_TYPE_AUDIO && | |
936 | !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) | |
937 | av_buffersink_set_frame_size(ost->filter->filter, | |
938 | ost->enc_ctx->frame_size); | |
939 | } | |
940 | ||
941 | return 0; | |
942 | } | |
943 | ||
944 | int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) | |
945 | { | |
946 | int i; | |
947 | for (i = 0; i < fg->nb_inputs; i++) | |
948 | if (fg->inputs[i]->ist == ist) | |
949 | return 1; | |
950 | return 0; | |
951 | } | |
952 |