]> git.sesse.net Git - ffmpeg/blob - fftools/ffmpeg_filter.c
avcodec/mjpegenc: Include all supported pix_fmts in mpegenc pix_fmts
[ffmpeg] / fftools / ffmpeg_filter.c
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 #include "libavfilter/buffersrc.h"
28
29 #include "libavresample/avresample.h"
30
31 #include "libavutil/avassert.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/display.h"
36 #include "libavutil/opt.h"
37 #include "libavutil/pixdesc.h"
38 #include "libavutil/pixfmt.h"
39 #include "libavutil/imgutils.h"
40 #include "libavutil/samplefmt.h"
41
42 // FIXME: YUV420P etc. are actually supported with full color range,
43 // yet the latter information isn't available here.
44 static const enum AVPixelFormat *get_compliance_normal_pix_fmts(enum AVCodecID codec_id, const enum AVPixelFormat default_formats[])
45 {
46     static const enum AVPixelFormat mjpeg_formats[] =
47         { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
48           AV_PIX_FMT_NONE };
49
50     if (codec_id == AV_CODEC_ID_MJPEG) {
51         return mjpeg_formats;
52     } else {
53         return default_formats;
54     }
55 }
56
57 static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx,
58                                     const AVCodec *codec, enum AVPixelFormat target)
59 {
60     if (codec && codec->pix_fmts) {
61         const enum AVPixelFormat *p = codec->pix_fmts;
62         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target);
63         //FIXME: This should check for AV_PIX_FMT_FLAG_ALPHA after PAL8 pixel format without alpha is implemented
64         int has_alpha = desc ? desc->nb_components % 2 == 0 : 0;
65         enum AVPixelFormat best= AV_PIX_FMT_NONE;
66
67         if (enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
68             p = get_compliance_normal_pix_fmts(enc_ctx->codec_id, p);
69         }
70         for (; *p != AV_PIX_FMT_NONE; p++) {
71             best = av_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL);
72             if (*p == target)
73                 break;
74         }
75         if (*p == AV_PIX_FMT_NONE) {
76             if (target != AV_PIX_FMT_NONE)
77                 av_log(NULL, AV_LOG_WARNING,
78                        "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
79                        av_get_pix_fmt_name(target),
80                        codec->name,
81                        av_get_pix_fmt_name(best));
82             return best;
83         }
84     }
85     return target;
86 }
87
88 static char *choose_pix_fmts(OutputFilter *ofilter)
89 {
90     OutputStream *ost = ofilter->ost;
91     AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0);
92     if (strict_dict)
93         // used by choose_pixel_fmt() and below
94         av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0);
95
96      if (ost->keep_pix_fmt) {
97         avfilter_graph_set_auto_convert(ofilter->graph->graph,
98                                             AVFILTER_AUTO_CONVERT_NONE);
99         if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE)
100             return NULL;
101         return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt));
102     }
103     if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) {
104         return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)));
105     } else if (ost->enc && ost->enc->pix_fmts) {
106         const enum AVPixelFormat *p;
107         AVIOContext *s = NULL;
108         uint8_t *ret;
109         int len;
110
111         if (avio_open_dyn_buf(&s) < 0)
112             exit_program(1);
113
114         p = ost->enc->pix_fmts;
115         if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
116             p = get_compliance_normal_pix_fmts(ost->enc_ctx->codec_id, p);
117         }
118
119         for (; *p != AV_PIX_FMT_NONE; p++) {
120             const char *name = av_get_pix_fmt_name(*p);
121             avio_printf(s, "%s|", name);
122         }
123         len = avio_close_dyn_buf(s, &ret);
124         ret[len - 1] = 0;
125         return ret;
126     } else
127         return NULL;
128 }
129
130 /* Define a function for building a string containing a list of
131  * allowed formats. */
132 #define DEF_CHOOSE_FORMAT(suffix, type, var, supported_list, none, get_name)   \
133 static char *choose_ ## suffix (OutputFilter *ofilter)                         \
134 {                                                                              \
135     if (ofilter->var != none) {                                                \
136         get_name(ofilter->var);                                                \
137         return av_strdup(name);                                                \
138     } else if (ofilter->supported_list) {                                      \
139         const type *p;                                                         \
140         AVIOContext *s = NULL;                                                 \
141         uint8_t *ret;                                                          \
142         int len;                                                               \
143                                                                                \
144         if (avio_open_dyn_buf(&s) < 0)                                         \
145             exit_program(1);                                                           \
146                                                                                \
147         for (p = ofilter->supported_list; *p != none; p++) {                   \
148             get_name(*p);                                                      \
149             avio_printf(s, "%s|", name);                                       \
150         }                                                                      \
151         len = avio_close_dyn_buf(s, &ret);                                     \
152         ret[len - 1] = 0;                                                      \
153         return ret;                                                            \
154     } else                                                                     \
155         return NULL;                                                           \
156 }
157
158 //DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats, AV_PIX_FMT_NONE,
159 //                  GET_PIX_FMT_NAME)
160
161 DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats,
162                   AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME)
163
164 DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,
165                   GET_SAMPLE_RATE_NAME)
166
167 DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0,
168                   GET_CH_LAYOUT_NAME)
169
170 int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
171 {
172     FilterGraph *fg = av_mallocz(sizeof(*fg));
173
174     if (!fg)
175         exit_program(1);
176     fg->index = nb_filtergraphs;
177
178     GROW_ARRAY(fg->outputs, fg->nb_outputs);
179     if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
180         exit_program(1);
181     fg->outputs[0]->ost   = ost;
182     fg->outputs[0]->graph = fg;
183     fg->outputs[0]->format = -1;
184
185     ost->filter = fg->outputs[0];
186
187     GROW_ARRAY(fg->inputs, fg->nb_inputs);
188     if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
189         exit_program(1);
190     fg->inputs[0]->ist   = ist;
191     fg->inputs[0]->graph = fg;
192     fg->inputs[0]->format = -1;
193
194     fg->inputs[0]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*));
195     if (!fg->inputs[0]->frame_queue)
196         exit_program(1);
197
198     GROW_ARRAY(ist->filters, ist->nb_filters);
199     ist->filters[ist->nb_filters - 1] = fg->inputs[0];
200
201     GROW_ARRAY(filtergraphs, nb_filtergraphs);
202     filtergraphs[nb_filtergraphs - 1] = fg;
203
204     return 0;
205 }
206
207 static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
208 {
209     AVFilterContext *ctx = inout->filter_ctx;
210     AVFilterPad *pads = in ? ctx->input_pads  : ctx->output_pads;
211     int       nb_pads = in ? ctx->nb_inputs   : ctx->nb_outputs;
212     AVIOContext *pb;
213     uint8_t *res = NULL;
214
215     if (avio_open_dyn_buf(&pb) < 0)
216         exit_program(1);
217
218     avio_printf(pb, "%s", ctx->filter->name);
219     if (nb_pads > 1)
220         avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));
221     avio_w8(pb, 0);
222     avio_close_dyn_buf(pb, &res);
223     return res;
224 }
225
226 static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
227 {
228     InputStream *ist = NULL;
229     enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
230     int i;
231
232     // TODO: support other filter types
233     if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
234         av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
235                "currently.\n");
236         exit_program(1);
237     }
238
239     if (in->name) {
240         AVFormatContext *s;
241         AVStream       *st = NULL;
242         char *p;
243         int file_idx = strtol(in->name, &p, 0);
244
245         if (file_idx < 0 || file_idx >= nb_input_files) {
246             av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
247                    file_idx, fg->graph_desc);
248             exit_program(1);
249         }
250         s = input_files[file_idx]->ctx;
251
252         for (i = 0; i < s->nb_streams; i++) {
253             enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type;
254             if (stream_type != type &&
255                 !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
256                   type == AVMEDIA_TYPE_VIDEO /* sub2video hack */))
257                 continue;
258             if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
259                 st = s->streams[i];
260                 break;
261             }
262         }
263         if (!st) {
264             av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
265                    "matches no streams.\n", p, fg->graph_desc);
266             exit_program(1);
267         }
268         ist = input_streams[input_files[file_idx]->ist_index + st->index];
269         if (ist->user_set_discard == AVDISCARD_ALL) {
270             av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
271                    "matches a disabled input stream.\n", p, fg->graph_desc);
272             exit_program(1);
273         }
274     } else {
275         /* find the first unused stream of corresponding type */
276         for (i = 0; i < nb_input_streams; i++) {
277             ist = input_streams[i];
278             if (ist->user_set_discard == AVDISCARD_ALL)
279                 continue;
280             if (ist->dec_ctx->codec_type == type && ist->discard)
281                 break;
282         }
283         if (i == nb_input_streams) {
284             av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
285                    "unlabeled input pad %d on filter %s\n", in->pad_idx,
286                    in->filter_ctx->name);
287             exit_program(1);
288         }
289     }
290     av_assert0(ist);
291
292     ist->discard         = 0;
293     ist->decoding_needed |= DECODING_FOR_FILTER;
294     ist->st->discard = AVDISCARD_NONE;
295
296     GROW_ARRAY(fg->inputs, fg->nb_inputs);
297     if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
298         exit_program(1);
299     fg->inputs[fg->nb_inputs - 1]->ist   = ist;
300     fg->inputs[fg->nb_inputs - 1]->graph = fg;
301     fg->inputs[fg->nb_inputs - 1]->format = -1;
302     fg->inputs[fg->nb_inputs - 1]->type = ist->st->codecpar->codec_type;
303     fg->inputs[fg->nb_inputs - 1]->name = describe_filter_link(fg, in, 1);
304
305     fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*));
306     if (!fg->inputs[fg->nb_inputs - 1]->frame_queue)
307         exit_program(1);
308
309     GROW_ARRAY(ist->filters, ist->nb_filters);
310     ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
311 }
312
313 int init_complex_filtergraph(FilterGraph *fg)
314 {
315     AVFilterInOut *inputs, *outputs, *cur;
316     AVFilterGraph *graph;
317     int ret = 0;
318
319     /* this graph is only used for determining the kinds of inputs
320      * and outputs we have, and is discarded on exit from this function */
321     graph = avfilter_graph_alloc();
322     if (!graph)
323         return AVERROR(ENOMEM);
324     graph->nb_threads = 1;
325
326     ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs);
327     if (ret < 0)
328         goto fail;
329
330     for (cur = inputs; cur; cur = cur->next)
331         init_input_filter(fg, cur);
332
333     for (cur = outputs; cur;) {
334         GROW_ARRAY(fg->outputs, fg->nb_outputs);
335         fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]));
336         if (!fg->outputs[fg->nb_outputs - 1])
337             exit_program(1);
338
339         fg->outputs[fg->nb_outputs - 1]->graph   = fg;
340         fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
341         fg->outputs[fg->nb_outputs - 1]->type    = avfilter_pad_get_type(cur->filter_ctx->output_pads,
342                                                                          cur->pad_idx);
343         fg->outputs[fg->nb_outputs - 1]->name = describe_filter_link(fg, cur, 0);
344         cur = cur->next;
345         fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
346     }
347
348 fail:
349     avfilter_inout_free(&inputs);
350     avfilter_graph_free(&graph);
351     return ret;
352 }
353
354 static int insert_trim(int64_t start_time, int64_t duration,
355                        AVFilterContext **last_filter, int *pad_idx,
356                        const char *filter_name)
357 {
358     AVFilterGraph *graph = (*last_filter)->graph;
359     AVFilterContext *ctx;
360     const AVFilter *trim;
361     enum AVMediaType type = avfilter_pad_get_type((*last_filter)->output_pads, *pad_idx);
362     const char *name = (type == AVMEDIA_TYPE_VIDEO) ? "trim" : "atrim";
363     int ret = 0;
364
365     if (duration == INT64_MAX && start_time == AV_NOPTS_VALUE)
366         return 0;
367
368     trim = avfilter_get_by_name(name);
369     if (!trim) {
370         av_log(NULL, AV_LOG_ERROR, "%s filter not present, cannot limit "
371                "recording time.\n", name);
372         return AVERROR_FILTER_NOT_FOUND;
373     }
374
375     ctx = avfilter_graph_alloc_filter(graph, trim, filter_name);
376     if (!ctx)
377         return AVERROR(ENOMEM);
378
379     if (duration != INT64_MAX) {
380         ret = av_opt_set_int(ctx, "durationi", duration,
381                                 AV_OPT_SEARCH_CHILDREN);
382     }
383     if (ret >= 0 && start_time != AV_NOPTS_VALUE) {
384         ret = av_opt_set_int(ctx, "starti", start_time,
385                                 AV_OPT_SEARCH_CHILDREN);
386     }
387     if (ret < 0) {
388         av_log(ctx, AV_LOG_ERROR, "Error configuring the %s filter", name);
389         return ret;
390     }
391
392     ret = avfilter_init_str(ctx, NULL);
393     if (ret < 0)
394         return ret;
395
396     ret = avfilter_link(*last_filter, *pad_idx, ctx, 0);
397     if (ret < 0)
398         return ret;
399
400     *last_filter = ctx;
401     *pad_idx     = 0;
402     return 0;
403 }
404
405 static int insert_filter(AVFilterContext **last_filter, int *pad_idx,
406                          const char *filter_name, const char *args)
407 {
408     AVFilterGraph *graph = (*last_filter)->graph;
409     AVFilterContext *ctx;
410     int ret;
411
412     ret = avfilter_graph_create_filter(&ctx,
413                                        avfilter_get_by_name(filter_name),
414                                        filter_name, args, NULL, graph);
415     if (ret < 0)
416         return ret;
417
418     ret = avfilter_link(*last_filter, *pad_idx, ctx, 0);
419     if (ret < 0)
420         return ret;
421
422     *last_filter = ctx;
423     *pad_idx     = 0;
424     return 0;
425 }
426
427 static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
428 {
429     char *pix_fmts;
430     OutputStream *ost = ofilter->ost;
431     OutputFile    *of = output_files[ost->file_index];
432     AVFilterContext *last_filter = out->filter_ctx;
433     int pad_idx = out->pad_idx;
434     int ret;
435     char name[255];
436
437     snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index);
438     ret = avfilter_graph_create_filter(&ofilter->filter,
439                                        avfilter_get_by_name("buffersink"),
440                                        name, NULL, NULL, fg->graph);
441
442     if (ret < 0)
443         return ret;
444
445     if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) {
446         char args[255];
447         AVFilterContext *filter;
448         AVDictionaryEntry *e = NULL;
449
450         snprintf(args, sizeof(args), "%d:%d",
451                  ofilter->width, ofilter->height);
452
453         while ((e = av_dict_get(ost->sws_dict, "", e,
454                                 AV_DICT_IGNORE_SUFFIX))) {
455             av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value);
456         }
457
458         snprintf(name, sizeof(name), "scaler_out_%d_%d",
459                  ost->file_index, ost->index);
460         if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
461                                                 name, args, NULL, fg->graph)) < 0)
462             return ret;
463         if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
464             return ret;
465
466         last_filter = filter;
467         pad_idx = 0;
468     }
469
470     if ((pix_fmts = choose_pix_fmts(ofilter))) {
471         AVFilterContext *filter;
472         snprintf(name, sizeof(name), "format_out_%d_%d",
473                  ost->file_index, ost->index);
474         ret = avfilter_graph_create_filter(&filter,
475                                            avfilter_get_by_name("format"),
476                                            "format", pix_fmts, NULL, fg->graph);
477         av_freep(&pix_fmts);
478         if (ret < 0)
479             return ret;
480         if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
481             return ret;
482
483         last_filter = filter;
484         pad_idx     = 0;
485     }
486
487     if (ost->frame_rate.num && 0) {
488         AVFilterContext *fps;
489         char args[255];
490
491         snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
492                  ost->frame_rate.den);
493         snprintf(name, sizeof(name), "fps_out_%d_%d",
494                  ost->file_index, ost->index);
495         ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"),
496                                            name, args, NULL, fg->graph);
497         if (ret < 0)
498             return ret;
499
500         ret = avfilter_link(last_filter, pad_idx, fps, 0);
501         if (ret < 0)
502             return ret;
503         last_filter = fps;
504         pad_idx = 0;
505     }
506
507     snprintf(name, sizeof(name), "trim_out_%d_%d",
508              ost->file_index, ost->index);
509     ret = insert_trim(of->start_time, of->recording_time,
510                       &last_filter, &pad_idx, name);
511     if (ret < 0)
512         return ret;
513
514
515     if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
516         return ret;
517
518     return 0;
519 }
520
521 static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
522 {
523     OutputStream *ost = ofilter->ost;
524     OutputFile    *of = output_files[ost->file_index];
525     AVCodecContext *codec  = ost->enc_ctx;
526     AVFilterContext *last_filter = out->filter_ctx;
527     int pad_idx = out->pad_idx;
528     char *sample_fmts, *sample_rates, *channel_layouts;
529     char name[255];
530     int ret;
531
532     snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index);
533     ret = avfilter_graph_create_filter(&ofilter->filter,
534                                        avfilter_get_by_name("abuffersink"),
535                                        name, NULL, NULL, fg->graph);
536     if (ret < 0)
537         return ret;
538     if ((ret = av_opt_set_int(ofilter->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0)
539         return ret;
540
541 #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do {                 \
542     AVFilterContext *filt_ctx;                                              \
543                                                                             \
544     av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
545            "similarly to -af " filter_name "=%s.\n", arg);                  \
546                                                                             \
547     ret = avfilter_graph_create_filter(&filt_ctx,                           \
548                                        avfilter_get_by_name(filter_name),   \
549                                        filter_name, arg, NULL, fg->graph);  \
550     if (ret < 0)                                                            \
551         return ret;                                                         \
552                                                                             \
553     ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0);                 \
554     if (ret < 0)                                                            \
555         return ret;                                                         \
556                                                                             \
557     last_filter = filt_ctx;                                                 \
558     pad_idx = 0;                                                            \
559 } while (0)
560     if (ost->audio_channels_mapped) {
561         int i;
562         AVBPrint pan_buf;
563         av_bprint_init(&pan_buf, 256, 8192);
564         av_bprintf(&pan_buf, "0x%"PRIx64,
565                    av_get_default_channel_layout(ost->audio_channels_mapped));
566         for (i = 0; i < ost->audio_channels_mapped; i++)
567             if (ost->audio_channels_map[i] != -1)
568                 av_bprintf(&pan_buf, "|c%d=c%d", i, ost->audio_channels_map[i]);
569
570         AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str);
571         av_bprint_finalize(&pan_buf, NULL);
572     }
573
574     if (codec->channels && !codec->channel_layout)
575         codec->channel_layout = av_get_default_channel_layout(codec->channels);
576
577     sample_fmts     = choose_sample_fmts(ofilter);
578     sample_rates    = choose_sample_rates(ofilter);
579     channel_layouts = choose_channel_layouts(ofilter);
580     if (sample_fmts || sample_rates || channel_layouts) {
581         AVFilterContext *format;
582         char args[256];
583         args[0] = 0;
584
585         if (sample_fmts)
586             av_strlcatf(args, sizeof(args), "sample_fmts=%s:",
587                             sample_fmts);
588         if (sample_rates)
589             av_strlcatf(args, sizeof(args), "sample_rates=%s:",
590                             sample_rates);
591         if (channel_layouts)
592             av_strlcatf(args, sizeof(args), "channel_layouts=%s:",
593                             channel_layouts);
594
595         av_freep(&sample_fmts);
596         av_freep(&sample_rates);
597         av_freep(&channel_layouts);
598
599         snprintf(name, sizeof(name), "format_out_%d_%d",
600                  ost->file_index, ost->index);
601         ret = avfilter_graph_create_filter(&format,
602                                            avfilter_get_by_name("aformat"),
603                                            name, args, NULL, fg->graph);
604         if (ret < 0)
605             return ret;
606
607         ret = avfilter_link(last_filter, pad_idx, format, 0);
608         if (ret < 0)
609             return ret;
610
611         last_filter = format;
612         pad_idx = 0;
613     }
614
615     if (ost->apad && of->shortest) {
616         char args[256];
617         int i;
618
619         for (i=0; i<of->ctx->nb_streams; i++)
620             if (of->ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
621                 break;
622
623         if (i<of->ctx->nb_streams) {
624             snprintf(args, sizeof(args), "%s", ost->apad);
625             AUTO_INSERT_FILTER("-apad", "apad", args);
626         }
627     }
628
629     snprintf(name, sizeof(name), "trim for output stream %d:%d",
630              ost->file_index, ost->index);
631     ret = insert_trim(of->start_time, of->recording_time,
632                       &last_filter, &pad_idx, name);
633     if (ret < 0)
634         return ret;
635
636     if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
637         return ret;
638
639     return 0;
640 }
641
642 static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter,
643                                    AVFilterInOut *out)
644 {
645     if (!ofilter->ost) {
646         av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name);
647         exit_program(1);
648     }
649
650     switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
651     case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
652     case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
653     default: av_assert0(0);
654     }
655 }
656
657 void check_filter_outputs(void)
658 {
659     int i;
660     for (i = 0; i < nb_filtergraphs; i++) {
661         int n;
662         for (n = 0; n < filtergraphs[i]->nb_outputs; n++) {
663             OutputFilter *output = filtergraphs[i]->outputs[n];
664             if (!output->ost) {
665                 av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", output->name);
666                 exit_program(1);
667             }
668         }
669     }
670 }
671
672 static int sub2video_prepare(InputStream *ist, InputFilter *ifilter)
673 {
674     AVFormatContext *avf = input_files[ist->file_index]->ctx;
675     int i, w, h;
676
677     /* Compute the size of the canvas for the subtitles stream.
678        If the subtitles codecpar has set a size, use it. Otherwise use the
679        maximum dimensions of the video streams in the same file. */
680     w = ifilter->width;
681     h = ifilter->height;
682     if (!(w && h)) {
683         for (i = 0; i < avf->nb_streams; i++) {
684             if (avf->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
685                 w = FFMAX(w, avf->streams[i]->codecpar->width);
686                 h = FFMAX(h, avf->streams[i]->codecpar->height);
687             }
688         }
689         if (!(w && h)) {
690             w = FFMAX(w, 720);
691             h = FFMAX(h, 576);
692         }
693         av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h);
694     }
695     ist->sub2video.w = ifilter->width  = w;
696     ist->sub2video.h = ifilter->height = h;
697
698     ifilter->width  = ist->dec_ctx->width  ? ist->dec_ctx->width  : ist->sub2video.w;
699     ifilter->height = ist->dec_ctx->height ? ist->dec_ctx->height : ist->sub2video.h;
700
701     /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
702        palettes for all rectangles are identical or compatible */
703     ifilter->format = AV_PIX_FMT_RGB32;
704
705     ist->sub2video.frame = av_frame_alloc();
706     if (!ist->sub2video.frame)
707         return AVERROR(ENOMEM);
708     ist->sub2video.last_pts = INT64_MIN;
709     ist->sub2video.end_pts  = INT64_MIN;
710
711     /* sub2video structure has been (re-)initialized.
712        Mark it as such so that the system will be
713        initialized with the first received heartbeat. */
714     ist->sub2video.initialize = 1;
715
716     return 0;
717 }
718
719 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
720                                         AVFilterInOut *in)
721 {
722     AVFilterContext *last_filter;
723     const AVFilter *buffer_filt = avfilter_get_by_name("buffer");
724     InputStream *ist = ifilter->ist;
725     InputFile     *f = input_files[ist->file_index];
726     AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) :
727                                          ist->st->time_base;
728     AVRational fr = ist->framerate;
729     AVRational sar;
730     AVBPrint args;
731     char name[255];
732     int ret, pad_idx = 0;
733     int64_t tsoffset = 0;
734     AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
735
736     if (!par)
737         return AVERROR(ENOMEM);
738     memset(par, 0, sizeof(*par));
739     par->format = AV_PIX_FMT_NONE;
740
741     if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
742         av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n");
743         ret = AVERROR(EINVAL);
744         goto fail;
745     }
746
747     if (!fr.num)
748         fr = av_guess_frame_rate(input_files[ist->file_index]->ctx, ist->st, NULL);
749
750     if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
751         ret = sub2video_prepare(ist, ifilter);
752         if (ret < 0)
753             goto fail;
754     }
755
756     sar = ifilter->sample_aspect_ratio;
757     if(!sar.den)
758         sar = (AVRational){0,1};
759     av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC);
760     av_bprintf(&args,
761              "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:"
762              "pixel_aspect=%d/%d",
763              ifilter->width, ifilter->height, ifilter->format,
764              tb.num, tb.den, sar.num, sar.den);
765     if (fr.num && fr.den)
766         av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den);
767     snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
768              ist->file_index, ist->st->index);
769
770
771     if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name,
772                                             args.str, NULL, fg->graph)) < 0)
773         goto fail;
774     par->hw_frames_ctx = ifilter->hw_frames_ctx;
775     ret = av_buffersrc_parameters_set(ifilter->filter, par);
776     if (ret < 0)
777         goto fail;
778     av_freep(&par);
779     last_filter = ifilter->filter;
780
781     if (ist->autorotate) {
782         double theta = get_rotation(ist->st);
783
784         if (fabs(theta - 90) < 1.0) {
785             ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock");
786         } else if (fabs(theta - 180) < 1.0) {
787             ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
788             if (ret < 0)
789                 return ret;
790             ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
791         } else if (fabs(theta - 270) < 1.0) {
792             ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock");
793         } else if (fabs(theta) > 1.0) {
794             char rotate_buf[64];
795             snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
796             ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
797         }
798         if (ret < 0)
799             return ret;
800     }
801
802     if (do_deinterlace) {
803         AVFilterContext *yadif;
804
805         snprintf(name, sizeof(name), "deinterlace_in_%d_%d",
806                  ist->file_index, ist->st->index);
807         if ((ret = avfilter_graph_create_filter(&yadif,
808                                                 avfilter_get_by_name("yadif"),
809                                                 name, "", NULL,
810                                                 fg->graph)) < 0)
811             return ret;
812
813         if ((ret = avfilter_link(last_filter, 0, yadif, 0)) < 0)
814             return ret;
815
816         last_filter = yadif;
817     }
818
819     snprintf(name, sizeof(name), "trim_in_%d_%d",
820              ist->file_index, ist->st->index);
821     if (copy_ts) {
822         tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time;
823         if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE)
824             tsoffset += f->ctx->start_time;
825     }
826     ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ?
827                       AV_NOPTS_VALUE : tsoffset, f->recording_time,
828                       &last_filter, &pad_idx, name);
829     if (ret < 0)
830         return ret;
831
832     if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0)
833         return ret;
834     return 0;
835 fail:
836     av_freep(&par);
837
838     return ret;
839 }
840
841 static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
842                                         AVFilterInOut *in)
843 {
844     AVFilterContext *last_filter;
845     const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer");
846     InputStream *ist = ifilter->ist;
847     InputFile     *f = input_files[ist->file_index];
848     AVBPrint args;
849     char name[255];
850     int ret, pad_idx = 0;
851     int64_t tsoffset = 0;
852
853     if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) {
854         av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n");
855         return AVERROR(EINVAL);
856     }
857
858     av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC);
859     av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s",
860              1, ifilter->sample_rate,
861              ifilter->sample_rate,
862              av_get_sample_fmt_name(ifilter->format));
863     if (ifilter->channel_layout)
864         av_bprintf(&args, ":channel_layout=0x%"PRIx64,
865                    ifilter->channel_layout);
866     else
867         av_bprintf(&args, ":channels=%d", ifilter->channels);
868     snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index,
869              ist->file_index, ist->st->index);
870
871     if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt,
872                                             name, args.str, NULL,
873                                             fg->graph)) < 0)
874         return ret;
875     last_filter = ifilter->filter;
876
877 #define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do {                 \
878     AVFilterContext *filt_ctx;                                              \
879                                                                             \
880     av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
881            "similarly to -af " filter_name "=%s.\n", arg);                  \
882                                                                             \
883     snprintf(name, sizeof(name), "graph_%d_%s_in_%d_%d",      \
884                 fg->index, filter_name, ist->file_index, ist->st->index);   \
885     ret = avfilter_graph_create_filter(&filt_ctx,                           \
886                                        avfilter_get_by_name(filter_name),   \
887                                        name, arg, NULL, fg->graph);         \
888     if (ret < 0)                                                            \
889         return ret;                                                         \
890                                                                             \
891     ret = avfilter_link(last_filter, 0, filt_ctx, 0);                       \
892     if (ret < 0)                                                            \
893         return ret;                                                         \
894                                                                             \
895     last_filter = filt_ctx;                                                 \
896 } while (0)
897
898     if (audio_sync_method > 0) {
899         char args[256] = {0};
900
901         av_strlcatf(args, sizeof(args), "async=%d", audio_sync_method);
902         if (audio_drift_threshold != 0.1)
903             av_strlcatf(args, sizeof(args), ":min_hard_comp=%f", audio_drift_threshold);
904         if (!fg->reconfiguration)
905             av_strlcatf(args, sizeof(args), ":first_pts=0");
906         AUTO_INSERT_FILTER_INPUT("-async", "aresample", args);
907     }
908
909 //     if (ost->audio_channels_mapped) {
910 //         int i;
911 //         AVBPrint pan_buf;
912 //         av_bprint_init(&pan_buf, 256, 8192);
913 //         av_bprintf(&pan_buf, "0x%"PRIx64,
914 //                    av_get_default_channel_layout(ost->audio_channels_mapped));
915 //         for (i = 0; i < ost->audio_channels_mapped; i++)
916 //             if (ost->audio_channels_map[i] != -1)
917 //                 av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
918 //         AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str);
919 //         av_bprint_finalize(&pan_buf, NULL);
920 //     }
921
922     if (audio_volume != 256) {
923         char args[256];
924
925         av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Use the volume "
926                "audio filter instead.\n");
927
928         snprintf(args, sizeof(args), "%f", audio_volume / 256.);
929         AUTO_INSERT_FILTER_INPUT("-vol", "volume", args);
930     }
931
932     snprintf(name, sizeof(name), "trim for input stream %d:%d",
933              ist->file_index, ist->st->index);
934     if (copy_ts) {
935         tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time;
936         if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE)
937             tsoffset += f->ctx->start_time;
938     }
939     ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ?
940                       AV_NOPTS_VALUE : tsoffset, f->recording_time,
941                       &last_filter, &pad_idx, name);
942     if (ret < 0)
943         return ret;
944
945     if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0)
946         return ret;
947
948     return 0;
949 }
950
951 static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter,
952                                   AVFilterInOut *in)
953 {
954     if (!ifilter->ist->dec) {
955         av_log(NULL, AV_LOG_ERROR,
956                "No decoder for stream #%d:%d, filtering impossible\n",
957                ifilter->ist->file_index, ifilter->ist->st->index);
958         return AVERROR_DECODER_NOT_FOUND;
959     }
960     switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) {
961     case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in);
962     case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in);
963     default: av_assert0(0);
964     }
965 }
966
967 static void cleanup_filtergraph(FilterGraph *fg)
968 {
969     int i;
970     for (i = 0; i < fg->nb_outputs; i++)
971         fg->outputs[i]->filter = (AVFilterContext *)NULL;
972     for (i = 0; i < fg->nb_inputs; i++)
973         fg->inputs[i]->filter = (AVFilterContext *)NULL;
974     avfilter_graph_free(&fg->graph);
975 }
976
977 int configure_filtergraph(FilterGraph *fg)
978 {
979     AVFilterInOut *inputs, *outputs, *cur;
980     int ret, i, simple = filtergraph_is_simple(fg);
981     const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
982                                       fg->graph_desc;
983
984     cleanup_filtergraph(fg);
985     if (!(fg->graph = avfilter_graph_alloc()))
986         return AVERROR(ENOMEM);
987
988     if (simple) {
989         OutputStream *ost = fg->outputs[0]->ost;
990         char args[512];
991         AVDictionaryEntry *e = NULL;
992
993         fg->graph->nb_threads = filter_nbthreads;
994
995         args[0] = 0;
996         while ((e = av_dict_get(ost->sws_dict, "", e,
997                                 AV_DICT_IGNORE_SUFFIX))) {
998             av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value);
999         }
1000         if (strlen(args))
1001             args[strlen(args)-1] = 0;
1002         fg->graph->scale_sws_opts = av_strdup(args);
1003
1004         args[0] = 0;
1005         while ((e = av_dict_get(ost->swr_opts, "", e,
1006                                 AV_DICT_IGNORE_SUFFIX))) {
1007             av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value);
1008         }
1009         if (strlen(args))
1010             args[strlen(args)-1] = 0;
1011         av_opt_set(fg->graph, "aresample_swr_opts", args, 0);
1012
1013         args[0] = '\0';
1014         while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e,
1015                                 AV_DICT_IGNORE_SUFFIX))) {
1016             av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value);
1017         }
1018         if (strlen(args))
1019             args[strlen(args) - 1] = '\0';
1020
1021         e = av_dict_get(ost->encoder_opts, "threads", NULL, 0);
1022         if (e)
1023             av_opt_set(fg->graph, "threads", e->value, 0);
1024     } else {
1025         fg->graph->nb_threads = filter_complex_nbthreads;
1026     }
1027
1028     if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
1029         goto fail;
1030
1031     ret = hw_device_setup_for_filter(fg);
1032     if (ret < 0)
1033         goto fail;
1034
1035     if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
1036         const char *num_inputs;
1037         const char *num_outputs;
1038         if (!outputs) {
1039             num_outputs = "0";
1040         } else if (outputs->next) {
1041             num_outputs = ">1";
1042         } else {
1043             num_outputs = "1";
1044         }
1045         if (!inputs) {
1046             num_inputs = "0";
1047         } else if (inputs->next) {
1048             num_inputs = ">1";
1049         } else {
1050             num_inputs = "1";
1051         }
1052         av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
1053                "to have exactly 1 input and 1 output."
1054                " However, it had %s input(s) and %s output(s)."
1055                " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n",
1056                graph_desc, num_inputs, num_outputs);
1057         ret = AVERROR(EINVAL);
1058         goto fail;
1059     }
1060
1061     for (cur = inputs, i = 0; cur; cur = cur->next, i++)
1062         if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) {
1063             avfilter_inout_free(&inputs);
1064             avfilter_inout_free(&outputs);
1065             goto fail;
1066         }
1067     avfilter_inout_free(&inputs);
1068
1069     for (cur = outputs, i = 0; cur; cur = cur->next, i++)
1070         configure_output_filter(fg, fg->outputs[i], cur);
1071     avfilter_inout_free(&outputs);
1072
1073     if (!auto_conversion_filters)
1074         avfilter_graph_set_auto_convert(fg->graph, AVFILTER_AUTO_CONVERT_NONE);
1075     if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
1076         goto fail;
1077
1078     /* limit the lists of allowed formats to the ones selected, to
1079      * make sure they stay the same if the filtergraph is reconfigured later */
1080     for (i = 0; i < fg->nb_outputs; i++) {
1081         OutputFilter *ofilter = fg->outputs[i];
1082         AVFilterContext *sink = ofilter->filter;
1083
1084         ofilter->format = av_buffersink_get_format(sink);
1085
1086         ofilter->width  = av_buffersink_get_w(sink);
1087         ofilter->height = av_buffersink_get_h(sink);
1088
1089         ofilter->sample_rate    = av_buffersink_get_sample_rate(sink);
1090         ofilter->channel_layout = av_buffersink_get_channel_layout(sink);
1091     }
1092
1093     fg->reconfiguration = 1;
1094
1095     for (i = 0; i < fg->nb_outputs; i++) {
1096         OutputStream *ost = fg->outputs[i]->ost;
1097         if (!ost->enc) {
1098             /* identical to the same check in ffmpeg.c, needed because
1099                complex filter graphs are initialized earlier */
1100             av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n",
1101                      avcodec_get_name(ost->st->codecpar->codec_id), ost->file_index, ost->index);
1102             ret = AVERROR(EINVAL);
1103             goto fail;
1104         }
1105         if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
1106             !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE))
1107             av_buffersink_set_frame_size(ost->filter->filter,
1108                                          ost->enc_ctx->frame_size);
1109     }
1110
1111     for (i = 0; i < fg->nb_inputs; i++) {
1112         while (av_fifo_size(fg->inputs[i]->frame_queue)) {
1113             AVFrame *tmp;
1114             av_fifo_generic_read(fg->inputs[i]->frame_queue, &tmp, sizeof(tmp), NULL);
1115             ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp);
1116             av_frame_free(&tmp);
1117             if (ret < 0)
1118                 goto fail;
1119         }
1120     }
1121
1122     /* send the EOFs for the finished inputs */
1123     for (i = 0; i < fg->nb_inputs; i++) {
1124         if (fg->inputs[i]->eof) {
1125             ret = av_buffersrc_add_frame(fg->inputs[i]->filter, NULL);
1126             if (ret < 0)
1127                 goto fail;
1128         }
1129     }
1130
1131     /* process queued up subtitle packets */
1132     for (i = 0; i < fg->nb_inputs; i++) {
1133         InputStream *ist = fg->inputs[i]->ist;
1134         if (ist->sub2video.sub_queue && ist->sub2video.frame) {
1135             while (av_fifo_size(ist->sub2video.sub_queue)) {
1136                 AVSubtitle tmp;
1137                 av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL);
1138                 sub2video_update(ist, INT64_MIN, &tmp);
1139                 avsubtitle_free(&tmp);
1140             }
1141         }
1142     }
1143
1144     return 0;
1145
1146 fail:
1147     cleanup_filtergraph(fg);
1148     return ret;
1149 }
1150
1151 int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
1152 {
1153     av_buffer_unref(&ifilter->hw_frames_ctx);
1154
1155     ifilter->format = frame->format;
1156
1157     ifilter->width               = frame->width;
1158     ifilter->height              = frame->height;
1159     ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
1160
1161     ifilter->sample_rate         = frame->sample_rate;
1162     ifilter->channels            = frame->channels;
1163     ifilter->channel_layout      = frame->channel_layout;
1164
1165     if (frame->hw_frames_ctx) {
1166         ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
1167         if (!ifilter->hw_frames_ctx)
1168             return AVERROR(ENOMEM);
1169     }
1170
1171     return 0;
1172 }
1173
1174 int filtergraph_is_simple(FilterGraph *fg)
1175 {
1176     return !fg->graph_desc;
1177 }