X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_scale.c;h=2fe9a1fb522ca6253b9cafcd81e8ac9722e8b6a3;hb=562f386c77151d5d59151071106170589bce8e63;hp=22bee96d75bc2261d7c4e743192d7b3d118bb1c1;hpb=a956164e1eb3418922cae949f02ad4035f013213;p=ffmpeg diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 22bee96d75b..2fe9a1fb522 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -29,9 +29,9 @@ #include "avfilter.h" #include "formats.h" #include "internal.h" +#include "scale.h" #include "video.h" #include "libavutil/avstring.h" -#include "libavutil/eval.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" @@ -41,43 +41,12 @@ #include "libavutil/avassert.h" #include "libswscale/swscale.h" -static const char *const var_names[] = { - "in_w", "iw", - "in_h", "ih", - "out_w", "ow", - "out_h", "oh", - "a", - "sar", - "dar", - "hsub", - "vsub", - "ohsub", - "ovsub", - NULL -}; - -enum var_name { - VAR_IN_W, VAR_IW, - VAR_IN_H, VAR_IH, - VAR_OUT_W, VAR_OW, - VAR_OUT_H, VAR_OH, - VAR_A, - VAR_SAR, - VAR_DAR, - VAR_HSUB, - VAR_VSUB, - VAR_OHSUB, - VAR_OVSUB, - VARS_NB -}; - enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, EVAL_MODE_NB }; - typedef struct ScaleContext { const AVClass *class; struct SwsContext *sws; ///< software scaler context @@ -256,74 +225,16 @@ static int config_props(AVFilterLink *outlink) outlink->src->inputs[1] : outlink->src->inputs[0]; enum AVPixelFormat outfmt = outlink->format; - ScaleContext *scale = ctx->priv; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format); - int64_t w, h; - double var_values[VARS_NB], res; - char *expr; + ScaleContext *scale = ctx->priv; + int w, h; int ret; - int factor_w, factor_h; - - var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; - var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; - var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; - var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; - var_values[VAR_A] = (double) inlink->w / inlink->h; - var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? - (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; - var_values[VAR_DAR] = var_values[VAR_A] * var_values[VAR_SAR]; - var_values[VAR_HSUB] = 1 << desc->log2_chroma_w; - var_values[VAR_VSUB] = 1 << desc->log2_chroma_h; - var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w; - var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h; - - /* evaluate width and height */ - av_expr_parse_and_eval(&res, (expr = scale->w_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx); - scale->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res; - if ((ret = av_expr_parse_and_eval(&res, (expr = scale->h_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) - goto fail; - scale->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res; - /* evaluate again the width, as it may depend on the output height */ - if ((ret = av_expr_parse_and_eval(&res, (expr = scale->w_expr), - var_names, var_values, - NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) - goto fail; - scale->w = res; - - w = scale->w; - h = scale->h; - - /* Check if it is requested that the result has to be divisible by a some - * factor (w or h = -n with n being the factor). */ - factor_w = 1; - factor_h = 1; - if (w < -1) { - factor_w = -w; - } - if (h < -1) { - factor_h = -h; - } - - if (w < 0 && h < 0) - scale->w = scale->h = 0; - if (!(w = scale->w)) - w = inlink->w; - if (!(h = scale->h)) - h = inlink->h; - - /* Make sure that the result is divisible by the factor we determined - * earlier. If no factor was set, it is nothing will happen as the default - * factor is 1 */ - if (w < 0) - w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w; - if (h < 0) - h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h; + if ((ret = ff_scale_eval_dimensions(ctx, + scale->w_expr, scale->h_expr, + inlink, outlink, + &w, &h)) < 0) + goto fail; /* Note that force_original_aspect_ratio may overwrite the previous set * dimensions so that it is not divisible by the set factors anymore. */ @@ -374,6 +285,7 @@ static int config_props(AVFilterLink *outlink) int i; for (i = 0; i < 3; i++) { + int in_v_chr_pos = scale->in_v_chr_pos, out_v_chr_pos = scale->out_v_chr_pos; struct SwsContext **s = swscs[i]; *s = sws_alloc_context(); if (!*s) @@ -406,17 +318,17 @@ static int config_props(AVFilterLink *outlink) * MPEG-2 chroma positions are used by convention * XXX: support other 4:2:0 pixel formats */ if (inlink0->format == AV_PIX_FMT_YUV420P && scale->in_v_chr_pos == -513) { - scale->in_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; + in_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; } if (outlink->format == AV_PIX_FMT_YUV420P && scale->out_v_chr_pos == -513) { - scale->out_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; + out_v_chr_pos = (i == 0) ? 128 : (i == 1) ? 64 : 192; } av_opt_set_int(*s, "src_h_chr_pos", scale->in_h_chr_pos, 0); - av_opt_set_int(*s, "src_v_chr_pos", scale->in_v_chr_pos, 0); + av_opt_set_int(*s, "src_v_chr_pos", in_v_chr_pos, 0); av_opt_set_int(*s, "dst_h_chr_pos", scale->out_h_chr_pos, 0); - av_opt_set_int(*s, "dst_v_chr_pos", scale->out_v_chr_pos, 0); + av_opt_set_int(*s, "dst_v_chr_pos", out_v_chr_pos, 0); if ((ret = sws_init_context(*s, NULL, NULL)) < 0) return ret; @@ -439,10 +351,6 @@ static int config_props(AVFilterLink *outlink) return 0; fail: - av_log(NULL, AV_LOG_ERROR, - "Error when evaluating the expression '%s'.\n" - "Maybe the expression for out_w:'%s' or for out_h:'%s' is self-referencing.\n", - expr, scale->w_expr, scale->h_expr); return ret; }