Browse code

scale: make the filter parametric

Make the filter accept parametric expressions for the output video
size.

Signed-off-by: Stefano Sabatini <stefano.sabatini-lala@poste.it>

Stefano Sabatini authored on 2011/03/28 05:58:08
Showing 3 changed files
... ...
@@ -1004,13 +1004,33 @@ can be used to test the monowhite pixel format descriptor definition.
1004 1004
 
1005 1005
 Scale the input video to @var{width}:@var{height} and/or convert the image format.
1006 1006
 
1007
-For example the command:
1007
+The parameters @var{width} and @var{height} are expressions containing
1008
+the following constants:
1008 1009
 
1009
-@example
1010
-./ffmpeg -i in.avi -vf "scale=200:100" out.avi
1011
-@end example
1010
+@table @option
1011
+@item E, PI, PHI
1012
+the corresponding mathematical approximated values for e
1013
+(euler number), pi (greek PI), phi (golden ratio)
1014
+
1015
+@item in_w, in_h
1016
+the input width and heigth
1017
+
1018
+@item iw, ih
1019
+same as @var{in_w} and @var{in_h}
1012 1020
 
1013
-will scale the input video to a size of 200x100.
1021
+@item out_w, out_h
1022
+the output (cropped) width and heigth
1023
+
1024
+@item ow, oh
1025
+same as @var{out_w} and @var{out_h}
1026
+
1027
+@item a
1028
+input display aspect ratio, same as @var{iw} / @var{ih}
1029
+
1030
+@item hsub, vsub
1031
+horizontal and vertical chroma subsample values. For example for the
1032
+pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1.
1033
+@end table
1014 1034
 
1015 1035
 If the input image format is different from the format requested by
1016 1036
 the next filter, the scale filter will convert the input to the
... ...
@@ -1025,6 +1045,36 @@ ratio of the input image.
1025 1025
 
1026 1026
 The default value of @var{width} and @var{height} is 0.
1027 1027
 
1028
+Some examples follow:
1029
+@example
1030
+# scale the input video to a size of 200x100.
1031
+scale=200:100
1032
+
1033
+# scale the input to 2x
1034
+scale=2*iw:2*ih
1035
+# the above is the same as
1036
+scale=2*in_w:2*in_h
1037
+
1038
+# scale the input to half size
1039
+scale=iw/2:ih/2
1040
+
1041
+# increase the width, and set the height to the same size
1042
+scale=3/2*iw:ow
1043
+
1044
+# seek for Greek harmony
1045
+scale=iw:1/PHI*iw
1046
+scale=ih*PHI:ih
1047
+
1048
+# increase the height, and set the width to 3/2 of the height
1049
+scale=3/2*oh:3/5*ih
1050
+
1051
+# increase the size, but make the size a multiple of the chroma
1052
+scale="trunc(3/2*iw/hsub)*hsub:trunc(3/2*ih/vsub)*vsub"
1053
+
1054
+# increase the width to a maximum of 500 pixels, keep the same input aspect ratio
1055
+scale='min(500\, iw*3/2):-1'
1056
+@end example
1057
+
1028 1058
 @anchor{setdar}
1029 1059
 @section setdar
1030 1060
 
... ...
@@ -27,7 +27,7 @@
27 27
 
28 28
 #define LIBAVFILTER_VERSION_MAJOR  1
29 29
 #define LIBAVFILTER_VERSION_MINOR 77
30
-#define LIBAVFILTER_VERSION_MICRO  0
30
+#define LIBAVFILTER_VERSION_MICRO  1
31 31
 
32 32
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
33 33
                                                LIBAVFILTER_VERSION_MINOR, \
... ...
@@ -24,10 +24,40 @@
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 {
44 44
     int slice_y;                ///< top of current output slice
45 45
     int input_is_pal;           ///< set to 1 if the input format is paletted
46 46
     int interlaced;
47
+
48
+    char w_expr[256];             ///< width  expression string
49
+    char h_expr[256];             ///< height expression string
47 50
 } ScaleContext;
48 51
 
49 52
 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)
51 51
     ScaleContext *scale = ctx->priv;
52 52
     const char *p;
53 53
 
54
+    av_strlcpy(scale->w_expr, "iw", sizeof(scale->w_expr));
55
+    av_strlcpy(scale->h_expr, "ih", sizeof(scale->h_expr));
56
+
54 57
     scale->flags = SWS_BILINEAR;
55 58
     if (args) {
56
-        sscanf(args, "%d:%d", &scale->w, &scale->h);
59
+        sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr);
57 60
         p = strstr(args,"flags=");
58 61
         if (p) scale->flags = strtoul(p+6, NULL, 0);
59 62
         if(strstr(args,"interl=1")){
... ...
@@ -62,14 +98,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
62 62
             scale->interlaced=-1;
63 63
     }
64 64
 
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 65
     return 0;
74 66
 }
75 67
 
... ...
@@ -118,6 +146,48 @@ static int config_props(AVFilterLink *outlink)
118 118
     AVFilterLink *inlink = outlink->src->inputs[0];
119 119
     ScaleContext *scale = ctx->priv;
120 120
     int64_t w, h;
121
+    double var_values[VARS_NB], res;
122
+    char *expr;
123
+    int ret;
124
+
125
+    var_values[VAR_PI]    = M_PI;
126
+    var_values[VAR_PHI]   = M_PHI;
127
+    var_values[VAR_E]     = M_E;
128
+    var_values[VAR_IN_W]  = var_values[VAR_IW] = inlink->w;
129
+    var_values[VAR_IN_H]  = var_values[VAR_IH] = inlink->h;
130
+    var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
131
+    var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
132
+    var_values[VAR_A]     = (float) inlink->w / inlink->h;
133
+    var_values[VAR_HSUB]  = 2<<av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
134
+    var_values[VAR_VSUB]  = 2<<av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
135
+
136
+    /* evaluate width and height */
137
+    av_expr_parse_and_eval(&res, (expr = scale->w_expr),
138
+                           var_names, var_values,
139
+                           NULL, NULL, NULL, NULL, NULL, 0, ctx);
140
+    scale->w = var_values[VAR_OW] = res;
141
+    if ((ret = av_expr_parse_and_eval(&res, (expr = scale->h_expr),
142
+                                      var_names, var_values,
143
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
144
+        goto fail;
145
+    scale->h = var_values[VAR_OH] = res;
146
+    /* evaluate again the width, as it may depend on the output height */
147
+    if ((ret = av_expr_parse_and_eval(&res, (expr = scale->w_expr),
148
+                                      var_names, var_values,
149
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
150
+        goto fail;
151
+    scale->w = res;
152
+
153
+    w = scale->w;
154
+    h = scale->h;
155
+
156
+    /* sanity check params */
157
+    if (w <  -1 || h <  -1) {
158
+        av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n");
159
+        return AVERROR(EINVAL);
160
+    }
161
+    if (w == -1 && h == -1)
162
+        scale->w = scale->h = 0;
121 163
 
122 164
     if (!(w = scale->w))
123 165
         w = inlink->w;
... ...
@@ -159,6 +229,11 @@ static int config_props(AVFilterLink *outlink)
159 159
         return AVERROR(EINVAL);
160 160
 
161 161
     return 0;
162
+
163
+fail:
164
+    av_log(NULL, AV_LOG_ERROR,
165
+           "Error when evaluating the expression '%s'\n", expr);
166
+    return ret;
162 167
 }
163 168
 
164 169
 static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)