[FFmpeg-devel] [PATCH] lavfi/scale: accept named option, make parsing more robust

Stefano Sabatini stefasab at gmail.com
Sat Oct 6 12:39:40 CEST 2012


Also update documentation accordingly.

TODO: bump micro
---
 doc/filters.texi       |   61 +++++++++++++++++++++++++++++++-------------
 libavfilter/vf_scale.c |   66 +++++++++++++++++++++++++++++------------------
 2 files changed, 84 insertions(+), 43 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 69a8ee1..d56a51a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -3005,13 +3005,50 @@ pixels will slow things down on a large logo.
 
 @section scale
 
-Scale the input video to @var{width}:@var{height}[:@var{interl}=@{1|-1@}] and/or convert the image format.
+Scale the input video.
 
 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
+ at 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.
+
+ at table @option
+ at item width, w
+Set the video width expression, default value is @code{iw}. See below
+for the list of accepted constants.
+
+ at item height, h
+Set the video heiht expression, default value is @code{ih}.
+See below for the list of accepted constants.
+
+ at item interl
+Set the interlacing. It accepts the following values:
+
+ at table @option
+ at item 1
+force interlaced aware scaling
+
+ at item 0
+do not apply interlaced scaling
+
+ at item -1
+select interlaced aware scaling depending on whether the source frames
+are flagged as interlaced or not
+ at end table
+
+Default value is @code{0}.
+
+ at item flags
+Set libswscale scaling flags.
+ at 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
@@ -3051,26 +3088,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:
-
- at table @option
- at item 1
-force interlaced aware scaling
-
- at item -1
-select interlaced aware scaling depending on whether the source frames
-are flagged as interlaced or not
- at 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
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index 49988bf..b7c5272 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -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,7 +77,8 @@ typedef struct {
      *  -1 = keep original aspect
      */
     int w, h;
-    unsigned int flags;         ///sws flags
+    const char *flags_str;      ///sws flags string
+    int         flags;          ///sws flags
 
     int hsub, vsub;             ///< chroma subsampling
     int slice_y;                ///< top of current output slice
@@ -84,35 +86,47 @@ 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 = "bilinear"}, 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;
-
-    av_strlcpy(scale->w_expr, "iw", sizeof(scale->w_expr));
-    av_strlcpy(scale->h_expr, "ih", sizeof(scale->h_expr));
-
-    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;
+    const char *shorthand[] = { "w", "h" };
+    int ret;
+
+    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);
+
+    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;
@@ -124,6 +138,7 @@ static av_cold void uninit(AVFilterContext *ctx)
     sws_freeContext(scale->sws);
     sws_freeContext(scale->isws[0]);
     sws_freeContext(scale->isws[1]);
+    av_opt_free(scale);
     scale->sws = NULL;
 }
 
@@ -416,4 +431,5 @@ AVFilter avfilter_vf_scale = {
                                           .type             = AVMEDIA_TYPE_VIDEO,
                                           .config_props     = config_props, },
                                         { .name = NULL}},
+    .priv_class = &scale_class,
 };
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list