[FFmpeg-cvslog] avfilter/vf_curves: add commands support

Paul B Mahol git at videolan.org
Tue Feb 9 19:20:47 EET 2021


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Tue Feb  9 18:08:16 2021 +0100| [d7cb8c51f05a2a73e899d88348d92c0f5f72d2fd] | committer: Paul B Mahol

avfilter/vf_curves: add commands support

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d7cb8c51f05a2a73e899d88348d92c0f5f72d2fd
---

 doc/filters.texi        |  4 +++
 libavfilter/vf_curves.c | 74 +++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index aeb20bc955..079bba9a1e 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -9257,6 +9257,10 @@ Save Gnuplot script of the curves in specified file.
 To avoid some filtergraph syntax conflicts, each key points list need to be
 defined using the following syntax: @code{x0/y0 x1/y1 x2/y2 ...}.
 
+ at subsection Commands
+
+This filter supports same @ref{commands} as options.
+
 @subsection Examples
 
 @itemize
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 883cc1c90c..3524fef1ad 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -69,8 +69,10 @@ typedef struct CurvesContext {
     uint8_t rgba_map[4];
     int step;
     char *plot_filename;
+    int saved_plot;
     int is_16bit;
     int depth;
+    int parsed_psfile;
 
     int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
 } CurvesContext;
@@ -80,20 +82,20 @@ typedef struct ThreadData {
 } ThreadData;
 
 #define OFFSET(x) offsetof(CurvesContext, x)
-#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
 static const AVOption curves_options[] = {
     { "preset", "select a color curves preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=PRESET_NONE}, PRESET_NONE, NB_PRESETS-1, FLAGS, "preset_name" },
-        { "none",               NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NONE},                 INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "color_negative",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE},       INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "cross_process",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS},        INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "darker",             NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER},               INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "increase_contrast",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST},    INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "lighter",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER},              INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "linear_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "medium_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "negative",           NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE},             INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "strong_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
-        { "vintage",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE},              INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "none",               NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NONE},                 0, 0, FLAGS, "preset_name" },
+        { "color_negative",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE},       0, 0, FLAGS, "preset_name" },
+        { "cross_process",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS},        0, 0, FLAGS, "preset_name" },
+        { "darker",             NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER},               0, 0, FLAGS, "preset_name" },
+        { "increase_contrast",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST},    0, 0, FLAGS, "preset_name" },
+        { "lighter",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER},              0, 0, FLAGS, "preset_name" },
+        { "linear_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST},      0, 0, FLAGS, "preset_name" },
+        { "medium_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST},      0, 0, FLAGS, "preset_name" },
+        { "negative",           NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE},             0, 0, FLAGS, "preset_name" },
+        { "strong_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST},      0, 0, FLAGS, "preset_name" },
+        { "vintage",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE},              0, 0, FLAGS, "preset_name" },
     { "master","set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "m",     "set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "red",   "set red points coordinates",   OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
@@ -486,10 +488,11 @@ static av_cold int curves_init(AVFilterContext *ctx)
         }
     }
 
-    if (curves->psfile) {
+    if (curves->psfile && !curves->parsed_psfile) {
         ret = parse_psfile(ctx, curves->psfile);
         if (ret < 0)
             return ret;
+        curves->parsed_psfile = 1;
     }
 
     if (curves->preset != PRESET_NONE) {
@@ -504,6 +507,7 @@ static av_cold int curves_init(AVFilterContext *ctx)
         SET_COMP_IF_NOT_SET(1, g);
         SET_COMP_IF_NOT_SET(2, b);
         SET_COMP_IF_NOT_SET(3, master);
+        curves->preset = PRESET_NONE;
     }
 
     return 0;
@@ -664,7 +668,8 @@ static int config_input(AVFilterLink *inlink)
     curves->filter_slice = desc->flags & AV_PIX_FMT_FLAG_PLANAR ? filter_slice_planar : filter_slice_packed;
 
     for (i = 0; i < NB_COMP + 1; i++) {
-        curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0]));
+        if (!curves->graph[i])
+            curves->graph[i] = av_mallocz_array(curves->lut_size, sizeof(*curves->graph[0]));
         if (!curves->graph[i])
             return AVERROR(ENOMEM);
         ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i], curves->lut_size);
@@ -699,8 +704,10 @@ static int config_input(AVFilterLink *inlink)
         }
     }
 
-    if (curves->plot_filename)
+    if (curves->plot_filename && !curves->saved_plot) {
         dump_curves(curves->plot_filename, curves->graph, comp_points, curves->lut_size);
+        curves->saved_plot = 1;
+    }
 
     for (i = 0; i < NB_COMP + 1; i++) {
         struct keypoint *point = comp_points[i];
@@ -743,6 +750,42 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     return ff_filter_frame(outlink, out);
 }
 
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    CurvesContext *curves = ctx->priv;
+    int ret;
+
+    if (!strcmp(cmd, "plot")) {
+        curves->saved_plot = 0;
+    } else if (!strcmp(cmd, "all") || !strcmp(cmd, "preset") || !strcmp(cmd, "psfile")) {
+        if (!strcmp(cmd, "psfile"))
+            curves->parsed_psfile = 0;
+        av_freep(&curves->comp_points_str_all);
+        av_freep(&curves->comp_points_str[0]);
+        av_freep(&curves->comp_points_str[1]);
+        av_freep(&curves->comp_points_str[2]);
+        av_freep(&curves->comp_points_str[NB_COMP]);
+    } else if (!strcmp(cmd, "red") || !strcmp(cmd, "r")) {
+        av_freep(&curves->comp_points_str[0]);
+    } else if (!strcmp(cmd, "green") || !strcmp(cmd, "g")) {
+        av_freep(&curves->comp_points_str[1]);
+    } else if (!strcmp(cmd, "blue") || !strcmp(cmd, "b")) {
+        av_freep(&curves->comp_points_str[2]);
+    } else if (!strcmp(cmd, "master") || !strcmp(cmd, "m")) {
+        av_freep(&curves->comp_points_str[NB_COMP]);
+    }
+
+    ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
+    if (ret < 0)
+        return ret;
+
+    ret = curves_init(ctx);
+    if (ret < 0)
+        return ret;
+    return config_input(ctx->inputs[0]);
+}
+
 static av_cold void curves_uninit(AVFilterContext *ctx)
 {
     int i;
@@ -781,4 +824,5 @@ AVFilter ff_vf_curves = {
     .outputs       = curves_outputs,
     .priv_class    = &curves_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
+    .process_command = process_command,
 };



More information about the ffmpeg-cvslog mailing list