avconv_filter.c
Go to the documentation of this file.
1 /*
2  * avconv filter configuration
3  *
4  * This file is part of Libav.
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "avconv.h"
22 
23 #include "libavfilter/avfilter.h"
25 
26 #include "libavutil/avassert.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/pixfmt.h"
30 #include "libavutil/samplefmt.h"
31 
32 /* Define a function for building a string containing a list of
33  * allowed formats. */
34 #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
35 static char *choose_ ## var ## s(OutputStream *ost) \
36 { \
37  if (ost->st->codec->var != none) { \
38  get_name(ost->st->codec->var); \
39  return av_strdup(name); \
40  } else if (ost->enc->supported_list) { \
41  const type *p; \
42  AVIOContext *s = NULL; \
43  uint8_t *ret; \
44  int len; \
45  \
46  if (avio_open_dyn_buf(&s) < 0) \
47  exit(1); \
48  \
49  for (p = ost->enc->supported_list; *p != none; p++) { \
50  get_name(*p); \
51  avio_printf(s, "%s" separator, name); \
52  } \
53  len = avio_close_dyn_buf(s, &ret); \
54  ret[len - 1] = 0; \
55  return ret; \
56  } else \
57  return NULL; \
58 }
59 
61  GET_PIX_FMT_NAME, ":")
62 
65 
66 DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0,
68 
69 DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0,
70  GET_CH_LAYOUT_NAME, ",")
71 
73 {
74  FilterGraph *fg = av_mallocz(sizeof(*fg));
75 
76  if (!fg)
77  exit(1);
78  fg->index = nb_filtergraphs;
79 
80  GROW_ARRAY(fg->outputs, fg->nb_outputs);
81  if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
82  exit(1);
83  fg->outputs[0]->ost = ost;
84  fg->outputs[0]->graph = fg;
85 
86  ost->filter = fg->outputs[0];
87 
88  GROW_ARRAY(fg->inputs, fg->nb_inputs);
89  if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
90  exit(1);
91  fg->inputs[0]->ist = ist;
92  fg->inputs[0]->graph = fg;
93 
94  GROW_ARRAY(ist->filters, ist->nb_filters);
95  ist->filters[ist->nb_filters - 1] = fg->inputs[0];
96 
98  filtergraphs[nb_filtergraphs - 1] = fg;
99 
100  return fg;
101 }
102 
104 {
105  InputStream *ist = NULL;
107  int i;
108 
109  // TODO: support other filter types
110  if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
111  av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
112  "currently.\n");
113  exit(1);
114  }
115 
116  if (in->name) {
117  AVFormatContext *s;
118  AVStream *st = NULL;
119  char *p;
120  int file_idx = strtol(in->name, &p, 0);
121 
122  if (file_idx < 0 || file_idx >= nb_input_files) {
123  av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtegraph description %s.\n",
124  file_idx, fg->graph_desc);
125  exit(1);
126  }
127  s = input_files[file_idx]->ctx;
128 
129  for (i = 0; i < s->nb_streams; i++) {
130  if (s->streams[i]->codec->codec_type != type)
131  continue;
132  if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
133  st = s->streams[i];
134  break;
135  }
136  }
137  if (!st) {
138  av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
139  "matches no streams.\n", p, fg->graph_desc);
140  exit(1);
141  }
142  ist = input_streams[input_files[file_idx]->ist_index + st->index];
143  } else {
144  /* find the first unused stream of corresponding type */
145  for (i = 0; i < nb_input_streams; i++) {
146  ist = input_streams[i];
147  if (ist->st->codec->codec_type == type && ist->discard)
148  break;
149  }
150  if (i == nb_input_streams) {
151  av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
152  "unlabeled input pad %d on filter %s", in->pad_idx,
153  in->filter_ctx->name);
154  exit(1);
155  }
156  }
157  av_assert0(ist);
158 
159  ist->discard = 0;
160  ist->decoding_needed = 1;
161  ist->st->discard = AVDISCARD_NONE;
162 
163  GROW_ARRAY(fg->inputs, fg->nb_inputs);
164  if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
165  exit(1);
166  fg->inputs[fg->nb_inputs - 1]->ist = ist;
167  fg->inputs[fg->nb_inputs - 1]->graph = fg;
168 
169  GROW_ARRAY(ist->filters, ist->nb_filters);
170  ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
171 }
172 
174 {
175  char *pix_fmts;
176  OutputStream *ost = ofilter->ost;
177  AVCodecContext *codec = ost->st->codec;
178  AVFilterContext *last_filter = out->filter_ctx;
179  int pad_idx = out->pad_idx;
180  int ret;
181  char name[255];
182 
183  snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
184  ret = avfilter_graph_create_filter(&ofilter->filter,
185  avfilter_get_by_name("buffersink"),
186  name, NULL, NULL, fg->graph);
187  if (ret < 0)
188  return ret;
189 
190  if (codec->width || codec->height) {
191  char args[255];
193 
194  snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
195  codec->width,
196  codec->height,
197  (unsigned)ost->sws_flags);
198  snprintf(name, sizeof(name), "scaler for output stream %d:%d",
199  ost->file_index, ost->index);
200  if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
201  name, args, NULL, fg->graph)) < 0)
202  return ret;
203  if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
204  return ret;
205 
206  last_filter = filter;
207  pad_idx = 0;
208  }
209 
210  if ((pix_fmts = choose_pix_fmts(ost))) {
212  snprintf(name, sizeof(name), "pixel format for output stream %d:%d",
213  ost->file_index, ost->index);
214  if ((ret = avfilter_graph_create_filter(&filter,
215  avfilter_get_by_name("format"),
216  "format", pix_fmts, NULL,
217  fg->graph)) < 0)
218  return ret;
219  if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
220  return ret;
221 
222  last_filter = filter;
223  pad_idx = 0;
224  av_freep(&pix_fmts);
225  }
226 
227  if (ost->frame_rate.num) {
228  AVFilterContext *fps;
229  char args[255];
230 
231  snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
232  ost->frame_rate.den);
233  snprintf(name, sizeof(name), "fps for output stream %d:%d",
234  ost->file_index, ost->index);
236  name, args, NULL, fg->graph);
237  if (ret < 0)
238  return ret;
239 
240  ret = avfilter_link(last_filter, pad_idx, fps, 0);
241  if (ret < 0)
242  return ret;
243  last_filter = fps;
244  pad_idx = 0;
245  }
246 
247  if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
248  return ret;
249 
250  return 0;
251 }
252 
254 {
255  OutputStream *ost = ofilter->ost;
256  AVCodecContext *codec = ost->st->codec;
257  AVFilterContext *last_filter = out->filter_ctx;
258  int pad_idx = out->pad_idx;
259  char *sample_fmts, *sample_rates, *channel_layouts;
260  char name[255];
261  int ret;
262 
263 
264  snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
265  ret = avfilter_graph_create_filter(&ofilter->filter,
266  avfilter_get_by_name("abuffersink"),
267  name, NULL, NULL, fg->graph);
268  if (ret < 0)
269  return ret;
270 
271  if (codec->channels && !codec->channel_layout)
273 
274  sample_fmts = choose_sample_fmts(ost);
275  sample_rates = choose_sample_rates(ost);
276  channel_layouts = choose_channel_layouts(ost);
277  if (sample_fmts || sample_rates || channel_layouts) {
278  AVFilterContext *format;
279  char args[256];
280  int len = 0;
281 
282  if (sample_fmts)
283  len += snprintf(args + len, sizeof(args) - len, "sample_fmts=%s:",
284  sample_fmts);
285  if (sample_rates)
286  len += snprintf(args + len, sizeof(args) - len, "sample_rates=%s:",
287  sample_rates);
288  if (channel_layouts)
289  len += snprintf(args + len, sizeof(args) - len, "channel_layouts=%s:",
290  channel_layouts);
291  args[len - 1] = 0;
292 
293  av_freep(&sample_fmts);
294  av_freep(&sample_rates);
295  av_freep(&channel_layouts);
296 
297  snprintf(name, sizeof(name), "audio format for output stream %d:%d",
298  ost->file_index, ost->index);
299  ret = avfilter_graph_create_filter(&format,
300  avfilter_get_by_name("aformat"),
301  name, args, NULL, fg->graph);
302  if (ret < 0)
303  return ret;
304 
305  ret = avfilter_link(last_filter, pad_idx, format, 0);
306  if (ret < 0)
307  return ret;
308 
309  last_filter = format;
310  pad_idx = 0;
311  }
312 
313  if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
314  return ret;
315 
316  return 0;
317 }
318 
319 #define DESCRIBE_FILTER_LINK(f, inout, in) \
320 { \
321  AVFilterContext *ctx = inout->filter_ctx; \
322  AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
323  int nb_pads = in ? ctx->input_count : ctx->output_count; \
324  AVIOContext *pb; \
325  \
326  if (avio_open_dyn_buf(&pb) < 0) \
327  exit(1); \
328  \
329  avio_printf(pb, "%s", ctx->filter->name); \
330  if (nb_pads > 1) \
331  avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
332  avio_w8(pb, 0); \
333  avio_close_dyn_buf(pb, &f->name); \
334 }
335 
337 {
338  av_freep(&ofilter->name);
339  DESCRIBE_FILTER_LINK(ofilter, out, 0);
340 
341  switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
342  case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
343  case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
344  default: av_assert0(0);
345  }
346 }
347 
349  AVFilterInOut *in)
350 {
351  AVFilterContext *first_filter = in->filter_ctx;
352  AVFilter *filter = avfilter_get_by_name("buffer");
353  InputStream *ist = ifilter->ist;
354  AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) :
355  ist->st->time_base;
356  AVRational sar;
357  char args[255], name[255];
358  int pad_idx = in->pad_idx;
359  int ret;
360 
361  sar = ist->st->sample_aspect_ratio.num ?
362  ist->st->sample_aspect_ratio :
364  snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
365  ist->st->codec->height, ist->st->codec->pix_fmt,
366  tb.num, tb.den, sar.num, sar.den);
367  snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
368  ist->file_index, ist->st->index);
369 
370  if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, name,
371  args, NULL, fg->graph)) < 0)
372  return ret;
373 
374  if (ist->framerate.num) {
375  AVFilterContext *setpts;
376 
377  snprintf(name, sizeof(name), "force CFR for input from stream %d:%d",
378  ist->file_index, ist->st->index);
379  if ((ret = avfilter_graph_create_filter(&setpts,
380  avfilter_get_by_name("setpts"),
381  name, "N", NULL,
382  fg->graph)) < 0)
383  return ret;
384 
385  if ((ret = avfilter_link(setpts, 0, first_filter, pad_idx)) < 0)
386  return ret;
387 
388  first_filter = setpts;
389  pad_idx = 0;
390  }
391 
392  if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
393  return ret;
394  return 0;
395 }
396 
398  AVFilterInOut *in)
399 {
400  AVFilterContext *first_filter = in->filter_ctx;
401  AVFilter *filter = avfilter_get_by_name("abuffer");
402  InputStream *ist = ifilter->ist;
403  int pad_idx = in->pad_idx;
404  char args[255], name[255];
405  int ret;
406 
407  snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
408  ":channel_layout=0x%"PRIx64,
409  1, ist->st->codec->sample_rate,
410  ist->st->codec->sample_rate,
412  ist->st->codec->channel_layout);
413  snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
414  ist->file_index, ist->st->index);
415 
416  if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter,
417  name, args, NULL,
418  fg->graph)) < 0)
419  return ret;
420 
421  if (audio_sync_method > 0) {
422  AVFilterContext *async;
423  int len = 0;
424 
425  av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
426  "asyncts audio filter instead.\n");
427 
428  if (audio_sync_method > 1)
429  len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
430  "max_comp=%d:", audio_sync_method);
431  snprintf(args + len, sizeof(args) - len, "min_delta=%f",
433 
434  snprintf(name, sizeof(name), "graph %d audio sync for input stream %d:%d",
435  fg->index, ist->file_index, ist->st->index);
436  ret = avfilter_graph_create_filter(&async,
437  avfilter_get_by_name("asyncts"),
438  name, args, NULL, fg->graph);
439  if (ret < 0)
440  return ret;
441 
442  ret = avfilter_link(async, 0, first_filter, pad_idx);
443  if (ret < 0)
444  return ret;
445 
446  first_filter = async;
447  pad_idx = 0;
448  }
449  if (audio_volume != 256) {
450  AVFilterContext *volume;
451 
452  av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Use the volume "
453  "audio filter instead.\n");
454 
455  snprintf(args, sizeof(args), "volume=%f", audio_volume / 256.0);
456 
457  snprintf(name, sizeof(name), "graph %d volume for input stream %d:%d",
458  fg->index, ist->file_index, ist->st->index);
459  ret = avfilter_graph_create_filter(&volume,
460  avfilter_get_by_name("volume"),
461  name, args, NULL, fg->graph);
462  if (ret < 0)
463  return ret;
464 
465  ret = avfilter_link(volume, 0, first_filter, pad_idx);
466  if (ret < 0)
467  return ret;
468 
469  first_filter = volume;
470  pad_idx = 0;
471  }
472  if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
473  return ret;
474 
475  return 0;
476 }
477 
479  AVFilterInOut *in)
480 {
481  av_freep(&ifilter->name);
482  DESCRIBE_FILTER_LINK(ifilter, in, 1);
483 
484  switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) {
485  case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in);
486  case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in);
487  default: av_assert0(0);
488  }
489 }
490 
492 {
493  AVFilterInOut *inputs, *outputs, *cur;
494  int ret, i, init = !fg->graph, simple = !fg->graph_desc;
495  const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
496  fg->graph_desc;
497 
499  if (!(fg->graph = avfilter_graph_alloc()))
500  return AVERROR(ENOMEM);
501 
502  if (simple) {
503  OutputStream *ost = fg->outputs[0]->ost;
504  char args[255];
505  snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
506  fg->graph->scale_sws_opts = av_strdup(args);
507  }
508 
509  if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
510  return ret;
511 
512  if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
513  av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have "
514  "exactly one input and output.\n", graph_desc);
515  return AVERROR(EINVAL);
516  }
517 
518  for (cur = inputs; !simple && init && cur; cur = cur->next)
519  init_input_filter(fg, cur);
520 
521  for (cur = inputs, i = 0; cur; cur = cur->next, i++)
522  if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0)
523  return ret;
524  avfilter_inout_free(&inputs);
525 
526  if (!init || simple) {
527  /* we already know the mappings between lavfi outputs and output streams,
528  * so we can finish the setup */
529  for (cur = outputs, i = 0; cur; cur = cur->next, i++)
530  configure_output_filter(fg, fg->outputs[i], cur);
531  avfilter_inout_free(&outputs);
532 
533  if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
534  return ret;
535  } else {
536  /* wait until output mappings are processed */
537  for (cur = outputs; cur;) {
538  GROW_ARRAY(fg->outputs, fg->nb_outputs);
539  if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
540  exit(1);
541  fg->outputs[fg->nb_outputs - 1]->graph = fg;
542  fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
543  cur = cur->next;
544  fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
545  }
546  }
547 
548  return 0;
549 }
550 
552 {
553  int i;
554  for (i = 0; i < fg->nb_inputs; i++)
555  if (fg->inputs[i]->ist == ist)
556  return 1;
557  return 0;
558 }
559