Commit ac1a1fd7 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit '1ae44c87'

* commit '1ae44c87':
  lavfi/gradfun: remove rounding to match C and SSE code.
  lavfi/gradfun: fix dithering in MMX code.
  lavfi/gradfun: fix rounding in MMX code.
  lavfi/gradfun: do not increment DC pointer for odd values.
  fate: filter: Add dependencies
  avconv: add options for reading filtergraphs from a file.

Conflicts:
	Changelog
	doc/ffmpeg.texi
	doc/filters.texi
	ffmpeg.h
	ffmpeg_opt.c
	libavfilter/vf_gradfun.c
	tests/fate/filter.mak
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 705b607d 1ae44c87
...@@ -12,6 +12,8 @@ version <next>: ...@@ -12,6 +12,8 @@ version <next>:
- 10% faster aac encoding on x86 and MIPS - 10% faster aac encoding on x86 and MIPS
- sine audio filter source - sine audio filter source
- WebP demuxing and decoding support - WebP demuxing and decoding support
- new ffmpeg options -filter_script and -filter_complex_script, which allow a
filtergraph description to be read from a file
version 1.2: version 1.2:
......
...@@ -359,6 +359,11 @@ syntax. ...@@ -359,6 +359,11 @@ syntax.
See the @ref{filter_complex_option,,-filter_complex option} if you See the @ref{filter_complex_option,,-filter_complex option} if you
want to create filter graphs with multiple inputs and/or outputs. 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}) @item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
Specify the preset for matching stream(s). Specify the preset for matching stream(s).
...@@ -1049,6 +1054,11 @@ ffmpeg -filter_complex 'color=c=red' -t 5 out.mkv ...@@ -1049,6 +1054,11 @@ ffmpeg -filter_complex 'color=c=red' -t 5 out.mkv
Define a complex filter graph, i.e. one with arbitrary number of inputs and/or Define a complex filter graph, i.e. one with arbitrary number of inputs and/or
outputs. Equivalent to @option{-filter_complex}. outputs. Equivalent to @option{-filter_complex}.
@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 @end table
As a special exception, you can use a bitmap subtitle stream as input: it As a special exception, you can use a bitmap subtitle stream as input: it
......
...@@ -442,6 +442,7 @@ static void exit_program(void) ...@@ -442,6 +442,7 @@ static void exit_program(void)
av_freep(&filtergraphs[i]->outputs[j]); av_freep(&filtergraphs[i]->outputs[j]);
} }
av_freep(&filtergraphs[i]->outputs); av_freep(&filtergraphs[i]->outputs);
av_freep(&filtergraphs[i]->graph_desc);
av_freep(&filtergraphs[i]); av_freep(&filtergraphs[i]);
} }
av_freep(&filtergraphs); av_freep(&filtergraphs);
......
...@@ -165,6 +165,8 @@ typedef struct OptionsContext { ...@@ -165,6 +165,8 @@ typedef struct OptionsContext {
int nb_copy_prior_start; int nb_copy_prior_start;
SpecifierOpt *filters; SpecifierOpt *filters;
int nb_filters; int nb_filters;
SpecifierOpt *filter_scripts;
int nb_filter_scripts;
SpecifierOpt *reinit_filters; SpecifierOpt *reinit_filters;
int nb_reinit_filters; int nb_reinit_filters;
SpecifierOpt *fix_sub_duration; SpecifierOpt *fix_sub_duration;
......
...@@ -1103,6 +1103,59 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) ...@@ -1103,6 +1103,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, int source_index) static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
{ {
AVStream *st; AVStream *st;
...@@ -1125,7 +1178,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ...@@ -1125,7 +1178,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
char *frame_size = NULL; char *frame_size = NULL;
char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL; char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
char *intra_matrix = NULL, *inter_matrix = NULL; char *intra_matrix = NULL, *inter_matrix = NULL;
const char *filters = "null";
int do_pass = 0; int do_pass = 0;
int i; int i;
...@@ -1236,8 +1288,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ...@@ -1236,8 +1288,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
ost->top_field_first = -1; ost->top_field_first = -1;
MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); 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 { } else {
MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
} }
...@@ -1260,7 +1314,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in ...@@ -1260,7 +1314,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
if (!ost->stream_copy) { if (!ost->stream_copy) {
char *sample_fmt = NULL; char *sample_fmt = NULL;
const char *filters = "anull";
MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st); MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
...@@ -1273,10 +1326,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in ...@@ -1273,10 +1326,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st); 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 = get_ost_filters(o, oc, ost);
if (!ost->avfilter)
av_assert1(filters); exit(1);
ost->avfilter = av_strdup(filters);
/* check for channel mapping for this audio stream */ /* check for channel mapping for this audio stream */
for (n = 0; n < o->nb_audio_channel_maps; n++) { for (n = 0; n < o->nb_audio_channel_maps; n++) {
...@@ -2291,8 +2343,24 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) ...@@ -2291,8 +2343,24 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg)
GROW_ARRAY(filtergraphs, nb_filtergraphs); GROW_ARRAY(filtergraphs, nb_filtergraphs);
if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
filtergraphs[nb_filtergraphs - 1]->graph_desc = arg; 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; return 0;
} }
...@@ -2590,12 +2658,16 @@ const OptionDef options[] = { ...@@ -2590,12 +2658,16 @@ const OptionDef options[] = {
"set profile", "profile" }, "set profile", "profile" },
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) }, { "filter", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
"set stream filtergraph", "filter_graph" }, "set stream filtergraph", "filter_graph" },
{ "filter_script", HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
"read stream filtergraph description from a file", "filename" },
{ "reinit_filter", HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(reinit_filters) }, { "reinit_filter", HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(reinit_filters) },
"reinit filtergraph on input parameter changes", "" }, "reinit filtergraph on input parameter changes", "" },
{ "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, { "filter_complex", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex },
"create a complex filtergraph", "graph_description" }, "create a complex filtergraph", "graph_description" },
{ "lavfi", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex }, { "lavfi", HAS_ARG | OPT_EXPERT, { .func_arg = opt_filter_complex },
"create a complex filtergraph", "graph_description" }, "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 }, { "stats", OPT_BOOL, { &print_stats },
"print progress report during encoding", }, "print progress report during encoding", },
{ "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT | { "attach", HAS_ARG | OPT_PERFILE | OPT_EXPERT |
......
FILTERDEMDEC = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER)
FILTERDEMDECMUX = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER $(4)_MUXER)
FILTERDEMDECENCMUX = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER $(4)_ENCODER $(5)_MUXER)
FATE_AMIX += fate-filter-amix-simple FATE_AMIX += fate-filter-amix-simple
fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le - fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le -
fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm
...@@ -18,9 +22,9 @@ $(FATE_AMIX): SRC1 = $(TARGET_PATH)/tests/data/asynth-44100-2-2.wav ...@@ -18,9 +22,9 @@ $(FATE_AMIX): SRC1 = $(TARGET_PATH)/tests/data/asynth-44100-2-2.wav
$(FATE_AMIX): CMP = oneoff $(FATE_AMIX): CMP = oneoff
$(FATE_AMIX): CMP_UNIT = f32 $(FATE_AMIX): CMP_UNIT = f32
FATE_FILTER-$(CONFIG_AMIX_FILTER) += $(FATE_AMIX) FATE_FILTER-$(call FILTERDEMDECENCMUX, AMIX, WAV, PCM_S16LE, PCM_F32LE, PCM_F32LE) += $(FATE_AMIX)
FATE_FILTER-$(CONFIG_ASYNCTS_FILTER) += fate-filter-asyncts FATE_FILTER-$(call FILTERDEMDECMUX, ASYNCTS, FLV, NELLYMOSER, PCM_S16LE) += fate-filter-asyncts
fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv
fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts
fate-filter-asyncts: CMP = oneoff fate-filter-asyncts: CMP = oneoff
...@@ -34,7 +38,7 @@ fate-filter-aresample: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm ...@@ -34,7 +38,7 @@ fate-filter-aresample: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm
fate-filter-delogo: CMD = framecrc -i $(SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an fate-filter-delogo: CMD = framecrc -i $(SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an
FATE_FILTER-$(call ALLYES, PERMS_FILTER DELOGO_FILTER) += fate-filter-delogo FATE_FILTER-$(call ALLYES, PERMS_FILTER DELOGO_FILTER RM_DEMUXER RV30_DECODER) += fate-filter-delogo
FATE_YADIF += fate-filter-yadif-mode0 FATE_YADIF += fate-filter-yadif-mode0
fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf yadif=0 fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf yadif=0
...@@ -42,7 +46,7 @@ fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLE ...@@ -42,7 +46,7 @@ fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLE
FATE_YADIF += fate-filter-yadif-mode1 FATE_YADIF += fate-filter-yadif-mode1
fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 59 -vf yadif=1 fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 59 -vf yadif=1
FATE_FILTER-$(CONFIG_YADIF_FILTER) += $(FATE_YADIF) FATE_FILTER-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF)
FATE_HQDN3D += fate-filter-hqdn3d FATE_HQDN3D += fate-filter-hqdn3d
fate-filter-hqdn3d: CMD = framecrc -idct simple -i $(SAMPLES)/smjpeg/scenwin.mjpg -vf perms=random,hqdn3d -an fate-filter-hqdn3d: CMD = framecrc -idct simple -i $(SAMPLES)/smjpeg/scenwin.mjpg -vf perms=random,hqdn3d -an
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment