[FFmpeg-devel] [PATCH 2/2] vf_hue: add named options syntax for the filter parameters

Jérémy Tran tran.jeremy.av at gmail.com
Sun Aug 12 13:26:18 CEST 2012


The old syntax has been kept.
It is now also possible to express the hue in radian.

Signed-off-by: Jérémy Tran <tran.jeremy.av at gmail.com>
---
 doc/filters.texi     |  2 ++
 libavfilter/vf_hue.c | 80 +++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 63 insertions(+), 19 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 71f6670..97bd9d2 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -2198,6 +2198,8 @@ ffmpeg -i in.avi -vf hue=100:1
 
 # same command but using named options
 ffmpeg -i in.avi -vf hue=h=100:s=1
+# it is possible to express the hue in radian
+ffmpeg -i in.avi -vf hue=hrad=PI/2:s=1
 @end example
 
 @table @option
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index 8523e66..f62c300 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -25,7 +25,10 @@
  * Ported from MPlayer libmpcodecs/vf_hue.c
  */
 
+#include <float.h>
+#include "libavutil/eval.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
@@ -34,42 +37,69 @@
 #include "video.h"
 
 typedef struct {
-    float    hue;
-    float    saturation;
-    int      hsub;
-    int      vsub;
-    uint32_t hue_sin;
-    uint32_t hue_cos;
+    const AVClass *class;
+    float         h;
+    char*         hrad; /* expr in radian */
+    float         s;
+    int32_t       hsub;
+    int32_t       vsub;
+    int32_t       hue_sin;
+    int32_t       hue_cos;
 } HueContext;
 
+#define OFFSET(x) offsetof(HueContext, x)
+static const AVOption hue_options[] = {
+    { "h", NULL, OFFSET(h), AV_OPT_TYPE_FLOAT, { 0 }, -FLT_MAX, FLT_MAX, AV_OPT_FLAG_VIDEO_PARAM },
+    { "hrad", NULL, OFFSET(hrad), AV_OPT_TYPE_STRING, { 0 }, .flags = AV_OPT_FLAG_VIDEO_PARAM },
+    { "s", NULL, OFFSET(s), AV_OPT_TYPE_FLOAT, { 1 }, 0, 2, AV_OPT_FLAG_VIDEO_PARAM },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(hue);
+
 static av_cold int init(AVFilterContext *ctx, const char *args)
 {
     HueContext *hue = ctx->priv;
+    char *equal;
+    char c1, c2;
     float h = 0, s = 1;
     int32_t ret;
-    char c1 = 0, c2 = 0;
 
-    if (args) {
+    hue->class = &hue_class;
+
+    // named options syntax
+    if (equal = strchr(args, '=')) {
+        av_opt_set_defaults(hue);
+        ret = av_set_options_string(hue, args, "=", ":");
+        if (ret < 0) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Error parsing the options string: %s\n", args);
+            av_opt_free(hue);
+            return ret;
+        }
+    // compatibility syntax
+    } else {
         ret = sscanf(args, "%f%c%f%c", &h, &c1, &s, &c2);
         if (!ret || c1 != ':' || c2) {
             av_log(ctx, AV_LOG_ERROR,
                    "Error parsing the options string: %s\n", args);
             return AVERROR(EINVAL);
         }
+
+        hue->h = h;
+        hue->s = s;
     }
 
-    if (s < 0 || s > 2) {
+    if (hue->s < 0 || hue->s > 2)
         av_log(ctx, AV_LOG_ERROR,
-               "Invalid value for s:%0.1f : must be included in the range 0-2\n",
-               s);
-        return AVERROR(EINVAL);
+               "Invalid value for s:%1.0f : must be included in the range 0-2\n", s);
+    else {
+        /* Convert angle from degree to radian */
+        hue->h *= M_PI / 180;
+        return 0;
     }
 
-    /* Convert angle from degree to radian */
-    hue->hue = h * M_PI / 180;
-    hue->saturation = s;
-
-    return 0;
+    return AVERROR(EINVAL);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -91,16 +121,28 @@ static int config_props(AVFilterLink *inlink)
 {
     HueContext *hue = inlink->dst->priv;
     const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[inlink->format];
+    double expr_res;
+    char *expr = hue->hrad;
+    const char *var_names[] = { "PI", NULL };
+    double var_values[] = { M_PI, 0 };
 
     hue->hsub = desc->log2_chroma_w;
     hue->vsub = desc->log2_chroma_h;
+
+    if (expr) {
+        av_expr_parse_and_eval(&expr_res, expr,
+                               var_names, var_values,
+                               NULL, NULL, NULL, NULL, NULL, 0, hue);
+        hue->h = expr_res;
+    }
+
     /*
      * Scale the value to the norm of the resulting (U,V) vector, that is
      * the saturation.
      * This will be useful in the process_chrominance function.
      */
-    hue->hue_sin = rint(sin(hue->hue) * (1 << 16) * hue->saturation);
-    hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation);
+    hue->hue_sin = rint(sin(hue->h) * (1 << 16) * hue->s);
+    hue->hue_cos = rint(cos(hue->h) * (1 << 16) * hue->s);
 
     return 0;
 }
-- 
1.7.11.3



More information about the ffmpeg-devel mailing list