Browse code

Merge commit '1ae44c87c924b69a0657256fbaa8ad140df2f27c'

* commit '1ae44c87c924b69a0657256fbaa8ad140df2f27c':
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: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2013/03/28 21:00:39
Showing 6 changed files
... ...
@@ -12,6 +12,8 @@ version <next>:
12 12
 - 10% faster aac encoding on x86 and MIPS
13 13
 - sine audio filter source
14 14
 - WebP demuxing and decoding support
15
+- new ffmpeg options -filter_script and -filter_complex_script, which allow a
16
+  filtergraph description to be read from a file
15 17
 
16 18
 
17 19
 version 1.2:
... ...
@@ -359,6 +359,11 @@ syntax.
359 359
 See the @ref{filter_complex_option,,-filter_complex option} if you
360 360
 want to create filter graphs with multiple inputs and/or outputs.
361 361
 
362
+@item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream})
363
+This option is similar to @option{-filter}, the only difference is that its
364
+argument is the name of the file from which a filtergraph description is to be
365
+read.
366
+
362 367
 @item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
363 368
 Specify the preset for matching stream(s).
364 369
 
... ...
@@ -1049,6 +1054,11 @@ ffmpeg -filter_complex 'color=c=red' -t 5 out.mkv
1049 1049
 Define a complex filter graph, i.e. one with arbitrary number of inputs and/or
1050 1050
 outputs. Equivalent to @option{-filter_complex}.
1051 1051
 
1052
+@item -filter_complex_script @var{filename} (@emph{global})
1053
+This option is similar to @option{-filter_complex}, the only difference is that
1054
+its argument is the name of the file from which a complex filtergraph
1055
+description is to be read.
1056
+
1052 1057
 @end table
1053 1058
 
1054 1059
 As a special exception, you can use a bitmap subtitle stream as input: it
... ...
@@ -442,6 +442,7 @@ static void exit_program(void)
442 442
             av_freep(&filtergraphs[i]->outputs[j]);
443 443
         }
444 444
         av_freep(&filtergraphs[i]->outputs);
445
+        av_freep(&filtergraphs[i]->graph_desc);
445 446
         av_freep(&filtergraphs[i]);
446 447
     }
447 448
     av_freep(&filtergraphs);
... ...
@@ -165,6 +165,8 @@ typedef struct OptionsContext {
165 165
     int        nb_copy_prior_start;
166 166
     SpecifierOpt *filters;
167 167
     int        nb_filters;
168
+    SpecifierOpt *filter_scripts;
169
+    int        nb_filter_scripts;
168 170
     SpecifierOpt *reinit_filters;
169 171
     int        nb_reinit_filters;
170 172
     SpecifierOpt *fix_sub_duration;
... ...
@@ -1103,6 +1103,59 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
1103 1103
     }
1104 1104
 }
1105 1105
 
1106
+/* read file contents into a string */
1107
+static uint8_t *read_file(const char *filename)
1108
+{
1109
+    AVIOContext *pb      = NULL;
1110
+    AVIOContext *dyn_buf = NULL;
1111
+    int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
1112
+    uint8_t buf[1024], *str;
1113
+
1114
+    if (ret < 0) {
1115
+        av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
1116
+        return NULL;
1117
+    }
1118
+
1119
+    ret = avio_open_dyn_buf(&dyn_buf);
1120
+    if (ret < 0) {
1121
+        avio_closep(&pb);
1122
+        return NULL;
1123
+    }
1124
+    while ((ret = avio_read(pb, buf, sizeof(buf))) > 0)
1125
+        avio_write(dyn_buf, buf, ret);
1126
+    avio_w8(dyn_buf, 0);
1127
+    avio_closep(&pb);
1128
+
1129
+    ret = avio_close_dyn_buf(dyn_buf, &str);
1130
+    if (ret < 0)
1131
+        return NULL;
1132
+    return str;
1133
+}
1134
+
1135
+static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
1136
+                             OutputStream *ost)
1137
+{
1138
+    AVStream *st = ost->st;
1139
+    char *filter = NULL, *filter_script = NULL;
1140
+
1141
+    MATCH_PER_STREAM_OPT(filter_scripts, str, filter_script, oc, st);
1142
+    MATCH_PER_STREAM_OPT(filters, str, filter, oc, st);
1143
+
1144
+    if (filter_script && filter) {
1145
+        av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for "
1146
+               "output stream #%d:%d.\n", nb_output_files, st->index);
1147
+        exit(1);
1148
+    }
1149
+
1150
+    if (filter_script)
1151
+        return read_file(filter_script);
1152
+    else if (filter)
1153
+        return av_strdup(filter);
1154
+
1155
+    return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
1156
+                     "null" : "anull");
1157
+}
1158
+
1106 1159
 static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
1107 1160
 {
1108 1161
     AVStream *st;
... ...
@@ -1125,7 +1178,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
1125 1125
         char *frame_size = NULL;
1126 1126
         char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
1127 1127
         char *intra_matrix = NULL, *inter_matrix = NULL;
1128
-        const char *filters = "null";
1129 1128
         int do_pass = 0;
1130 1129
         int i;
1131 1130
 
... ...
@@ -1236,8 +1288,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
1236 1236
         ost->top_field_first = -1;
1237 1237
         MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
1238 1238
 
1239
-        MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
1240
-        ost->avfilter = av_strdup(filters);
1239
+
1240
+        ost->avfilter = get_ost_filters(o, oc, ost);
1241
+        if (!ost->avfilter)
1242
+            exit(1);
1241 1243
     } else {
1242 1244
         MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
1243 1245
     }
