2 * avconv filter configuration
4 * This file is part of Libav.
6 * Libav 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.
11 * Libav 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libavfilter/avfilter.h"
24 #include "libavfilter/avfiltergraph.h"
26 #include "libavutil/avassert.h"
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/pixfmt.h"
30 #include "libavutil/samplefmt.h"
32 /* Define a function for building a string containing a list of
34 #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
35 static char *choose_ ## var ## s(OutputStream *ost) \
37 if (ost->st->codec->var != none) { \
38 get_name(ost->st->codec->var); \
39 return av_strdup(name); \
40 } else if (ost->enc->supported_list) { \
42 AVIOContext *s = NULL; \
46 if (avio_open_dyn_buf(&s) < 0) \
49 for (p = ost->enc->supported_list; *p != none; p++) { \
51 avio_printf(s, "%s" separator, name); \
53 len = avio_close_dyn_buf(s, &ret); \
60 DEF_CHOOSE_FORMAT(enum AVPixelFormat
, pix_fmt
, pix_fmts
, AV_PIX_FMT_NONE
,
61 GET_PIX_FMT_NAME
, ":")
63 DEF_CHOOSE_FORMAT(enum AVSampleFormat
, sample_fmt
, sample_fmts
,
64 AV_SAMPLE_FMT_NONE
, GET_SAMPLE_FMT_NAME
, ",")
66 DEF_CHOOSE_FORMAT(int, sample_rate
, supported_samplerates
, 0,
67 GET_SAMPLE_RATE_NAME
, ",")
69 DEF_CHOOSE_FORMAT(uint64_t, channel_layout
, channel_layouts
, 0,
70 GET_CH_LAYOUT_NAME
, ",")
72 FilterGraph
*init_simple_filtergraph(InputStream
*ist
, OutputStream
*ost
)
74 FilterGraph
*fg
= av_mallocz(sizeof(*fg
));
78 fg
->index
= nb_filtergraphs
;
80 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
81 if (!(fg
->outputs
[0] = av_mallocz(sizeof(*fg
->outputs
[0]))))
83 fg
->outputs
[0]->ost
= ost
;
84 fg
->outputs
[0]->graph
= fg
;
86 ost
->filter
= fg
->outputs
[0];
88 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
89 if (!(fg
->inputs
[0] = av_mallocz(sizeof(*fg
->inputs
[0]))))
91 fg
->inputs
[0]->ist
= ist
;
92 fg
->inputs
[0]->graph
= fg
;
94 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
95 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[0];
97 GROW_ARRAY(filtergraphs
, nb_filtergraphs
);
98 filtergraphs
[nb_filtergraphs
- 1] = fg
;
103 static void init_input_filter(FilterGraph
*fg
, AVFilterInOut
*in
)
105 InputStream
*ist
= NULL
;
106 enum AVMediaType type
= avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
);
109 // TODO: support other filter types
110 if (type
!= AVMEDIA_TYPE_VIDEO
&& type
!= AVMEDIA_TYPE_AUDIO
) {
111 av_log(NULL
, AV_LOG_FATAL
, "Only video and audio filters supported "
120 int file_idx
= strtol(in
->name
, &p
, 0);
122 if (file_idx
< 0 || file_idx
>= nb_input_files
) {
123 av_log(NULL
, AV_LOG_FATAL
, "Invalid file index %d in filtegraph description %s.\n",
124 file_idx
, fg
->graph_desc
);
127 s
= input_files
[file_idx
]->ctx
;
129 for (i
= 0; i
< s
->nb_streams
; i
++) {
130 if (s
->streams
[i
]->codec
->codec_type
!= type
)
132 if (check_stream_specifier(s
, s
->streams
[i
], *p
== ':' ? p
+ 1 : p
) == 1) {
138 av_log(NULL
, AV_LOG_FATAL
, "Stream specifier '%s' in filtergraph description %s "
139 "matches no streams.\n", p
, fg
->graph_desc
);
142 ist
= input_streams
[input_files
[file_idx
]->ist_index
+ st
->index
];
144 /* find the first unused stream of corresponding type */
145 for (i
= 0; i
< nb_input_streams
; i
++) {
146 ist
= input_streams
[i
];
147 if (ist
->st
->codec
->codec_type
== type
&& ist
->discard
)
150 if (i
== nb_input_streams
) {
151 av_log(NULL
, AV_LOG_FATAL
, "Cannot find a matching stream for "
152 "unlabeled input pad %d on filter %s", in
->pad_idx
,
153 in
->filter_ctx
->name
);
160 ist
->decoding_needed
= 1;
161 ist
->st
->discard
= AVDISCARD_NONE
;
163 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
164 if (!(fg
->inputs
[fg
->nb_inputs
- 1] = av_mallocz(sizeof(*fg
->inputs
[0]))))
166 fg
->inputs
[fg
->nb_inputs
- 1]->ist
= ist
;
167 fg
->inputs
[fg
->nb_inputs
- 1]->graph
= fg
;
169 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
170 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[fg
->nb_inputs
- 1];
173 static int configure_output_video_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
176 OutputStream
*ost
= ofilter
->ost
;
177 AVCodecContext
*codec
= ost
->st
->codec
;
178 AVFilterContext
*last_filter
= out
->filter_ctx
;
179 int pad_idx
= out
->pad_idx
;
183 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
184 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
185 avfilter_get_by_name("buffersink"),
186 name
, NULL
, NULL
, fg
->graph
);
190 if (codec
->width
|| codec
->height
) {
192 AVFilterContext
*filter
;
194 snprintf(args
, sizeof(args
), "%d:%d:flags=0x%X",
197 (unsigned)ost
->sws_flags
);
198 snprintf(name
, sizeof(name
), "scaler for output stream %d:%d",
199 ost
->file_index
, ost
->index
);
200 if ((ret
= avfilter_graph_create_filter(&filter
, avfilter_get_by_name("scale"),
201 name
, args
, NULL
, fg
->graph
)) < 0)
203 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
206 last_filter
= filter
;
210 if ((pix_fmts
= choose_pix_fmts(ost
))) {
211 AVFilterContext
*filter
;
212 snprintf(name
, sizeof(name
), "pixel format for output stream %d:%d",
213 ost
->file_index
, ost
->index
);
214 if ((ret
= avfilter_graph_create_filter(&filter
,
215 avfilter_get_by_name("format"),
216 "format", pix_fmts
, NULL
,
219 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
222 last_filter
= filter
;
227 if (ost
->frame_rate
.num
) {
228 AVFilterContext
*fps
;
231 snprintf(args
, sizeof(args
), "fps=%d/%d", ost
->frame_rate
.num
,
232 ost
->frame_rate
.den
);
233 snprintf(name
, sizeof(name
), "fps for output stream %d:%d",
234 ost
->file_index
, ost
->index
);
235 ret
= avfilter_graph_create_filter(&fps
, avfilter_get_by_name("fps"),
236 name
, args
, NULL
, fg
->graph
);
240 ret
= avfilter_link(last_filter
, pad_idx
, fps
, 0);
247 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
253 static int configure_output_audio_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
255 OutputStream
*ost
= ofilter
->ost
;
256 AVCodecContext
*codec
= ost
->st
->codec
;
257 AVFilterContext
*last_filter
= out
->filter_ctx
;
258 int pad_idx
= out
->pad_idx
;
259 char *sample_fmts
, *sample_rates
, *channel_layouts
;
264 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
265 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
266 avfilter_get_by_name("abuffersink"),
267 name
, NULL
, NULL
, fg
->graph
);
271 if (codec
->channels
&& !codec
->channel_layout
)
272 codec
->channel_layout
= av_get_default_channel_layout(codec
->channels
);
274 sample_fmts
= choose_sample_fmts(ost
);
275 sample_rates
= choose_sample_rates(ost
);
276 channel_layouts
= choose_channel_layouts(ost
);
277 if (sample_fmts
|| sample_rates
|| channel_layouts
) {
278 AVFilterContext
*format
;
283 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_fmts=%s:",
286 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_rates=%s:",
289 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "channel_layouts=%s:",
293 av_freep(&sample_fmts
);
294 av_freep(&sample_rates
);
295 av_freep(&channel_layouts
);
297 snprintf(name
, sizeof(name
), "audio format for output stream %d:%d",
298 ost
->file_index
, ost
->index
);
299 ret
= avfilter_graph_create_filter(&format
,
300 avfilter_get_by_name("aformat"),
301 name
, args
, NULL
, fg
->graph
);
305 ret
= avfilter_link(last_filter
, pad_idx
, format
, 0);
309 last_filter
= format
;
313 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
319 #define DESCRIBE_FILTER_LINK(f, inout, in) \
321 AVFilterContext *ctx = inout->filter_ctx; \
322 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
323 int nb_pads = in ? ctx->input_count : ctx->output_count; \
326 if (avio_open_dyn_buf(&pb) < 0) \
329 avio_printf(pb, "%s", ctx->filter->name); \
331 avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
333 avio_close_dyn_buf(pb, &f->name); \
336 int configure_output_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
338 av_freep(&ofilter
->name
);
339 DESCRIBE_FILTER_LINK(ofilter
, out
, 0);
341 switch (avfilter_pad_get_type(out
->filter_ctx
->output_pads
, out
->pad_idx
)) {
342 case AVMEDIA_TYPE_VIDEO
: return configure_output_video_filter(fg
, ofilter
, out
);
343 case AVMEDIA_TYPE_AUDIO
: return configure_output_audio_filter(fg
, ofilter
, out
);
344 default: av_assert0(0);
348 static int configure_input_video_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
351 AVFilterContext
*first_filter
= in
->filter_ctx
;
352 AVFilter
*filter
= avfilter_get_by_name("buffer");
353 InputStream
*ist
= ifilter
->ist
;
354 AVRational tb
= ist
->framerate
.num
? av_inv_q(ist
->framerate
) :
357 char args
[255], name
[255];
358 int pad_idx
= in
->pad_idx
;
361 sar
= ist
->st
->sample_aspect_ratio
.num
?
362 ist
->st
->sample_aspect_ratio
:
363 ist
->st
->codec
->sample_aspect_ratio
;
364 snprintf(args
, sizeof(args
), "%d:%d:%d:%d:%d:%d:%d", ist
->st
->codec
->width
,
365 ist
->st
->codec
->height
, ist
->st
->codec
->pix_fmt
,
366 tb
.num
, tb
.den
, sar
.num
, sar
.den
);
367 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
368 ist
->file_index
, ist
->st
->index
);
370 if ((ret
= avfilter_graph_create_filter(&ifilter
->filter
, filter
, name
,
371 args
, NULL
, fg
->graph
)) < 0)
374 if (ist
->framerate
.num
) {
375 AVFilterContext
*setpts
;
377 snprintf(name
, sizeof(name
), "force CFR for input from stream %d:%d",
378 ist
->file_index
, ist
->st
->index
);
379 if ((ret
= avfilter_graph_create_filter(&setpts
,
380 avfilter_get_by_name("setpts"),
385 if ((ret
= avfilter_link(setpts
, 0, first_filter
, pad_idx
)) < 0)
388 first_filter
= setpts
;
392 if ((ret
= avfilter_link(ifilter
->filter
, 0, first_filter
, pad_idx
)) < 0)
397 static int configure_input_audio_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
400 AVFilterContext
*first_filter
= in
->filter_ctx
;
401 AVFilter
*filter
= avfilter_get_by_name("abuffer");
402 InputStream
*ist
= ifilter
->ist
;
403 int pad_idx
= in
->pad_idx
;
404 char args
[255], name
[255];
407 snprintf(args
, sizeof(args
), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
408 ":channel_layout=0x%"PRIx64
,
409 1, ist
->st
->codec
->sample_rate
,
410 ist
->st
->codec
->sample_rate
,
411 av_get_sample_fmt_name(ist
->st
->codec
->sample_fmt
),
412 ist
->st
->codec
->channel_layout
);
413 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
414 ist
->file_index
, ist
->st
->index
);
416 if ((ret
= avfilter_graph_create_filter(&ifilter
->filter
, filter
,
421 if (audio_sync_method
> 0) {
422 AVFilterContext
*async
;
425 av_log(NULL
, AV_LOG_WARNING
, "-async has been deprecated. Used the "
426 "asyncts audio filter instead.\n");
428 if (audio_sync_method
> 1)
429 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "compensate=1:"
430 "max_comp=%d:", audio_sync_method
);
431 snprintf(args
+ len
, sizeof(args
) - len
, "min_delta=%f",
432 audio_drift_threshold
);
434 snprintf(name
, sizeof(name
), "graph %d audio sync for input stream %d:%d",
435 fg
->index
, ist
->file_index
, ist
->st
->index
);
436 ret
= avfilter_graph_create_filter(&async
,
437 avfilter_get_by_name("asyncts"),
438 name
, args
, NULL
, fg
->graph
);
442 ret
= avfilter_link(async
, 0, first_filter
, pad_idx
);
446 first_filter
= async
;
449 if (audio_volume
!= 256) {
450 AVFilterContext
*volume
;
452 av_log(NULL
, AV_LOG_WARNING
, "-vol has been deprecated. Use the volume "
453 "audio filter instead.\n");
455 snprintf(args
, sizeof(args
), "volume=%f", audio_volume
/ 256.0);
457 snprintf(name
, sizeof(name
), "graph %d volume for input stream %d:%d",
458 fg
->index
, ist
->file_index
, ist
->st
->index
);
459 ret
= avfilter_graph_create_filter(&volume
,
460 avfilter_get_by_name("volume"),
461 name
, args
, NULL
, fg
->graph
);
465 ret
= avfilter_link(volume
, 0, first_filter
, pad_idx
);
469 first_filter
= volume
;
472 if ((ret
= avfilter_link(ifilter
->filter
, 0, first_filter
, pad_idx
)) < 0)
478 static int configure_input_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
481 av_freep(&ifilter
->name
);
482 DESCRIBE_FILTER_LINK(ifilter
, in
, 1);
484 switch (avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
)) {
485 case AVMEDIA_TYPE_VIDEO
: return configure_input_video_filter(fg
, ifilter
, in
);
486 case AVMEDIA_TYPE_AUDIO
: return configure_input_audio_filter(fg
, ifilter
, in
);
487 default: av_assert0(0);
491 int configure_filtergraph(FilterGraph
*fg
)
493 AVFilterInOut
*inputs
, *outputs
, *cur
;
494 int ret
, i
, init
= !fg
->graph
, simple
= !fg
->graph_desc
;
495 const char *graph_desc
= simple
? fg
->outputs
[0]->ost
->avfilter
:
498 avfilter_graph_free(&fg
->graph
);
499 if (!(fg
->graph
= avfilter_graph_alloc()))
500 return AVERROR(ENOMEM
);
503 OutputStream
*ost
= fg
->outputs
[0]->ost
;
505 snprintf(args
, sizeof(args
), "flags=0x%X", (unsigned)ost
->sws_flags
);
506 fg
->graph
->scale_sws_opts
= av_strdup(args
);
509 if ((ret
= avfilter_graph_parse2(fg
->graph
, graph_desc
, &inputs
, &outputs
)) < 0)
512 if (simple
&& (!inputs
|| inputs
->next
|| !outputs
|| outputs
->next
)) {
513 av_log(NULL
, AV_LOG_ERROR
, "Simple filtergraph '%s' does not have "
514 "exactly one input and output.\n", graph_desc
);
515 return AVERROR(EINVAL
);
518 for (cur
= inputs
; !simple
&& init
&& cur
; cur
= cur
->next
)
519 init_input_filter(fg
, cur
);
521 for (cur
= inputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
522 if ((ret
= configure_input_filter(fg
, fg
->inputs
[i
], cur
)) < 0)
524 avfilter_inout_free(&inputs
);
526 if (!init
|| simple
) {
527 /* we already know the mappings between lavfi outputs and output streams,
528 * so we can finish the setup */
529 for (cur
= outputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
530 configure_output_filter(fg
, fg
->outputs
[i
], cur
);
531 avfilter_inout_free(&outputs
);
533 if ((ret
= avfilter_graph_config(fg
->graph
, NULL
)) < 0)
536 /* wait until output mappings are processed */
537 for (cur
= outputs
; cur
;) {
538 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
539 if (!(fg
->outputs
[fg
->nb_outputs
- 1] = av_mallocz(sizeof(*fg
->outputs
[0]))))
541 fg
->outputs
[fg
->nb_outputs
- 1]->graph
= fg
;
542 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
= cur
;
544 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
->next
= NULL
;
551 int ist_in_filtergraph(FilterGraph
*fg
, InputStream
*ist
)
554 for (i
= 0; i
< fg
->nb_inputs
; i
++)
555 if (fg
->inputs
[i
]->ist
== ist
)