Browse code

avconv: add options for reading filtergraphs from a file.

Anton Khirnov authored on 2013/03/13 22:24:45
Showing 5 changed files
... ...
@@ -7,6 +7,8 @@ version 10:
7 7
 - reference-counting for AVFrame and AVPacket data
8 8
 - avconv now fails when input options are used for output file
9 9
   or vice versa
10
+- new avconv options -filter_script and -filter_complex_script, which allow a
11
+  filtergraph description to be read from a file
10 12
 
11 13
 
12 14
 version 9:
... ...
@@ -160,6 +160,7 @@ static void exit_program(void)
160 160
             av_freep(&filtergraphs[i]->outputs[j]);
161 161
         }
162 162
         av_freep(&filtergraphs[i]->outputs);
163
+        av_freep(&filtergraphs[i]->graph_desc);
163 164
         av_freep(&filtergraphs[i]);
164 165
     }
165 166
     av_freep(&filtergraphs);
... ...
@@ -158,6 +158,8 @@ typedef struct OptionsContext {
158 158
     int        nb_copy_initial_nonkeyframes;
159 159
     SpecifierOpt *filters;
160 160
     int        nb_filters;
161
+    SpecifierOpt *filter_scripts;
162
+    int        nb_filter_scripts;
161 163
     SpecifierOpt *pass;
162 164
     int        nb_pass;
163 165
     SpecifierOpt *passlogfiles;
... ...
@@ -926,6 +926,59 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str)
926 926
     }
927 927
 }
928 928
 
929
+/* read file contents into a string */
930
+static uint8_t *read_file(const char *filename)
931
+{
932
+    AVIOContext *pb      = NULL;
933
+    AVIOContext *dyn_buf = NULL;
934
+    int ret = avio_open(&pb, filename, AVIO_FLAG_READ);
935
+    uint8_t buf[1024], *str;
936
+
937
+    if (ret < 0) {
938
+        av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename);
939
+        return NULL;
940
+    }
941
+
942
+    ret = avio_open_dyn_buf(&dyn_buf);
943
+    if (ret < 0) {
944
+        avio_closep(&pb);
945
+        return NULL;
946
+    }
947
+    while ((ret = avio_read(pb, buf, sizeof(buf))) > 0)
948
+        avio_write(dyn_buf, buf, ret);
949
+    avio_w8(dyn_buf, 0);
950
+    avio_closep(&pb);
951
+
952
+    ret = avio_close_dyn_buf(dyn_buf, &str);
953
+    if (ret < 0)
954
+        return NULL;
955
+    return str;
956
+}
957
+
958
+static char *get_ost_filters(OptionsContext *o, AVFormatContext *oc,
959
+                             OutputStream *ost)
960
+{
961
+    AVStream *st = ost->st;
962
+    char *filter = NULL, *filter_script = NULL;
963
+
964
+    MATCH_PER_STREAM_OPT(filter_scripts, str, filter_script, oc, st);
965
+    MATCH_PER_STREAM_OPT(filters, str, filter, oc, st);
966
+
967
+    if (filter_script && filter) {
968
+        av_log(NULL, AV_LOG_ERROR, "Both -filter and -filter_script set for "
969
+               "output stream #%d:%d.\n", nb_output_files, st->index);
970
+        exit(1);
971
+    }
972
+
973
+    if (filter_script)
974
+        return read_file(filter_script);
975
+    else if (filter)
976
+        return av_strdup(filter);
977
+
978
+    return av_strdup(st->codec->codec_type == AVMEDIA_TYPE_VIDEO ?
979
+                     "null" : "anull");
980
+}
981
+
929 982
 static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
930 983
 {
931 984
     AVStream *st;
... ...
@@ -941,7 +994,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
941 941
         char *frame_rate = NULL, *frame_size = NULL;
942 942
         char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
943 943
         char *intra_matrix = NULL, *inter_matrix = NULL;
944
-        const char *filters = "null";
945 944
         int do_pass = 0;
946 945
         int i;
947 946
 
... ...
@@ -1036,8 +1088,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
1036 1036
         ost->top_field_first = -1;
1037 1037
         MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st);
1038 1038
 
