lavfi/scale: accept named options, make parsing more robust
authorStefano Sabatini <stefasab@gmail.com>
Sat, 6 Oct 2012 10:30:26 +0000 (12:30 +0200)
committerStefano Sabatini <stefasab@gmail.com>
Mon, 29 Oct 2012 16:39:26 +0000 (17:39 +0100)
Also update documentation accordingly.

doc/filters.texi
libavfilter/version.h
libavfilter/vf_scale.c
tests/lavfi-regression.sh

index 19b8bf2..94ce594 100644 (file)
@@ -3009,13 +3009,51 @@ pixels will slow things down on a large logo.
 
 @section scale
 
-Scale (resize) the input video to @var{width}:@var{height}[:@var{interl}=@{1|-1@}] and/or convert the image format.
+Scale (resize) the input video, using the libswscale library.
 
 The scale filter forces the output display aspect ratio to be the same
 of the input, by changing the output sample aspect ratio.
 
-The parameters @var{width} and @var{height} are expressions containing
-the following constants:
+This filter accepts a list of named options in the form of
+@var{key}=@var{value} pairs separated by ":". If the key for the first
+two options is not specified, the assumed keys for the first two
+values are @code{w} and @code{h}.
+
+A description of the accepted options follows.
+
+@table @option
+@item width, w
+Set the video width expression, default value is @code{iw}. See below
+for the list of accepted constants.
+
+@item height, h
+Set the video heiht expression, default value is @code{ih}.
+See below for the list of accepted constants.
+
+@item interl
+Set the interlacing. It accepts the following values:
+
+@table @option
+@item 1
+force interlaced aware scaling
+
+@item 0
+do not apply interlaced scaling
+
+@item -1
+select interlaced aware scaling depending on whether the source frames
+are flagged as interlaced or not
+@end table
+
+Default value is @code{0}.
+
+@item flags
+Set libswscale scaling flags. If not explictly specified the filter
+applies a bilinear scaling algorithm.
+@end table
+
+The values of the @var{w} and @var{h} options are expressions
+containing the following constants:
 
 @table @option
 @item in_w, in_h
@@ -3055,26 +3093,14 @@ If the value for @var{width} or @var{height} is -1, the scale filter will
 use, for the respective output size, a value that maintains the aspect
 ratio of the input image.
 
-The default value of @var{width} and @var{height} is 0.
-
-Valid values for the optional parameter @var{interl} are:
-
-@table @option
-@item 1
-force interlaced aware scaling
-
-@item -1
-select interlaced aware scaling depending on whether the source frames
-are flagged as interlaced or not
-@end table
-
-Unless @var{interl} is set to one of the above options, interlaced scaling will not be used.
-
 Some examples follow:
 @example
 # scale the input video to a size of 200x100.
 scale=200:100
 
+# the above example is the same as:
+scale=w=200:h=100
+
 # scale the input to 2x
 scale=2*iw:2*ih
 # the above is the same as
index 7b55903..3ce13c1 100644 (file)
@@ -30,7 +30,7 @@
 
 #define LIBAVFILTER_VERSION_MAJOR  3
 #define LIBAVFILTER_VERSION_MINOR  20
