Commit 1e5492ff authored by Stefano Sabatini's avatar Stefano Sabatini

lavfi/crop: add support to option parsing

Also fix documentation accordingly.
parent 2b643855
...@@ -1518,11 +1518,40 @@ testing purposes. ...@@ -1518,11 +1518,40 @@ testing purposes.
@section crop @section crop
Crop the input video to @var{out_w}:@var{out_h}:@var{x}:@var{y}:@var{keep_aspect} Crop the input video.
The @var{keep_aspect} parameter is optional, if specified and set to a This filter accepts a list of @var{key}=@var{value} pairs as argument,
non-zero value will force the output display aspect ratio to be the separated by ':'. If the key of the first options is omitted, the
same of the input, by changing the output sample aspect ratio. arguments are interpreted according to the syntax
@var{out_w}:@var{out_h}:@var{x}:@var{y}:@var{keep_aspect}.
A description of the accepted options follows:
@table @option
@item w, out_w
Set the crop area width. It defaults to @code{iw}.
This expression is evaluated only once during the filter
configuration.
@item h, out_h
Set the crop area width. It defaults to @code{ih}.
This expression is evaluated only once during the filter
configuration.
@item x
Set the expression for the x top-left coordinate of the cropped area.
It defaults to @code{(in_w-out_w)/2}.
This expression is evaluated per-frame.
@item y
Set the expression for the y top-left coordinate of the cropped area.
It defaults to @code{(in_h-out_h)/2}.
This expression is evaluated per-frame.
@item keep_aspect
If set to 1 will force the output display aspect ratio
to be the same of the input, by changing the output sample aspect
ratio. It defaults to 0.
@end table
The @var{out_w}, @var{out_h}, @var{x}, @var{y} parameters are The @var{out_w}, @var{out_h}, @var{x}, @var{y} parameters are
expressions containing the following constants: expressions containing the following constants:
...@@ -1568,13 +1597,6 @@ timestamp expressed in seconds, NAN if the input timestamp is unknown ...@@ -1568,13 +1597,6 @@ timestamp expressed in seconds, NAN if the input timestamp is unknown
@end table @end table
The @var{out_w} and @var{out_h} parameters specify the expressions for
the width and height of the output (cropped) video. They are
evaluated just at the configuration of the filter.
The default value of @var{out_w} is "in_w", and the default value of
@var{out_h} is "in_h".
The expression for @var{out_w} may depend on the value of @var{out_h}, The expression for @var{out_w} may depend on the value of @var{out_h},
and the expression for @var{out_h} may depend on @var{out_w}, but they and the expression for @var{out_h} may depend on @var{out_w}, but they
cannot depend on @var{x} and @var{y}, as @var{x} and @var{y} are cannot depend on @var{x} and @var{y}, as @var{x} and @var{y} are
...@@ -1585,10 +1607,6 @@ position of the top-left corner of the output (non-cropped) area. They ...@@ -1585,10 +1607,6 @@ position of the top-left corner of the output (non-cropped) area. They
are evaluated for each frame. If the evaluated value is not valid, it are evaluated for each frame. If the evaluated value is not valid, it
is approximated to the nearest valid value. is approximated to the nearest valid value.
The default value of @var{x} is "(in_w-out_w)/2", and the default
value for @var{y} is "(in_h-out_h)/2", which set the cropped area at
the center of the input image.
The expression for @var{x} may depend on @var{y}, and the expression The expression for @var{x} may depend on @var{y}, and the expression
for @var{y} may depend on @var{x}. for @var{y} may depend on @var{x}.
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 27 #define LIBAVFILTER_VERSION_MINOR 27
#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_MICRO 102
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \ LIBAVFILTER_VERSION_MINOR, \
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "libavutil/libm.h" #include "libavutil/libm.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/opt.h"
static const char *const var_names[] = { static const char *const var_names[] = {
"in_w", "iw", ///< width of the input video "in_w", "iw", ///< width of the input video
...@@ -75,6 +76,7 @@ enum var_name { ...@@ -75,6 +76,7 @@ enum var_name {
}; };
typedef struct { typedef struct {
const AVClass *class;
int x; ///< x offset of the non-cropped area with respect to the input area int x; ///< x offset of the non-cropped area with respect to the input area
int y; ///< y offset of the non-cropped area with respect to the input area int y; ///< y offset of the non-cropped area with respect to the input area
int w; ///< width of the cropped area int w; ///< width of the cropped area
...@@ -85,11 +87,44 @@ typedef struct { ...@@ -85,11 +87,44 @@ typedef struct {
int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes
int hsub, vsub; ///< chroma subsampling int hsub, vsub; ///< chroma subsampling
char x_expr[256], y_expr[256], ow_expr[256], oh_expr[256]; char *x_expr, *y_expr, *w_expr, *h_expr;
AVExpr *x_pexpr, *y_pexpr; /* parsed expressions for x and y */ AVExpr *x_pexpr, *y_pexpr; /* parsed expressions for x and y */
double var_values[VAR_VARS_NB]; double var_values[VAR_VARS_NB];
} CropContext; } CropContext;
#define OFFSET(x) offsetof(CropContext, x)
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
static const AVOption crop_options[] = {
{ "x", "set the x crop area expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "y", "set the y crop area expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "out_w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "w", "set the width crop area expression", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "out_h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "h", "set the height crop area expression", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
{ "keep_aspect", "force packed RGB in input and output", OFFSET(keep_aspect), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS },
{NULL}
};
AVFILTER_DEFINE_CLASS(crop);
static av_cold int init(AVFilterContext *ctx, const char *args)
{
CropContext *crop = ctx->priv;
static const char *shorthand[] = { "w", "h", "x", "y", "keep_aspect", NULL };
crop->class = &crop_class;
av_opt_set_defaults(crop);
return av_opt_set_from_string(crop, args, shorthand, "=", ":");
}
static av_cold void uninit(AVFilterContext *ctx)
{
CropContext *crop = ctx->priv;
av_opt_free(crop);
}
static int query_formats(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx)
{ {
static const enum AVPixelFormat pix_fmts[] = { static const enum AVPixelFormat pix_fmts[] = {
...@@ -123,29 +158,6 @@ static int query_formats(AVFilterContext *ctx) ...@@ -123,29 +158,6 @@ static int query_formats(AVFilterContext *ctx)
return 0; return 0;
} }
static av_cold int init(AVFilterContext *ctx, const char *args)
{
CropContext *crop = ctx->priv;
av_strlcpy(crop->ow_expr, "iw", sizeof(crop->ow_expr));
av_strlcpy(crop->oh_expr, "ih", sizeof(crop->oh_expr));
av_strlcpy(crop->x_expr, "(in_w-out_w)/2", sizeof(crop->x_expr));
av_strlcpy(crop->y_expr, "(in_h-out_h)/2", sizeof(crop->y_expr));
if (args)
sscanf(args, "%255[^:]:%255[^:]:%255[^:]:%255[^:]:%d", crop->ow_expr, crop->oh_expr, crop->x_expr, crop->y_expr, &crop->keep_aspect);
return 0;
}
static av_cold void uninit(AVFilterContext *ctx)
{
CropContext *crop = ctx->priv;
av_expr_free(crop->x_pexpr); crop->x_pexpr = NULL;
av_expr_free(crop->y_pexpr); crop->y_pexpr = NULL;
}
static inline int normalize_double(int *n, double d) static inline int normalize_double(int *n, double d)
{ {
int ret = 0; int ret = 0;
...@@ -189,16 +201,16 @@ static int config_input(AVFilterLink *link) ...@@ -189,16 +201,16 @@ static int config_input(AVFilterLink *link)
crop->hsub = pix_desc->log2_chroma_w; crop->hsub = pix_desc->log2_chroma_w;
crop->vsub = pix_desc->log2_chroma_h; crop->vsub = pix_desc->log2_chroma_h;
if ((ret = av_expr_parse_and_eval(&res, (expr = crop->ow_expr), if ((ret = av_expr_parse_and_eval(&res, (expr = crop->w_expr),
var_names, crop->var_values, var_names, crop->var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr; NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
crop->var_values[VAR_OUT_W] = crop->var_values[VAR_OW] = res; crop->var_values[VAR_OUT_W] = crop->var_values[VAR_OW] = res;
if ((ret = av_expr_parse_and_eval(&res, (expr = crop->oh_expr), if ((ret = av_expr_parse_and_eval(&res, (expr = crop->h_expr),
var_names, crop->var_values, var_names, crop->var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr; NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
crop->var_values[VAR_OUT_H] = crop->var_values[VAR_OH] = res; crop->var_values[VAR_OUT_H] = crop->var_values[VAR_OH] = res;
/* evaluate again ow as it may depend on oh */ /* evaluate again ow as it may depend on oh */
if ((ret = av_expr_parse_and_eval(&res, (expr = crop->ow_expr), if ((ret = av_expr_parse_and_eval(&res, (expr = crop->w_expr),
var_names, crop->var_values, var_names, crop->var_values,
NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr; NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
crop->var_values[VAR_OUT_W] = crop->var_values[VAR_OW] = res; crop->var_values[VAR_OUT_W] = crop->var_values[VAR_OW] = res;
...@@ -207,7 +219,7 @@ static int config_input(AVFilterLink *link) ...@@ -207,7 +219,7 @@ static int config_input(AVFilterLink *link)
av_log(ctx, AV_LOG_ERROR, av_log(ctx, AV_LOG_ERROR,
"Too big value or invalid expression for out_w/ow or out_h/oh. " "Too big value or invalid expression for out_w/ow or out_h/oh. "
"Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n", "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n",
crop->ow_expr, crop->oh_expr); crop->w_expr, crop->h_expr);
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
crop->w &= ~((1 << crop->hsub) - 1); crop->w &= ~((1 << crop->hsub) - 1);
...@@ -348,4 +360,5 @@ AVFilter avfilter_vf_crop = { ...@@ -348,4 +360,5 @@ AVFilter avfilter_vf_crop = {
.inputs = avfilter_vf_crop_inputs, .inputs = avfilter_vf_crop_inputs,
.outputs = avfilter_vf_crop_outputs, .outputs = avfilter_vf_crop_outputs,
.priv_class = &crop_class,
}; };
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