1039
-        MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
1040
-        ost->avfilter = av_strdup(filters);
1039
+
1040
+        ost->avfilter = get_ost_filters(o, oc, ost);
1041
+        if (!ost->avfilter)
1042
+            exit(1);
1041 1043
     } else {
1042 1044
         MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st);
1043 1045
     }
... ...
@@ -1059,7 +1113,6 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
1059 1059
 
1060 1060
     if (!ost->stream_copy) {
1061 1061
         char *sample_fmt = NULL;
1062
-        const char *filters = "anull";
1063 1062
 
1064 1063
         MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st);
1065 1064
 
... ...
@@ -1072,8 +1125,9 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
1072 1072
 
1073 1073
         MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
1074 1074
 
1075
-        MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
1076
-        ost->avfilter = av_strdup(filters);
1075
+        ost->avfilter = get_ost_filters(o, oc, ost);
1076
+        if (!ost->avfilter)
1077
+            exit(1);
1077 1078
     }
1078 1079
 
1079 1080
     return ost;
... ...
@@ -1878,8 +1932,24 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg)
1878 1878
     GROW_ARRAY(filtergraphs, nb_filtergraphs);
1879 1879
     if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
1880 1880
         return AVERROR(ENOMEM);
1881
-    filtergraphs[nb_filtergraphs - 1]->index       = nb_filtergraphs - 1;
1882
-    filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
1881
+    filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
1882
+    filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg);
1883
+    if (!filtergraphs[nb_filtergraphs - 1]->graph_desc)
1884
+        return AVERROR(ENOMEM);
1885
+    return 0;
1886
+}
1887
+
1888
+static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg)
1889
+{
1890
+    uint8_t *graph_desc = read_file(arg);
1891
+    if (!graph_desc)
1892
+        return AVERROR(EINVAL);
1893
+
1894
+    GROW_ARRAY(filtergraphs, nb_filtergraphs);
1895
+    if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
1896
+        return AVERROR(ENOMEM);
1897
+    filtergraphs[nb_filtergraphs - 1]->index      = nb_filtergraphs - 1;
1898
+    filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc;
1883 1899
     return 0;
1884 1900
 }
1885 1901
 
... ...
@@ -2138,8 +2208,12 @@ const OptionDef options[] = {
2138 2138
         "use fixed quality scale (VBR)", "q" },
2139 2139
     { "filter",         HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
2140 2140
         "set stream filterchain", "filter_list" },
2141
+    { "filter_script",  HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },
2142
+        "read stream filtergraph description from a file", "filename" },
2141 2143
     { "filter_complex", HAS_ARG | OPT_EXPERT,                        { .func_arg = opt_filter_complex },
2142 2144
         "create a complex filtergraph", "graph_description" },
2145
+    { "filter_complex_script", HAS_ARG | OPT_EXPERT,                 { .func_arg = opt_filter_complex_script },
2146
+        "read complex filtergraph description from a file", "filename" },
2143 2147
     { "stats",          OPT_BOOL,                                    { &print_stats },
2144 2148
         "print progress report during encoding", },
2145 2149
     { "attach",         HAS_ARG | OPT_PERFILE | OPT_EXPERT |
... ...
@@ -330,6 +330,12 @@ the stream. Use @code{-filters} to show all the available filters
330 330
 
331 331
 See also the @option{-filter_complex} option if you want to create filter graphs
332 332
 with multiple inputs and/or outputs.
333
+
334
+@item -filter_script[:@var{stream_specifier}] @var{filename} (@emph{output,per-stream})
335
+This option is similar to @option{-filter}, the only difference is that its
336
+argument is the name of the file from which a filtergraph description is to be
337
+read.
338
+
333 339
 @item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
334 340
 Specify the preset for matching stream(s).
335 341
 
... ...
@@ -823,6 +829,12 @@ To generate 5 seconds of pure red video using lavfi @code{color} source:
823 823
 @example
824 824
 avconv -filter_complex 'color=red' -t 5 out.mkv
825 825
 @end example
826
+
827
+@item -filter_complex_script @var{filename} (@emph{global})
828
+This option is similar to @option{-filter_complex}, the only difference is that
829
+its argument is the name of the file from which a complex filtergraph
830
+description is to be read.
831
+
826 832
 @end table
827 833
 @c man end OPTIONS
828 834