| @@ -24,10 +24,40 @@ · 23 unmodified lines |
| 24 | */ | 24 | */ |
| 25 | | 25 | |
| 26 | #include "avfilter.h" | 26 | #include "avfilter.h" |
| | 27 | #include "libavutil/avstring.h" |
| | 28 | #include "libavutil/eval.h" |
| 27 | #include "libavutil/pixdesc.h" | 29 | #include "libavutil/pixdesc.h" |
| 28 | #include "libavutil/avassert.h" | 30 | #include "libavutil/avassert.h" |
| 29 | #include "libswscale/swscale.h" | 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 | typedef struct { | 61 | typedef struct { |
| 32 | struct SwsContext *sws; ///< software scaler context | 62 | struct SwsContext *sws; ///< software scaler context |
| 33 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material | 63 | struct SwsContext *isws[2]; ///< software scaler context for interlaced material |
| @@ -44,6 +74,9 @@ typedef struct { · 10 unmodified lines |
| 44 | int slice_y; ///< top of current output slice | 74 | int slice_y; ///< top of current output slice |
| 45 | int input_is_pal; ///< set to 1 if the input format is paletted | 75 | int input_is_pal; ///< set to 1 if the input format is paletted |
| 46 | int interlaced; | 76 | int interlaced; |
| | 77 | |
| | 78 | char w_expr[256]; ///< width expression string |
| | 79 | char h_expr[256]; ///< height expression string |
| 47 | } ScaleContext; | 80 | } ScaleContext; |
| 48 | | 81 | |
| 49 | static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) | 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 | ScaleContext *scale = ctx->priv; | 84 | ScaleContext *scale = ctx->priv; |
| 52 | const char *p; | 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 | scale->flags = SWS_BILINEAR; | 90 | scale->flags = SWS_BILINEAR; |
| 55 | if (args) { | 91 | if (args) { |
| 56 | sscanf(args, "%d:%d", &scale->w, &scale->h); | 92 | sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr); |
| 57 | p = strstr(args,"flags="); | 93 | p = strstr(args,"flags="); |
| 58 | if (p) scale->flags = strtoul(p+6, NULL, 0); | 94 | if (p) scale->flags = strtoul(p+6, NULL, 0); |
| 59 | if(strstr(args,"interl=1")){ | 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 | scale->interlaced=-1; | 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 | return 0; | 101 | return 0; |
| 74 | } | 102 | } |
| 75 | | 103 | |
| @@ -118,6 +146,48 @@ static int config_props(AVFilterLink *outlink) · 42 unmodified lines |
| 118 | AVFilterLink *inlink = outlink->src->inputs[0]; | 146 | AVFilterLink *inlink = outlink->src->inputs[0]; |
| 119 | ScaleContext *scale = ctx->priv; | 147 | ScaleContext *scale = ctx->priv; |
| 120 | int64_t w, h; | 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 | if (!(w = scale->w)) | 192 | if (!(w = scale->w)) |
| 123 | w = inlink->w; | 193 | w = inlink->w; |
| @@ -159,6 +229,11 @@ static int config_props(AVFilterLink *outlink) · 35 unmodified lines |
| 159 | return AVERROR(EINVAL); | 229 | return AVERROR(EINVAL); |
| 160 | | 230 | |
| 161 | return 0; | 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 | static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 239 | static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref) |