[FFmpeg-devel] [PATCH 4/4] Make the crop filter accept parametric expressions.
Stefano Sabatini
stefano.sabatini-lala
Tue Sep 21 10:36:52 CEST 2010
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
More information about the ffmpeg-devel
mailing list