Make the filter accept parametric expressions for the output video
size.
Signed-off-by: Stefano Sabatini <stefano.sabatini-lala@poste.it>
| ... | ... |
@@ -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) |