[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, ¶m);
> 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