]> git.sesse.net Git - ffmpeg/commitdiff
avconv: add options for reading filtergraphs from a file.
authorAnton Khirnov <anton@khirnov.net>
Wed, 13 Mar 2013 13:24:45 +0000 (14:24 +0100)
committerAnton Khirnov <anton@khirnov.net>
Thu, 28 Mar 2013 06:55:48 +0000 (07:55 +0100)
Changelog
avconv.c
avconv.h
avconv_opt.c
doc/avconv.texi

index 15c08737687afb4caab5aa5f99c5fdee5032901c..1c493c2dc86468be00337d91c63ad9a5217d1d31 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -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:
index 1a18ad336d14b04d0cf0e61648341c8ab4c099c0..a5a4c7f61e9939b9bf51ba8dabac07f67bc3cf54 100644 (file)
--- a/avconv.c
+++ b/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);
index eb9df9b16a213fd464c88832868144d8b7fc3e2c..73e20e8fe051f6338cd4119f163ffd00766dbd7b 100644 (file)
--- a/avconv.h
+++ b/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;
index 2c43da2bbd3b59fc451f6e2508c8feaff06b0152..2e5cb05a4a9bf48cbab89124c1efa560ddb0e740 100644 (file)
@@ -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 |
index 7341d2fda600d92e93904a5fc488f0ea0e169d29..3e1dc4cf344cb4ce7f623d19d58853f067fb1354 100644 (file)
@@ -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