| @@ -24,10 +24,40 @@ · 23 unmodified lines |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | 26 | #include "avfilter.h" |
| 27 | +#include "libavutil/avstring.h" |
| 28 | +#include "libavutil/eval.h" |
| 27 | 29 | #include "libavutil/pixdesc.h" |
| 28 | 30 | #include "libavutil/avassert.h" |
| 29 | 31 | #include "libswscale/swscale.h" |
| 30 | 32 | |
| 33 | +static const char *var_names[] = { |
| 34 | + "PI", |
| 35 | + "PHI", |
| 36 | + "E", |
| 37 | + "in_w", "iw", |
| 38 | + "in_h", "ih", |
| 39 | + "out_w", "ow", |
| 40 | + "out_h", "oh", |
| 41 | + "a", |
| 42 | + "hsub", |
| 43 | + "vsub", |
| 44 | + NULL |
| 45 | +}; |
| 46 | + |
| 47 | +enum var_name { |
| 48 | + VAR_PI, |
| 49 | + VAR_PHI, |
| 50 | + VAR_E, |
| 51 | + VAR_IN_W, VAR_IW, |
| 52 | + VAR_IN_H, VAR_IH, |
| 53 | + VAR_OUT_W, VAR_OW, |
| 54 | + VAR_OUT_H, VAR_OH, |
| 55 | + VAR_A, |
| 56 | + VAR_HSUB, |
| 57 | + VAR_VSUB, |
| 58 | + VARS_NB |
| 59 | +}; |
| 60 | + |
| 31 | 61 | typedef struct { |
| 32 | 62 | struct SwsContext *sws; ///< software scaler context |
| 33 | 63 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material |
| @@ -44,6 +74,9 @@ typedef struct { · 10 unmodified lines |
| 44 | 74 | int slice_y; ///< top of current output slice |
| 45 | 75 | int input_is_pal; ///< set to 1 if the input format is paletted |
| 46 | 76 | int interlaced; |
| 77 | + |
| 78 | + char w_expr[256]; ///< width expression string |
| 79 | + char h_expr[256]; ///< height expression string |
| 47 | 80 | } ScaleContext; |
| 48 | 81 | |
| 49 | 82 | static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
| @@ -51,9 +84,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) · 1 unmodified line |
| 51 | 84 | ScaleContext *scale = ctx->priv; |
| 52 | 85 | const char *p; |
| 53 | 86 | |
| 87 | + av_strlcpy(scale->w_expr, "iw", sizeof(scale->w_expr)); |
| 88 | + av_strlcpy(scale->h_expr, "ih", sizeof(scale->h_expr)); |
| 89 | + |
| 54 | 90 | scale->flags = SWS_BILINEAR; |
| 55 | 91 | if (args) { |
| 56 | | − sscanf(args, "%d:%d", &scale->w, &scale->h); |
| 92 | + sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr); |
| 57 | 93 | p = strstr(args,"flags="); |
| 58 | 94 | if (p) scale->flags = strtoul(p+6, NULL, 0); |
| 59 | 95 | if(strstr(args,"interl=1")){ |
| @@ -62,14 +98,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) · 2 unmodified lines |
| 62 | 98 | scale->interlaced=-1; |
| 63 | 99 | } |
| 64 | 100 | |
| 65 | | − /* sanity check params */ |
| 66 | | − if (scale->w < -1 || scale->h < -1) { |
| 67 | | − av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); |
| 68 | | − return AVERROR(EINVAL); |
| 69 | | − } |
| 70 | | − if (scale->w == -1 && scale->h == -1) |
| 71 | | − scale->w = scale->h = 0; |
| 72 | | − |
| 73 | 101 | return 0; |
| 74 | 102 | } |
| 75 | 103 | |
| @@ -118,6 +146,48 @@ static int config_props(AVFilterLink *outlink) · 42 unmodified lines |
| 118 | 146 | AVFilterLink *inlink = outlink->src->inputs[0]; |
| 119 | 147 | ScaleContext *scale = ctx->priv; |
| 120 | 148 | int64_t w, h; |
| 149 | + double var_values[VARS_NB], res; |
| 150 | + char *expr; |
| 151 | + int ret; |
| 152 | + |
| 153 | + var_values[VAR_PI] = M_PI; |
| 154 | + var_values[VAR_PHI] = M_PHI; |
| 155 | + var_values[VAR_E] = M_E; |
| 156 | + var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w; |
| 157 | + var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h; |
| 158 | + var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN; |
| 159 | + var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN; |
| 160 | + var_values[VAR_A] = (float) inlink->w / inlink->h; |
| 161 | + var_values[VAR_HSUB] = 2<<av_pix_fmt_descriptors[inlink->format].log2_chroma_w; |
| 162 | + var_values[VAR_VSUB] = 2<<av_pix_fmt_descriptors[inlink->format].log2_chroma_h; |
| 163 | + |
| 164 | + /* evaluate width and height */ |
| 165 | + av_expr_parse_and_eval(&res, (expr = scale->w_expr), |
| 166 | + var_names, var_values, |
| 167 | + NULL, NULL, NULL, NULL, NULL, 0, ctx); |
| 168 | + scale->w = var_values[VAR_OW] = res; |
| 169 | + if ((ret = av_expr_parse_and_eval(&res, (expr = scale->h_expr), |
| 170 | + var_names, var_values, |
| 171 | + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) |
| 172 | + goto fail; |
| 173 | + scale->h = var_values[VAR_OH] = res; |
| 174 | + /* evaluate again the width, as it may depend on the output height */ |
| 175 | + if ((ret = av_expr_parse_and_eval(&res, (expr = scale->w_expr), |
| 176 | + var_names, var_values, |
| 177 | + NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0) |
| 178 | + goto fail; |
| 179 | + scale->w = res; |
| 180 | + |
| 181 | + w = scale->w; |
| 182 | + h = scale->h; |
| 183 | + |
| 184 | + /* sanity check params */ |
| 185 | + if (w < -1 || h < -1) { |
| 186 | + av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n"); |
| 187 | + return AVERROR(EINVAL); |
| 188 | + } |
| 189 | + if (w == -1 && h == -1) |
| 190 | + scale->w = scale->h = 0; |
| 121 | 191 | |
| 122 | 192 | if (!(w = scale->w)) |
| 123 | 193 | w = inlink->w; |
| @@ -159,6 +229,11 @@ static int config_props(AVFilterLink *outlink) · 35 unmodified lines |
| 159 | 229 | return AVERROR(EINVAL); |
| 160 | 230 | |
| 161 | 231 | return 0; |
| 232 | + |
| 233 | +fail: |
| 234 | + av_log(NULL, AV_LOG_ERROR, |
| 235 | + "Error when evaluating the expression '%s'\n", expr); |
| 236 | + return ret; |
| 162 | 237 | } |
| 163 | 238 | |
| 164 | 239 | static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) |