Browse code

Merge commit '34a0ac41a880039c7fb4b3abce10d8e2ce48fac7'

* commit '34a0ac41a880039c7fb4b3abce10d8e2ce48fac7':
vf_aspect: support variables in evaluating the aspect ratios

Conflicts:
Changelog
doc/filters.texi
libavfilter/vf_aspect.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2013/11/03 19:36:16
Showing 3 changed files
... ...
@@ -5,6 +5,7 @@ version <next>
5 5
 
6 6
 - HNM version 4 demuxer and video decoder
7 7
 - Live HDS muxer
8
+- setsar/setdar filters now support variables in ratio expressions
8 9
 
9 10
 
10 11
 version 2.1:
... ...
@@ -6970,6 +6970,31 @@ Default value is @code{100}.
6970 6970
 
6971 6971
 @end table
6972 6972
 
6973
+The parameter @var{sar} is an expression containing
6974
+the following constants:
6975
+
6976
+@table @option
6977
+@item E, PI, PHI
6978
+the corresponding mathematical approximated values for e
6979
+(euler number), pi (greek PI), phi (golden ratio)
6980
+
6981
+@item w, h
6982
+the input width and height
6983
+
6984
+@item a
6985
+same as @var{w} / @var{h}
6986
+
6987
+@item sar
6988
+input sample aspect ratio
6989
+
6990
+@item dar
6991
+input display aspect ratio, it is the same as (@var{w} / @var{h}) * @var{sar}
6992
+
6993
+@item hsub, vsub
6994
+horizontal and vertical chroma subsample values. For example for the
6995
+pixel format "yuv422p" @var{hsub} is 2 and @var{vsub} is 1.
6996
+@end table
6997
+
6973 6998
 @subsection Examples
6974 6999
 
6975 7000
 @itemize
... ...
@@ -30,11 +30,38 @@
30 30
 #include "libavutil/mathematics.h"
31 31
 #include "libavutil/opt.h"
32 32
 #include "libavutil/parseutils.h"
33
+#include "libavutil/pixdesc.h"
33 34
 
34 35
 #include "avfilter.h"
35 36
 #include "internal.h"
36 37
 #include "video.h"
37 38
 
39
+static const char *const var_names[] = {
40
+    "PI",
41
+    "PHI",
42
+    "E",
43
+    "w",
44
+    "h",
45
+    "a", "dar",
46
+    "sar",
47
+    "hsub",
48
+    "vsub",
49
+    NULL
50
+};
51
+
52
+enum var_name {
53
+    VAR_PI,
54
+    VAR_PHI,
55
+    VAR_E,
56
+    VAR_W,
57
+    VAR_H,
58
+    VAR_A, VAR_DAR,
59
+    VAR_SAR,
60
+    VAR_HSUB,
61
+    VAR_VSUB,
62
+    VARS_NB
63
+};
64
+
38 65
 typedef struct {
39 66
     const AVClass *class;
40 67
     AVRational dar;
... ...
@@ -43,7 +70,7 @@ typedef struct {
43 43
 #if FF_API_OLD_FILTER_OPTS
44 44
     float aspect_den;
45 45
 #endif
46
-    char *ratio_str;
46
+    char *ratio_expr;
47 47
 } AspectContext;
48 48
 
49 49
 static av_cold int init(AVFilterContext *ctx)
... ...
@@ -52,28 +79,20 @@ static av_cold int init(AVFilterContext *ctx)
52 52
     int ret;
53 53
 
54 54
 #if FF_API_OLD_FILTER_OPTS
55
-    if (s->ratio_str && s->aspect_den > 0) {
55
+    if (s->ratio_expr && s->aspect_den > 0) {
56 56
         double num;
57 57
         av_log(ctx, AV_LOG_WARNING,
58 58
                "num:den syntax is deprecated, please use num/den or named options instead\n");
59
-        ret = av_expr_parse_and_eval(&num, s->ratio_str, NULL, NULL,
59
+        ret = av_expr_parse_and_eval(&num, s->ratio_expr, NULL, NULL,
60 60
                                      NULL, NULL, NULL, NULL, NULL, 0, ctx);
61 61
         if (ret < 0) {
62
-            av_log(ctx, AV_LOG_ERROR, "Unable to parse ratio numerator \"%s\"\n", s->ratio_str);
62
+            av_log(ctx, AV_LOG_ERROR, "Unable to parse ratio numerator \"%s\"\n", s->ratio_expr);
63 63
             return AVERROR(EINVAL);
64 64
         }
65 65
         s->sar = s->dar = av_d2q(num / s->aspect_den, s->max);
66
-    } else
67
-#endif
68
-    if (s->ratio_str) {
69
-        ret = av_parse_ratio(&s->sar, s->ratio_str, s->max, 0, ctx);
70
-        if (ret < 0 || s->sar.num < 0 || s->sar.den <= 0) {
71
-            av_log(ctx, AV_LOG_ERROR,
72
-                   "Invalid string '%s' for aspect ratio\n", s->ratio_str);
73
-            return AVERROR(EINVAL);
74
-        }
75
-        s->dar = s->sar;
76 66
     }
67
+#endif
68
+
77 69
     return 0;
78 70
 }
79 71
 
... ...
@@ -97,6 +116,48 @@ static inline void compute_dar(AVRational *dar, AVRational sar, int w, int h)
97 97
     }
98 98
 }
99 99
 
100
+static int get_aspect_ratio(AVFilterLink *inlink, AVRational *aspect_ratio)
101
+{
102
+    AVFilterContext *ctx = inlink->dst;
103
+    AspectContext *s = inlink->dst->priv;
104
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
105
+    double var_values[VARS_NB], res;
106
+    int ret;
107
+
108
+    var_values[VAR_PI]    = M_PI;
109
+    var_values[VAR_PHI]   = M_PHI;
110
+    var_values[VAR_E]     = M_E;
111
+    var_values[VAR_W]     = inlink->w;
112
+    var_values[VAR_H]     = inlink->h;
113
+    var_values[VAR_A]     = (double) inlink->w / inlink->h;
114
+    var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ?
115
+        (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
116
+    var_values[VAR_DAR]   = var_values[VAR_A] * var_values[VAR_SAR];
117
+    var_values[VAR_HSUB]  = 1 << desc->log2_chroma_w;
118
+    var_values[VAR_VSUB]  = 1 << desc->log2_chroma_h;
119
+
120
+    /* evaluate new aspect ratio*/
121
+    ret = av_expr_parse_and_eval(&res, s->ratio_expr,
122
+                                      var_names, var_values,
123
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx);
124
+    if (ret < 0) {
125
+        ret = av_parse_ratio(aspect_ratio, s->ratio_expr, s->max, 0, ctx);
126
+    } else
127
+        *aspect_ratio = av_d2q(res, s->max);
128
+
129
+    if (ret < 0) {
130
+        av_log(ctx, AV_LOG_ERROR,
131
+               "Error when evaluating the expression '%s'\n", s->ratio_expr);
132
+        return ret;
133
+    }
134
+    if (aspect_ratio->num < 0 || aspect_ratio->den <= 0) {
135
+        av_log(ctx, AV_LOG_ERROR,
136
+                "Invalid string '%s' for aspect ratio\n", s->ratio_expr);
137
+        return AVERROR(EINVAL);
138
+    }
139
+    return 0;
140
+}
141
+
100 142
 #if CONFIG_SETDAR_FILTER
101 143
 
102 144
 static int setdar_config_props(AVFilterLink *inlink)
... ...
@@ -105,6 +166,16 @@ static int setdar_config_props(AVFilterLink *inlink)
105 105
     AVRational dar;
106 106
     AVRational old_dar;
107 107
     AVRational old_sar = inlink->sample_aspect_ratio;
108
+    int ret;
109
+
110
+#if FF_API_OLD_FILTER_OPTS
111
+    if (!(s->ratio_expr && s->aspect_den > 0)) {
112
+#endif
113
+    if ((ret = get_aspect_ratio(inlink, &s->dar)))
114
+        return ret;
115
+#if FF_API_OLD_FILTER_OPTS
116
+    }
117
+#endif
108 118
 
109 119
     if (s->dar.num && s->dar.den) {
110 120
         av_reduce(&s->sar.num, &s->sar.den,
... ...
@@ -126,9 +197,9 @@ static int setdar_config_props(AVFilterLink *inlink)
126 126
 }
127 127
 
128 128
 static const AVOption setdar_options[] = {
129
-    { "dar",   "set display aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
130
-    { "ratio", "set display aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
131
-    { "r",     "set display aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
129
+    { "dar",   "set display aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
130
+    { "ratio", "set display aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
131
+    { "r",     "set display aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
132 132
 #if FF_API_OLD_FILTER_OPTS
133 133
     { "dar_den", NULL, OFFSET(aspect_den), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS },
134 134
 #endif
... ...
@@ -175,6 +246,16 @@ static int setsar_config_props(AVFilterLink *inlink)
175 175
     AspectContext *s = inlink->dst->priv;
176 176
     AVRational old_sar = inlink->sample_aspect_ratio;
177 177
     AVRational old_dar, dar;
178
+    int ret;
179
+
180
+#if FF_API_OLD_FILTER_OPTS
181
+    if (!(s->ratio_expr && s->aspect_den > 0)) {
182
+#endif
183
+    if ((ret = get_aspect_ratio(inlink, &s->sar)))
184
+        return ret;
185
+#if FF_API_OLD_FILTER_OPTS
186
+    }
187
+#endif
178 188
 
179 189
     inlink->sample_aspect_ratio = s->sar;
180 190
 
... ...
@@ -188,9 +269,9 @@ static int setsar_config_props(AVFilterLink *inlink)
188 188
 }
189 189
 
190 190
 static const AVOption setsar_options[] = {
191
-    { "sar",   "set sample (pixel) aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
192
-    { "ratio", "set sample (pixel) aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
193
-    { "r",     "set sample (pixel) aspect ratio", OFFSET(ratio_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags=FLAGS },
191
+    { "sar",   "set sample (pixel) aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
192
+    { "ratio", "set sample (pixel) aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
193
+    { "r",     "set sample (pixel) aspect ratio", OFFSET(ratio_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
194 194
 #if FF_API_OLD_FILTER_OPTS
195 195
     { "sar_den", NULL, OFFSET(aspect_den), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0, FLT_MAX, FLAGS },
196 196
 #endif