Commit 84f571e3 authored by Mark Visser's avatar Mark Visser

enabled expressions on x, y, w, h and t parameters for drawgrid and drawbox, added examples

parent 7fff3df6
......@@ -2886,11 +2886,11 @@ This filter accepts the following options:
@table @option
@item x
@item y
Specify the top left corner coordinates of the box. Default to 0.
The expressions which specify the top left corner coordinates of the box. Default to 0.
@item width, w
@item height, h
Specify the width and height of the box, if 0 they are interpreted as
The expressions which specify the width and height of the box, if 0 they are interpreted as
the input width and height. Default to 0.
@item color, c
......@@ -2900,7 +2900,44 @@ value @code{invert} is used, the box edge color is the same as the
video with inverted luma.
@item thickness, t
Set the thickness of the box edge. Default value is @code{3}.
The expression which sets the thickness of the box edge. Default value is @code{3}.
See below for the list of accepted constants.
@end table
The parameters for @var{x}, @var{y}, @var{w} and @var{h} and @var{t} are expressions containing the
following constants:
@table @option
@item dar
The input display aspect ratio, it is the same as (@var{w} / @var{h}) * @var{sar}.
@item hsub
@item vsub
horizontal and vertical chroma subsample values. For example for the
pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1.
@item in_h, ih
@item in_w, iw
The input width and height.
@item sar
The input sample aspect ratio.
@item x
@item y
The x and y offset coordinates where the box is drawn.
@item w
@item h
The width and height of the drawn box.
@item t
The thickness of the drawn box.
These constants allow the @var{x}, @var{y}, @var{w}, @var{h} and @var{t} expressions to refer to
each other, so you may for example specify @code(y=x/dar} or @code(h=w/dar).
@end table
@subsection Examples
......@@ -2928,6 +2965,12 @@ Fill the box with pink color:
@example
drawbox=x=10:y=10:w=100:h=100:color=pink@@0.5:t=max
@end example
@item
Draw a 2-pixel red 2.40:1 mask:
@example
drawbox=x=-t:y=0.5*(ih-iw/2.4)-t:w=iw+t*2:h=iw/2.4+t*2:t=2:c=red
@end example
@end itemize
@section drawgrid
......@@ -2939,11 +2982,11 @@ This filter accepts the following options:
@table @option
@item x
@item y
Specify the coordinates of some point of grid intersection (meant to configure offset). Both default to 0.
The expressions which specify the coordinates of some point of grid intersection (meant to configure offset). Both default to 0.
@item width, w
@item height, h
Specify the width and height of the grid cell, if 0 they are interpreted as the
The expressions which specify the width and height of the grid cell, if 0 they are interpreted as the
input width and height, respectively, minus @code{thickness}, so image gets
framed. Default to 0.
......@@ -2956,7 +2999,44 @@ Note that you can append opacity value (in range of 0.0 - 1.0)
to color name after @@ sign.
@item thickness, t
Set the thickness of the grid line. Default value is @code{1}.
The expression which sets the thickness of the grid line. Default value is @code{1}.
See below for the list of accepted constants.
@end table
The parameters for @var{x}, @var{y}, @var{w} and @var{h} and @var{t} are expressions containing the
following constants:
@table @option
@item dar
The input display aspect ratio, it is the same as (@var{w} / @var{h}) * @var{sar}.
@item hsub
@item vsub
horizontal and vertical chroma subsample values. For example for the
pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1.
@item in_h, ih
@item in_w, iw
The input grid cell width and height.
@item sar
The input sample aspect ratio.
@item x
@item y
The x and y coordinates of some point of grid intersection (meant to configure offset).
@item w
@item h
The width and height of the drawn cell.
@item t
The thickness of the drawn cell.
These constants allow the @var{x}, @var{y}, @var{w}, @var{h} and @var{t} expressions to refer to
each other, so you may for example specify @code(y=x/dar} or @code(h=w/dar).
@end table
@subsection Examples
......@@ -2967,6 +3047,12 @@ Draw a grid with cell 100x100 pixels, thickness 2 pixels, with color red and an
@example
drawgrid=width=100:height=100:thickness=2:color=red@@0.5
@end example
@item
Draw a white 3x3 grid with an opacity of 50%:
@example
drawgrid=w=iw/3:h=ih/3:t=2:c=white@@0.5
@end example
@end itemize
@anchor{drawtext}
......
......@@ -28,6 +28,7 @@
#include "libavutil/colorspace.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
#include "libavutil/eval.h"
#include "libavutil/pixdesc.h"
#include "libavutil/parseutils.h"
#include "avfilter.h"
......@@ -35,18 +36,51 @@
#include "internal.h"
#include "video.h"
static const char *const var_names[] = {
"dar",
"hsub", "vsub",
"in_h", "ih", ///< height of the input video
"in_w", "iw", ///< width of the input video
"sar",
"x",
"y",
"h", ///< height of the rendered box
"w", ///< width of the rendered box
"t",
NULL
};
enum { Y, U, V, A };
enum var_name {
VAR_DAR,
VAR_HSUB, VAR_VSUB,
VAR_IN_H, VAR_IH,
VAR_IN_W, VAR_IW,
VAR_SAR,
VAR_X,
VAR_Y,
VAR_H,
VAR_W,
VAR_T,
VARS_NB
};
typedef struct {
const AVClass *class;
int x, y, w_opt, h_opt, w, h;
int x, y, w, h;
int thickness;
char *color_str;
unsigned char yuv_color[4];
int invert_color; ///< invert luma color
int vsub, hsub; ///< chroma subsampling
char *x_expr, *y_expr; ///< expression for x and y
char *w_expr, *h_expr; ///< expression for width and height
char *t_expr; ///< expression for thickness
} DrawBoxContext;
static const int NUM_EXPR_EVALS = 5;
static av_cold int init(AVFilterContext *ctx)
{
DrawBoxContext *s = ctx->priv;
......@@ -83,20 +117,82 @@ static int query_formats(AVFilterContext *ctx)
static int config_input(AVFilterLink *inlink)
{
DrawBoxContext *s = inlink->dst->priv;
AVFilterContext *ctx = inlink->dst;
DrawBoxContext *s = ctx->priv;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
double var_values[VARS_NB], res;
char *expr;
int ret;
s->hsub = desc->log2_chroma_w;
s->vsub = desc->log2_chroma_h;
s->w = (s->w_opt > 0) ? s->w_opt : inlink->w;
s->h = (s->h_opt > 0) ? s->h_opt : inlink->h;
var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? av_q2d(inlink->sample_aspect_ratio) : 1;
var_values[VAR_DAR] = (double)inlink->w / inlink->h * var_values[VAR_SAR];
var_values[VAR_HSUB] = s->hsub;
var_values[VAR_VSUB] = s->vsub;
var_values[VAR_X] = NAN;
var_values[VAR_Y] = NAN;
var_values[VAR_H] = NAN;
var_values[VAR_W] = NAN;
var_values[VAR_T] = NAN;
for (int i = 0; i <= NUM_EXPR_EVALS; i++) {
/* evaluate expressions, fail on last iteration */
if ((ret = av_expr_parse_and_eval(&res, (expr = s->x_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS)
goto fail;
s->x = var_values[VAR_X] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->y_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS)
goto fail;
s->y = var_values[VAR_Y] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS)
goto fail;
s->w = var_values[VAR_W] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS)
goto fail;
s->h = var_values[VAR_H] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = s->t_expr),
var_names, var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0 && i == NUM_EXPR_EVALS)
goto fail;
s->thickness = var_values[VAR_T] = res;
}
/* if w or h are zero, use the input w/h */
s->w = (s->w > 0) ? s->w : inlink->w;
s->h = (s->h > 0) ? s->h : inlink->h;
/* sanity check width and height */
if (s->w < 0 || s->h < 0) {
av_log(ctx, AV_LOG_ERROR, "Size values less than 0 are not acceptable.\n");
return AVERROR(EINVAL);
}
av_log(inlink->dst, AV_LOG_VERBOSE, "x:%d y:%d w:%d h:%d color:0x%02X%02X%02X%02X\n",
av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d w:%d h:%d color:0x%02X%02X%02X%02X\n",
s->x, s->y, s->w, s->h,
s->yuv_color[Y], s->yuv_color[U], s->yuv_color[V], s->yuv_color[A]);
return 0;
fail:
av_log(NULL, AV_LOG_ERROR,
"Error when evaluating the expression '%s'.\n",
expr);
return ret;
}
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
......@@ -140,16 +236,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
#if CONFIG_DRAWBOX_FILTER
static const AVOption drawbox_options[] = {
{ "x", "set horizontal position of the left box edge", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "y", "set vertical position of the top box edge", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "width", "set width of the box", OFFSET(w_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "w", "set width of the box", OFFSET(w_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "height", "set height of the box", OFFSET(h_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "h", "set height of the box", OFFSET(h_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "x", "set horizontal position of the left box edge", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "y", "set vertical position of the top box edge", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "width", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "w", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "height", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "h", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "color", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "thickness", "set the box thickness", OFFSET(thickness), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, INT_MAX, FLAGS },
{ "t", "set the box thickness", OFFSET(thickness), AV_OPT_TYPE_INT, { .i64 = 3 }, 0, INT_MAX, FLAGS },
{ "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ NULL }
};
......@@ -248,16 +344,16 @@ static int drawgrid_filter_frame(AVFilterLink *inlink, AVFrame *frame)
}
static const AVOption drawgrid_options[] = {
{ "x", "set horizontal offset", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "y", "set vertical offset", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS },
{ "width", "set width of grid cell", OFFSET(w_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "w", "set width of grid cell", OFFSET(w_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "height", "set height of grid cell", OFFSET(h_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "h", "set height of grid cell", OFFSET(h_opt), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
{ "x", "set horizontal offset", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "y", "set vertical offset", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "width", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "w", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "height", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "h", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "color", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
{ "thickness", "set grid line thickness", OFFSET(thickness), AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
{ "t", "set grid line thickness", OFFSET(thickness), AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
{ "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ NULL }
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment