[FFmpeg-devel] [PATCH 4/4] Make the crop filter accept parametric expressions.

Stefano Sabatini stefano.sabatini-lala
Fri Sep 24 15:52:58 CEST 2010


On date Wednesday 2010-09-22 22:59:50 +0200, Michael Niedermayer encoded:
> On Tue, Sep 21, 2010 at 10:36:52AM +0200, Stefano Sabatini wrote:
> > On date Friday 2010-09-17 12:09:04 +0200, Michael Niedermayer encoded:
> > > On Wed, Sep 15, 2010 at 12:28:06AM +0200, Stefano Sabatini wrote:
> > > [...]
> > > > +static inline int normalize_double(int *n, double d)
> > > > +{
> > > > +    int ret = 0;
> > > > +
> > > > +    if (isnan(d)) {
> > > > +        ret = AVERROR(EINVAL);
> > > > +    } else if (d > INT_MAX || d < INT_MIN) {
> > > > +        *n = d > INT_MAX ? INT_MAX : INT_MIN;
> > > > +        ret = AVERROR(EINVAL);
> > > > +    } else
> > > 
> > > > +        *n = d;
> > > 
> > > something that rounds to nearest should be used
> > 
> > round()
> > 
> > > > +
> > > > +    return ret;
> > > > +}
> > > > +
> > > >  static int config_input(AVFilterLink *link)
> > > >  {
> > > >      AVFilterContext *ctx = link->dst;
> > > >      CropContext *crop = ctx->priv;
> > > >      const AVPixFmtDescriptor *pix_desc = &av_pix_fmt_descriptors[link->format];
> > > > +    int ret;
> > > > +    const char *expr;
> > > > +    double res;
> > > > +
> > > > +    crop->var_values[E]     = M_E;
> > > > +    crop->var_values[PHI]   = M_PHI;
> > > > +    crop->var_values[PI]    = M_PI;
> > > > +    crop->var_values[IN_W]  = crop->var_values[IW] = ctx->inputs[0]->w;
> > > > +    crop->var_values[IN_H]  = crop->var_values[IH] = ctx->inputs[0]->h;
> > > > +    crop->var_values[X]     = NAN;
> > > > +    crop->var_values[Y]     = NAN;
> > > > +    crop->var_values[OUT_W] = crop->var_values[OW] = NAN;
> > > > +    crop->var_values[OUT_H] = crop->var_values[OH] = NAN;
> > > > +    crop->var_values[N]     = 0;
> > > 
> > > T/POS are random?
> > 
> > Fixed, set now to NAN.
> > 
> > > >      av_image_fill_max_pixsteps(crop->max_step, NULL, pix_desc);
> > > >      crop->hsub = av_pix_fmt_descriptors[link->format].log2_chroma_w;
> > > >      crop->vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
> > > >  
> > > > -    if (crop->w == 0)
> > > > -        crop->w = link->w - crop->x;
> > > > -    if (crop->h == 0)
> > > > -        crop->h = link->h - crop->y;
> > > > +    if ((ret = av_parse_and_eval_expr(&res, (expr = crop->ow_expr),
> > > > +                                      var_names, crop->var_values,
> > > > +                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
> > > > +    crop->var_values[OUT_W] = crop->var_values[OW] = res;
> > > > +    if ((ret = av_parse_and_eval_expr(&res, (expr = crop->oh_expr),
> > > > +                                      var_names, crop->var_values,
> > > > +                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
> > > > +    crop->var_values[OUT_H] = crop->var_values[OH] = res;
> > > > +    /* evaluate again ow as it may depend on oh */
> > > > +    if ((ret = av_parse_and_eval_expr(&res, (expr = crop->ow_expr),
> > > > +                                      var_names, crop->var_values,
> > > > +                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) goto fail_expr;
> > > > +    crop->var_values[OUT_W] = crop->var_values[OW] = res;
> > > > +    if (normalize_double(&crop->w, crop->var_values[OUT_W]) < 0 ||
> > > > +        normalize_double(&crop->h, crop->var_values[OUT_H]) < 0) {
> > > > +        av_log(ctx, AV_LOG_ERROR,
> > > > +               "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",
> > > > +               crop->ow_expr, crop->oh_expr);
> > > > +        return AVERROR(EINVAL);
> > > > +    }
> > > > +    crop->w &= ~((1 << crop->hsub) - 1);
> > > > +    crop->h &= ~((1 << crop->vsub) - 1);
> > > > +
> > > > +    if ((ret = av_parse_expr(&crop->x_pexpr, crop->x_expr, var_names,
> > > > +                             NULL, NULL, NULL, NULL, 0, ctx)) < 0 ||
> > > > +        (ret = av_parse_expr(&crop->y_pexpr, crop->y_expr, var_names,
> > > > +                             NULL, NULL, NULL, NULL, 0, ctx)) < 0)
> > > > +        return AVERROR(EINVAL);
> > > >  
> > > > +    crop->var_values[X] = av_eval_expr(crop->x_pexpr, crop->var_values, NULL);
> > > > +    crop->var_values[Y] = av_eval_expr(crop->y_pexpr, crop->var_values, NULL);
> > > > +    /* evaluate again x as it may depend on y */
> > > > +    crop->var_values[X] = av_eval_expr(crop->x_pexpr, crop->var_values, NULL);
> > > > +    if (normalize_double(&crop->x, crop->var_values[X]) < 0 ||
> > > > +        normalize_double(&crop->y, crop->var_values[Y]) < 0) {
> > > > +        av_log(ctx, AV_LOG_ERROR,
> > > > +               "Too big value or invalid expression for x or y. "
> > > > +               "Maybe the expression for x:'%s' or for y:'%s' is self-referencing.\n",
> > > > +               crop->x_expr, crop->y_expr);
> > > > +        return AVERROR(EINVAL);
> > > > +    }
> > > 
> > > i dont think that will work they can depend on N/T/POS which should be NAN for W/H
> > 
> > Changed the logic, now x/y is evaluated only in start_frame(), a
> > default value is set in case the first evaluated x/y is not valid.
> > This way the filter won't fail if the initial value of x/y is not
> > invalid (and the last valid value is used).
> > 
> > Regards.
> > -- 
> > FFmpeg = Fascinating and Fostering MultiPurpose Extroverse Gnome
> 
> >  doc/ffmpeg-doc.texi       |    8 +-
> >  doc/filters.texi          |  104 ++++++++++++++++++++++-----
> >  ffmpeg.c                  |    4 -
> >  libavfilter/vf_crop.c     |  176 +++++++++++++++++++++++++++++++++++++++++-----
> >  tests/lavfi-regression.sh |   10 +-
> >  5 files changed, 254 insertions(+), 48 deletions(-)
> > 39c3adc9137408cd71d23329d7c7da16b8abada3  0001-Make-the-crop-filter-accept-parametric-expressions.patch
> > From 9330a5223bfeeadd1ffbb1c8e6d39c6d95906812 Mon Sep 17 00:00:00 2001
> > From: Stefano Sabatini <stefano.sabatini-lala at poste.it>
> > Date: Thu, 9 Sep 2010 01:05:04 +0200
> > Subject: [PATCH] Make the crop filter accept parametric expressions.
> > 
> > Also change the syntax of the crop filter, from:
> > x:y:w:h
> > to
> > w:h:x:y
> > 
> > which looks more useful.
> > ---
> >  doc/ffmpeg-doc.texi       |    8 +-
> >  doc/filters.texi          |  104 ++++++++++++++++++++++-----
> >  ffmpeg.c                  |    4 +-
> >  libavfilter/vf_crop.c     |  176 ++++++++++++++++++++++++++++++++++++++++-----
> >  tests/lavfi-regression.sh |   10 ++--
> >  5 files changed, 254 insertions(+), 48 deletions(-)
> > 
> > diff --git a/doc/ffmpeg-doc.texi b/doc/ffmpeg-doc.texi
> > index d9c5c14..e43e87e 100644
> > --- a/doc/ffmpeg-doc.texi
> > +++ b/doc/ffmpeg-doc.texi
> > @@ -226,13 +226,13 @@ The following abbreviations are recognized:
> >  
> >  @item -aspect @var{aspect}
> >  Set aspect ratio (4:3, 16:9 or 1.3333, 1.7777).
> > - at item -croptop @var{size} (deprecated - use -vf crop=x:y:width:height instead)
> > + at item -croptop @var{size} (deprecated - use the crop filter instead)
> >  Set top crop band size (in pixels).
> > - at item -cropbottom @var{size} (deprecated - use -vf crop=x:y:width:height instead)
> > + at item -cropbottom @var{size} (deprecated - use the crop filter instead)
> >  Set bottom crop band size (in pixels).
> > - at item -cropleft @var{size} (deprecated - use -vf crop=x:y:width:height instead)
> > + at item -cropleft @var{size} (deprecated - use the crop filter instead)
> >  Set left crop band size (in pixels).
> > - at item -cropright @var{size} (deprecated - use -vf crop=x:y:width:height instead)
> > + at item -cropright @var{size} (deprecated - use the crop filter instead)
> >  Set right crop band size (in pixels).
> >  @item -padtop @var{size}
> >  @item -padbottom @var{size}
> > diff --git a/doc/filters.texi b/doc/filters.texi
> > index 262116c..209fa2a 100644
> > --- a/doc/filters.texi
> > +++ b/doc/filters.texi
> > @@ -26,34 +26,102 @@ Below is a description of the currently available video filters.
> >  
> >  @section crop
> >  
> > -Crop the input video to @var{x}:@var{y}:@var{width}:@var{height}.
> > +Crop the input video to @var{out_w}:@var{out_h}:@var{x}:@var{y}.
> >  
> > - at example
> > -./ffmpeg -i in.avi -vf "crop=0:0:0:240" out.avi
> > - at end example
> > +The parameters are expressions containing the following constants:
> >  
> > - at var{x} and @var{y} specify the position of the top-left corner of the
> > -output (non-cropped) area.
> > + at table @option
> > + at item E, PI, PHI
> > +the corresponding mathematical approximated values for e
> > +(euler number), pi (greek PI), PHI (golden ratio)
> >  
> > -The default value of @var{x} and @var{y} is 0.
> > + at item x, y
> > +the computed values for @var{x} and @var{y}. They are evaluated for
> > +each new frame.
> > +
> > + at item in_w, in_h
> > +the input width and heigth
> > +
> > + at item iw, ih
> > +same as @var{in_w} and @var{in_h}
> > +
> > + at item out_w, out_h
> > +the output (cropped) width and heigth
> > +
> > + at item ow, oh
> > +same as @var{out_w} and @var{out_h}
> > +
> > + at item n
> > +the number of input frame, starting from 0
> > +
> > + at item pos
> > +the position in the file of the input frame, NAN if unknown
> > +
> 
> > + at item t
> > +timestamp expressed in seconds, NAN if the input timestamp is invalid
> 
> is unknown
> 
> 
> > +
> > + at end table
> >  
> > -The @var{width} and @var{height} parameters specify the width and height
> > -of the output (non-cropped) area.
> > +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.
> >  
> > -A value of 0 is interpreted as the maximum possible size contained in
> > -the area delimited by the top-left corner at position x:y.
> > +The default value of @var{out_w} is "in_w", and the default value of
> > + at var{out_h} is "in_h".
> >
> 
> > -For example the parameters:
> > +The expression for @var{out_w} may depend on the value of
> > + at var{out_h}, and the expression for @var{out_h} may depend on
> > + at var{out_h}, but they cannot depend on @var{y} and @var{y}, as
> 
> out_h may depend on out_h ?
> 
> 
> > + at var{x} and @var{y} are evaluated are evaluated after @var{out_w} and
> > + at var{out_h}.
> 
> are evaluated are evaluated
> 
> please review your own patch before submitting
> thank you

Sorry for that, it should be fixed now.
-- 
FFmpeg = Fancy Fascinating MultiPurpose Evangelical Gymnast



More information about the ffmpeg-devel mailing list