[FFmpeg-devel] [PATCH, v3] lavf/vf_vpp_qsv: add support for QSV transpose filter

Li, Zhong zhong.li at intel.com
Thu Jul 11 17:35:57 EEST 2019


> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces at ffmpeg.org] On Behalf
> Of Linjie Fu
> Sent: Thursday, July 11, 2019 1:58 AM
> To: ffmpeg-devel at ffmpeg.org
> Cc: Fu, Linjie <linjie.fu at intel.com>
> Subject: [FFmpeg-devel] [PATCH, v3] lavf/vf_vpp_qsv: add support for QSV
> transpose filter
> 
> Add transpose support for qsv_vpp with rotate and hflip:
>     - rotate: [0, 3] support clockwise rotation of 0, 90, 180, 270;
>     - hflip:  [0, 1] support horizontal flip;
> 
> Configure with:
> {"cclock_hflip","clock","cclock","clock_hflip","reversal","hflip","vflip"}
> 
> Limitation:
>     If pipeline contains resize, mirroring and other, VPP skips other filters in
> MSDK when IOPattern equals d3d->d3d. So "cclock_hflip, clock_hflip, vflip"
> will not work in d3d->d3d condition.
> 
> This pr is fixing this:
> https://github.com/Intel-Media-SDK/MediaSDK/pull/1491
> 
> CMD:
> ffmpeg -hwaccel qsv -c:v h264_qsv -i input.h264
>     -vf 'format=qsv,vpp_qsv=transpose=clock' -c:v h264_qsv output.h264
> 
> ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -c:v h264_qsv -i
> input.h264
>     -vf
> 'hwupload=extra_hw_frames=64,format=qsv,vpp_qsv=transpose=cclock_hfli
> p'
>                             -f rawvideo -pix_fmt nv12 ./transpose.yuv
> 
> Signed-off-by: Linjie Fu <linjie.fu at intel.com>
> ---
>  libavfilter/vf_vpp_qsv.c | 101
> ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 99 insertions(+), 2 deletions(-)
> 
> diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index
> dd05e8baff..01ff42a677 100644
> --- a/libavfilter/vf_vpp_qsv.c
> +++ b/libavfilter/vf_vpp_qsv.c
> @@ -36,12 +36,15 @@
>  #include "libavformat/avformat.h"
> 
>  #include "qsvvpp.h"
> +#include "transpose.h"
> 
>  #define OFFSET(x) offsetof(VPPContext, x)  #define FLAGS
> (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
> 
>  /* number of video enhancement filters */ -#define ENH_FILTERS_COUNT
> (5)
> +#define ENH_FILTERS_COUNT (7)
> +#define QSV_HAVE_ROTATION  QSV_VERSION_ATLEAST(1, 17) #define
> +QSV_HAVE_MIRRORING QSV_VERSION_ATLEAST(1, 19)
> 
>  typedef struct VPPContext{
>      const AVClass *class;
> @@ -54,6 +57,8 @@ typedef struct VPPContext{
>      mfxExtVPPDenoise denoise_conf;
>      mfxExtVPPDetail detail_conf;
>      mfxExtVPPProcAmp procamp_conf;
> +    mfxExtVPPRotation rotation_conf;
> +    mfxExtVPPMirroring mirroring_conf;
> 
>      int out_width;
>      int out_height;
> @@ -70,6 +75,10 @@ typedef struct VPPContext{
>      int crop_x;
>      int crop_y;
> 
> +    int transpose;
> +    int rotate;                 /* rotate angle : [0, 90, 180, 270] */
> +    int hflip;                  /* flip mode : 0 = off, 1 = HORIZONTAL
> flip */
> +
>      /* param for the procamp */
>      int    procamp;            /* enable procamp */
>      float  hue;
> @@ -95,6 +104,15 @@ static const AVOption options[] = {
>      { "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},
> 
> +    { "transpose",  "set transpose direction",       OFFSET(transpose),
> AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, 6, FLAGS, "transpose"},
> +        { "cclock_hflip",  "rotate counter-clockwise with horizontal flip",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "transpose" },
> +        { "clock",         "rotate clockwise",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_CLOCK       }, .flags=FLAGS, .unit = "transpose" },
> +        { "cclock",        "rotate counter-clockwise",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_CCLOCK      }, .flags=FLAGS, .unit = "transpose" },
> +        { "clock_hflip",   "rotate clockwise with horizontal flip",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_CLOCK_FLIP  }, .flags=FLAGS, .unit = "transpose" },
> +        { "reversal",      "rotate by half-turn",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_REVERSAL    }, .flags=FLAGS, .unit = "transpose" },
> +        { "hflip",         "flip horizontally",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_HFLIP       }, .flags=FLAGS, .unit = "transpose" },
> +        { "vflip",         "flip vertically",
> 0, AV_OPT_TYPE_CONST, { .i64 =
> TRANSPOSE_VFLIP       }, .flags=FLAGS, .unit = "transpose" },
> +
>      { "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 },
> @@ -322,8 +340,87 @@ static int config_output(AVFilterLink *outlink)
>          param.ext_buf[param.num_ext_buf++] =
> (mfxExtBuffer*)&vpp->procamp_conf;
>      }
> 
> +    if (vpp->transpose >= 0) {
> +#ifdef QSV_HAVE_ROTATION
> +        switch (vpp->transpose) {
> +        case TRANSPOSE_CCLOCK_FLIP:
> +            vpp->rotate = MFX_ANGLE_270;
> +            vpp->hflip  = MFX_MIRRORING_HORIZONTAL;
> +            break;
> +        case TRANSPOSE_CLOCK:
> +            vpp->rotate = MFX_ANGLE_90;
> +            vpp->hflip  = MFX_MIRRORING_DISABLED;
> +            break;
> +        case TRANSPOSE_CCLOCK:
> +            vpp->rotate = MFX_ANGLE_270;
> +            vpp->hflip  = MFX_MIRRORING_DISABLED;
> +            break;
> +        case TRANSPOSE_CLOCK_FLIP:
> +            vpp->rotate = MFX_ANGLE_90;
> +            vpp->hflip  = MFX_MIRRORING_HORIZONTAL;
> +            break;
> +        case TRANSPOSE_REVERSAL:
> +            vpp->rotate = MFX_ANGLE_180;
> +            vpp->hflip  = MFX_MIRRORING_DISABLED;
> +            break;
> +        case TRANSPOSE_HFLIP:
> +            vpp->rotate = MFX_ANGLE_0;
> +            vpp->hflip  = MFX_MIRRORING_HORIZONTAL;
> +            break;
> +        case TRANSPOSE_VFLIP:
> +            vpp->rotate = MFX_ANGLE_180;
> +            vpp->hflip  = MFX_MIRRORING_HORIZONTAL;
> +            break;
> +        default:
> +            av_log(ctx, AV_LOG_ERROR, "Failed to set transpose mode
> to %d.\n", vpp->transpose);
> +            return AVERROR(EINVAL);
> +        }
> +#else
> +        av_log(ctx, AV_LOG_WARNING, "The QSV VPP transpose option is
> "
> +            "not supported with this MSDK version.\n");
> +        vpp->transpose = 0;
> +#endif
> +    }
> +
> +    if (vpp->rotate) {
> +#ifdef QSV_HAVE_ROTATION
> +        memset(&vpp->rotation_conf, 0, sizeof(mfxExtVPPRotation));
> +        vpp->rotation_conf.Header.BufferId  =
> MFX_EXTBUFF_VPP_ROTATION;
> +        vpp->rotation_conf.Header.BufferSz  =
> sizeof(mfxExtVPPRotation);
> +        vpp->rotation_conf.Angle = vpp->rotate;
> +
> +        if (MFX_ANGLE_90 == vpp->rotate || MFX_ANGLE_270 ==
> vpp->rotate) {
> +            FFSWAP(int, vpp->out_width, vpp->out_height);
> +            FFSWAP(int, outlink->w, outlink->h);
> +            av_log(ctx, AV_LOG_DEBUG, "Swap width and height for
> clock/cclock rotation.\n");
> +        }
> +
> +        param.ext_buf[param.num_ext_buf++] =
> +(mfxExtBuffer*)&vpp->rotation_conf;
> +#else
> +        av_log(ctx, AV_LOG_WARNING, "The QSV VPP rotate option is "
> +            "not supported with this MSDK version.\n");
> +        vpp->rotate = 0;
> +#endif
> +    }
> +
> +    if (vpp->hflip) {
> +#ifdef QSV_HAVE_MIRRORING
> +        memset(&vpp->mirroring_conf, 0, sizeof(mfxExtVPPMirroring));
> +        vpp->mirroring_conf.Header.BufferId =
> MFX_EXTBUFF_VPP_MIRRORING;
> +        vpp->mirroring_conf.Header.BufferSz =
> sizeof(mfxExtVPPMirroring);
> +        vpp->mirroring_conf.Type = vpp->hflip;
> +
> +        param.ext_buf[param.num_ext_buf++] =
> +(mfxExtBuffer*)&vpp->mirroring_conf;
> +#else
> +        av_log(ctx, AV_LOG_WARNING, "The QSV VPP hflip option is "
> +            "not supported with this MSDK version.\n");
> +        vpp->hflip = 0;
> +#endif
> +    }
> +
>      if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise
> ||
> -        vpp->detail || vpp->procamp || inlink->w != outlink->w ||
> inlink->h != outlink->h)
> +        vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip ||
> +        inlink->w != outlink->w || inlink->h != outlink->h)
>          return ff_qsvvpp_create(ctx, &vpp->qsv, &param);
>      else {
>          av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n");
> --
> 2.17.1

LGTM. Will verify and merge if no problem. 


More information about the ffmpeg-devel mailing list