[FFmpeg-devel] [PATCH 3/3] lavfi/overlay: support timeline through the new system.
Clément Bœsch
ubitux at gmail.com
Sat Apr 20 15:17:23 CEST 2013
On Sat, Apr 20, 2013 at 11:49:24AM +0200, Stefano Sabatini wrote:
> On date Friday 2013-04-19 00:28:54 +0200, Clément Bœsch encoded:
> > ---
> > doc/filters.texi | 15 +++---------
> > libavfilter/vf_overlay.c | 64 +++++++++++++++++++++++++-----------------------
> > 2 files changed, 37 insertions(+), 42 deletions(-)
> [...]
>
> I see two issues with this patch:
> - some variables are not supported in the generic enable expression
> - enable command is removed
>
> The First problem should be mostly addressed by adding pos to the list
> of supported variables. You may ask, why is pos relevant? Well if you
> know the total size of a file pos can provide some hints about the
> position of the frame in the file (so you can roughly say: enable this
> if it is between 50% and 60% of the file).
>
Interesting approach, why not, added. New patch attached.
> The second problem is more serious, indeed the enable command was the
> main reason for which I added that option.
Added another patch on top of this one to enable the enable command
injection, please comment.
--
Clément B.
-------------- next part --------------
From 7a5aa2e8bd93fa887ccb83fefb76b9eb96564e62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
Date: Mon, 8 Apr 2013 20:35:02 +0200
Subject: [PATCH 2/4] lavfi: add timeline support.
Flag added in a few simple filters. A bunch of other filters can likely
use the feature as well.
---
Changelog | 1 +
cmdutils.c | 2 ++
doc/filters.texi | 32 ++++++++++++++++++++++++++++
libavfilter/af_volume.c | 1 +
libavfilter/avfilter.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
libavfilter/avfilter.h | 25 +++++++++++++++++++++-
libavfilter/vf_boxblur.c | 1 +
libavfilter/vf_colormatrix.c | 1 +
libavfilter/vf_cropdetect.c | 1 +
libavfilter/vf_curves.c | 1 +
libavfilter/vf_drawbox.c | 1 +
libavfilter/vf_edgedetect.c | 1 +
libavfilter/vf_gradfun.c | 1 +
libavfilter/vf_histeq.c | 1 +
libavfilter/vf_hqdn3d.c | 2 +-
libavfilter/vf_hue.c | 1 +
libavfilter/vf_lut.c | 1 +
libavfilter/vf_noise.c | 1 +
libavfilter/vf_pp.c | 2 +-
libavfilter/vf_smartblur.c | 1 +
libavfilter/vf_unsharp.c | 2 +-
21 files changed, 125 insertions(+), 4 deletions(-)
diff --git a/Changelog b/Changelog
index 7b2ae6b..dc871dc 100644
--- a/Changelog
+++ b/Changelog
@@ -28,6 +28,7 @@ version <next>:
- The matroska demuxer can now output proper verbatim ASS packets. It will
become the default at the next libavformat major bump.
- decent native animated GIF encoding
+- timeline editing with filters
version 1.2:
diff --git a/cmdutils.c b/cmdutils.c
index cc88697..b9985d6 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -1683,6 +1683,8 @@ static void show_help_filter(const char *name)
if (f->priv_class)
show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM |
AV_OPT_FLAG_AUDIO_PARAM);
+ if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)
+ printf("This filter has support for timeline through the 'enable' option.\n");
#else
av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; "
"can not to satisfy request\n");
diff --git a/doc/filters.texi b/doc/filters.texi
index 4c702a9..b443643 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -267,6 +267,36 @@ See the ``Quoting and escaping'' section in the ffmpeg-utils manual
for more information about the escaping and quoting rules adopted by
FFmpeg.
+ at chapter Timeline editing
+
+Some filters support a generic @option{enable} option. For the filters
+supporting timeline editing, this option can be set to an expression which is
+evaluated before sending a frame to the filter. If the evaluation is non-zero,
+the filter will be enabled, otherwise the frame will be sent unchanged to the
+next filter in the filtergraph.
+
+The expression accepts the following values:
+ at table @samp
+ at item t
+timestamp expressed in seconds, NAN if the input timestamp is unknown
+
+ at item n
+sequential number of the input frame, starting from 0
+
+ at item pos
+the position in the file of the input frame, NAN if unknown
+ at end table
+
+Like any other filtering option, the @option{enable} option follows the same
+rules.
+
+For example, to enable a denoiser filter (@ref{hqdn3d}) from 10 seconds to 3
+minutes, and a @ref{curves} filter starting at 3 seconds:
+ at example
+hqdn3d = enable='between(t,10,3*60)',
+curves = enable='gte(t,3)' : preset=cross_process
+ at end example
+
@c man end FILTERGRAPH DESCRIPTION
@chapter Audio Filters
@@ -2397,6 +2427,7 @@ indicates never reset and return the largest area encountered during
playback.
@end table
+ at anchor{curves}
@section curves
Apply color adjustments using curves.
@@ -3983,6 +4014,7 @@ ffplay -i input -vf histogram
@end itemize
+ at anchor{hqdn3d}
@section hqdn3d
High precision/quality 3d denoise filter. This filter aims to reduce
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 7d2b9ba..a55e1a3 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -296,4 +296,5 @@ AVFilter avfilter_af_volume = {
.init = init,
.inputs = avfilter_af_volume_inputs,
.outputs = avfilter_af_volume_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 43340d1..0c6f1f1 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -23,6 +23,7 @@
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
+#include "libavutil/eval.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
@@ -483,12 +484,20 @@ static const AVClass *filter_child_class_next(const AVClass *prev)
return NULL;
}
+#define OFFSET(x) offsetof(AVFilterContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM
+static const AVOption filters_common_options[] = {
+ { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
+ { NULL }
+};
+
static const AVClass avfilter_class = {
.class_name = "AVFilter",
.item_name = default_filter_name,
.version = LIBAVUTIL_VERSION_INT,
.category = AV_CLASS_CATEGORY_FILTER,
.child_next = filter_child_next,
+ .option = filters_common_options,
.child_class_next = filter_child_class_next,
};
@@ -618,9 +627,16 @@ void avfilter_free(AVFilterContext *filter)
while(filter->command_queue){
ff_command_queue_pop(filter);
}
+ av_opt_free(filter);
+ av_expr_free(filter->enable);
+ filter->enable = NULL;
+ av_freep(&filter->var_values);
av_free(filter);
}
+static const char *const var_names[] = { "t", "n", "pos", NULL };
+enum { VAR_T, VAR_N, VAR_POS, VAR_VARS_NB };
+
static int process_options(AVFilterContext *ctx, AVDictionary **options,
const char *args)
{
@@ -630,6 +646,8 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options,
const char *key;
int offset= -1;
+ av_opt_set_defaults(ctx);
+
if (!args)
return 0;
@@ -665,6 +683,12 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options,
}
av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value);
+
+ if (av_opt_find(ctx, key, NULL, 0, 0)) {
+ ret = av_opt_set(ctx, key, value, 0);
+ if (ret < 0)
+ return ret;
+ } else {
av_dict_set(options, key, value, 0);
if ((ret = av_opt_set(ctx->priv, key, value, 0)) < 0) {
if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) {
@@ -675,11 +699,27 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options,
return ret;
}
}
+ }
av_free(value);
av_free(parsed_key);
count++;
}
+
+ if (ctx->enable_str) {
+ if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) {
+ av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported "
+ "with filter '%s'\n", ctx->filter->name);
+ return AVERROR_PATCHWELCOME;
+ }
+ ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values));
+ if (!ctx->var_values)
+ return AVERROR(ENOMEM);
+ ret = av_expr_parse((AVExpr**)&ctx->enable, ctx->enable_str, var_names,
+ NULL, NULL, NULL, NULL, 0, ctx->priv);
+ if (ret < 0)
+ return ret;
+ }
return count;
}
@@ -852,6 +892,7 @@ static int default_filter_frame(AVFilterLink *link, AVFrame *frame)
static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
{
int (*filter_frame)(AVFilterLink *, AVFrame *);
+ AVFilterContext *dstctx = link->dst;
AVFilterPad *dst = link->dstpad;
AVFrame *out;
int ret;
@@ -914,6 +955,15 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
}
pts = out->pts;
+ if (dstctx->enable_str) {
+ int64_t pos = av_frame_get_pkt_pos(out);
+ dstctx->var_values[VAR_N] = link->frame_count;
+ dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base);
+ dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos;
+ if (!av_expr_eval(dstctx->enable, dstctx->var_values, NULL))
+ filter_frame = dst->passthrough_filter_frame ? dst->passthrough_filter_frame
+ : default_filter_frame;
+ }
ret = filter_frame(link, out);
link->frame_count++;
link->frame_requested = 0;
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 047208c..62b7c55 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -385,6 +385,19 @@ struct AVFilterPad {
int needs_fifo;
int needs_writable;
+
+ /**
+ * Passthrough filtering callback.
+ *
+ * If a filter supports timeline editing (AVFILTER_FLAG_SUPPORT_TIMELINE)
+ * then it can implement a custom passthrough callback to update its local
+ * context (for example to keep a frame reference, or simply send the
+ * filter to a custom outlink). The filter must not do any change to the
+ * frame in this callback.
+ *
+ * Input pads only.
+ */
+ int (*passthrough_filter_frame)(AVFilterLink *link, AVFrame *frame);
};
#endif
@@ -428,6 +441,12 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
* the options supplied to it.
*/
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS (1 << 1)
+/**
+ * Some filters support a generic "enable" expression option that can be used
+ * to enable or disable a filter in the timeline. Filters supporting this
+ * option have this flag set.
+ */
+#define AVFILTER_FLAG_SUPPORT_TIMELINE (1 << 16)
/**
* Filter definition. This defines the pads a filter contains, and all the
@@ -522,7 +541,7 @@ typedef struct AVFilter {
/** An instance of a filter */
struct AVFilterContext {
- const AVClass *av_class; ///< needed for av_log()
+ const AVClass *av_class; ///< needed for av_log() and filters common options
const AVFilter *filter; ///< the AVFilter of which this is an instance
@@ -547,6 +566,10 @@ struct AVFilterContext {
struct AVFilterGraph *graph; ///< filtergraph this filter belongs to
struct AVFilterCommand *command_queue;
+
+ char *enable_str; ///< enable expression string
+ void *enable; ///< parsed expression (AVExpr*)
+ double *var_values; ///< variable values for the enable expression
};
/**
diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c
index 7589644..b010670 100644
--- a/libavfilter/vf_boxblur.c
+++ b/libavfilter/vf_boxblur.c
@@ -383,4 +383,5 @@ AVFilter avfilter_vf_boxblur = {
.inputs = avfilter_vf_boxblur_inputs,
.outputs = avfilter_vf_boxblur_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c
index d25ce60..8db5fcf 100644
--- a/libavfilter/vf_colormatrix.c
+++ b/libavfilter/vf_colormatrix.c
@@ -385,4 +385,5 @@ AVFilter avfilter_vf_colormatrix = {
.inputs = colormatrix_inputs,
.outputs = colormatrix_outputs,
.priv_class = &colormatrix_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c
index 3d109f8..cb170d0 100644
--- a/libavfilter/vf_cropdetect.c
+++ b/libavfilter/vf_cropdetect.c
@@ -233,4 +233,5 @@ AVFilter avfilter_vf_cropdetect = {
.query_formats = query_formats,
.inputs = avfilter_vf_cropdetect_inputs,
.outputs = avfilter_vf_cropdetect_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 9f5d8bd..626b4ea 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -514,4 +514,5 @@ AVFilter avfilter_vf_curves = {
.inputs = curves_inputs,
.outputs = curves_outputs,
.priv_class = &curves_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c
index edb77cc..c2ffbf3 100644
--- a/libavfilter/vf_drawbox.c
+++ b/libavfilter/vf_drawbox.c
@@ -181,4 +181,5 @@ AVFilter avfilter_vf_drawbox = {
.query_formats = query_formats,
.inputs = avfilter_vf_drawbox_inputs,
.outputs = avfilter_vf_drawbox_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c
index f29c7ee..b4698a8 100644
--- a/libavfilter/vf_edgedetect.c
+++ b/libavfilter/vf_edgedetect.c
@@ -327,4 +327,5 @@ AVFilter avfilter_vf_edgedetect = {
.inputs = edgedetect_inputs,
.outputs = edgedetect_outputs,
.priv_class = &edgedetect_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c
index 9e21560..48ac378 100644
--- a/libavfilter/vf_gradfun.c
+++ b/libavfilter/vf_gradfun.c
@@ -260,4 +260,5 @@ AVFilter avfilter_vf_gradfun = {
.query_formats = query_formats,
.inputs = avfilter_vf_gradfun_inputs,
.outputs = avfilter_vf_gradfun_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_histeq.c b/libavfilter/vf_histeq.c
index 33cddaa..a4166c6 100644
--- a/libavfilter/vf_histeq.c
+++ b/libavfilter/vf_histeq.c
@@ -279,4 +279,5 @@ AVFilter avfilter_vf_histeq = {
.inputs = histeq_inputs,
.outputs = histeq_outputs,
.priv_class = &histeq_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c
index a722d8f..003f175 100644
--- a/libavfilter/vf_hqdn3d.c
+++ b/libavfilter/vf_hqdn3d.c
@@ -355,6 +355,6 @@ AVFilter avfilter_vf_hqdn3d = {
.query_formats = query_formats,
.inputs = avfilter_vf_hqdn3d_inputs,
-
.outputs = avfilter_vf_hqdn3d_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index a1280be..9f63240 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -349,4 +349,5 @@ AVFilter avfilter_vf_hue = {
.inputs = hue_inputs,
.outputs = hue_outputs,
.priv_class = &hue_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 4c0cdfc..4313e77 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -350,6 +350,7 @@ static const AVFilterPad outputs[] = {
\
.inputs = inputs, \
.outputs = outputs, \
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE, \
}
#if CONFIG_LUT_FILTER
diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c
index ae64b76..996311a 100644
--- a/libavfilter/vf_noise.c
+++ b/libavfilter/vf_noise.c
@@ -471,4 +471,5 @@ AVFilter avfilter_vf_noise = {
.inputs = noise_inputs,
.outputs = noise_outputs,
.priv_class = &noise_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_pp.c b/libavfilter/vf_pp.c
index d2c1965..0571cfc 100644
--- a/libavfilter/vf_pp.c
+++ b/libavfilter/vf_pp.c
@@ -180,5 +180,5 @@ AVFilter avfilter_vf_pp = {
.outputs = pp_outputs,
.process_command = pp_process_command,
.priv_class = &pp_class,
-
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_smartblur.c b/libavfilter/vf_smartblur.c
index aed3fa6..4dd1664 100644
--- a/libavfilter/vf_smartblur.c
+++ b/libavfilter/vf_smartblur.c
@@ -301,4 +301,5 @@ AVFilter avfilter_vf_smartblur = {
.inputs = smartblur_inputs,
.outputs = smartblur_outputs,
.priv_class = &smartblur_class,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c
index 038ba4b..2d7aab2 100644
--- a/libavfilter/vf_unsharp.c
+++ b/libavfilter/vf_unsharp.c
@@ -299,6 +299,6 @@ AVFilter avfilter_vf_unsharp = {
.query_formats = query_formats,
.inputs = avfilter_vf_unsharp_inputs,
-
.outputs = avfilter_vf_unsharp_outputs,
+ .flags = AVFILTER_FLAG_SUPPORT_TIMELINE,
};
--
1.8.2.1
-------------- next part --------------
From 60dbcae7054b2334b578c6d78e517ed051358840 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
Date: Sat, 20 Apr 2013 14:11:21 +0200
Subject: [PATCH 3/4] lavfi: add 'enable' command injection to filters
supporting timeline.
---
doc/filters.texi | 3 +++
libavfilter/avfilter.c | 59 +++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 49 insertions(+), 13 deletions(-)
diff --git a/doc/filters.texi b/doc/filters.texi
index b443643..e650f1d 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -287,6 +287,9 @@ sequential number of the input frame, starting from 0
the position in the file of the input frame, NAN if unknown
@end table
+Additionally, these filters support an @option{enable} command that can be used
+to re-define the expression.
+
Like any other filtering option, the @option{enable} option follows the same
rules.
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 0c6f1f1..06d92b2 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -366,6 +366,49 @@ int ff_poll_frame(AVFilterLink *link)
return min;
}
+static const char *const var_names[] = { "t", "n", "pos", NULL };
+enum { VAR_T, VAR_N, VAR_POS, VAR_VARS_NB };
+
+static int set_enable_expr(AVFilterContext *ctx, const char *expr)
+{
+ int ret;
+ char *expr_dup;
+ AVExpr *old = ctx->enable;
+
+ if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) {
+ av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported "
+ "with filter '%s'\n", ctx->filter->name);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ expr_dup = av_strdup(expr);
+ if (!expr_dup)
+ return AVERROR(ENOMEM);
+
+ if (!ctx->var_values) {
+ ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values));
+ if (!ctx->var_values) {
+ av_free(expr_dup);
+ return AVERROR(ENOMEM);
+ }
+ }
+
+ ret = av_expr_parse((AVExpr**)&ctx->enable, expr_dup, var_names,
+ NULL, NULL, NULL, NULL, 0, ctx->priv);
+ if (ret < 0) {
+ av_log(ctx->priv, AV_LOG_ERROR,
+ "Error when evaluating the expression '%s' for enable\n",
+ expr_dup);
+ av_free(expr_dup);
+ return ret;
+ }
+
+ av_expr_free(old);
+ av_free(ctx->enable_str);
+ ctx->enable_str = expr_dup;
+ return 0;
+}
+
void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
{
if (pts == AV_NOPTS_VALUE)
@@ -381,6 +424,8 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha
if(!strcmp(cmd, "ping")){
av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name);
return 0;
+ }else if(!strcmp(cmd, "enable")) {
+ return set_enable_expr(filter, arg);
}else if(filter->filter->process_command) {
return filter->filter->process_command(filter, cmd, arg, res, res_len, flags);
}
@@ -634,9 +679,6 @@ void avfilter_free(AVFilterContext *filter)
av_free(filter);
}
-static const char *const var_names[] = { "t", "n", "pos", NULL };
-enum { VAR_T, VAR_N, VAR_POS, VAR_VARS_NB };
-
static int process_options(AVFilterContext *ctx, AVDictionary **options,
const char *args)
{
@@ -707,16 +749,7 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options,
}
if (ctx->enable_str) {
- if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) {
- av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported "
- "with filter '%s'\n", ctx->filter->name);
- return AVERROR_PATCHWELCOME;
- }
- ctx->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctx->var_values));
- if (!ctx->var_values)
- return AVERROR(ENOMEM);
- ret = av_expr_parse((AVExpr**)&ctx->enable, ctx->enable_str, var_names,
- NULL, NULL, NULL, NULL, 0, ctx->priv);
+ ret = set_enable_expr(ctx, ctx->enable_str);
if (ret < 0)
return ret;
}
--
1.8.2.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130420/df0ebba9/attachment.asc>
More information about the ffmpeg-devel
mailing list