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
25 #include "libavfilter/avfilter.h"
26 #include "libavfilter/buffersrc.h"
28 #include "libavresample/avresample.h"
30 #include "libavutil/avassert.h"
31 #include "libavutil/avstring.h"
32 #include "libavutil/channel_layout.h"
33 #include "libavutil/display.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/pixdesc.h"
36 #include "libavutil/pixfmt.h"
37 #include "libavutil/samplefmt.h"
39 /* Define a function for building a string containing a list of
41 #define DEF_CHOOSE_FORMAT(suffix, type, var, supported_list, none, get_name) \
42 static char *choose_ ## suffix (OutputFilter *ofilter) \
44 if (ofilter->var != none) { \
45 get_name(ofilter->var); \
46 return av_strdup(name); \
47 } else if (ofilter->supported_list) { \
49 AVIOContext *s = NULL; \
53 if (avio_open_dyn_buf(&s) < 0) \
56 for (p = ofilter->supported_list; *p != none; p++) { \
58 avio_printf(s, "%s|", name); \
60 len = avio_close_dyn_buf(s, &ret); \
67 DEF_CHOOSE_FORMAT(pix_fmts
, enum AVPixelFormat
, format
, formats
, AV_PIX_FMT_NONE
,
70 DEF_CHOOSE_FORMAT(sample_fmts
, enum AVSampleFormat
, format
, formats
,
71 AV_SAMPLE_FMT_NONE
, GET_SAMPLE_FMT_NAME
)
73 DEF_CHOOSE_FORMAT(sample_rates
, int, sample_rate
, sample_rates
, 0,
76 DEF_CHOOSE_FORMAT(channel_layouts
, uint64_t, channel_layout
, channel_layouts
, 0,
79 int init_simple_filtergraph(InputStream
*ist
, OutputStream
*ost
)
81 FilterGraph
*fg
= av_mallocz(sizeof(*fg
));
85 fg
->index
= nb_filtergraphs
;
87 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
88 if (!(fg
->outputs
[0] = av_mallocz(sizeof(*fg
->outputs
[0]))))
90 fg
->outputs
[0]->ost
= ost
;
91 fg
->outputs
[0]->graph
= fg
;
92 fg
->outputs
[0]->format
= -1;
94 ost
->filter
= fg
->outputs
[0];
96 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
97 if (!(fg
->inputs
[0] = av_mallocz(sizeof(*fg
->inputs
[0]))))
99 fg
->inputs
[0]->ist
= ist
;
100 fg
->inputs
[0]->graph
= fg
;
101 fg
->inputs
[0]->format
= -1;
103 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
104 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[0];
106 GROW_ARRAY(filtergraphs
, nb_filtergraphs
);
107 filtergraphs
[nb_filtergraphs
- 1] = fg
;
112 static void init_input_filter(FilterGraph
*fg
, AVFilterInOut
*in
)
114 InputStream
*ist
= NULL
;
115 enum AVMediaType type
= avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
);
118 // TODO: support other filter types
119 if (type
!= AVMEDIA_TYPE_VIDEO
&& type
!= AVMEDIA_TYPE_AUDIO
) {
120 av_log(NULL
, AV_LOG_FATAL
, "Only video and audio filters supported "
129 int file_idx
= strtol(in
->name
, &p
, 0);
131 if (file_idx
< 0 || file_idx
>= nb_input_files
) {
132 av_log(NULL
, AV_LOG_FATAL
, "Invalid file index %d in filtegraph description %s.\n",
133 file_idx
, fg
->graph_desc
);
136 s
= input_files
[file_idx
]->ctx
;
138 for (i
= 0; i
< s
->nb_streams
; i
++) {
139 if (s
->streams
[i
]->codecpar
->codec_type
!= type
)
141 if (check_stream_specifier(s
, s
->streams
[i
], *p
== ':' ? p
+ 1 : p
) == 1) {
147 av_log(NULL
, AV_LOG_FATAL
, "Stream specifier '%s' in filtergraph description %s "
148 "matches no streams.\n", p
, fg
->graph_desc
);
151 ist
= input_streams
[input_files
[file_idx
]->ist_index
+ st
->index
];
153 /* find the first unused stream of corresponding type */
154 for (i
= 0; i
< nb_input_streams
; i
++) {
155 ist
= input_streams
[i
];
156 if (ist
->dec_ctx
->codec_type
== type
&& ist
->discard
)
159 if (i
== nb_input_streams
) {
160 av_log(NULL
, AV_LOG_FATAL
, "Cannot find a matching stream for "
161 "unlabeled input pad %d on filter %s\n", in
->pad_idx
,
162 in
->filter_ctx
->name
);
169 ist
->decoding_needed
= 1;
170 ist
->st
->discard
= AVDISCARD_NONE
;
172 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
173 if (!(fg
->inputs
[fg
->nb_inputs
- 1] = av_mallocz(sizeof(*fg
->inputs
[0]))))
175 fg
->inputs
[fg
->nb_inputs
- 1]->ist
= ist
;
176 fg
->inputs
[fg
->nb_inputs
- 1]->graph
= fg
;
177 fg
->inputs
[fg
->nb_inputs
- 1]->format
= -1;
179 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
180 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[fg
->nb_inputs
- 1];
183 int init_complex_filtergraph(FilterGraph
*fg
)
185 AVFilterInOut
*inputs
, *outputs
, *cur
;
186 AVFilterGraph
*graph
;
189 /* this graph is only used for determining the kinds of inputs
190 * and outputs we have, and is discarded on exit from this function */
191 graph
= avfilter_graph_alloc();
193 return AVERROR(ENOMEM
);
195 ret
= avfilter_graph_parse2(graph
, fg
->graph_desc
, &inputs
, &outputs
);
199 for (cur
= inputs
; cur
; cur
= cur
->next
)
200 init_input_filter(fg
, cur
);
202 for (cur
= outputs
; cur
;) {
203 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
204 fg
->outputs
[fg
->nb_outputs
- 1] = av_mallocz(sizeof(*fg
->outputs
[0]));
205 if (!fg
->outputs
[fg
->nb_outputs
- 1])
208 fg
->outputs
[fg
->nb_outputs
- 1]->graph
= fg
;
209 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
= cur
;
210 fg
->outputs
[fg
->nb_outputs
- 1]->type
= avfilter_pad_get_type(cur
->filter_ctx
->output_pads
,
213 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
->next
= NULL
;
217 avfilter_inout_free(&inputs
);
218 avfilter_graph_free(&graph
);
222 static int insert_trim(int64_t start_time
, int64_t duration
,
223 AVFilterContext
**last_filter
, int *pad_idx
,
224 const char *filter_name
)
226 AVFilterGraph
*graph
= (*last_filter
)->graph
;
227 AVFilterContext
*ctx
;
228 const AVFilter
*trim
;
229 enum AVMediaType type
= avfilter_pad_get_type((*last_filter
)->output_pads
, *pad_idx
);
230 const char *name
= (type
== AVMEDIA_TYPE_VIDEO
) ?
"trim" : "atrim";
233 if (duration
== INT64_MAX
&& start_time
== AV_NOPTS_VALUE
)
236 trim
= avfilter_get_by_name(name
);
238 av_log(NULL
, AV_LOG_ERROR
, "%s filter not present, cannot limit "
239 "recording time.\n", name
);
240 return AVERROR_FILTER_NOT_FOUND
;
243 ctx
= avfilter_graph_alloc_filter(graph
, trim
, filter_name
);
245 return AVERROR(ENOMEM
);
247 if (duration
!= INT64_MAX
) {
248 ret
= av_opt_set_double(ctx
, "duration", (double)duration
/ 1e6
,
249 AV_OPT_SEARCH_CHILDREN
);
251 if (ret
>= 0 && start_time
!= AV_NOPTS_VALUE
) {
252 ret
= av_opt_set_double(ctx
, "start", (double)start_time
/ 1e6
,
253 AV_OPT_SEARCH_CHILDREN
);
256 av_log(ctx
, AV_LOG_ERROR
, "Error configuring the %s filter", name
);
260 ret
= avfilter_init_str(ctx
, NULL
);
264 ret
= avfilter_link(*last_filter
, *pad_idx
, ctx
, 0);
273 static int insert_filter(AVFilterContext
**last_filter
, int *pad_idx
,
274 const char *filter_name
, const char *args
)
276 AVFilterGraph
*graph
= (*last_filter
)->graph
;
277 AVFilterContext
*ctx
;
280 ret
= avfilter_graph_create_filter(&ctx
,
281 avfilter_get_by_name(filter_name
),
282 filter_name
, args
, NULL
, graph
);
286 ret
= avfilter_link(*last_filter
, *pad_idx
, ctx
, 0);
295 static int configure_output_video_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
298 OutputStream
*ost
= ofilter
->ost
;
299 OutputFile
*of
= output_files
[ost
->file_index
];
300 AVFilterContext
*last_filter
= out
->filter_ctx
;
301 int pad_idx
= out
->pad_idx
;
305 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
306 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
307 avfilter_get_by_name("buffersink"),
308 name
, NULL
, NULL
, fg
->graph
);
312 if (!hw_device_ctx
&& (ofilter
->width
|| ofilter
->height
)) {
314 AVFilterContext
*filter
;
316 snprintf(args
, sizeof(args
), "%d:%d:0x%X",
317 ofilter
->width
, ofilter
->height
,
318 (unsigned)ost
->sws_flags
);
319 snprintf(name
, sizeof(name
), "scaler for output stream %d:%d",
320 ost
->file_index
, ost
->index
);
321 if ((ret
= avfilter_graph_create_filter(&filter
, avfilter_get_by_name("scale"),
322 name
, args
, NULL
, fg
->graph
)) < 0)
324 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
327 last_filter
= filter
;
331 if ((pix_fmts
= choose_pix_fmts(ofilter
))) {
332 AVFilterContext
*filter
;
333 snprintf(name
, sizeof(name
), "pixel format for output stream %d:%d",
334 ost
->file_index
, ost
->index
);
335 ret
= avfilter_graph_create_filter(&filter
,
336 avfilter_get_by_name("format"),
337 "format", pix_fmts
, NULL
, fg
->graph
);
341 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
344 last_filter
= filter
;
348 if (ost
->frame_rate
.num
) {
349 AVFilterContext
*fps
;
352 snprintf(args
, sizeof(args
), "fps=%d/%d", ost
->frame_rate
.num
,
353 ost
->frame_rate
.den
);
354 snprintf(name
, sizeof(name
), "fps for output stream %d:%d",
355 ost
->file_index
, ost
->index
);
356 ret
= avfilter_graph_create_filter(&fps
, avfilter_get_by_name("fps"),
357 name
, args
, NULL
, fg
->graph
);
361 ret
= avfilter_link(last_filter
, pad_idx
, fps
, 0);
368 snprintf(name
, sizeof(name
), "trim for output stream %d:%d",
369 ost
->file_index
, ost
->index
);
370 ret
= insert_trim(of
->start_time
, of
->recording_time
,
371 &last_filter
, &pad_idx
, name
);
376 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
382 static int configure_output_audio_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
384 OutputStream
*ost
= ofilter
->ost
;
385 OutputFile
*of
= output_files
[ost
->file_index
];
386 AVCodecContext
*codec
= ost
->enc_ctx
;
387 AVFilterContext
*last_filter
= out
->filter_ctx
;
388 int pad_idx
= out
->pad_idx
;
389 char *sample_fmts
, *sample_rates
, *channel_layouts
;
394 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
395 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
396 avfilter_get_by_name("abuffersink"),
397 name
, NULL
, NULL
, fg
->graph
);
401 if (codec
->channels
&& !codec
->channel_layout
)
402 codec
->channel_layout
= av_get_default_channel_layout(codec
->channels
);
404 sample_fmts
= choose_sample_fmts(ofilter
);
405 sample_rates
= choose_sample_rates(ofilter
);
406 channel_layouts
= choose_channel_layouts(ofilter
);
407 if (sample_fmts
|| sample_rates
|| channel_layouts
) {
408 AVFilterContext
*format
;
413 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_fmts=%s:",
416 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_rates=%s:",
419 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "channel_layouts=%s:",
423 av_freep(&sample_fmts
);
424 av_freep(&sample_rates
);
425 av_freep(&channel_layouts
);
427 snprintf(name
, sizeof(name
), "audio format for output stream %d:%d",
428 ost
->file_index
, ost
->index
);
429 ret
= avfilter_graph_create_filter(&format
,
430 avfilter_get_by_name("aformat"),
431 name
, args
, NULL
, fg
->graph
);
435 ret
= avfilter_link(last_filter
, pad_idx
, format
, 0);
439 last_filter
= format
;
443 snprintf(name
, sizeof(name
), "trim for output stream %d:%d",
444 ost
->file_index
, ost
->index
);
445 ret
= insert_trim(of
->start_time
, of
->recording_time
,
446 &last_filter
, &pad_idx
, name
);
450 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
456 #define DESCRIBE_FILTER_LINK(f, inout, in) \
458 AVFilterContext *ctx = inout->filter_ctx; \
459 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
460 int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; \
463 if (avio_open_dyn_buf(&pb) < 0) \
466 avio_printf(pb, "%s", ctx->filter->name); \
468 avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
470 avio_close_dyn_buf(pb, &f->name); \
473 int configure_output_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
475 av_freep(&ofilter
->name
);
476 DESCRIBE_FILTER_LINK(ofilter
, out
, 0);
478 switch (avfilter_pad_get_type(out
->filter_ctx
->output_pads
, out
->pad_idx
)) {
479 case AVMEDIA_TYPE_VIDEO
: return configure_output_video_filter(fg
, ofilter
, out
);
480 case AVMEDIA_TYPE_AUDIO
: return configure_output_audio_filter(fg
, ofilter
, out
);
481 default: av_assert0(0);
485 static int configure_input_video_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
488 AVFilterContext
*last_filter
;
489 const AVFilter
*buffer_filt
= avfilter_get_by_name("buffer");
490 InputStream
*ist
= ifilter
->ist
;
491 InputFile
*f
= input_files
[ist
->file_index
];
492 AVRational tb
= ist
->framerate
.num ?
av_inv_q(ist
->framerate
) :
494 AVBufferSrcParameters
*par
;
496 int ret
, pad_idx
= 0;
498 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
499 ist
->file_index
, ist
->st
->index
);
501 ifilter
->filter
= avfilter_graph_alloc_filter(fg
->graph
, buffer_filt
, name
);
502 if (!ifilter
->filter
)
503 return AVERROR(ENOMEM
);
505 par
= av_buffersrc_parameters_alloc();
507 return AVERROR(ENOMEM
);
509 par
->sample_aspect_ratio
= ifilter
->sample_aspect_ratio
;
510 par
->width
= ifilter
->width
;
511 par
->height
= ifilter
->height
;
512 par
->format
= ifilter
->format
;
514 par
->hw_frames_ctx
= ifilter
->hw_frames_ctx
;
516 ret
= av_buffersrc_parameters_set(ifilter
->filter
, par
);
521 ret
= avfilter_init_str(ifilter
->filter
, NULL
);
525 last_filter
= ifilter
->filter
;
527 if (ist
->autorotate
) {
528 uint8_t* displaymatrix
= av_stream_get_side_data(ist
->st
,
529 AV_PKT_DATA_DISPLAYMATRIX
, NULL
);
531 double rot
= av_display_rotation_get((int32_t*) displaymatrix
);
532 if (rot
< -135 || rot
> 135) {
533 ret
= insert_filter(&last_filter
, &pad_idx
, "vflip", NULL
);
536 ret
= insert_filter(&last_filter
, &pad_idx
, "hflip", NULL
);
537 } else if (rot
< -45) {
538 ret
= insert_filter(&last_filter
, &pad_idx
, "transpose", "dir=clock");
539 } else if (rot
> 45) {
540 ret
= insert_filter(&last_filter
, &pad_idx
, "transpose", "dir=cclock");
547 if (ist
->framerate
.num
) {
548 AVFilterContext
*setpts
;
550 snprintf(name
, sizeof(name
), "force CFR for input from stream %d:%d",
551 ist
->file_index
, ist
->st
->index
);
552 if ((ret
= avfilter_graph_create_filter(&setpts
,
553 avfilter_get_by_name("setpts"),
558 if ((ret
= avfilter_link(last_filter
, 0, setpts
, 0)) < 0)
561 last_filter
= setpts
;
564 snprintf(name
, sizeof(name
), "trim for input stream %d:%d",
565 ist
->file_index
, ist
->st
->index
);
566 ret
= insert_trim(((f
->start_time
== AV_NOPTS_VALUE
) || !f
->accurate_seek
) ?
567 AV_NOPTS_VALUE
: 0, f
->recording_time
, &last_filter
, &pad_idx
, name
);
571 if ((ret
= avfilter_link(last_filter
, 0, in
->filter_ctx
, in
->pad_idx
)) < 0)
576 static int configure_input_audio_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
579 AVFilterContext
*last_filter
;
580 const AVFilter
*abuffer_filt
= avfilter_get_by_name("abuffer");
581 InputStream
*ist
= ifilter
->ist
;
582 InputFile
*f
= input_files
[ist
->file_index
];
583 AVBufferSrcParameters
*par
;
584 char args
[255], name
[255];
585 int ret
, pad_idx
= 0;
587 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
588 ist
->file_index
, ist
->st
->index
);
590 ifilter
->filter
= avfilter_graph_alloc_filter(fg
->graph
, abuffer_filt
, name
);
591 if (!ifilter
->filter
)
592 return AVERROR(ENOMEM
);
594 par
= av_buffersrc_parameters_alloc();
596 return AVERROR(ENOMEM
);
598 par
->time_base
= (AVRational
){ 1, ifilter
->sample_rate
};
599 par
->sample_rate
= ifilter
->sample_rate
;
600 par
->format
= ifilter
->format
;
601 par
->channel_layout
= ifilter
->channel_layout
;
603 ret
= av_buffersrc_parameters_set(ifilter
->filter
, par
);
608 ret
= avfilter_init_str(ifilter
->filter
, NULL
);
611 last_filter
= ifilter
->filter
;
613 if (audio_sync_method
> 0) {
614 AVFilterContext
*async
;
617 av_log(NULL
, AV_LOG_WARNING
, "-async has been deprecated. Used the "
618 "asyncts audio filter instead.\n");
620 if (audio_sync_method
> 1)
621 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "compensate=1:"
622 "max_comp=%d:", audio_sync_method
);
623 snprintf(args
+ len
, sizeof(args
) - len
, "min_delta=%f",
624 audio_drift_threshold
);
626 snprintf(name
, sizeof(name
), "graph %d audio sync for input stream %d:%d",
627 fg
->index
, ist
->file_index
, ist
->st
->index
);
628 ret
= avfilter_graph_create_filter(&async
,
629 avfilter_get_by_name("asyncts"),
630 name
, args
, NULL
, fg
->graph
);
634 ret
= avfilter_link(last_filter
, 0, async
, 0);
640 if (audio_volume
!= 256) {
641 AVFilterContext
*volume
;
643 av_log(NULL
, AV_LOG_WARNING
, "-vol has been deprecated. Use the volume "
644 "audio filter instead.\n");
646 snprintf(args
, sizeof(args
), "volume=%f", audio_volume
/ 256.0);
648 snprintf(name
, sizeof(name
), "graph %d volume for input stream %d:%d",
649 fg
->index
, ist
->file_index
, ist
->st
->index
);
650 ret
= avfilter_graph_create_filter(&volume
,
651 avfilter_get_by_name("volume"),
652 name
, args
, NULL
, fg
->graph
);
656 ret
= avfilter_link(last_filter
, 0, volume
, 0);
660 last_filter
= volume
;
663 snprintf(name
, sizeof(name
), "trim for input stream %d:%d",
664 ist
->file_index
, ist
->st
->index
);
665 ret
= insert_trim(((f
->start_time
== AV_NOPTS_VALUE
) || !f
->accurate_seek
) ?
666 AV_NOPTS_VALUE
: 0, f
->recording_time
, &last_filter
, &pad_idx
, name
);
670 if ((ret
= avfilter_link(last_filter
, 0, in
->filter_ctx
, in
->pad_idx
)) < 0)
676 static int configure_input_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
679 av_freep(&ifilter
->name
);
680 DESCRIBE_FILTER_LINK(ifilter
, in
, 1);
682 switch (avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
)) {
683 case AVMEDIA_TYPE_VIDEO
: return configure_input_video_filter(fg
, ifilter
, in
);
684 case AVMEDIA_TYPE_AUDIO
: return configure_input_audio_filter(fg
, ifilter
, in
);
685 default: av_assert0(0);
689 int configure_filtergraph(FilterGraph
*fg
)
691 AVFilterInOut
*inputs
, *outputs
, *cur
;
692 int ret
, i
, simple
= filtergraph_is_simple(fg
);
693 const char *graph_desc
= simple ? fg
->outputs
[0]->ost
->avfilter
:
696 avfilter_graph_free(&fg
->graph
);
697 if (!(fg
->graph
= avfilter_graph_alloc()))
698 return AVERROR(ENOMEM
);
701 OutputStream
*ost
= fg
->outputs
[0]->ost
;
703 AVDictionaryEntry
*e
= NULL
;
705 snprintf(args
, sizeof(args
), "flags=0x%X", (unsigned)ost
->sws_flags
);
706 fg
->graph
->scale_sws_opts
= av_strdup(args
);
709 while ((e
= av_dict_get(fg
->outputs
[0]->ost
->resample_opts
, "", e
,
710 AV_DICT_IGNORE_SUFFIX
))) {
711 av_strlcatf(args
, sizeof(args
), "%s=%s:", e
->key
, e
->value
);
714 args
[strlen(args
) - 1] = '\0';
715 fg
->graph
->resample_lavr_opts
= av_strdup(args
);
718 if ((ret
= avfilter_graph_parse2(fg
->graph
, graph_desc
, &inputs
, &outputs
)) < 0)
722 for (i
= 0; i
< fg
->graph
->nb_filters
; i
++) {
723 fg
->graph
->filters
[i
]->hw_device_ctx
= av_buffer_ref(hw_device_ctx
);
727 if (simple
&& (!inputs
|| inputs
->next
|| !outputs
|| outputs
->next
)) {
728 av_log(NULL
, AV_LOG_ERROR
, "Simple filtergraph '%s' does not have "
729 "exactly one input and output.\n", graph_desc
);
730 return AVERROR(EINVAL
);
733 for (cur
= inputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
734 if ((ret
= configure_input_filter(fg
, fg
->inputs
[i
], cur
)) < 0)
736 avfilter_inout_free(&inputs
);
738 for (cur
= outputs
, i
= 0; cur
; cur
= cur
->next
, i
++) {
739 OutputFilter
*ofilter
= fg
->outputs
[i
];
741 configure_output_filter(fg
, ofilter
, cur
);
744 avfilter_inout_free(&outputs
);
746 if ((ret
= avfilter_graph_config(fg
->graph
, NULL
)) < 0)
749 /* limit the lists of allowed formats to the ones selected, to
750 * make sure they stay the same if the filtergraph is reconfigured later */
751 for (i
= 0; i
< fg
->nb_outputs
; i
++) {
752 OutputFilter
*ofilter
= fg
->outputs
[i
];
753 AVFilterLink
*link
= ofilter
->filter
->inputs
[0];
755 ofilter
->format
= link
->format
;
757 ofilter
->width
= link
->w
;
758 ofilter
->height
= link
->h
;
760 ofilter
->sample_rate
= link
->sample_rate
;
761 ofilter
->channel_layout
= link
->channel_layout
;
767 int ifilter_parameters_from_frame(InputFilter
*ifilter
, const AVFrame
*frame
)
769 av_buffer_unref(&ifilter
->hw_frames_ctx
);
771 ifilter
->format
= frame
->format
;
773 ifilter
->width
= frame
->width
;
774 ifilter
->height
= frame
->height
;
775 ifilter
->sample_aspect_ratio
= frame
->sample_aspect_ratio
;
777 ifilter
->sample_rate
= frame
->sample_rate
;
778 ifilter
->channel_layout
= frame
->channel_layout
;
780 if (frame
->hw_frames_ctx
) {
781 ifilter
->hw_frames_ctx
= av_buffer_ref(frame
->hw_frames_ctx
);
782 if (!ifilter
->hw_frames_ctx
)
783 return AVERROR(ENOMEM
);
789 int ifilter_parameters_from_decoder(InputFilter
*ifilter
, const AVCodecContext
*avctx
)
791 av_buffer_unref(&ifilter
->hw_frames_ctx
);
793 if (avctx
->codec_type
== AVMEDIA_TYPE_VIDEO
)
794 ifilter
->format
= avctx
->pix_fmt
;
796 ifilter
->format
= avctx
->sample_fmt
;
798 ifilter
->width
= avctx
->width
;
799 ifilter
->height
= avctx
->height
;
800 ifilter
->sample_aspect_ratio
= avctx
->sample_aspect_ratio
;
802 ifilter
->sample_rate
= avctx
->sample_rate
;
803 ifilter
->channel_layout
= avctx
->channel_layout
;
805 if (avctx
->hw_frames_ctx
) {
806 ifilter
->hw_frames_ctx
= av_buffer_ref(avctx
->hw_frames_ctx
);
807 if (!ifilter
->hw_frames_ctx
)
808 return AVERROR(ENOMEM
);
814 int ist_in_filtergraph(FilterGraph
*fg
, InputStream
*ist
)
817 for (i
= 0; i
< fg
->nb_inputs
; i
++)
818 if (fg
->inputs
[i
]->ist
== ist
)
823 int filtergraph_is_simple(FilterGraph
*fg
)
825 return !fg
->graph_desc
;