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 "libavresample/avresample.h"
28 #include "libavutil/avassert.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/channel_layout.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/pixdesc.h"
33 #include "libavutil/pixfmt.h"
34 #include "libavutil/samplefmt.h"
36 /* Define a function for building a string containing a list of
38 #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
39 static char *choose_ ## var ## s(OutputStream *ost) \
41 if (ost->st->codec->var != none) { \
42 get_name(ost->st->codec->var); \
43 return av_strdup(name); \
44 } else if (ost->enc && ost->enc->supported_list) { \
46 AVIOContext *s = NULL; \
50 if (avio_open_dyn_buf(&s) < 0) \
53 for (p = ost->enc->supported_list; *p != none; p++) { \
55 avio_printf(s, "%s" separator, name); \
57 len = avio_close_dyn_buf(s, &ret); \
64 DEF_CHOOSE_FORMAT(enum AVPixelFormat
, pix_fmt
, pix_fmts
, AV_PIX_FMT_NONE
,
65 GET_PIX_FMT_NAME
, ":")
67 DEF_CHOOSE_FORMAT(enum AVSampleFormat
, sample_fmt
, sample_fmts
,
68 AV_SAMPLE_FMT_NONE
, GET_SAMPLE_FMT_NAME
, ",")
70 DEF_CHOOSE_FORMAT(int, sample_rate
, supported_samplerates
, 0,
71 GET_SAMPLE_RATE_NAME
, ",")
73 DEF_CHOOSE_FORMAT(uint64_t, channel_layout
, channel_layouts
, 0,
74 GET_CH_LAYOUT_NAME
, ",")
76 FilterGraph
*init_simple_filtergraph(InputStream
*ist
, OutputStream
*ost
)
78 FilterGraph
*fg
= av_mallocz(sizeof(*fg
));
82 fg
->index
= nb_filtergraphs
;
84 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
85 if (!(fg
->outputs
[0] = av_mallocz(sizeof(*fg
->outputs
[0]))))
87 fg
->outputs
[0]->ost
= ost
;
88 fg
->outputs
[0]->graph
= fg
;
90 ost
->filter
= fg
->outputs
[0];
92 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
93 if (!(fg
->inputs
[0] = av_mallocz(sizeof(*fg
->inputs
[0]))))
95 fg
->inputs
[0]->ist
= ist
;
96 fg
->inputs
[0]->graph
= fg
;
98 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
99 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[0];
101 GROW_ARRAY(filtergraphs
, nb_filtergraphs
);
102 filtergraphs
[nb_filtergraphs
- 1] = fg
;
107 static void init_input_filter(FilterGraph
*fg
, AVFilterInOut
*in
)
109 InputStream
*ist
= NULL
;
110 enum AVMediaType type
= avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
);
113 // TODO: support other filter types
114 if (type
!= AVMEDIA_TYPE_VIDEO
&& type
!= AVMEDIA_TYPE_AUDIO
) {
115 av_log(NULL
, AV_LOG_FATAL
, "Only video and audio filters supported "
124 int file_idx
= strtol(in
->name
, &p
, 0);
126 if (file_idx
< 0 || file_idx
>= nb_input_files
) {
127 av_log(NULL
, AV_LOG_FATAL
, "Invalid file index %d in filtegraph description %s.\n",
128 file_idx
, fg
->graph_desc
);
131 s
= input_files
[file_idx
]->ctx
;
133 for (i
= 0; i
< s
->nb_streams
; i
++) {
134 if (s
->streams
[i
]->codec
->codec_type
!= type
)
136 if (check_stream_specifier(s
, s
->streams
[i
], *p
== ':' ? p
+ 1 : p
) == 1) {
142 av_log(NULL
, AV_LOG_FATAL
, "Stream specifier '%s' in filtergraph description %s "
143 "matches no streams.\n", p
, fg
->graph_desc
);
146 ist
= input_streams
[input_files
[file_idx
]->ist_index
+ st
->index
];
148 /* find the first unused stream of corresponding type */
149 for (i
= 0; i
< nb_input_streams
; i
++) {
150 ist
= input_streams
[i
];
151 if (ist
->st
->codec
->codec_type
== type
&& ist
->discard
)
154 if (i
== nb_input_streams
) {
155 av_log(NULL
, AV_LOG_FATAL
, "Cannot find a matching stream for "
156 "unlabeled input pad %d on filter %s", in
->pad_idx
,
157 in
->filter_ctx
->name
);
164 ist
->decoding_needed
= 1;
165 ist
->st
->discard
= AVDISCARD_NONE
;
167 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
168 if (!(fg
->inputs
[fg
->nb_inputs
- 1] = av_mallocz(sizeof(*fg
->inputs
[0]))))
170 fg
->inputs
[fg
->nb_inputs
- 1]->ist
= ist
;
171 fg
->inputs
[fg
->nb_inputs
- 1]->graph
= fg
;
173 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
174 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[fg
->nb_inputs
- 1];
177 static int configure_output_video_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
180 OutputStream
*ost
= ofilter
->ost
;
181 AVCodecContext
*codec
= ost
->st
->codec
;
182 AVFilterContext
*last_filter
= out
->filter_ctx
;
183 int pad_idx
= out
->pad_idx
;
187 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
188 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
189 avfilter_get_by_name("buffersink"),
190 name
, NULL
, NULL
, fg
->graph
);
194 if (codec
->width
|| codec
->height
) {
196 AVFilterContext
*filter
;
198 snprintf(args
, sizeof(args
), "%d:%d:flags=0x%X",
201 (unsigned)ost
->sws_flags
);
202 snprintf(name
, sizeof(name
), "scaler for output stream %d:%d",
203 ost
->file_index
, ost
->index
);
204 if ((ret
= avfilter_graph_create_filter(&filter
, avfilter_get_by_name("scale"),
205 name
, args
, NULL
, fg
->graph
)) < 0)
207 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
210 last_filter
= filter
;
214 if ((pix_fmts
= choose_pix_fmts(ost
))) {
215 AVFilterContext
*filter
;
216 snprintf(name
, sizeof(name
), "pixel format for output stream %d:%d",
217 ost
->file_index
, ost
->index
);
218 if ((ret
= avfilter_graph_create_filter(&filter
,
219 avfilter_get_by_name("format"),
220 "format", pix_fmts
, NULL
,
223 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
226 last_filter
= filter
;
231 if (ost
->frame_rate
.num
) {
232 AVFilterContext
*fps
;
235 snprintf(args
, sizeof(args
), "fps=%d/%d", ost
->frame_rate
.num
,
236 ost
->frame_rate
.den
);
237 snprintf(name
, sizeof(name
), "fps for output stream %d:%d",
238 ost
->file_index
, ost
->index
);
239 ret
= avfilter_graph_create_filter(&fps
, avfilter_get_by_name("fps"),
240 name
, args
, NULL
, fg
->graph
);
244 ret
= avfilter_link(last_filter
, pad_idx
, fps
, 0);
251 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
257 static int configure_output_audio_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
259 OutputStream
*ost
= ofilter
->ost
;
260 AVCodecContext
*codec
= ost
->st
->codec
;
261 AVFilterContext
*last_filter
= out
->filter_ctx
;
262 int pad_idx
= out
->pad_idx
;
263 char *sample_fmts
, *sample_rates
, *channel_layouts
;
268 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
269 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
270 avfilter_get_by_name("abuffersink"),
271 name
, NULL
, NULL
, fg
->graph
);
275 if (codec
->channels
&& !codec
->channel_layout
)
276 codec
->channel_layout
= av_get_default_channel_layout(codec
->channels
);
278 sample_fmts
= choose_sample_fmts(ost
);
279 sample_rates
= choose_sample_rates(ost
);
280 channel_layouts
= choose_channel_layouts(ost
);
281 if (sample_fmts
|| sample_rates
|| channel_layouts
) {
282 AVFilterContext
*format
;
287 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_fmts=%s:",
290 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_rates=%s:",
293 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "channel_layouts=%s:",
297 av_freep(&sample_fmts
);
298 av_freep(&sample_rates
);
299 av_freep(&channel_layouts
);
301 snprintf(name
, sizeof(name
), "audio format for output stream %d:%d",
302 ost
->file_index
, ost
->index
);
303 ret
= avfilter_graph_create_filter(&format
,
304 avfilter_get_by_name("aformat"),
305 name
, args
, NULL
, fg
->graph
);
309 ret
= avfilter_link(last_filter
, pad_idx
, format
, 0);
313 last_filter
= format
;
317 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
323 #define DESCRIBE_FILTER_LINK(f, inout, in) \
325 AVFilterContext *ctx = inout->filter_ctx; \
326 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
327 int nb_pads = in ? ctx->input_count : ctx->output_count; \
330 if (avio_open_dyn_buf(&pb) < 0) \
333 avio_printf(pb, "%s", ctx->filter->name); \
335 avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
337 avio_close_dyn_buf(pb, &f->name); \
340 int configure_output_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
342 av_freep(&ofilter
->name
);
343 DESCRIBE_FILTER_LINK(ofilter
, out
, 0);
345 switch (avfilter_pad_get_type(out
->filter_ctx
->output_pads
, out
->pad_idx
)) {
346 case AVMEDIA_TYPE_VIDEO
: return configure_output_video_filter(fg
, ofilter
, out
);
347 case AVMEDIA_TYPE_AUDIO
: return configure_output_audio_filter(fg
, ofilter
, out
);
348 default: av_assert0(0);
352 static int configure_input_video_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
355 AVFilterContext
*first_filter
= in
->filter_ctx
;
356 AVFilter
*filter
= avfilter_get_by_name("buffer");
357 InputStream
*ist
= ifilter
->ist
;
358 AVRational tb
= ist
->framerate
.num
? av_inv_q(ist
->framerate
) :
361 char args
[255], name
[255];
362 int pad_idx
= in
->pad_idx
;
365 sar
= ist
->st
->sample_aspect_ratio
.num
?
366 ist
->st
->sample_aspect_ratio
:
367 ist
->st
->codec
->sample_aspect_ratio
;
368 snprintf(args
, sizeof(args
), "%d:%d:%d:%d:%d:%d:%d", ist
->st
->codec
->width
,
369 ist
->st
->codec
->height
, ist
->st
->codec
->pix_fmt
,
370 tb
.num
, tb
.den
, sar
.num
, sar
.den
);
371 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
372 ist
->file_index
, ist
->st
->index
);
374 if ((ret
= avfilter_graph_create_filter(&ifilter
->filter
, filter
, name
,
375 args
, NULL
, fg
->graph
)) < 0)
378 if (ist
->framerate
.num
) {
379 AVFilterContext
*setpts
;
381 snprintf(name
, sizeof(name
), "force CFR for input from stream %d:%d",
382 ist
->file_index
, ist
->st
->index
);
383 if ((ret
= avfilter_graph_create_filter(&setpts
,
384 avfilter_get_by_name("setpts"),
389 if ((ret
= avfilter_link(setpts
, 0, first_filter
, pad_idx
)) < 0)
392 first_filter
= setpts
;
396 if ((ret
= avfilter_link(ifilter
->filter
, 0, first_filter
, pad_idx
)) < 0)
401 static int configure_input_audio_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
404 AVFilterContext
*first_filter
= in
->filter_ctx
;
405 AVFilter
*filter
= avfilter_get_by_name("abuffer");
406 InputStream
*ist
= ifilter
->ist
;
407 int pad_idx
= in
->pad_idx
;
408 char args
[255], name
[255];
411 snprintf(args
, sizeof(args
), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
412 ":channel_layout=0x%"PRIx64
,
413 1, ist
->st
->codec
->sample_rate
,
414 ist
->st
->codec
->sample_rate
,
415 av_get_sample_fmt_name(ist
->st
->codec
->sample_fmt
),
416 ist
->st
->codec
->channel_layout
);
417 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
418 ist
->file_index
, ist
->st
->index
);
420 if ((ret
= avfilter_graph_create_filter(&ifilter
->filter
, filter
,
425 if (audio_sync_method
> 0) {
426 AVFilterContext
*async
;
429 av_log(NULL
, AV_LOG_WARNING
, "-async has been deprecated. Used the "
430 "asyncts audio filter instead.\n");
432 if (audio_sync_method
> 1)
433 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "compensate=1:"
434 "max_comp=%d:", audio_sync_method
);
435 snprintf(args
+ len
, sizeof(args
) - len
, "min_delta=%f",
436 audio_drift_threshold
);
438 snprintf(name
, sizeof(name
), "graph %d audio sync for input stream %d:%d",
439 fg
->index
, ist
->file_index
, ist
->st
->index
);
440 ret
= avfilter_graph_create_filter(&async
,
441 avfilter_get_by_name("asyncts"),
442 name
, args
, NULL
, fg
->graph
);
446 ret
= avfilter_link(async
, 0, first_filter
, pad_idx
);
450 first_filter
= async
;
453 if (audio_volume
!= 256) {
454 AVFilterContext
*volume
;
456 av_log(NULL
, AV_LOG_WARNING
, "-vol has been deprecated. Use the volume "
457 "audio filter instead.\n");
459 snprintf(args
, sizeof(args
), "volume=%f", audio_volume
/ 256.0);
461 snprintf(name
, sizeof(name
), "graph %d volume for input stream %d:%d",
462 fg
->index
, ist
->file_index
, ist
->st
->index
);
463 ret
= avfilter_graph_create_filter(&volume
,
464 avfilter_get_by_name("volume"),
465 name
, args
, NULL
, fg
->graph
);
469 ret
= avfilter_link(volume
, 0, first_filter
, pad_idx
);
473 first_filter
= volume
;
476 if ((ret
= avfilter_link(ifilter
->filter
, 0, first_filter
, pad_idx
)) < 0)
482 static int configure_input_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
485 av_freep(&ifilter
->name
);
486 DESCRIBE_FILTER_LINK(ifilter
, in
, 1);
488 switch (avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
)) {
489 case AVMEDIA_TYPE_VIDEO
: return configure_input_video_filter(fg
, ifilter
, in
);
490 case AVMEDIA_TYPE_AUDIO
: return configure_input_audio_filter(fg
, ifilter
, in
);
491 default: av_assert0(0);
495 int configure_filtergraph(FilterGraph
*fg
)
497 AVFilterInOut
*inputs
, *outputs
, *cur
;
498 int ret
, i
, init
= !fg
->graph
, simple
= !fg
->graph_desc
;
499 const char *graph_desc
= simple
? fg
->outputs
[0]->ost
->avfilter
:
502 avfilter_graph_free(&fg
->graph
);
503 if (!(fg
->graph
= avfilter_graph_alloc()))
504 return AVERROR(ENOMEM
);
507 OutputStream
*ost
= fg
->outputs
[0]->ost
;
509 AVDictionaryEntry
*e
= NULL
;
511 snprintf(args
, sizeof(args
), "flags=0x%X", (unsigned)ost
->sws_flags
);
512 fg
->graph
->scale_sws_opts
= av_strdup(args
);
515 while ((e
= av_dict_get(fg
->outputs
[0]->ost
->resample_opts
, "", e
,
516 AV_DICT_IGNORE_SUFFIX
))) {
517 av_strlcatf(args
, sizeof(args
), "%s=%s:", e
->key
, e
->value
);
520 args
[strlen(args
) - 1] = '\0';
521 fg
->graph
->resample_lavr_opts
= av_strdup(args
);
524 if ((ret
= avfilter_graph_parse2(fg
->graph
, graph_desc
, &inputs
, &outputs
)) < 0)
527 if (simple
&& (!inputs
|| inputs
->next
|| !outputs
|| outputs
->next
)) {
528 av_log(NULL
, AV_LOG_ERROR
, "Simple filtergraph '%s' does not have "
529 "exactly one input and output.\n", graph_desc
);
530 return AVERROR(EINVAL
);
533 for (cur
= inputs
; !simple
&& init
&& cur
; cur
= cur
->next
)
534 init_input_filter(fg
, cur
);
536 for (cur
= inputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
537 if ((ret
= configure_input_filter(fg
, fg
->inputs
[i
], cur
)) < 0)
539 avfilter_inout_free(&inputs
);
541 if (!init
|| simple
) {
542 /* we already know the mappings between lavfi outputs and output streams,
543 * so we can finish the setup */
544 for (cur
= outputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
545 configure_output_filter(fg
, fg
->outputs
[i
], cur
);
546 avfilter_inout_free(&outputs
);
548 if ((ret
= avfilter_graph_config(fg
->graph
, NULL
)) < 0)
551 /* wait until output mappings are processed */
552 for (cur
= outputs
; cur
;) {
553 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
554 if (!(fg
->outputs
[fg
->nb_outputs
- 1] = av_mallocz(sizeof(*fg
->outputs
[0]))))
556 fg
->outputs
[fg
->nb_outputs
- 1]->graph
= fg
;
557 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
= cur
;
559 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
->next
= NULL
;
566 int ist_in_filtergraph(FilterGraph
*fg
, InputStream
*ist
)
569 for (i
= 0; i
< fg
->nb_inputs
; i
++)
570 if (fg
->inputs
[i
]->ist
== ist
)