Quoting Huang, Zhengxu (2017-08-04 05:15:26)
>From 0d3fcc7322b86e236596aad21f704b5844d14446 Mon Sep 17 00:00:00 2001
>From: "Huang, Zhengxu" <zhengxu.maxw...@gmail.com>
>Date: Wed, 26 Jul 2017 04:50:06 +0800
>Subject: [PATCH 2/2] libavfilter/vf_vpp: Add common filters of the qsv vpp
>
>Add common filters of the qsv vpp features including scale denosie deinterlace
>frc crop and procAmp.
>
>Performance will be significantly reduced in the test if using cascade mode 
>just
>like qsv framerate + qsv scale + qsv deinterlace + qsv denoise in separated way
>no matter in system or video memmory cases. And the code is so redundant 
>because
>so much the same just as session and surface's creation and management. So we 
>add
>a common qsv filter.
>
>Usage:
>-hwaccel qsv -c:v h264_qsv -r 25 -i in -vf 
>vpp_qsv=w=iw/2:h=400:deinterlace=1:framerate=60:detail=50:denoise=50
>-b 2M -maxrate 3M -c:v h264_qsv -y out.h264
>
>Signed-off-by: ChaoX A Liu <chaox.a....@gmail.com>
>Signed-off-by: Zhengxu Huang <zhengxu.maxw...@gmail.com>
>Signed-off-by: Andrew Zhang <huazh...@gmail.com>
>Change-Id: I130392ce722138c209ab658c5f03f0009b6e8024
>---
> configure                |   2 +
> libavfilter/Makefile     |   1 +
> libavfilter/allfilters.c |   1 +
> libavfilter/vf_vpp_qsv.c | 405 +++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 409 insertions(+)
> create mode 100644 libavfilter/vf_vpp_qsv.c
>
>diff --git a/configure b/configure
>index e6ea18a..70eee5e 100755
>--- a/configure
>+++ b/configure
>@@ -2535,6 +2535,8 @@ resample_filter_deps="avresample"
> scale_filter_deps="swscale"
> scale_qsv_filter_deps="libmfx"
> scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer"
>+vpp_qsv_filter_deps="libmfx"
>+vpp_qsv_filter_select="qsvvpp"
> 
> # examples
> decode_audio_example_deps="avcodec avutil"
>diff --git a/libavfilter/Makefile b/libavfilter/Makefile
>index 8d9ed6a..3f13d29 100644
>--- a/libavfilter/Makefile
>+++ b/libavfilter/Makefile
>@@ -94,6 +94,7 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER)              += 
>vf_transpose.o
> OBJS-$(CONFIG_TRIM_FILTER)                   += trim.o
> OBJS-$(CONFIG_UNSHARP_FILTER)                += vf_unsharp.o
> OBJS-$(CONFIG_VFLIP_FILTER)                  += vf_vflip.o
>+OBJS-$(CONFIG_VPP_QSV_FILTER)                += qsvvpp.o vf_vpp_qsv.o

Needs the same changes you did to the overlay filter.