... ...
@@ -1260,7 +1314,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
1260 1260
 
1261 1261
     if (!ost->stream_copy) {
1262 1262
         char *sample_fmt = NULL;
1263
-        const char *filters = "anull";
1264 1263
 
1265 1264
         MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
1266 1265
 
... ...
@@ -1273,10 +1326,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
1273 1273
 
1274 1274
         MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
1275 1275
 
1276
-        MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
1277
-
1278
-        av_assert1(filters);
1279
-        ost->avfilter = av_strdup(filters);
1276
+        ost->avfilter = get_ost_filters(o, oc, ost);
1277
+        if (!ost->avfilter)
1278
+            exit(1);
1280 1279
 
1281 1280
         /* check for channel mapping for this audio stream */
1282 1281
         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 2291
     GROW_ARRAY(filtergraphs, nb_filtergraphs);
2292 2292
     if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
2293 2293
         return AVERROR(ENOMEM);
2294
-    filtergraphs[nb_filtergraphs - 1]->index       = nb_filtergraphs - 1;
2295
-    filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
2294
+    filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
2295
+    filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg);
2296
+    if (!filtergraphs[nb_filtergraphs - 1]->graph_desc)
2297
+        return AVERROR(ENOMEM);
2298
+    return 0;
2299
+}
2300
+
2301
+static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg)
2302
+{
2303
+    uint8_t *graph_desc = read_file(arg);
2304
+    if (!graph_desc)
2305
+        return AVERROR(EINVAL);
2306
+
2307
+    GROW_ARRAY(filtergraphs, nb_filtergraphs);
2308
+    if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
2309
+        return AVERROR(ENOMEM);
2310
+    filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
2311
+    filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc;
2296 2312
     return 0;
2297 2313
 }
2298 2314
 
... ...
@@ -2590,12 +2658,16 @@ const OptionDef options[] = {
2590 2590
         "set profile", "profile" },
2591 2591
     { "filter",         HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
2592 2592
         "set stream filtergraph", "filter_graph" },
2593
+    { "filter_script",  HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
2594
+        "read stream filtergraph description from a file", "filename" },
2593 2595
     { "reinit_filter",  HAS_ARG | OPT_INT | OPT_SPEC | OPT_INPUT,    { .off = OFFSET(reinit_filters) },
2594 2596
         "reinit filtergraph on input parameter changes", "" },
2595 2597
     { "filter_complex", HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_filter_complex },
2596 2598
         "create a complex filtergraph", "graph_description" },
2597 2599
     { "lavfi",          HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_filter_complex },
2598 2600
         "create a complex filtergraph", "graph_description" },
2601
+    { "filter_complex_script", HAS_ARG | OPT_EXPERT,                 { .func_arg = opt_filter_complex_script },
2602
+        "read complex filtergraph description from a file", "filename" },
2599 2603
     { "stats",          OPT_BOOL,                                    { &print_stats },
2600 2604
         "print progress report during encoding", },
2601 2605
     { "attach",         HAS_ARG | OPT_PERFILE | OPT_EXPERT |
... ...
@@ -1,3 +1,7 @@
1
+FILTERDEMDEC        = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER)
2
+FILTERDEMDECMUX     = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER $(4)_MUXER)
3
+FILTERDEMDECENCMUX  = $(call ALLYES, $(1)_FILTER $(2)_DEMUXER $(3)_DECODER $(4)_ENCODER $(5)_MUXER)
4
+
1 5
 FATE_AMIX += fate-filter-amix-simple
2 6
 fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le -
3 7
 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 18
 $(FATE_AMIX): CMP  = oneoff
19 19
 $(FATE_AMIX): CMP_UNIT = f32
20 20
 
21
-FATE_FILTER-$(CONFIG_AMIX_FILTER) += $(FATE_AMIX)
21
+FATE_FILTER-$(call FILTERDEMDECENCMUX, AMIX, WAV, PCM_S16LE, PCM_F32LE, PCM_F32LE) += $(FATE_AMIX)
22 22
 
23
-FATE_FILTER-$(CONFIG_ASYNCTS_FILTER) += fate-filter-asyncts
23
+FATE_FILTER-$(call FILTERDEMDECMUX, ASYNCTS, FLV, NELLYMOSER, PCM_S16LE) += fate-filter-asyncts
24 24
 fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv
25 25
 fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts
26 26
 fate-filter-asyncts: CMP = oneoff
... ...
@@ -34,7 +38,7 @@ fate-filter-aresample: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm
34 34
 
35 35
 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
36 36
 
37
-FATE_FILTER-$(call ALLYES, PERMS_FILTER DELOGO_FILTER) += fate-filter-delogo
37
+FATE_FILTER-$(call ALLYES, PERMS_FILTER DELOGO_FILTER RM_DEMUXER RV30_DECODER) += fate-filter-delogo
38 38
 
39 39
 FATE_YADIF += fate-filter-yadif-mode0
40 40
 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 42
 FATE_YADIF += fate-filter-yadif-mode1
43 43
 fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 59 -vf yadif=1
44 44
 
45
-FATE_FILTER-$(CONFIG_YADIF_FILTER) += $(FATE_YADIF)
45
+FATE_FILTER-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF)
46 46
 
47 47
 FATE_HQDN3D += fate-filter-hqdn3d
48 48
 fate-filter-hqdn3d: CMD = framecrc -idct simple -i $(SAMPLES)/smjpeg/scenwin.mjpg -vf perms=random,hqdn3d -an