From 4d7d74802d0c857d365f95d7cd712581cce93323 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 21 Aug 2016 00:01:57 +0200 Subject: [PATCH] avfilter/vf_crop: make possible to do exact cropping for subsampled videos --- doc/filters.texi | 5 +++++ libavfilter/vf_crop.c | 21 +++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index e9b8c93529..591a55db03 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -5633,6 +5633,11 @@ This expression is evaluated per-frame. 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. + +@item exact +Enable exact cropping. If enabled, subsampled videos will be cropped at exact +width/height/x/y as specified and will not be rounded to nearest smaller value. +It defaults to 0. @end table The @var{out_w}, @var{out_h}, @var{x}, @var{y} parameters are diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index 01773fa3cf..bcdbb8cd58 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -82,6 +82,7 @@ typedef struct CropContext { AVRational out_sar; ///< output sample aspect ratio int keep_aspect; ///< keep display aspect ratio when cropping + int exact; ///< exact cropping, for subsampled formats int max_step[4]; ///< max pixel step for each plane, expressed as a number of bytes int hsub, vsub; ///< chroma subsampling @@ -184,8 +185,11 @@ static int config_input(AVFilterLink *link) s->w_expr, s->h_expr); return AVERROR(EINVAL); } - s->w &= ~((1 << s->hsub) - 1); - s->h &= ~((1 << s->vsub) - 1); + + if (!s->exact) { + s->w &= ~((1 << s->hsub) - 1); + s->h &= ~((1 << s->vsub) - 1); + } av_expr_free(s->x_pexpr); av_expr_free(s->y_pexpr); @@ -219,8 +223,10 @@ static int config_input(AVFilterLink *link) /* set default, required in the case the first computed value for x/y is NAN */ s->x = (link->w - s->w) / 2; s->y = (link->h - s->h) / 2; - s->x &= ~((1 << s->hsub) - 1); - s->y &= ~((1 << s->vsub) - 1); + if (!s->exact) { + s->x &= ~((1 << s->hsub) - 1); + s->y &= ~((1 << s->vsub) - 1); + } return 0; fail_expr: @@ -269,8 +275,10 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame) s->x = link->w - s->w; if ((unsigned)s->y + (unsigned)s->h > link->h) s->y = link->h - s->h; - s->x &= ~((1 << s->hsub) - 1); - s->y &= ~((1 << s->vsub) - 1); + if (!s->exact) { + s->x &= ~((1 << s->hsub) - 1); + s->y &= ~((1 << s->vsub) - 1); + } av_log(ctx, AV_LOG_TRACE, "n:%d t:%f pos:%f x:%d y:%d x+w:%d y+h:%d\n", (int)s->var_values[VAR_N], s->var_values[VAR_T], s->var_values[VAR_POS], @@ -344,6 +352,7 @@ 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 }, { "keep_aspect", "keep aspect ratio", OFFSET(keep_aspect), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "exact", "do exact cropping", OFFSET(exact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL } };