aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2021-02-09 18:08:16 +0100
committerPaul B Mahol <onemda@gmail.com>2021-02-09 18:20:15 +0100
commitd7cb8c51f05a2a73e899d88348d92c0f5f72d2fd (patch)
tree0b69d18f52603b73951bf46a8f413a23ce114a8f
parentb6327612abc0448e95f9a1c4375b594635134188 (diff)
downloadffmpeg-d7cb8c51f05a2a73e899d88348d92c0f5f72d2fd.tar.gz
avfilter/vf_curves: add commands support
-rw-r--r--doc/filters.texi4
-rw-r--r--libavfilter/vf_curves.c74
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 ...}.
+@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,
};