diff options
author | Thilo Borgmann <thilo.borgmann@mail.de> | 2016-04-10 18:18:17 +0200 |
---|---|---|
committer | Thilo Borgmann <thilo.borgmann@mail.de> | 2016-04-17 21:12:34 +0200 |
commit | 37a4d3383fb9deb8b94053195727ed0fe6406409 (patch) | |
tree | 3ff79b27ce769fdd02c5225f1779ebfff3bdb194 /libavfilter/vf_perspective.c | |
parent | d97a61a8f132e749f5b808300e126f9c0c3acfa1 (diff) | |
download | ffmpeg-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.
Diffstat (limited to 'libavfilter/vf_perspective.c')
-rw-r--r-- | libavfilter/vf_perspective.c | 82 |
1 files changed, 59 insertions, 23 deletions
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; |