]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_scale.c
vf_yadif: switch to filter_frame, this filter did not support slices
[ffmpeg] / libavfilter / vf_scale.c
index c42f9f20aaaad0568944ff78daa7db2f6eeecfc9..081da851c83ee6255908f232970e5cb2931597c6 100644 (file)
@@ -35,6 +35,7 @@
 #include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
+#include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/avassert.h"
@@ -67,6 +68,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 +78,8 @@ typedef struct {
      *  -1 = keep original aspect
      */
     int w, h;
+    char *flags_str;            ///sws flags string
+    char *size_str;
     unsigned int flags;         ///sws flags
 
     int hsub, vsub;             ///< chroma subsampling
@@ -84,35 +88,82 @@ 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 = NULL}, 0, 0, FLAGS },
+    { "width",  "set width expression",    OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
+    { "h",      "set height expression",   OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
+    { "height", "set height expression",   OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = NULL}, 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 },
+    { "size",   "set video size",          OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, FLAGS },
+    { "s",      "set video size",          OFFSET(size_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 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;
+    const char *args0 = args;
 
-    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);
 
-    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 (args && (scale->size_str = av_get_token(&args, ":"))) {
+        if (av_parse_video_size(&scale->w, &scale->h, scale->size_str) < 0) {
+            av_freep(&scale->size_str);
+            args = args0;
+        } else if (*args)
+            args++;
+    }
+
+    if ((ret = av_opt_set_from_string(scale, args, shorthand, "=", ":")) < 0)
+        return ret;
+
+    if (scale->size_str && (scale->w_expr || scale->h_expr)) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Size and width/height expressions cannot be set at the same time.\n");
+            return AVERROR(EINVAL);
+    }
+
+    if (scale->size_str) {
+        char buf[32];
+        if ((ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str)) < 0) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Invalid size '%s'\n", scale->size_str);
+            return ret;
         }
-        if(strstr(args,"interl=1")){
-            scale->interlaced=1;
-        }else if(strstr(args,"interl=-1"))
-            scale->interlaced=-1;
+        snprintf(buf, sizeof(buf)-1, "%d", scale->w);
+        av_opt_set(scale, "w", buf, 0);
+        snprintf(buf, sizeof(buf)-1, "%d", scale->h);
+        av_opt_set(scale, "h", buf, 0);
+    }
+    if (!scale->w_expr)
+        av_opt_set(scale, "w", "iw", 0);
+    if (!scale->h_expr)
+        av_opt_set(scale, "h", "ih", 0);
+
+    av_log(ctx, AV_LOG_VERBOSE, "w:%s h:%s flags:'%s' interl:%d\n",
+           scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced);
+
+    scale->flags = SWS_BILINEAR;
+    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 +176,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,24 +335,26 @@ 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;
         link->dst->inputs[0]->h      = picref->video->h;
 
         if ((ret = config_props(outlink)) < 0)
-            av_assert0(0); //what to do here ?
+            return ret;
     }
 
-
     if (!scale->sws) {
         outpicref = avfilter_ref_buffer(picref, ~0);
         if (!outpicref)
@@ -430,4 +484,5 @@ AVFilter avfilter_vf_scale = {
 
     .inputs    = avfilter_vf_scale_inputs,
     .outputs   = avfilter_vf_scale_outputs,
+    .priv_class = &scale_class,
 };