aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThilo Borgmann <thilo.borgmann@mail.de>2016-04-10 18:18:17 +0200
committerThilo Borgmann <thilo.borgmann@mail.de>2016-04-17 21:12:34 +0200
commit37a4d3383fb9deb8b94053195727ed0fe6406409 (patch)
tree3ff79b27ce769fdd02c5225f1779ebfff3bdb194
parentd97a61a8f132e749f5b808300e126f9c0c3acfa1 (diff)
downloadffmpeg-37a4d3383fb9deb8b94053195727ed0fe6406409.tar.gz
lavfi/perspective: Add basic timeline editing.
Add number of input and output frames to possible variables. Add option eval to reevaluate coordinate expressions during initialization or for every frame.
-rw-r--r--doc/filters.texi19
-rw-r--r--libavfilter/vf_perspective.c82
2 files changed, 78 insertions, 23 deletions
diff --git a/doc/filters.texi b/doc/filters.texi
index b17b115288..7634b25532 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -10128,6 +10128,10 @@ The expressions can use the following variables:
@item W
@item H
the width and height of video frame.
+@item in
+Input frame count.
+@item on
+Output frame count.
@end table
@item interpolation
@@ -10158,6 +10162,21 @@ by the given coordinates.
Default value is @samp{source}.
@end table
+
+@item eval
+Set when the expressions for coordinates @option{x0,y0,...x3,y3} are evaluated.
+
+It accepts the following values:
+@table @samp
+@item init
+only evaluate expressions once during the filter initialization or
+when a command is processed
+
+@item frame
+evaluate expressions for each incoming frame
+@end table
+
+Default value is @samp{init}.
@end table
@section phase
diff --git a/libavfilter/vf_perspective.c b/libavfilter/vf_perspective.c
index 4949ee82c3..2b5afcea35 100644
--- a/libavfilter/vf_perspective.c
+++ b/libavfilter/vf_perspective.c
@@ -48,6 +48,7 @@ typedef struct PerspectiveContext {
int hsub, vsub;
int nb_planes;
int sense;
+ int eval_mode;
int (*perspective)(AVFilterContext *ctx,
void *arg, int job, int nb_jobs);
@@ -61,6 +62,12 @@ enum PERSPECTIVESense {
PERSPECTIVE_SENSE_DESTINATION = 1, ///< coordinates give locations in destination of corners of source.
};
+enum EvalMode {
+ EVAL_MODE_INIT,
+ EVAL_MODE_FRAME,
+ EVAL_MODE_NB
+};
+
static const AVOption perspective_options[] = {
{ "x0", "set top left x coordinate", OFFSET(expr_str[0][0]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS },
{ "y0", "set top left y coordinate", OFFSET(expr_str[0][1]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS },
@@ -78,6 +85,9 @@ static const AVOption perspective_options[] = {
0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_SOURCE}, 0, 0, FLAGS, "sense"},
{ "destination", "specify locations in destination to send corners of source",
0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_DESTINATION}, 0, 0, FLAGS, "sense"},
+ { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
+ { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags = FLAGS, .unit = "eval" },
+ { "frame", "eval expressions per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
{ NULL }
};
@@ -115,20 +125,22 @@ static inline double get_coeff(double d)
return coeff;
}
-static const char *const var_names[] = { "W", "H", NULL };
-enum { VAR_W, VAR_H, VAR_VARS_NB };
+static const char *const var_names[] = { "W", "H", "in", "on", NULL };
+enum { VAR_W, VAR_H, VAR_IN, VAR_ON, VAR_VARS_NB };
-static int config_input(AVFilterLink *inlink)
+static int calc_persp_luts(AVFilterContext *ctx, AVFilterLink *inlink)
{
+ PerspectiveContext *s = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ double (*ref)[2] = s->ref;
+
+ double values[VAR_VARS_NB] = { [VAR_W] = inlink->w, [VAR_H] = inlink->h,
+ [VAR_IN] = inlink->frame_count + 1,
+ [VAR_ON] = outlink->frame_count + 1 };
+ const int h = values[VAR_H];
+ const int w = values[VAR_W];
double x0, x1, x2, x3, x4, x5, x6, x7, x8, q;
double t0, t1, t2, t3;
- AVFilterContext *ctx = inlink->dst;
- PerspectiveContext *s = ctx->priv;
- double (*ref)[2] = s->ref;
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
- double values[VAR_VARS_NB] = { [VAR_W] = inlink->w, [VAR_H] = inlink->h };
- int h = inlink->h;
- int w = inlink->w;
int x, y, i, j, ret;
for (i = 0; i < 4; i++) {
@@ -144,19 +156,6 @@ static int config_input(AVFilterLink *inlink)
}
}
- s->hsub = desc->log2_chroma_w;
- s->vsub = desc->log2_chroma_h;
- s->nb_planes = av_pix_fmt_count_planes(inlink->format);
- if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
- return ret;
-
- s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
- s->height[0] = s->height[3] = inlink->h;
-
- s->pv = av_realloc_f(s->pv, w * h, 2 * sizeof(*s->pv));
- if (!s->pv)
- return AVERROR(ENOMEM);
-
switch (s->sense) {
case PERSPECTIVE_SENSE_SOURCE:
x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) *
@@ -223,6 +222,36 @@ static int config_input(AVFilterLink *inlink)
}
}
+ return 0;
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+ AVFilterContext *ctx = inlink->dst;
+ PerspectiveContext *s = ctx->priv;
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+ int h = inlink->h;
+ int w = inlink->w;
+ int i, j, ret;
+ s->hsub = desc->log2_chroma_w;
+ s->vsub = desc->log2_chroma_h;
+ s->nb_planes = av_pix_fmt_count_planes(inlink->format);
+ if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
+ return ret;
+
+ s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
+ s->height[0] = s->height[3] = inlink->h;
+
+ s->pv = av_realloc_f(s->pv, w * h, 2 * sizeof(*s->pv));
+ if (!s->pv)
+ return AVERROR(ENOMEM);
+
+ if (s->eval_mode == EVAL_MODE_INIT) {
+ if ((ret = calc_persp_luts(ctx, inlink)) < 0) {
+ return ret;
+ }
+ }
+
for (i = 0; i < SUB_PIXELS; i++){
double d = i / (double)SUB_PIXELS;
double temp[4];
@@ -423,6 +452,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
PerspectiveContext *s = ctx->priv;
AVFrame *out;
int plane;
+ int ret;
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
if (!out) {
@@ -431,6 +461,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
}
av_frame_copy_props(out, frame);
+ if (s->eval_mode == EVAL_MODE_FRAME) {
+ if ((ret = calc_persp_luts(ctx, inlink)) < 0) {
+ return ret;
+ }
+ }
+
for (plane = 0; plane < s->nb_planes; plane++) {
int hsub = plane == 1 || plane == 2 ? s->hsub : 0;
int vsub = plane == 1 || plane == 2 ? s->vsub : 0;