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