mirror of
https://gitee.com/openharmony/third_party_ffmpeg
synced 2024-11-23 11:19:55 +00:00
avconv: add options for reading filtergraphs from a file.
This commit is contained in:
parent
cf53704c55
commit
a4208b9b7d
@ -7,6 +7,8 @@ version 10:
|
||||
- reference-counting for AVFrame and AVPacket data
|
||||
- avconv now fails when input options are used for output file
|
||||
or vice versa
|
||||
- new avconv options -filter_script and -filter_complex_script, which allow a
|
||||
filtergraph description to be read from a file
|
||||
|
||||
|
||||
version 9:
|
||||
|
1
avconv.c
1
avconv.c
@ -160,6 +160,7 @@ static void exit_program(void)
|
||||
av_freep(&filtergraphs[i]->outputs[j]);
|
||||
}
|
||||
av_freep(&filtergraphs[i]->outputs);
|
||||
av_freep(&filtergraphs[i]->graph_desc);
|
||||
av_freep(&filtergraphs[i]);
|
||||
}
|
||||
av_freep(&filtergraphs);
|
||||
|
2
avconv.h
2
avconv.h
@ -158,6 +158,8 @@ typedef struct OptionsContext {
|
||||
int nb_copy_initial_nonkeyframes;
|
||||
SpecifierOpt *filters;
|
||||
int nb_filters;
|
||||
SpecifierOpt *filter_scripts;
|
||||
int nb_filter_scripts;
|
||||
SpecifierOpt *pass;
|
||||
int nb_pass;
|
||||
SpecifierOpt *passlogfiles;
|
||||
|
90
avconv_opt.c
90
avconv_opt.c
@ -926,6 +926,59 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
|
||||
}
|
||||
}
|
||||
|
||||
/* read file contents into a string */
|
||||
static uint8_t *read_file(const char *filename)
|
||||
{
|
||||
AVIOContext *pb = NULL;
|
||||
AVIOContext *dyn_buf = NULL;
|
||||
int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
|
||||
uint8_t buf[1024], *str;
|
||||
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = avio_open_dyn_buf(&dyn_buf);
|
||||
if (ret < 0) {
|
||||
avio_closep(&pb);
|
||||
return NULL;
|
||||
}
|
||||
while ((ret = avio_read(pb, buf, sizeof(buf))) > 0)
|
||||
avio_write(dyn_buf, buf, ret);
|
||||
avio_w8(dyn_buf, 0);
|
||||
avio_closep(&pb);
|
||||
|
||||
ret = avio_close_dyn_buf(dyn_buf, &str);
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
|
||||
OutputStream *ost)
|
||||
{
|
||||
AVStream *st = ost->st;
|
||||
char *filter = NULL, *filter_script = NULL;
|
||||
|
||||
MATCH_PER_STREAM_OPT(filter_scripts, str, filter_script, oc, st);
|
||||
MATCH_PER_STREAM_OPT(filters, str, filter, oc, st);
|
||||
|
||||
if (filter_script && filter) {
|
||||
av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for "
|
||||
"output stream #%d:%d.\n", nb_output_files, st->index);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (filter_script)
|
||||
return read_file(filter_script);
|
||||
else if (filter)
|
||||
return av_strdup(filter);
|
||||
|
||||
return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
|
||||
"null" : "anull");
|
||||
}
|
||||
|
||||
static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
|
||||
{
|
||||
AVStream *st;
|
||||
@ -941,7 +994,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
|
||||
char *frame_rate = NULL, *frame_size = NULL;
|
||||
char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
|
||||
char *intra_matrix = NULL, *inter_matrix = NULL;
|
||||
const char *filters = "null";
|
||||
int do_pass = 0;
|
||||
int i;
|
||||
|
||||
@ -1036,8 +1088,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
|
||||
ost->top_field_first = -1;
|
||||
MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
|
||||
|
||||
MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
|
||||
ost->avfilter = av_strdup(filters);
|
||||
|
||||
ost->avfilter = get_ost_filters(o, oc, ost);
|
||||
if (!ost->avfilter)
|
||||
exit(1);
|
||||
} else {
|
||||
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
|
||||
}
|
||||
@ -1059,7 +1113,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
|
||||
|
||||
if (!ost->stream_copy) {
|
||||
char *sample_fmt = NULL;
|
||||
const char *filters = "anull";
|
||||
|
||||
MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
|
||||
|
||||
@ -1072,8 +1125,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
|
||||
|
||||
MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
|
||||
|
||||
MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
|
||||
ost->avfilter = av_strdup(filters);
|
||||
ost->avfilter = get_ost_filters(o, oc, ost);
|
||||
if (!ost->avfilter)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ost;
|
||||
@ -1878,8 +1932,24 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg)
|
||||
GROW_ARRAY(filtergraphs, nb_filtergraphs);
|
||||
if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
|
||||
return AVERROR(ENOMEM);
|
||||
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
|
||||
filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
|
||||
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
|
||||
filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg);
|
||||
if (!filtergraphs[nb_filtergraphs - 1]->graph_desc)
|
||||
return AVERROR(ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
uint8_t *graph_desc = read_file(arg);
|
||||
if (!graph_desc)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
GROW_ARRAY(filtergraphs, nb_filtergraphs);
|
||||
if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
|
||||
return AVERROR(ENOMEM);
|
||||
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
|
||||
filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2138,8 +2208,12 @@ const OptionDef options[] = {
|
||||
"use fixed quality scale (VBR)", "q" },
|
||||
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
|
||||
"set stream filterchain", "filter_list" },
|
||||
{ "filter_script", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
|
||||
"read stream filtergraph description from a file", "filename" },
|
||||
{ "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex },
|
||||
"create a complex filtergraph", "graph_description" },
|
||||
{ "filter_complex_script", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex_script },
|
||||
"read complex filtergraph description from a file", "filename" },
|
||||
{ "stats", OPT_BOOL, { &print_stats },
|
||||
"print progress report during encoding", },
|
||||
{ "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
|
||||
|
@ -330,6 +330,12 @@ the stream. Use @code{-filters} to show all the available filters
|
||||
|
||||
See also the @option{-filter_complex} option if you want to create filter graphs
|
||||
with multiple inputs and/or outputs.
|
||||
|
||||
@item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream})
|
||||
This option is similar to @option{-filter}, the only difference is that its
|
||||
argument is the name of the file from which a filtergraph description is to be
|
||||
read.
|
||||
|
||||
@item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
|
||||
Specify the preset for matching stream(s).
|
||||
|
||||
@ -823,6 +829,12 @@ To generate 5 seconds of pure red video using lavfi @code{color} source:
|
||||
@example
|
||||
avconv -filter_complex 'color=red' -t 5 out.mkv
|
||||
@end example
|
||||
|
||||
@item -filter_complex_script @var{filename} (@emph{global})
|
||||
This option is similar to @option{-filter_complex}, the only difference is that
|
||||
its argument is the name of the file from which a complex filtergraph
|
||||
description is to be read.
|
||||
|
||||
@end table
|
||||
@c man end OPTIONS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user