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 fg
->inputs
[0]->frame_queue
= av_fifo_alloc(8 * sizeof(AVFrame
*));
107 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
108 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[0];
110 GROW_ARRAY(filtergraphs
, nb_filtergraphs
);
111 filtergraphs
[nb_filtergraphs
- 1] = fg
;
116 static void init_input_filter(FilterGraph
*fg
, AVFilterInOut
*in
)
118 InputStream
*ist
= NULL
;
119 enum AVMediaType type
= avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
);
122 // TODO: support other filter types
123 if (type
!= AVMEDIA_TYPE_VIDEO
&& type
!= AVMEDIA_TYPE_AUDIO
) {
124 av_log(NULL
, AV_LOG_FATAL
, "Only video and audio filters supported "
133 int file_idx
= strtol(in
->name
, &p
, 0);
135 if (file_idx
< 0 || file_idx
>= nb_input_files
) {
136 av_log(NULL
, AV_LOG_FATAL
, "Invalid file index %d in filtegraph description %s.\n",
137 file_idx
, fg
->graph_desc
);
140 s
= input_files
[file_idx
]->ctx
;
142 for (i
= 0; i
< s
->nb_streams
; i
++) {
143 if (s
->streams
[i
]->codecpar
->codec_type
!= type
)
145 if (check_stream_specifier(s
, s
->streams
[i
], *p
== ':' ? p
+ 1 : p
) == 1) {
151 av_log(NULL
, AV_LOG_FATAL
, "Stream specifier '%s' in filtergraph description %s "
152 "matches no streams.\n", p
, fg
->graph_desc
);
155 ist
= input_streams
[input_files
[file_idx
]->ist_index
+ st
->index
];
157 /* find the first unused stream of corresponding type */
158 for (i
= 0; i
< nb_input_streams
; i
++) {
159 ist
= input_streams
[i
];
160 if (ist
->dec_ctx
->codec_type
== type
&& ist
->discard
)
163 if (i
== nb_input_streams
) {
164 av_log(NULL
, AV_LOG_FATAL
, "Cannot find a matching stream for "
165 "unlabeled input pad %d on filter %s\n", in
->pad_idx
,
166 in
->filter_ctx
->name
);
173 ist
->decoding_needed
= 1;
174 ist
->st
->discard
= AVDISCARD_NONE
;
176 GROW_ARRAY(fg
->inputs
, fg
->nb_inputs
);
177 if (!(fg
->inputs
[fg
->nb_inputs
- 1] = av_mallocz(sizeof(*fg
->inputs
[0]))))
179 fg
->inputs
[fg
->nb_inputs
- 1]->ist
= ist
;
180 fg
->inputs
[fg
->nb_inputs
- 1]->graph
= fg
;
181 fg
->inputs
[fg
->nb_inputs
- 1]->format
= -1;
183 fg
->inputs
[fg
->nb_inputs
- 1]->frame_queue
= av_fifo_alloc(8 * sizeof(AVFrame
*));
184 if (!fg
->inputs
[fg
->nb_inputs
- 1]->frame_queue
)
187 GROW_ARRAY(ist
->filters
, ist
->nb_filters
);
188 ist
->filters
[ist
->nb_filters
- 1] = fg
->inputs
[fg
->nb_inputs
- 1];
191 int init_complex_filtergraph(FilterGraph
*fg
)
193 AVFilterInOut
*inputs
, *outputs
, *cur
;
194 AVFilterGraph
*graph
;
197 /* this graph is only used for determining the kinds of inputs
198 * and outputs we have, and is discarded on exit from this function */
199 graph
= avfilter_graph_alloc();
201 return AVERROR(ENOMEM
);
203 ret
= avfilter_graph_parse2(graph
, fg
->graph_desc
, &inputs
, &outputs
);
207 for (cur
= inputs
; cur
; cur
= cur
->next
)
208 init_input_filter(fg
, cur
);
210 for (cur
= outputs
; cur
;) {
211 GROW_ARRAY(fg
->outputs
, fg
->nb_outputs
);
212 fg
->outputs
[fg
->nb_outputs
- 1] = av_mallocz(sizeof(*fg
->outputs
[0]));
213 if (!fg
->outputs
[fg
->nb_outputs
- 1])
216 fg
->outputs
[fg
->nb_outputs
- 1]->graph
= fg
;
217 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
= cur
;
218 fg
->outputs
[fg
->nb_outputs
- 1]->type
= avfilter_pad_get_type(cur
->filter_ctx
->output_pads
,
221 fg
->outputs
[fg
->nb_outputs
- 1]->out_tmp
->next
= NULL
;
225 avfilter_inout_free(&inputs
);
226 avfilter_graph_free(&graph
);
230 static int insert_trim(int64_t start_time
, int64_t duration
,
231 AVFilterContext
**last_filter
, int *pad_idx
,
232 const char *filter_name
)
234 AVFilterGraph
*graph
= (*last_filter
)->graph
;
235 AVFilterContext
*ctx
;
236 const AVFilter
*trim
;
237 enum AVMediaType type
= avfilter_pad_get_type((*last_filter
)->output_pads
, *pad_idx
);
238 const char *name
= (type
== AVMEDIA_TYPE_VIDEO
) ?
"trim" : "atrim";
241 if (duration
== INT64_MAX
&& start_time
== AV_NOPTS_VALUE
)
244 trim
= avfilter_get_by_name(name
);
246 av_log(NULL
, AV_LOG_ERROR
, "%s filter not present, cannot limit "
247 "recording time.\n", name
);
248 return AVERROR_FILTER_NOT_FOUND
;
251 ctx
= avfilter_graph_alloc_filter(graph
, trim
, filter_name
);
253 return AVERROR(ENOMEM
);
255 if (duration
!= INT64_MAX
) {
256 ret
= av_opt_set_double(ctx
, "duration", (double)duration
/ 1e6
,
257 AV_OPT_SEARCH_CHILDREN
);
259 if (ret
>= 0 && start_time
!= AV_NOPTS_VALUE
) {
260 ret
= av_opt_set_double(ctx
, "start", (double)start_time
/ 1e6
,
261 AV_OPT_SEARCH_CHILDREN
);
264 av_log(ctx
, AV_LOG_ERROR
, "Error configuring the %s filter", name
);
268 ret
= avfilter_init_str(ctx
, NULL
);
272 ret
= avfilter_link(*last_filter
, *pad_idx
, ctx
, 0);
281 static int insert_filter(AVFilterContext
**last_filter
, int *pad_idx
,
282 const char *filter_name
, const char *args
)
284 AVFilterGraph
*graph
= (*last_filter
)->graph
;
285 AVFilterContext
*ctx
;
288 ret
= avfilter_graph_create_filter(&ctx
,
289 avfilter_get_by_name(filter_name
),
290 filter_name
, args
, NULL
, graph
);
294 ret
= avfilter_link(*last_filter
, *pad_idx
, ctx
, 0);
303 static int configure_output_video_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
306 OutputStream
*ost
= ofilter
->ost
;
307 OutputFile
*of
= output_files
[ost
->file_index
];
308 AVFilterContext
*last_filter
= out
->filter_ctx
;
309 int pad_idx
= out
->pad_idx
;
313 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
314 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
315 avfilter_get_by_name("buffersink"),
316 name
, NULL
, NULL
, fg
->graph
);
320 if (ofilter
->width
|| ofilter
->height
) {
322 AVFilterContext
*filter
;
324 snprintf(args
, sizeof(args
), "%d:%d:0x%X",
325 ofilter
->width
, ofilter
->height
,
326 (unsigned)ost
->sws_flags
);
327 snprintf(name
, sizeof(name
), "scaler for output stream %d:%d",
328 ost
->file_index
, ost
->index
);
329 if ((ret
= avfilter_graph_create_filter(&filter
, avfilter_get_by_name("scale"),
330 name
, args
, NULL
, fg
->graph
)) < 0)
332 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
335 last_filter
= filter
;
339 if ((pix_fmts
= choose_pix_fmts(ofilter
))) {
340 AVFilterContext
*filter
;
341 snprintf(name
, sizeof(name
), "pixel format for output stream %d:%d",
342 ost
->file_index
, ost
->index
);
343 ret
= avfilter_graph_create_filter(&filter
,
344 avfilter_get_by_name("format"),
345 "format", pix_fmts
, NULL
, fg
->graph
);
349 if ((ret
= avfilter_link(last_filter
, pad_idx
, filter
, 0)) < 0)
352 last_filter
= filter
;
356 if (ost
->frame_rate
.num
) {
357 AVFilterContext
*fps
;
360 snprintf(args
, sizeof(args
), "fps=%d/%d", ost
->frame_rate
.num
,
361 ost
->frame_rate
.den
);
362 snprintf(name
, sizeof(name
), "fps for output stream %d:%d",
363 ost
->file_index
, ost
->index
);
364 ret
= avfilter_graph_create_filter(&fps
, avfilter_get_by_name("fps"),
365 name
, args
, NULL
, fg
->graph
);
369 ret
= avfilter_link(last_filter
, pad_idx
, fps
, 0);
376 snprintf(name
, sizeof(name
), "trim for output stream %d:%d",
377 ost
->file_index
, ost
->index
);
378 ret
= insert_trim(of
->start_time
, of
->recording_time
,
379 &last_filter
, &pad_idx
, name
);
384 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
390 static int configure_output_audio_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
392 OutputStream
*ost
= ofilter
->ost
;
393 OutputFile
*of
= output_files
[ost
->file_index
];
394 AVCodecContext
*codec
= ost
->enc_ctx
;
395 AVFilterContext
*last_filter
= out
->filter_ctx
;
396 int pad_idx
= out
->pad_idx
;
397 char *sample_fmts
, *sample_rates
, *channel_layouts
;
402 snprintf(name
, sizeof(name
), "output stream %d:%d", ost
->file_index
, ost
->index
);
403 ret
= avfilter_graph_create_filter(&ofilter
->filter
,
404 avfilter_get_by_name("abuffersink"),
405 name
, NULL
, NULL
, fg
->graph
);
409 if (codec
->channels
&& !codec
->channel_layout
)
410 codec
->channel_layout
= av_get_default_channel_layout(codec
->channels
);
412 sample_fmts
= choose_sample_fmts(ofilter
);
413 sample_rates
= choose_sample_rates(ofilter
);
414 channel_layouts
= choose_channel_layouts(ofilter
);
415 if (sample_fmts
|| sample_rates
|| channel_layouts
) {
416 AVFilterContext
*format
;
421 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_fmts=%s:",
424 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "sample_rates=%s:",
427 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "channel_layouts=%s:",
431 av_freep(&sample_fmts
);
432 av_freep(&sample_rates
);
433 av_freep(&channel_layouts
);
435 snprintf(name
, sizeof(name
), "audio format for output stream %d:%d",
436 ost
->file_index
, ost
->index
);
437 ret
= avfilter_graph_create_filter(&format
,
438 avfilter_get_by_name("aformat"),
439 name
, args
, NULL
, fg
->graph
);
443 ret
= avfilter_link(last_filter
, pad_idx
, format
, 0);
447 last_filter
= format
;
451 snprintf(name
, sizeof(name
), "trim for output stream %d:%d",
452 ost
->file_index
, ost
->index
);
453 ret
= insert_trim(of
->start_time
, of
->recording_time
,
454 &last_filter
, &pad_idx
, name
);
458 if ((ret
= avfilter_link(last_filter
, pad_idx
, ofilter
->filter
, 0)) < 0)
464 #define DESCRIBE_FILTER_LINK(f, inout, in) \
466 AVFilterContext *ctx = inout->filter_ctx; \
467 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
468 int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; \
471 if (avio_open_dyn_buf(&pb) < 0) \
474 avio_printf(pb, "%s", ctx->filter->name); \
476 avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
478 avio_close_dyn_buf(pb, &f->name); \
481 int configure_output_filter(FilterGraph
*fg
, OutputFilter
*ofilter
, AVFilterInOut
*out
)
483 av_freep(&ofilter
->name
);
484 DESCRIBE_FILTER_LINK(ofilter
, out
, 0);
486 switch (avfilter_pad_get_type(out
->filter_ctx
->output_pads
, out
->pad_idx
)) {
487 case AVMEDIA_TYPE_VIDEO
: return configure_output_video_filter(fg
, ofilter
, out
);
488 case AVMEDIA_TYPE_AUDIO
: return configure_output_audio_filter(fg
, ofilter
, out
);
489 default: av_assert0(0);
493 static int configure_input_video_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
496 AVFilterContext
*last_filter
;
497 const AVFilter
*buffer_filt
= avfilter_get_by_name("buffer");
498 InputStream
*ist
= ifilter
->ist
;
499 InputFile
*f
= input_files
[ist
->file_index
];
500 AVRational tb
= ist
->framerate
.num ?
av_inv_q(ist
->framerate
) :
502 AVBufferSrcParameters
*par
;
504 int ret
, pad_idx
= 0;
506 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
507 ist
->file_index
, ist
->st
->index
);
509 ifilter
->filter
= avfilter_graph_alloc_filter(fg
->graph
, buffer_filt
, name
);
510 if (!ifilter
->filter
)
511 return AVERROR(ENOMEM
);
513 par
= av_buffersrc_parameters_alloc();
515 return AVERROR(ENOMEM
);
517 par
->sample_aspect_ratio
= ifilter
->sample_aspect_ratio
;
518 par
->width
= ifilter
->width
;
519 par
->height
= ifilter
->height
;
520 par
->format
= ifilter
->format
;
522 if (ist
->framerate
.num
)
523 par
->frame_rate
= ist
->framerate
;
524 par
->hw_frames_ctx
= ifilter
->hw_frames_ctx
;
526 ret
= av_buffersrc_parameters_set(ifilter
->filter
, par
);
531 ret
= avfilter_init_str(ifilter
->filter
, NULL
);
535 last_filter
= ifilter
->filter
;
537 if (ist
->autorotate
) {
538 uint8_t* displaymatrix
= av_stream_get_side_data(ist
->st
,
539 AV_PKT_DATA_DISPLAYMATRIX
, NULL
);
541 double rot
= av_display_rotation_get((int32_t*) displaymatrix
);
542 if (rot
< -135 || rot
> 135) {
543 ret
= insert_filter(&last_filter
, &pad_idx
, "vflip", NULL
);
546 ret
= insert_filter(&last_filter
, &pad_idx
, "hflip", NULL
);
547 } else if (rot
< -45) {
548 ret
= insert_filter(&last_filter
, &pad_idx
, "transpose", "dir=clock");
549 } else if (rot
> 45) {
550 ret
= insert_filter(&last_filter
, &pad_idx
, "transpose", "dir=cclock");
557 snprintf(name
, sizeof(name
), "trim for input stream %d:%d",
558 ist
->file_index
, ist
->st
->index
);
559 ret
= insert_trim(((f
->start_time
== AV_NOPTS_VALUE
) || !f
->accurate_seek
) ?
560 AV_NOPTS_VALUE
: 0, f
->recording_time
, &last_filter
, &pad_idx
, name
);
564 if ((ret
= avfilter_link(last_filter
, 0, in
->filter_ctx
, in
->pad_idx
)) < 0)
569 static int configure_input_audio_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
572 AVFilterContext
*last_filter
;
573 const AVFilter
*abuffer_filt
= avfilter_get_by_name("abuffer");
574 InputStream
*ist
= ifilter
->ist
;
575 InputFile
*f
= input_files
[ist
->file_index
];
576 AVBufferSrcParameters
*par
;
577 char args
[255], name
[255];
578 int ret
, pad_idx
= 0;
580 snprintf(name
, sizeof(name
), "graph %d input from stream %d:%d", fg
->index
,
581 ist
->file_index
, ist
->st
->index
);
583 ifilter
->filter
= avfilter_graph_alloc_filter(fg
->graph
, abuffer_filt
, name
);
584 if (!ifilter
->filter
)
585 return AVERROR(ENOMEM
);
587 par
= av_buffersrc_parameters_alloc();
589 return AVERROR(ENOMEM
);
591 par
->time_base
= (AVRational
){ 1, ifilter
->sample_rate
};
592 par
->sample_rate
= ifilter
->sample_rate
;
593 par
->format
= ifilter
->format
;
594 par
->channel_layout
= ifilter
->channel_layout
;
596 ret
= av_buffersrc_parameters_set(ifilter
->filter
, par
);
601 ret
= avfilter_init_str(ifilter
->filter
, NULL
);
604 last_filter
= ifilter
->filter
;
606 if (audio_sync_method
> 0) {
607 AVFilterContext
*async
;
610 av_log(NULL
, AV_LOG_WARNING
, "-async has been deprecated. Used the "
611 "asyncts audio filter instead.\n");
613 if (audio_sync_method
> 1)
614 len
+= snprintf(args
+ len
, sizeof(args
) - len
, "compensate=1:"
615 "max_comp=%d:", audio_sync_method
);
616 snprintf(args
+ len
, sizeof(args
) - len
, "min_delta=%f",
617 audio_drift_threshold
);
619 snprintf(name
, sizeof(name
), "graph %d audio sync for input stream %d:%d",
620 fg
->index
, ist
->file_index
, ist
->st
->index
);
621 ret
= avfilter_graph_create_filter(&async
,
622 avfilter_get_by_name("asyncts"),
623 name
, args
, NULL
, fg
->graph
);
627 ret
= avfilter_link(last_filter
, 0, async
, 0);
633 if (audio_volume
!= 256) {
634 AVFilterContext
*volume
;
636 av_log(NULL
, AV_LOG_WARNING
, "-vol has been deprecated. Use the volume "
637 "audio filter instead.\n");
639 snprintf(args
, sizeof(args
), "volume=%f", audio_volume
/ 256.0);
641 snprintf(name
, sizeof(name
), "graph %d volume for input stream %d:%d",
642 fg
->index
, ist
->file_index
, ist
->st
->index
);
643 ret
= avfilter_graph_create_filter(&volume
,
644 avfilter_get_by_name("volume"),
645 name
, args
, NULL
, fg
->graph
);
649 ret
= avfilter_link(last_filter
, 0, volume
, 0);
653 last_filter
= volume
;
656 snprintf(name
, sizeof(name
), "trim for input stream %d:%d",
657 ist
->file_index
, ist
->st
->index
);
658 ret
= insert_trim(((f
->start_time
== AV_NOPTS_VALUE
) || !f
->accurate_seek
) ?
659 AV_NOPTS_VALUE
: 0, f
->recording_time
, &last_filter
, &pad_idx
, name
);
663 if ((ret
= avfilter_link(last_filter
, 0, in
->filter_ctx
, in
->pad_idx
)) < 0)
669 static int configure_input_filter(FilterGraph
*fg
, InputFilter
*ifilter
,
672 av_freep(&ifilter
->name
);
673 DESCRIBE_FILTER_LINK(ifilter
, in
, 1);
675 switch (avfilter_pad_get_type(in
->filter_ctx
->input_pads
, in
->pad_idx
)) {
676 case AVMEDIA_TYPE_VIDEO
: return configure_input_video_filter(fg
, ifilter
, in
);
677 case AVMEDIA_TYPE_AUDIO
: return configure_input_audio_filter(fg
, ifilter
, in
);
678 default: av_assert0(0);
682 int configure_filtergraph(FilterGraph
*fg
)
684 AVFilterInOut
*inputs
, *outputs
, *cur
;
685 int ret
, i
, simple
= filtergraph_is_simple(fg
);
686 const char *graph_desc
= simple ? fg
->outputs
[0]->ost
->avfilter
:
689 avfilter_graph_free(&fg
->graph
);
690 if (!(fg
->graph
= avfilter_graph_alloc()))
691 return AVERROR(ENOMEM
);
694 OutputStream
*ost
= fg
->outputs
[0]->ost
;
696 AVDictionaryEntry
*e
= NULL
;
698 snprintf(args
, sizeof(args
), "flags=0x%X", (unsigned)ost
->sws_flags
);
699 fg
->graph
->scale_sws_opts
= av_strdup(args
);
702 while ((e
= av_dict_get(fg
->outputs
[0]->ost
->resample_opts
, "", e
,
703 AV_DICT_IGNORE_SUFFIX
))) {
704 av_strlcatf(args
, sizeof(args
), "%s=%s:", e
->key
, e
->value
);
707 args
[strlen(args
) - 1] = '\0';
708 fg
->graph
->resample_lavr_opts
= av_strdup(args
);
711 if ((ret
= avfilter_graph_parse2(fg
->graph
, graph_desc
, &inputs
, &outputs
)) < 0)
715 for (i
= 0; i
< fg
->graph
->nb_filters
; i
++) {
716 fg
->graph
->filters
[i
]->hw_device_ctx
= av_buffer_ref(hw_device_ctx
);
720 if (simple
&& (!inputs
|| inputs
->next
|| !outputs
|| outputs
->next
)) {
721 av_log(NULL
, AV_LOG_ERROR
, "Simple filtergraph '%s' does not have "
722 "exactly one input and output.\n", graph_desc
);
723 ret
= AVERROR(EINVAL
);
727 for (cur
= inputs
, i
= 0; cur
; cur
= cur
->next
, i
++)
728 if ((ret
= configure_input_filter(fg
, fg
->inputs
[i
], cur
)) < 0)
730 avfilter_inout_free(&inputs
);
732 for (cur
= outputs
, i
= 0; cur
; cur
= cur
->next
, i
++) {
733 OutputFilter
*ofilter
= fg
->outputs
[i
];
735 configure_output_filter(fg
, ofilter
, cur
);
738 avfilter_inout_free(&outputs
);
740 if ((ret
= avfilter_graph_config(fg
->graph
, NULL
)) < 0)
743 /* limit the lists of allowed formats to the ones selected, to
744 * make sure they stay the same if the filtergraph is reconfigured later */
745 for (i
= 0; i
< fg
->nb_outputs
; i
++) {
746 OutputFilter
*ofilter
= fg
->outputs
[i
];
747 AVFilterLink
*link
= ofilter
->filter
->inputs
[0];
749 ofilter
->format
= link
->format
;
751 ofilter
->width
= link
->w
;
752 ofilter
->height
= link
->h
;
754 ofilter
->sample_rate
= link
->sample_rate
;
755 ofilter
->channel_layout
= link
->channel_layout
;
758 for (i
= 0; i
< fg
->nb_inputs
; i
++) {
759 while (av_fifo_size(fg
->inputs
[i
]->frame_queue
)) {
761 av_fifo_generic_read(fg
->inputs
[i
]->frame_queue
, &tmp
, sizeof(tmp
), NULL
);
762 ret
= av_buffersrc_add_frame(fg
->inputs
[i
]->filter
, tmp
);
769 /* send the EOFs for the finished inputs */
770 for (i
= 0; i
< fg
->nb_inputs
; i
++) {
771 if (fg
->inputs
[i
]->eof
) {
772 ret
= av_buffersrc_add_frame(fg
->inputs
[i
]->filter
, NULL
);
780 avfilter_graph_free(&fg
->graph
);
784 int ifilter_parameters_from_frame(InputFilter
*ifilter
, const AVFrame
*frame
)
786 av_buffer_unref(&ifilter
->hw_frames_ctx
);
788 ifilter
->format
= frame
->format
;
790 ifilter
->width
= frame
->width
;
791 ifilter
->height
= frame
->height
;
792 ifilter
->sample_aspect_ratio
= frame
->sample_aspect_ratio
;
794 ifilter
->sample_rate
= frame
->sample_rate
;
795 ifilter
->channel_layout
= frame
->channel_layout
;
797 if (frame
->hw_frames_ctx
) {
798 ifilter
->hw_frames_ctx
= av_buffer_ref(frame
->hw_frames_ctx
);
799 if (!ifilter
->hw_frames_ctx
)
800 return AVERROR(ENOMEM
);
806 int ist_in_filtergraph(FilterGraph
*fg
, InputStream
*ist
)
809 for (i
= 0; i
< fg
->nb_inputs
; i
++)
810 if (fg
->inputs
[i
]->ist
== ist
)
815 int filtergraph_is_simple(FilterGraph
*fg
)
817 return !fg
->graph_desc
;