-#define LIBAVFILTER_VERSION_MICRO 106
+#define LIBAVFILTER_VERSION_MICRO 107
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                LIBAVFILTER_VERSION_MINOR, \
index c42f9f2..1a4784d 100644 (file)
@@ -67,6 +67,7 @@ enum var_name {
 };
 
 typedef struct {
+    const AVClass *class;
     struct SwsContext *sws;     ///< software scaler context
     struct SwsContext *isws[2]; ///< software scaler context for interlaced material
 
@@ -76,6 +77,7 @@ typedef struct {
      *  -1 = keep original aspect
      */
     int w, h;
+    char *flags_str;            ///sws flags string
     unsigned int flags;         ///sws flags
 
     int hsub, vsub;             ///< chroma subsampling
@@ -84,35 +86,48 @@ typedef struct {
     int output_is_pal;          ///< set to 1 if the output format is paletted
     int interlaced;
 
-    char w_expr[256];           ///< width  expression string
-    char h_expr[256];           ///< height expression string
+    char *w_expr;               ///< width  expression string
+    char *h_expr;               ///< height expression string
 } ScaleContext;
 
+#define OFFSET(x) offsetof(ScaleContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption scale_options[] = {
+    { "w",      "set width expression",    OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS },
+    { "width",  "set width expression",    OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, 0, 0, FLAGS },
+    { "h",      "set height expression",   OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS },
+    { "height", "set height expression",   OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, 0, 0, FLAGS },
+    { "flags",  "set libswscale flags",    OFFSET(flags_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, INT_MAX, FLAGS },
+    { "interl", "set interlacing", OFFSET(interlaced), AV_OPT_TYPE_INT, {.i64 = 0 }, -1, 1, FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(scale);
+
 static av_cold int init(AVFilterContext *ctx, const char *args)
 {
     ScaleContext *scale = ctx->priv;
-    const char *p;
+    static const char *shorthand[] = { "w", "h", NULL };
+    int ret;
 
-    av_strlcpy(scale->w_expr, "iw", sizeof(scale->w_expr));
-    av_strlcpy(scale->h_expr, "ih", sizeof(scale->h_expr));
+    scale->class = &scale_class;
+    av_opt_set_defaults(scale);
+
+    if ((ret = av_opt_set_from_string(scale, args, shorthand, "=", ":")) < 0)
+        return ret;
+
+    av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:%s interl:%d\n",
+           scale->w_expr, scale->h_expr, scale->flags_str, scale->interlaced);
 
     scale->flags = SWS_BILINEAR;
-    if (args) {
-        sscanf(args, "%255[^:]:%255[^:]", scale->w_expr, scale->h_expr);
-        p = strstr(args,"flags=");
-        if (p) {
-            const AVClass *class = sws_get_class();
-            const AVOption    *o = av_opt_find(&class, "sws_flags", NULL, 0,
-                                               AV_OPT_SEARCH_FAKE_OBJ);
-            int ret = av_opt_eval_flags(&class, o, p + 6, &scale->flags);
-
-            if (ret < 0)
-                return ret;
-        }
-        if(strstr(args,"interl=1")){
-            scale->interlaced=1;
-        }else if(strstr(args,"interl=-1"))
-            scale->interlaced=-1;
+    if (scale->flags_str) {
+        const AVClass *class = sws_get_class();
+        const AVOption    *o = av_opt_find(&class, "sws_flags", NULL, 0,
+                                           AV_OPT_SEARCH_FAKE_OBJ);
+        int ret = av_opt_eval_flags(&class, o, scale->flags_str, &scale->flags);
+        if (ret < 0)
+            return ret;
     }
 
     return 0;
@@ -125,6 +140,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     sws_freeContext(scale->isws[0]);
     sws_freeContext(scale->isws[1]);
     scale->sws = NULL;
+    av_opt_free(scale);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -283,14 +299,17 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
     AVFilterLink *outlink = link->dst->outputs[0];
     AVFilterBufferRef *outpicref, *for_next_filter;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
+    char buf[32];
     int ret = 0;
 
     if(   picref->video->w != link->w
        || picref->video->h != link->h
        || picref->format   != link->format) {
         int ret;
-        snprintf(scale->w_expr, sizeof(scale->w_expr)-1, "%d", outlink->w);
-        snprintf(scale->h_expr, sizeof(scale->h_expr)-1, "%d", outlink->h);
+        snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
+        av_opt_set(scale, "w", buf, 0);
+        snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
+        av_opt_set(scale, "h", buf, 0);
 
         link->dst->inputs[0]->format = picref->format;
         link->dst->inputs[0]->w      = picref->video->w;
index 5027f9d..703d56c 100755 (executable)
@@ -132,7 +132,7 @@ do_lavfi_lavd() {
 
 do_lavfi_lavd "life"                 "life=s=40x40:r=5:seed=42:mold=64" -t 2
 do_lavfi_lavd "testsrc"              "testsrc=r=7:n=2:d=10"
-do_lavfi_lavd "scalenorm"            "sws_flags=+accurate_rnd+bitexact;testsrc=s=128x96:d=1:r=5,format=yuv420p[a];testsrc=s=160x120:d=1:r=5[b];[a][b]concat=unsafe=1,scale=::flags=+accurate_rnd+bitexact"
+do_lavfi_lavd "scalenorm"            "sws_flags=+accurate_rnd+bitexact;testsrc=s=128x96:d=1:r=5,format=yuv420p[a];testsrc=s=160x120:d=1:r=5[b];[a][b]concat=unsafe=1,scale=flags=+accurate_rnd+bitexact"
 
 # TODO: add tests for
 # direct rendering,