> OBJS-$(CONFIG_YADIF_FILTER)                  += vf_yadif.o
> 
> OBJS-$(CONFIG_NULLSINK_FILTER)               += vsink_nullsink.o
>diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
>index dc59ccd..2b3a672 100644
>--- a/libavfilter/allfilters.c
>+++ b/libavfilter/allfilters.c
>@@ -117,6 +117,7 @@ void avfilter_register_all(void)
>     REGISTER_FILTER(TRIM,           trim,           vf);
>     REGISTER_FILTER(UNSHARP,        unsharp,        vf);
>     REGISTER_FILTER(VFLIP,          vflip,          vf);
>+    REGISTER_FILTER(VPP_QSV,        vpp_qsv,        vf);
>     REGISTER_FILTER(YADIF,          yadif,          vf);
> 
>     REGISTER_FILTER(COLOR,          color,          vsrc);
>diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
>new file mode 100644
>index 0000000..4e14245
>--- /dev/null
>+++ b/libavfilter/vf_vpp_qsv.c
>@@ -0,0 +1,405 @@
>+/*
>+ * This file is part of Libav.
>+ *
>+ * Libav is free software; you can redistribute it and/or
>+ * modify it under the terms of the GNU Lesser General Public
>+ * License as published by the Free Software Foundation; either
>+ * version 2.1 of the License, or (at your option) any later version.
>+ *
>+ * Libav is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>+ * Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>+ * License along with Libav; if not, write to the Free Software
>+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
>USA
>+ */
>+
>+#include <float.h>
>+#include "internal.h"
>+#include "formats.h"
>+#include "libavutil/eval.h"
>+#include "avfilter.h"
>+#include "libavutil/avassert.h"
>+#include "libavutil/opt.h"
>+#include "libavcodec/avcodec.h"
>+#include "libavformat/avformat.h"
>+#include "libavutil/pixdesc.h"
>+#include "qsvvpp.h"
>+
>+#define OFFSET(x) offsetof(VPPContext, x)
>+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM
>+
>+/* number of video enhancement filters */
>+#define ENH_FILTERS_COUNT (5)
>+
>+typedef struct VPPContext{
>+    const AVClass *class;
>+
>+    FFQSVVPPContext *qsv;
>+
>+    /* Video Enhancement Algorithms */
>+    mfxExtVPPDeinterlacing  deinterlace_conf;
>+    mfxExtVPPFrameRateConversion frc_conf;
>+    mfxExtVPPDenoise denoise_conf;
>+    mfxExtVPPDetail detail_conf;
>+    mfxExtVPPProcAmp procamp_conf;
>+
>+    int out_width;
>+    int out_height;
>+
>+    AVRational framerate;       ///< target framerate
>+    /**
>+     * destination picture structure
>+     * -1 = unkown
>+     * 0 = interlaced top field first
>+     * 1 = progressive
>+     * 2 = interlaced bottom field first
>+     */
>+    int dpic;
>+    int use_frc;                ///< use framerate conversion
>+    int deinterlace;            ///< deinterlace mode : 0=off, 1=bob, 
>2=advanced
>+    int denoise;                ///< Enable Denoise algorithm. Level is the 
>optional value from the interval [0; 100]
>+    int detail;                 ///< Enable Detail Enhancement algorithm.
>+                                ///< Level is the optional value from the 
>interval [0; 100]
>+    int use_crop;               ///< 1 = use crop; 0=none
>+    int crop_w;
>+    int crop_h;
>+    int crop_x;
>+    int crop_y;
>+
>+    /* param for the procamp */
>+    int    procamp;            ///< enable the procamp
>+    float  hue;
>+    float  saturation;
>+    float  contrast;
>+    float  brightness;
>+
>+    char *cx, *cy, *cw, *ch;
>+    char *ow, *oh;
>+} VPPContext;
>+
>+static const AVOption options[] = {
>+    { "deinterlace", "deinterlace mode: 0=off, 1=bob, 2=advanced",            
> OFFSET(deinterlace),  AV_OPT_TYPE_INT, {.i64=0}, 0, 
>MFX_DEINTERLACING_ADVANCED, .flags = FLAGS },

The values should be named constants. For their use see e.g. the overlay
filter (the eof_action option).

>+    { "denoise",     "denoise level [0, 100]",                                
> OFFSET(denoise),      AV_OPT_TYPE_INT, {.i64=0}, 0, 100, .flags = FLAGS },
>+    { "detail",      "detail enhancement level [0, 100]",                     
> OFFSET(detail),       AV_OPT_TYPE_INT, {.i64=0}, 0, 100, .flags = FLAGS },
>+    { "dpic",        "dest pic struct: 0=tff, 1=progressive [default], 
>2=bff", OFFSET(dpic),         AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 2, .flags = 
>FLAGS },

same

>+    { "framerate",   "output framerate",                                      
> OFFSET(framerate),    AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 },0, DBL_MAX, .flags 
>= FLAGS },
>+    { "procamp",     "Enable ProcAmp",                                        
> OFFSET(procamp),    AV_OPT_TYPE_INT,   {.i64 = 0}, 0, 1, .flags = FLAGS},
>+    { "hue",         "ProcAmp hue",                                           
> OFFSET(hue),        AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -180.0, 180.0, .flags = 
>FLAGS},
>+    { "saturation",  "ProcAmp saturation",                                    
> OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, 0.0, 10.0, .flags = 
>FLAGS},
>+    { "contrast",    "ProcAmp contrast",                                      
> OFFSET(contrast),   AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, 0.0, 10.0, .flags = 
>FLAGS},
>+    { "brightness",  "ProcAmp brightness",                                    
> OFFSET(brightness), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, -100.0, 100.0, .flags = 
>FLAGS},
>+
>+    { "cw",   "set the width crop area expression",       OFFSET(cw), 
>AV_OPT_TYPE_STRING, {.str = "iw"}, CHAR_MIN, CHAR_MAX, FLAGS },
>+    { "ch",   "set the height crop area expression",      OFFSET(ch), 
>AV_OPT_TYPE_STRING, {.str = "ih"}, CHAR_MIN, CHAR_MAX, FLAGS },
>+    { "cx",   "set the x crop area expression",           OFFSET(cx), 
>AV_OPT_TYPE_STRING, {.str = "(in_w-out_w)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
>+    { "cy",   "set the y crop area expression",           OFFSET(cy), 
>AV_OPT_TYPE_STRING, {.str = "(in_h-out_h)/2"}, CHAR_MIN, CHAR_MAX, FLAGS },
>+
>+    { "w",      "Output video width",  OFFSET(ow), AV_OPT_TYPE_STRING, 
>{.str="cw"}, 0, 255, .flags = FLAGS },
>+    { "width",  "Output video width",  OFFSET(ow), AV_OPT_TYPE_STRING, 
>{.str="cw"}, 0, 255, .flags = FLAGS },
>+    { "h",      "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, 
>{.str="w*ch/cw"}, 0, 255, .flags = FLAGS },
>+    { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, 
>{.str="w*ch/cw"}, 0, 255, .flags = FLAGS },
>+    { NULL }
>+};
>+
>+static const char *const var_names[] = {
>+    "iw", "in_w",
>+    "ih", "in_h",
>+    "ow", "out_w", "w",
>+    "oh", "out_h", "h",
>+    "cw",
>+    "ch",
>+    "cx",
>+    "cy",
>+    NULL
>+};
>+
>+enum var_name {
>+    VAR_iW, VAR_IN_W,
>+    VAR_iH, VAR_IN_H,
>+    VAR_oW, VAR_OUT_W, VAR_W,
>+    VAR_oH, VAR_OUT_H, VAR_H,
>+    CW,
>+    CH,
>+    CX,
>+    CY,
>+    VAR_VARS_NB
>+};
>+
>+static int eval_expr(AVFilterContext *ctx)
>+{
>+#define PASS_EXPR(e, s) {\
>+    ret = av_expr_parse(&e, s, var_names, NULL, NULL, NULL, NULL, 0, ctx); \
>+    if (ret < 0) {\
>+        av_log(ctx, AV_LOG_ERROR, "Error when passing '%s'.\n", s);\
>+        return ret;\

Same leak as in the overlay filter.

>+    }\
>+}
>+#define CALC_EXPR(e, v, i) {\
>+    i = v = av_expr_eval(e, var_values, NULL); \
>+}
>+    VPPContext *vpp = ctx->priv;
>+    double  var_values[VAR_VARS_NB] = { NAN };
>+    AVExpr *w_expr = NULL, *h_expr = NULL;
>+    AVExpr *cw_expr = NULL, *ch_expr = NULL;
>+    AVExpr *cx_expr = NULL, *cy_expr = NULL;
>+    int     ret = 0;
>+
>+    PASS_EXPR(cw_expr, vpp->cw);
>+    PASS_EXPR(ch_expr, vpp->ch);
>+
>+    PASS_EXPR(w_expr, vpp->ow);
>+    PASS_EXPR(h_expr, vpp->oh);
>+
>+    PASS_EXPR(cx_expr, vpp->cx);
>+    PASS_EXPR(cy_expr, vpp->cy);
>+
>+    var_values[VAR_iW] =
>+    var_values[VAR_IN_W] = ctx->inputs[0]->w;
>+
>+    var_values[VAR_iH] =
>+    var_values[VAR_IN_H] = ctx->inputs[0]->h;
>+
>+    /* crop params */
>+    CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w);
>+    CALC_EXPR(ch_expr, var_values[CH], vpp->crop_h);
>+
>+    /* calc again in case cw is relative to ch */
>+    CALC_EXPR(cw_expr, var_values[CW], vpp->crop_w);
>+
>+    CALC_EXPR(w_expr,
>+            var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W],
>+            vpp->out_width);
>+    CALC_EXPR(h_expr,
>+            var_values[VAR_OUT_H] = var_values[VAR_oH] = var_values[VAR_H],
>+            vpp->out_height);
>+
>+    /* calc again in case ow is relative to oh */
>+    CALC_EXPR(w_expr,
>+            var_values[VAR_OUT_W] = var_values[VAR_oW] = var_values[VAR_W],
>+            vpp->out_width);
>+
>+
>+    CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x);
>+    CALC_EXPR(cy_expr, var_values[CY], vpp->crop_y);
>+
>+    /* calc again in case cx is relative to cy */
>+    CALC_EXPR(cx_expr, var_values[CX], vpp->crop_x);
>+
>+    if((vpp->crop_w != var_values[VAR_iW]) || (vpp->crop_h != 
>var_values[VAR_iH])) {

Why only width/height and not the x/y?
Also, missing space.

>+        vpp->use_crop = 1;
>+        av_log(NULL, AV_LOG_INFO, "Using the crop feature \n");

This seems unnecessary. And in any case it should use a proper logging
context and have a lower verbosity level.

>+     }
>+
>+    av_expr_free(w_expr);
>+    av_expr_free(h_expr);
>+    av_expr_free(cw_expr);
>+    av_expr_free(ch_expr);
>+    av_expr_free(cx_expr);
>+    av_expr_free(cy_expr);
>+#undef PASS_EXPR
>+#undef CALC_EXPR
>+
>+    return ret;
>+}
>+
>+static int config_input(AVFilterLink *inlink)
>+{
>+    AVFilterContext *ctx = inlink->dst;
>+    VPPContext      *vpp = ctx->priv;
>+    int              ret;
>+
>+    if (vpp->framerate.den == 0 || vpp->framerate.num == 0)
>+        vpp->framerate = inlink->frame_rate;

The input framerate is not always set, the input could be VFR or its
framerate could be unknown. Can MSDK do VFR to CFR conversion?

>+
>+    if (av_q2d(vpp->framerate) != av_q2d(inlink->frame_rate))

Use av_cmp_q()

>+        vpp->use_frc = 1;
>+
>+    ret = eval_expr(ctx);
>+    if (ret != 0) {
>+        av_log(ctx, AV_LOG_ERROR, "Fail to eval expr.\n");
>+        return ret;
>+    }
>+
>+    if (vpp->out_height == 0 || vpp->out_width == 0) {
>+        vpp->out_width  = inlink->w;
>+        vpp->out_height = inlink->h;
>+    }
>+
>+    if (vpp->use_crop) {
>+        if (vpp->crop_x < 0)  vpp->crop_x = 0;

Here and below use FFMIN/FFMAX for clipping, it's shorter and more
readable.

>+        if (vpp->crop_y < 0)  vpp->crop_y = 0;
>+
>+        if(vpp->crop_w % 2)       vpp->crop_w++;
>+        if(vpp->crop_h % 2)       vpp->crop_h++;
>+        if(vpp->out_width % 2)    vpp->out_width++;
>+        if(vpp->out_height % 2)   vpp->out_height++;

This should not silently do something different from what the caller
requested - it should at the very least warn.

>+
>+        if(vpp->crop_w + vpp->crop_x > inlink->w)
>+           vpp->crop_x = inlink->w - vpp->crop_w;
>+        if(vpp->crop_h + vpp->crop_y > inlink->h)
>+           vpp->crop_y = inlink->h - vpp->crop_h;
>+    }
>+
>+    return 0;
>+}

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to