[FFmpeg-devel] [PATCH] libavfilter/vaapi: enable vaapi rotation feature via call Intel iHD driver

Li, Zhong zhong.li at intel.com
Tue Oct 23 12:52:49 EEST 2018


> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces at ffmpeg.org] On Behalf
> Of Zachary Zhou
> Sent: Tuesday, October 23, 2018 3:53 PM
> To: ffmpeg-devel at ffmpeg.org
> Cc: Zhou, Zachary <zachary.zhou at intel.com>
> Subject: [FFmpeg-devel] [PATCH] libavfilter/vaapi: enable vaapi rotation
> feature via call Intel iHD driver
> 
> It supports clockwise rotation by 0/90/180/270 degrees defined in
> va/va_vpp.h, tested following command line on SKL platform
> 
> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=angle=90"
> -c:v h264_vaapi output.h264
> ---
>  libavfilter/Makefile        |   1 +
>  libavfilter/allfilters.c    |   1 +
>  libavfilter/vaapi_vpp.h     |   1 +
>  libavfilter/vf_misc_vaapi.c | 122
> ++++++++++++++++++++++++++++++++++++
>  4 files changed, 125 insertions(+)
> 
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile index
> 108a2f87d7..81afc100dc 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -349,6 +349,7 @@ OBJS-$(CONFIG_SETRANGE_FILTER)
> += vf_setparams.o
>  OBJS-$(CONFIG_SETSAR_FILTER)                 += vf_aspect.o
>  OBJS-$(CONFIG_SETTB_FILTER)                  += settb.o
>  OBJS-$(CONFIG_SHARPNESS_VAAPI_FILTER)        += vf_misc_vaapi.o
> vaapi_vpp.o
> +OBJS-$(CONFIG_ROTATION_VAAPI_FILTER)         += vf_misc_vaapi.o
> vaapi_vpp.o
>  OBJS-$(CONFIG_SHOWINFO_FILTER)               += vf_showinfo.o
>  OBJS-$(CONFIG_SHOWPALETTE_FILTER)            +=
> vf_showpalette.o
>  OBJS-$(CONFIG_SHUFFLEFRAMES_FILTER)          +=
> vf_shuffleframes.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index
> 557590850b..4b90a7f440 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -333,6 +333,7 @@ extern AVFilter ff_vf_setrange;  extern AVFilter
> ff_vf_setsar;  extern AVFilter ff_vf_settb;  extern AVFilter
> ff_vf_sharpness_vaapi;
> +extern AVFilter ff_vf_rotation_vaapi;
>  extern AVFilter ff_vf_showinfo;
>  extern AVFilter ff_vf_showpalette;
>  extern AVFilter ff_vf_shuffleframes;
> diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h index
> 0bc31018d4..cfe19b689f 100644
> --- a/libavfilter/vaapi_vpp.h
> +++ b/libavfilter/vaapi_vpp.h
> @@ -44,6 +44,7 @@ typedef struct VAAPIVPPContext {
>      int output_width;   // computed width
>      int output_height;  // computed height
> 
> +    int rotation_state;
>      VABufferID         filter_buffers[VAProcFilterCount];
>      int                nb_filter_buffers;
> 
> diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index
> 30b808a993..e5d354e3dc 100644
> --- a/libavfilter/vf_misc_vaapi.c
> +++ b/libavfilter/vf_misc_vaapi.c
> @@ -37,6 +37,18 @@
>  #define SHARPNESS_MAX          64
>  #define SHARPNESS_DEFAULT      44
> 
> +// Rotation angle values
> +enum RotationAngle {
> +    ROTATION_0   = 0,
> +    ROTATION_90  = 90,
> +    ROTATION_180 = 180,
> +    ROTATION_270 = 270,
> +
> +    ROTATION_MIN     = ROTATION_0,
> +    ROTATION_MAX     = ROTATION_270,
> +    ROTATION_DEFAULT = ROTATION_0,
> +};
> +
>  typedef struct DenoiseVAAPIContext {
>      VAAPIVPPContext vpp_ctx; // must be the first field
> 
> @@ -49,6 +61,12 @@ typedef struct SharpnessVAAPIContext {
>      int sharpness;       // enable sharpness.
>  } SharpnessVAAPIContext;
> 
> +typedef struct RotationVAAPIContext {
> +    VAAPIVPPContext vpp_ctx; // must be the first field
> +
> +    int rotation;        // enable rotation.

Looks like it means rotation degree, not a flag to enable/disable rotation. 
So the comment here may be not precise.

> +} RotationVAAPIContext;
> +
>  static float map(int x, int in_min, int in_max, float out_min, float out_max)
> {
>      double slope, output;
> @@ -123,6 +141,64 @@ static int
> sharpness_vaapi_build_filter_params(AVFilterContext *avctx)
>      return 0;
>  }
> 
> +static int rotation_vaapi_build_filter_params(AVFilterContext *avctx) {
> +    VAAPIVPPContext *vpp_ctx  = avctx->priv;
> +    RotationVAAPIContext *ctx = avctx->priv;
> +
> +    VAStatus vas;
> +    int support_flag;
> +
> +    VAProcPipelineCaps pipeline_caps;
> +
> +    memset(&pipeline_caps, 0, sizeof(pipeline_caps));
> +    vas = vaQueryVideoProcPipelineCaps(vpp_ctx->hwctx->display,
> +                                       vpp_ctx->va_context,
> +                                       NULL, 0,
> +                                       &pipeline_caps);
> +    if (vas != VA_STATUS_SUCCESS) {
> +        av_log(avctx, AV_LOG_ERROR, "Failed to query pipeline "
> +               "caps: %d (%s).\n", vas, vaErrorStr(vas));
> +        return AVERROR(EIO);
> +    }
> +
> +    if (!pipeline_caps.rotation_flags) {
> +        av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't support
> rotation\n");
> +        return AVERROR(EINVAL);
> +    }
> +
> +    switch (ctx->rotation) {
> +    case ROTATION_0:
> +        vpp_ctx->rotation_state = VA_ROTATION_NONE;
> +        break;
> +    case ROTATION_90:
> +        vpp_ctx->rotation_state = VA_ROTATION_90;
> +        break;
> +    case ROTATION_180:
> +        vpp_ctx->rotation_state = VA_ROTATION_180;
> +        break;
> +    case ROTATION_270:
> +        vpp_ctx->rotation_state = VA_ROTATION_270;
> +        break;
> +    default:
> +        av_log(avctx, AV_LOG_ERROR, "Failed to set rotation_state
> to %d. "
> +               "Clockwise %d, %d, %d and %d are only supported\n",
> +               ctx->rotation,
> +               ROTATION_0, ROTATION_90, ROTATION_180,
> ROTATION_270);
> +        return AVERROR(EINVAL);
> +    }
> +
> +    support_flag = pipeline_caps.rotation_flags &
> +                   (1 << vpp_ctx->rotation_state);
> +    if (!support_flag) {
> +        av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't
> support %d\n",
> +               ctx->rotation);
> +        return AVERROR(EINVAL);
> +    }
> +
> +    return 0;
> +}
> +
>  static int misc_vaapi_filter_frame(AVFilterLink *inlink, AVFrame
> *input_frame)  {
>      AVFilterContext *avctx   = inlink->dst;
> @@ -164,6 +240,19 @@ static int misc_vaapi_filter_frame(AVFilterLink
> *inlink, AVFrame *input_frame)
>          .height = input_frame->height,
>      };
> 
> +    switch (vpp_ctx->rotation_state) {
> +    case VA_ROTATION_NONE:

Should be this case by-passed? I guess can bring a little performance benefit.

> +    case VA_ROTATION_90:
> +    case VA_ROTATION_180:
> +    case VA_ROTATION_270:
> +        params.rotation_state = vpp_ctx->rotation_state;
> +        break;
> +    default:
> +        av_log(avctx, AV_LOG_ERROR, "VAAPI doesn't support %d\n",
> +               vpp_ctx->rotation_state);
> +        goto fail;
> +    }
> +
>      if (vpp_ctx->nb_filter_buffers) {
>          params.filters     = &vpp_ctx->filter_buffers[0];
>          params.num_filters = vpp_ctx->nb_filter_buffers; @@ -225,6
> +314,18 @@ static av_cold int sharpness_vaapi_init(AVFilterContext *avctx)
>      return 0;
>  }
> 
> +static av_cold int rotation_vaapi_init(AVFilterContext *avctx) {
> +    VAAPIVPPContext *vpp_ctx = avctx->priv;
> +
> +    ff_vaapi_vpp_ctx_init(avctx);
> +    vpp_ctx->pipeline_uninit     = ff_vaapi_vpp_pipeline_uninit;
> +    vpp_ctx->build_filter_params = rotation_vaapi_build_filter_params;
> +    vpp_ctx->output_format       = AV_PIX_FMT_NONE;
> +
> +    return 0;
> +}
> +
>  #define DOFFSET(x) offsetof(DenoiseVAAPIContext, x)  #define FLAGS
> (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)  static
> const AVOption denoise_vaapi_options[] = { @@ -240,8 +341,16 @@ static
> const AVOption sharpness_vaapi_options[] = {
>      { NULL },
>  };
> 
> +#define ROFFSET(x) offsetof(RotationVAAPIContext, x) static const
> +AVOption rotation_vaapi_options[] = {
> +    { "angle", "clockwise rotation angle 0/90/180/270 are only
> supported",

Should be better if sub-options can be added, just like cclock_flip option in transpose_options.

> +      ROFFSET(rotation), AV_OPT_TYPE_INT, { .i64 =
> ROTATION_DEFAULT }, ROTATION_MIN, ROTATION_MAX, .flags = FLAGS },
> +    { NULL },
> +};
> +
>  AVFILTER_DEFINE_CLASS(denoise_vaapi);
>  AVFILTER_DEFINE_CLASS(sharpness_vaapi);
> +AVFILTER_DEFINE_CLASS(rotation_vaapi);
> 
>  static const AVFilterPad misc_vaapi_inputs[] = {
>      {
> @@ -287,3 +396,16 @@ AVFilter ff_vf_sharpness_vaapi = {
>      .priv_class    = &sharpness_vaapi_class,
>      .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,  };
> +
> +AVFilter ff_vf_rotation_vaapi = {
> +    .name          = "rotation_vaapi",
> +    .description   = NULL_IF_CONFIG_SMALL("VAAPI VPP for rotation"),
> +    .priv_size     = sizeof(RotationVAAPIContext),
> +    .init          = &rotation_vaapi_init,
> +    .uninit        = &ff_vaapi_vpp_ctx_uninit,
> +    .query_formats = &ff_vaapi_vpp_query_formats,
> +    .inputs        = misc_vaapi_inputs,
> +    .outputs       = misc_vaapi_outputs,
> +    .priv_class    = &rotation_vaapi_class,
> +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };
> --
> 2.17.1

The rest LGTM.


More information about the ffmpeg-devel mailing list