diff mbox

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

Message ID 20181025065201.27115-1-zachary.zhou@intel.com
State Superseded
Headers show

Commit Message

Zachary Zhou Oct. 25, 2018, 6:52 a.m. UTC
It supports clockwise rotation by 0/90/180/270 degrees defined in
va/va_vpp.h, tested following command line on SKL platform

dir=0 for 0   degree
dir=1 for 90  degree
dir=2 for 180 degree
dir=3 for 270 degree

ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
-hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"
-c:v h264_vaapi output.h264

Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
---
 configure                     |   3 +
 libavfilter/Makefile          |   1 +
 libavfilter/allfilters.c      |   1 +
 libavfilter/vaapi_vpp.h       |   1 +
 libavfilter/vf_rotate_vaapi.c | 252 ++++++++++++++++++++++++++++++++++
 5 files changed, 258 insertions(+)
 create mode 100644 libavfilter/vf_rotate_vaapi.c

Comments

sean darcy Oct. 25, 2018, 3:50 p.m. UTC | #1
On 10/25/18 2:52 AM, Zachary Zhou wrote:
> It supports clockwise rotation by 0/90/180/270 degrees defined in
> va/va_vpp.h, tested following command line on SKL platform
> 
> dir=0 for 0   degree
> dir=1 for 90  degree
> dir=2 for 180 degree
> dir=3 for 270 degree
> 
> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"
> -c:v h264_vaapi output.h264
> 
> Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
> ---
>   configure                     |   3 +
>   libavfilter/Makefile          |   1 +
>   libavfilter/allfilters.c      |   1 +
>   libavfilter/vaapi_vpp.h       |   1 +
>   libavfilter/vf_rotate_vaapi.c | 252 ++++++++++++++++++++++++++++++++++
>   5 files changed, 258 insertions(+)
>   create mode 100644 libavfilter/vf_rotate_vaapi.c
> 
> diff --git a/configure b/configure
> index 85d5dd5962..33aced3d78 100755
> --- a/configure
> +++ b/configure
> @@ -6390,6 +6390,9 @@ if enabled vaapi; then
>       fi
>   
>       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)"
> +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps" rotation_flags; then
> +        disable rotation_vaapi_filter
> +    fi
>   fi
>   
>   if enabled_all opencl libdrm ; then
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c b/libavfilter/vf_rotate_vaapi.c
> new file mode 100644
> index 0000000000..34c270e9c7
> --- /dev/null
> +++ b/libavfilter/vf_rotate_vaapi.c
> @@ -0,0 +1,252 @@
> +/*
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg 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.
> + *
> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +#include <string.h>
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/mem.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/pixdesc.h"
> +
> +#include "avfilter.h"
> +#include "formats.h"
> +#include "internal.h"
> +#include "vaapi_vpp.h"
> +
> +// Rotation angle values
> +enum RotationAngle {
> +    ROTATION_0   = 0,
> +    ROTATION_90  = 1,
> +    ROTATION_180 = 2,
> +    ROTATION_270 = 3,
> +
> +    ROTATION_MIN     = ROTATION_0,
> +    ROTATION_MAX     = ROTATION_270,
> +    ROTATION_DEFAULT = ROTATION_0,
> +};
> +
> +typedef struct RotationVAAPIContext {
> +    VAAPIVPPContext vpp_ctx; // must be the first field
> +
> +    int rotation;        // enable rotation.
> +} RotationVAAPIContext;
> +
> +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 rotation_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
> +{
> +    AVFilterContext *avctx   = inlink->dst;
> +    AVFilterLink *outlink    = avctx->outputs[0];
> +    VAAPIVPPContext *vpp_ctx = avctx->priv;
> +    AVFrame *output_frame    = NULL;
> +    VASurfaceID input_surface, output_surface;
> +    VARectangle input_region;
> +
> +    VAProcPipelineParameterBuffer params;
> +    int err;
> +
> +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
> +           av_get_pix_fmt_name(input_frame->format),
> +           input_frame->width, input_frame->height, input_frame->pts);
> +
> +    if (vpp_ctx->va_context == VA_INVALID_ID)
> +        return AVERROR(EINVAL);
> +
> +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp input.\n",
> +           input_surface);
> +
> +    output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,
> +                                       vpp_ctx->output_height);
> +    if (!output_frame) {
> +        err = AVERROR(ENOMEM);
> +        goto fail;
> +    }
> +
> +    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];
> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp output.\n",
> +           output_surface);
> +    memset(&params, 0, sizeof(params));
> +    input_region = (VARectangle) {
> +        .x      = 0,
> +        .y      = 0,
> +        .width  = input_frame->width,
> +        .height = input_frame->height,
> +    };
> +
> +    switch (vpp_ctx->rotation_state) {
> +    case VA_ROTATION_NONE:
> +    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;
> +    }
> +    params.surface = input_surface;
> +    params.surface_region = &input_region;
> +    params.surface_color_standard =
> +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
> +
> +    params.output_region = NULL;
> +    params.output_background_color = 0xff000000;
> +    params.output_color_standard = params.surface_color_standard;
> +
> +    params.pipeline_flags = 0;
> +    params.filter_flags = VA_FRAME_PICTURE;
> +
> +    err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);
> +    if (err < 0)
> +        goto fail;
> +
> +    err = av_frame_copy_props(output_frame, input_frame);
> +    if (err < 0)
> +        goto fail;
> +    av_frame_free(&input_frame);
> +
> +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n",
> +           av_get_pix_fmt_name(output_frame->format),
> +           output_frame->width, output_frame->height, output_frame->pts);
> +
> +    return ff_filter_frame(outlink, output_frame);
> +
> +fail:
> +    av_frame_free(&input_frame);
> +    av_frame_free(&output_frame);
> +    return err;
> +}
> +
> +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 ROFFSET(x) offsetof(RotationVAAPIContext, x)
> +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
> +static const AVOption rotation_vaapi_options[] = {
> +    { "dir", "set roation direction", ROFFSET(rotation), AV_OPT_TYPE_INT, { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
> +        { "clock_0",   "rotate clockwise 0 degrees",   0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
> +        { "clock_90",  "rotate clockwise 90 degrees",  0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
> +        { "clock_180", "rotate clockwise 180 degrees", 0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
> +        { "clock_270", "rotate clockwise 270 degrees", 0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
> +    { NULL },
> +};
> +
> +AVFILTER_DEFINE_CLASS(rotation_vaapi);
> +
> +static const AVFilterPad rotation_vaapi_inputs[] = {
> +    {
> +        .name         = "default",
> +        .type         = AVMEDIA_TYPE_VIDEO,
> +        .filter_frame = &rotation_vaapi_filter_frame,
> +        .config_props = &ff_vaapi_vpp_config_input,
> +    },
> +    { NULL }
> +};
> +
> +static const AVFilterPad rotation_vaapi_outputs[] = {
> +    {
> +        .name = "default",
> +        .type = AVMEDIA_TYPE_VIDEO,
> +        .config_props = &ff_vaapi_vpp_config_output,
> +    },
> +    { NULL }
> +};
> +
> +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        = rotation_vaapi_inputs,
> +    .outputs       = rotation_vaapi_outputs,
> +    .priv_class    = &rotation_vaapi_class,
> +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
> +};
> 
How about:

deg=0 for 0   degree
deg=90 for 90  degree
deg=180 for 180 degree
deg=270 for 270 degree

ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
  -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=deg=90"
  -c:v h264_vaapi output.h264

The rotation is in degrees , not direction. And using the actual degrees 
instead of magic numbers makes it more obvious for the user.
Zachary Zhou Oct. 26, 2018, 3:05 a.m. UTC | #2
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> sean darcy

> Sent: Thursday, October 25, 2018 11:51 PM

> To: ffmpeg-devel@ffmpeg.org

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On 10/25/18 2:52 AM, Zachary Zhou wrote:

> > It supports clockwise rotation by 0/90/180/270 degrees defined in

> > va/va_vpp.h, tested following command line on SKL platform

> >

> > dir=0 for 0   degree

> > dir=1 for 90  degree

> > dir=2 for 180 degree

> > dir=3 for 270 degree

> >

> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"

> > -c:v h264_vaapi output.h264

> >

> > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> > ---

> >   configure                     |   3 +

> >   libavfilter/Makefile          |   1 +

> >   libavfilter/allfilters.c      |   1 +

> >   libavfilter/vaapi_vpp.h       |   1 +

> >   libavfilter/vf_rotate_vaapi.c | 252 ++++++++++++++++++++++++++++++++++

> >   5 files changed, 258 insertions(+)

> >   create mode 100644 libavfilter/vf_rotate_vaapi.c

> >

> > diff --git a/configure b/configure

> > index 85d5dd5962..33aced3d78 100755

> > --- a/configure

> > +++ b/configure

> > @@ -6390,6 +6390,9 @@ if enabled vaapi; then

> >       fi

> >

> >       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)"

> > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps" rotation_flags;

> then

> > +        disable rotation_vaapi_filter

> > +    fi

> >   fi

> >

> >   if enabled_all opencl libdrm ; then

> > diff --git a/libavfilter/Makefile b/libavfilter/Makefile index

> > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c

> > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index

> > 0000000000..34c270e9c7

> > --- /dev/null

> > +++ b/libavfilter/vf_rotate_vaapi.c

> > @@ -0,0 +1,252 @@

> > +/*

> > + * This file is part of FFmpeg.

> > + *

> > + * FFmpeg 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.

> > + *

> > + * FFmpeg 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 FFmpeg; if not, write to the Free Software

> > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA

> > +02110-1301 USA  */ #include <string.h>

> > +

> > +#include "libavutil/avassert.h"

> > +#include "libavutil/mem.h"

> > +#include "libavutil/opt.h"

> > +#include "libavutil/pixdesc.h"

> > +

> > +#include "avfilter.h"

> > +#include "formats.h"

> > +#include "internal.h"

> > +#include "vaapi_vpp.h"

> > +

> > +// Rotation angle values

> > +enum RotationAngle {

> > +    ROTATION_0   = 0,

> > +    ROTATION_90  = 1,

> > +    ROTATION_180 = 2,

> > +    ROTATION_270 = 3,

> > +

> > +    ROTATION_MIN     = ROTATION_0,

> > +    ROTATION_MAX     = ROTATION_270,

> > +    ROTATION_DEFAULT = ROTATION_0,

> > +};

> > +

> > +typedef struct RotationVAAPIContext {

> > +    VAAPIVPPContext vpp_ctx; // must be the first field

> > +

> > +    int rotation;        // enable rotation.

> > +} RotationVAAPIContext;

> > +

> > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink, AVFrame

> > +*input_frame) {

> > +    AVFilterContext *avctx   = inlink->dst;

> > +    AVFilterLink *outlink    = avctx->outputs[0];

> > +    VAAPIVPPContext *vpp_ctx = avctx->priv;

> > +    AVFrame *output_frame    = NULL;

> > +    VASurfaceID input_surface, output_surface;

> > +    VARectangle input_region;

> > +

> > +    VAProcPipelineParameterBuffer params;

> > +    int err;

> > +

> > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",

> > +           av_get_pix_fmt_name(input_frame->format),

> > +           input_frame->width, input_frame->height,

> > + input_frame->pts);

> > +

> > +    if (vpp_ctx->va_context == VA_INVALID_ID)

> > +        return AVERROR(EINVAL);

> > +

> > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];

> > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp input.\n",

> > +           input_surface);

> > +

> > +    output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,

> > +                                       vpp_ctx->output_height);

> > +    if (!output_frame) {

> > +        err = AVERROR(ENOMEM);

> > +        goto fail;

> > +    }

> > +

> > +    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];

> > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp

> output.\n",

> > +           output_surface);

> > +    memset(&params, 0, sizeof(params));

> > +    input_region = (VARectangle) {

> > +        .x      = 0,

> > +        .y      = 0,

> > +        .width  = input_frame->width,

> > +        .height = input_frame->height,

> > +    };

> > +

> > +    switch (vpp_ctx->rotation_state) {

> > +    case VA_ROTATION_NONE:

> > +    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;

> > +    }

> > +    params.surface = input_surface;

> > +    params.surface_region = &input_region;

> > +    params.surface_color_standard =

> > +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);

> > +

> > +    params.output_region = NULL;

> > +    params.output_background_color = 0xff000000;

> > +    params.output_color_standard = params.surface_color_standard;

> > +

> > +    params.pipeline_flags = 0;

> > +    params.filter_flags = VA_FRAME_PICTURE;

> > +

> > +    err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);

> > +    if (err < 0)

> > +        goto fail;

> > +

> > +    err = av_frame_copy_props(output_frame, input_frame);

> > +    if (err < 0)

> > +        goto fail;

> > +    av_frame_free(&input_frame);

> > +

> > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u

> (%"PRId64").\n",

> > +           av_get_pix_fmt_name(output_frame->format),

> > +           output_frame->width, output_frame->height,

> > + output_frame->pts);

> > +

> > +    return ff_filter_frame(outlink, output_frame);

> > +

> > +fail:

> > +    av_frame_free(&input_frame);

> > +    av_frame_free(&output_frame);

> > +    return err;

> > +}

> > +

> > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define FLAGS

> > +(AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) static

> const

> > +AVOption rotation_vaapi_options[] = {

> > +    { "dir", "set roation direction", ROFFSET(rotation), AV_OPT_TYPE_INT,

> { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },

> > +        { "clock_0",   "rotate clockwise 0 degrees",   0, AV_OPT_TYPE_CONST,

> { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },

> > +        { "clock_90",  "rotate clockwise 90 degrees",  0, AV_OPT_TYPE_CONST,

> { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },

> > +        { "clock_180", "rotate clockwise 180 degrees", 0, AV_OPT_TYPE_CONST,

> { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },

> > +        { "clock_270", "rotate clockwise 270 degrees", 0, AV_OPT_TYPE_CONST,

> { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },

> > +    { NULL },

> > +};

> > +

> > +AVFILTER_DEFINE_CLASS(rotation_vaapi);

> > +

> > +static const AVFilterPad rotation_vaapi_inputs[] = {

> > +    {

> > +        .name         = "default",

> > +        .type         = AVMEDIA_TYPE_VIDEO,

> > +        .filter_frame = &rotation_vaapi_filter_frame,

> > +        .config_props = &ff_vaapi_vpp_config_input,

> > +    },

> > +    { NULL }

> > +};

> > +

> > +static const AVFilterPad rotation_vaapi_outputs[] = {

> > +    {

> > +        .name = "default",

> > +        .type = AVMEDIA_TYPE_VIDEO,

> > +        .config_props = &ff_vaapi_vpp_config_output,

> > +    },

> > +    { NULL }

> > +};

> > +

> > +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        = rotation_vaapi_inputs,

> > +    .outputs       = rotation_vaapi_outputs,

> > +    .priv_class    = &rotation_vaapi_class,

> > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };

> >

> How about:

> 

> deg=0 for 0   degree

> deg=90 for 90  degree

> deg=180 for 180 degree

> deg=270 for 270 degree

> 

> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

>   -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=deg=90"

>   -c:v h264_vaapi output.h264

> 

> The rotation is in degrees , not direction. And using the actual degrees instead

> of magic numbers makes it more obvious for the user.



My first version of the patch(https://patchwork.ffmpeg.org/patch/10754/) just like this.

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

And I got comments to add sub-options. the sub-options are clock_0, clock_90, clock_180, clock_270, the command line likes this.

ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
-hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi= clock_270"
-c:v h264_vaapi output.h264


> 

> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Rostislav Pehlivanov Oct. 26, 2018, 1:01 p.m. UTC | #3
On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com> wrote:

>
>
> > -----Original Message-----
> > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
> > sean darcy
> > Sent: Thursday, October 25, 2018 11:51 PM
> > To: ffmpeg-devel@ffmpeg.org
> > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi
> > rotation feature via call Intel iHD driver
> >
> > On 10/25/18 2:52 AM, Zachary Zhou wrote:
> > > It supports clockwise rotation by 0/90/180/270 degrees defined in
> > > va/va_vpp.h, tested following command line on SKL platform
> > >
> > > dir=0 for 0   degree
> > > dir=1 for 90  degree
> > > dir=2 for 180 degree
> > > dir=3 for 270 degree
> > >
> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> > > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"
> > > -c:v h264_vaapi output.h264
> > >
> > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
> > > ---
> > >   configure                     |   3 +
> > >   libavfilter/Makefile          |   1 +
> > >   libavfilter/allfilters.c      |   1 +
> > >   libavfilter/vaapi_vpp.h       |   1 +
> > >   libavfilter/vf_rotate_vaapi.c | 252
> ++++++++++++++++++++++++++++++++++
> > >   5 files changed, 258 insertions(+)
> > >   create mode 100644 libavfilter/vf_rotate_vaapi.c
> > >
> > > diff --git a/configure b/configure
> > > index 85d5dd5962..33aced3d78 100755
> > > --- a/configure
> > > +++ b/configure
> > > @@ -6390,6 +6390,9 @@ if enabled vaapi; then
> > >       fi
> > >
> > >       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)"
> > > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"
> rotation_flags;
> > then
> > > +        disable rotation_vaapi_filter
> > > +    fi
> > >   fi
> > >
> > >   if enabled_all opencl libdrm ; then
> > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile index
> > > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c
> > > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index
> > > 0000000000..34c270e9c7
> > > --- /dev/null
> > > +++ b/libavfilter/vf_rotate_vaapi.c
> > > @@ -0,0 +1,252 @@
> > > +/*
> > > + * This file is part of FFmpeg.
> > > + *
> > > + * FFmpeg 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.
> > > + *
> > > + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> > > +02110-1301 USA  */ #include <string.h>
> > > +
> > > +#include "libavutil/avassert.h"
> > > +#include "libavutil/mem.h"
> > > +#include "libavutil/opt.h"
> > > +#include "libavutil/pixdesc.h"
> > > +
> > > +#include "avfilter.h"
> > > +#include "formats.h"
> > > +#include "internal.h"
> > > +#include "vaapi_vpp.h"
> > > +
> > > +// Rotation angle values
> > > +enum RotationAngle {
> > > +    ROTATION_0   = 0,
> > > +    ROTATION_90  = 1,
> > > +    ROTATION_180 = 2,
> > > +    ROTATION_270 = 3,
> > > +
> > > +    ROTATION_MIN     = ROTATION_0,
> > > +    ROTATION_MAX     = ROTATION_270,
> > > +    ROTATION_DEFAULT = ROTATION_0,
> > > +};
> > > +
> > > +typedef struct RotationVAAPIContext {
> > > +    VAAPIVPPContext vpp_ctx; // must be the first field
> > > +
> > > +    int rotation;        // enable rotation.
> > > +} RotationVAAPIContext;
> > > +
> > > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink, AVFrame
> > > +*input_frame) {
> > > +    AVFilterContext *avctx   = inlink->dst;
> > > +    AVFilterLink *outlink    = avctx->outputs[0];
> > > +    VAAPIVPPContext *vpp_ctx = avctx->priv;
> > > +    AVFrame *output_frame    = NULL;
> > > +    VASurfaceID input_surface, output_surface;
> > > +    VARectangle input_region;
> > > +
> > > +    VAProcPipelineParameterBuffer params;
> > > +    int err;
> > > +
> > > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u
> (%"PRId64").\n",
> > > +           av_get_pix_fmt_name(input_frame->format),
> > > +           input_frame->width, input_frame->height,
> > > + input_frame->pts);
> > > +
> > > +    if (vpp_ctx->va_context == VA_INVALID_ID)
> > > +        return AVERROR(EINVAL);
> > > +
> > > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
> > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
> input.\n",
> > > +           input_surface);
> > > +
> > > +    output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,
> > > +                                       vpp_ctx->output_height);
> > > +    if (!output_frame) {
> > > +        err = AVERROR(ENOMEM);
> > > +        goto fail;
> > > +    }
> > > +
> > > +    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];
> > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
> > output.\n",
> > > +           output_surface);
> > > +    memset(&params, 0, sizeof(params));
> > > +    input_region = (VARectangle) {
> > > +        .x      = 0,
> > > +        .y      = 0,
> > > +        .width  = input_frame->width,
> > > +        .height = input_frame->height,
> > > +    };
> > > +
> > > +    switch (vpp_ctx->rotation_state) {
> > > +    case VA_ROTATION_NONE:
> > > +    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;
> > > +    }
> > > +    params.surface = input_surface;
> > > +    params.surface_region = &input_region;
> > > +    params.surface_color_standard =
> > > +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
> > > +
> > > +    params.output_region = NULL;
> > > +    params.output_background_color = 0xff000000;
> > > +    params.output_color_standard = params.surface_color_standard;
> > > +
> > > +    params.pipeline_flags = 0;
> > > +    params.filter_flags = VA_FRAME_PICTURE;
> > > +
> > > +    err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);
> > > +    if (err < 0)
> > > +        goto fail;
> > > +
> > > +    err = av_frame_copy_props(output_frame, input_frame);
> > > +    if (err < 0)
> > > +        goto fail;
> > > +    av_frame_free(&input_frame);
> > > +
> > > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u
> > (%"PRId64").\n",
> > > +           av_get_pix_fmt_name(output_frame->format),
> > > +           output_frame->width, output_frame->height,
> > > + output_frame->pts);
> > > +
> > > +    return ff_filter_frame(outlink, output_frame);
> > > +
> > > +fail:
> > > +    av_frame_free(&input_frame);
> > > +    av_frame_free(&output_frame);
> > > +    return err;
> > > +}
> > > +
> > > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define FLAGS
> > > +(AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) static
> > const
> > > +AVOption rotation_vaapi_options[] = {
> > > +    { "dir", "set roation direction", ROFFSET(rotation),
> AV_OPT_TYPE_INT,
> > { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
> > > +        { "clock_0",   "rotate clockwise 0 degrees",   0,
> AV_OPT_TYPE_CONST,
> > { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
> > > +        { "clock_90",  "rotate clockwise 90 degrees",  0,
> AV_OPT_TYPE_CONST,
> > { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
> > > +        { "clock_180", "rotate clockwise 180 degrees", 0,
> AV_OPT_TYPE_CONST,
> > { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
> > > +        { "clock_270", "rotate clockwise 270 degrees", 0,
> AV_OPT_TYPE_CONST,
> > { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
> > > +    { NULL },
> > > +};
> > > +
> > > +AVFILTER_DEFINE_CLASS(rotation_vaapi);
> > > +
> > > +static const AVFilterPad rotation_vaapi_inputs[] = {
> > > +    {
> > > +        .name         = "default",
> > > +        .type         = AVMEDIA_TYPE_VIDEO,
> > > +        .filter_frame = &rotation_vaapi_filter_frame,
> > > +        .config_props = &ff_vaapi_vpp_config_input,
> > > +    },
> > > +    { NULL }
> > > +};
> > > +
> > > +static const AVFilterPad rotation_vaapi_outputs[] = {
> > > +    {
> > > +        .name = "default",
> > > +        .type = AVMEDIA_TYPE_VIDEO,
> > > +        .config_props = &ff_vaapi_vpp_config_output,
> > > +    },
> > > +    { NULL }
> > > +};
> > > +
> > > +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        = rotation_vaapi_inputs,
> > > +    .outputs       = rotation_vaapi_outputs,
> > > +    .priv_class    = &rotation_vaapi_class,
> > > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };
> > >
> > How about:
> >
> > deg=0 for 0   degree
> > deg=90 for 90  degree
> > deg=180 for 180 degree
> > deg=270 for 270 degree
> >
> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> >   -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=deg=90"
> >   -c:v h264_vaapi output.h264
> >
> > The rotation is in degrees , not direction. And using the actual degrees
> instead
> > of magic numbers makes it more obvious for the user.
>
>
> My first version of the patch(https://patchwork.ffmpeg.org/patch/10754/)
> just like this.
>
> 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
>
> And I got comments to add sub-options. the sub-options are clock_0,
> clock_90, clock_180, clock_270, the command line likes this.
>
> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi= clock_270"
> -c:v h264_vaapi output.h264
>
>
> >
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Please, call it transpose_vaapi, and make it accept the same options as the
transpose filter we have.
transpose != rotation.
Zachary Zhou Oct. 26, 2018, 3:13 p.m. UTC | #4
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> Rostislav Pehlivanov

> Sent: Friday, October 26, 2018 9:02 PM

> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com> wrote:

> 

> >

> >

> > > -----Original Message-----

> > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> > > Behalf Of sean darcy

> > > Sent: Thursday, October 25, 2018 11:51 PM

> > > To: ffmpeg-devel@ffmpeg.org

> > > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable

> > > vaapi rotation feature via call Intel iHD driver

> > >

> > > On 10/25/18 2:52 AM, Zachary Zhou wrote:

> > > > It supports clockwise rotation by 0/90/180/270 degrees defined in

> > > > va/va_vpp.h, tested following command line on SKL platform

> > > >

> > > > dir=0 for 0   degree

> > > > dir=1 for 90  degree

> > > > dir=2 for 180 degree

> > > > dir=3 for 270 degree

> > > >

> > > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > > > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"

> > > > -c:v h264_vaapi output.h264

> > > >

> > > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> > > > ---

> > > >   configure                     |   3 +

> > > >   libavfilter/Makefile          |   1 +

> > > >   libavfilter/allfilters.c      |   1 +

> > > >   libavfilter/vaapi_vpp.h       |   1 +

> > > >   libavfilter/vf_rotate_vaapi.c | 252

> > ++++++++++++++++++++++++++++++++++

> > > >   5 files changed, 258 insertions(+)

> > > >   create mode 100644 libavfilter/vf_rotate_vaapi.c

> > > >

> > > > diff --git a/configure b/configure index 85d5dd5962..33aced3d78

> > > > 100755

> > > > --- a/configure

> > > > +++ b/configure

> > > > @@ -6390,6 +6390,9 @@ if enabled vaapi; then

> > > >       fi

> > > >

> > > >       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0,

> 0)"

> > > > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"

> > rotation_flags;

> > > then

> > > > +        disable rotation_vaapi_filter

> > > > +    fi

> > > >   fi

> > > >

> > > >   if enabled_all opencl libdrm ; then diff --git

> > > > a/libavfilter/Makefile b/libavfilter/Makefile index

> > > > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c

> > > > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index

> > > > 0000000000..34c270e9c7

> > > > --- /dev/null

> > > > +++ b/libavfilter/vf_rotate_vaapi.c

> > > > @@ -0,0 +1,252 @@

> > > > +/*

> > > > + * This file is part of FFmpeg.

> > > > + *

> > > > + * FFmpeg 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.

> > > > + *

> > > > + * FFmpeg 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 FFmpeg; if not, write to the Free Software

> > > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA

> > > > +02110-1301 USA  */ #include <string.h>

> > > > +

> > > > +#include "libavutil/avassert.h"

> > > > +#include "libavutil/mem.h"

> > > > +#include "libavutil/opt.h"

> > > > +#include "libavutil/pixdesc.h"

> > > > +

> > > > +#include "avfilter.h"

> > > > +#include "formats.h"

> > > > +#include "internal.h"

> > > > +#include "vaapi_vpp.h"

> > > > +

> > > > +// Rotation angle values

> > > > +enum RotationAngle {

> > > > +    ROTATION_0   = 0,

> > > > +    ROTATION_90  = 1,

> > > > +    ROTATION_180 = 2,

> > > > +    ROTATION_270 = 3,

> > > > +

> > > > +    ROTATION_MIN     = ROTATION_0,

> > > > +    ROTATION_MAX     = ROTATION_270,

> > > > +    ROTATION_DEFAULT = ROTATION_0, };

> > > > +

> > > > +typedef struct RotationVAAPIContext {

> > > > +    VAAPIVPPContext vpp_ctx; // must be the first field

> > > > +

> > > > +    int rotation;        // enable rotation.

> > > > +} RotationVAAPIContext;

> > > > +

> > > > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,

> > > > +AVFrame

> > > > +*input_frame) {

> > > > +    AVFilterContext *avctx   = inlink->dst;

> > > > +    AVFilterLink *outlink    = avctx->outputs[0];

> > > > +    VAAPIVPPContext *vpp_ctx = avctx->priv;

> > > > +    AVFrame *output_frame    = NULL;

> > > > +    VASurfaceID input_surface, output_surface;

> > > > +    VARectangle input_region;

> > > > +

> > > > +    VAProcPipelineParameterBuffer params;

> > > > +    int err;

> > > > +

> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u

> > (%"PRId64").\n",

> > > > +           av_get_pix_fmt_name(input_frame->format),

> > > > +           input_frame->width, input_frame->height,

> > > > + input_frame->pts);

> > > > +

> > > > +    if (vpp_ctx->va_context == VA_INVALID_ID)

> > > > +        return AVERROR(EINVAL);

> > > > +

> > > > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];

> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp

> > input.\n",

> > > > +           input_surface);

> > > > +

> > > > +    output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,

> > > > +                                       vpp_ctx->output_height);

> > > > +    if (!output_frame) {

> > > > +        err = AVERROR(ENOMEM);

> > > > +        goto fail;

> > > > +    }

> > > > +

> > > > +    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];

> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp

> > > output.\n",

> > > > +           output_surface);

> > > > +    memset(&params, 0, sizeof(params));

> > > > +    input_region = (VARectangle) {

> > > > +        .x      = 0,

> > > > +        .y      = 0,

> > > > +        .width  = input_frame->width,

> > > > +        .height = input_frame->height,

> > > > +    };

> > > > +

> > > > +    switch (vpp_ctx->rotation_state) {

> > > > +    case VA_ROTATION_NONE:

> > > > +    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;

> > > > +    }

> > > > +    params.surface = input_surface;

> > > > +    params.surface_region = &input_region;

> > > > +    params.surface_color_standard =

> > > > +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);

> > > > +

> > > > +    params.output_region = NULL;

> > > > +    params.output_background_color = 0xff000000;

> > > > +    params.output_color_standard = params.surface_color_standard;

> > > > +

> > > > +    params.pipeline_flags = 0;

> > > > +    params.filter_flags = VA_FRAME_PICTURE;

> > > > +

> > > > +    err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);

> > > > +    if (err < 0)

> > > > +        goto fail;

> > > > +

> > > > +    err = av_frame_copy_props(output_frame, input_frame);

> > > > +    if (err < 0)

> > > > +        goto fail;

> > > > +    av_frame_free(&input_frame);

> > > > +

> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u

> > > (%"PRId64").\n",

> > > > +           av_get_pix_fmt_name(output_frame->format),

> > > > +           output_frame->width, output_frame->height,

> > > > + output_frame->pts);

> > > > +

> > > > +    return ff_filter_frame(outlink, output_frame);

> > > > +

> > > > +fail:

> > > > +    av_frame_free(&input_frame);

> > > > +    av_frame_free(&output_frame);

> > > > +    return err;

> > > > +}

> > > > +

> > > > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define

> > > > +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |

> AV_OPT_FLAG_FILTERING_PARAM)

> > > > +static

> > > const

> > > > +AVOption rotation_vaapi_options[] = {

> > > > +    { "dir", "set roation direction", ROFFSET(rotation),

> > AV_OPT_TYPE_INT,

> > > { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },

> > > > +        { "clock_0",   "rotate clockwise 0 degrees",   0,

> > AV_OPT_TYPE_CONST,

> > > { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },

> > > > +        { "clock_90",  "rotate clockwise 90 degrees",  0,

> > AV_OPT_TYPE_CONST,

> > > { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },

> > > > +        { "clock_180", "rotate clockwise 180 degrees", 0,

> > AV_OPT_TYPE_CONST,

> > > { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },

> > > > +        { "clock_270", "rotate clockwise 270 degrees", 0,

> > AV_OPT_TYPE_CONST,

> > > { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },

> > > > +    { NULL },

> > > > +};

> > > > +

> > > > +AVFILTER_DEFINE_CLASS(rotation_vaapi);

> > > > +

> > > > +static const AVFilterPad rotation_vaapi_inputs[] = {

> > > > +    {

> > > > +        .name         = "default",

> > > > +        .type         = AVMEDIA_TYPE_VIDEO,

> > > > +        .filter_frame = &rotation_vaapi_filter_frame,

> > > > +        .config_props = &ff_vaapi_vpp_config_input,

> > > > +    },

> > > > +    { NULL }

> > > > +};

> > > > +

> > > > +static const AVFilterPad rotation_vaapi_outputs[] = {

> > > > +    {

> > > > +        .name = "default",

> > > > +        .type = AVMEDIA_TYPE_VIDEO,

> > > > +        .config_props = &ff_vaapi_vpp_config_output,

> > > > +    },

> > > > +    { NULL }

> > > > +};

> > > > +

> > > > +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        = rotation_vaapi_inputs,

> > > > +    .outputs       = rotation_vaapi_outputs,

> > > > +    .priv_class    = &rotation_vaapi_class,

> > > > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };

> > > >

> > > How about:

> > >

> > > deg=0 for 0   degree

> > > deg=90 for 90  degree

> > > deg=180 for 180 degree

> > > deg=270 for 270 degree

> > >

> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > >   -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=deg=90"

> > >   -c:v h264_vaapi output.h264

> > >

> > > The rotation is in degrees , not direction. And using the actual

> > > degrees

> > instead

> > > of magic numbers makes it more obvious for the user.

> >

> >

> > My first version of the

> > patch(https://patchwork.ffmpeg.org/patch/10754/)

> > just like this.

> >

> > 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

> >

> > And I got comments to add sub-options. the sub-options are clock_0,

> > clock_90, clock_180, clock_270, the command line likes this.

> >

> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi= clock_270"

> > -c:v h264_vaapi output.h264

> >

> >

> > >

> > > _______________________________________________

> > > ffmpeg-devel mailing list

> > > ffmpeg-devel@ffmpeg.org

> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> > _______________________________________________

> > ffmpeg-devel mailing list

> > ffmpeg-devel@ffmpeg.org

> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> 

> 

> Please, call it transpose_vaapi, and make it accept the same options as the

> transpose filter we have.

> transpose != rotation.


Actually, I want to change back to "rotation_vaapi=angle=90", I agree  "sean darcy <seandarcy2@gmail.com>" comments, and I think this filter is different with transpose.

1. This filter no vflip/hflip support, but transpose has vflip/hflip, in VAAPI another feature Mirroring, hflip/vflip are supported by using VAProcPipelineParameterBuffer::mirror_state. I was planning enable VAAPI mirroring in another patch.
2. Currently VAAPI rotation only support 0/90/180/270 degrees, not sure VAAPI will add more degrees in future, so I want to keep the name rotation_vaapi to align VAAPI. 
3. I don't want to put VAAPI rotation and VAAPI mirroring together to enable a similar but not same with transpose currently, Because the same options and the different functions may call people confuse.

My first version patch has already included  the discussion regarding the filter name and options. https://patchwork.ffmpeg.org/patch/10754/


> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Paul B Mahol Oct. 26, 2018, 3:18 p.m. UTC | #5
On 10/26/18, Zhou, Zachary <zachary.zhou@intel.com> wrote:
>
>
>> -----Original Message-----
>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
>> Rostislav Pehlivanov
>> Sent: Friday, October 26, 2018 9:02 PM
>> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
>> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi
>> rotation feature via call Intel iHD driver
>>
>> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com>
>> wrote:
>>
>> >
>> >
>> > > -----Original Message-----
>> > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On
>> > > Behalf Of sean darcy
>> > > Sent: Thursday, October 25, 2018 11:51 PM
>> > > To: ffmpeg-devel@ffmpeg.org
>> > > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable
>> > > vaapi rotation feature via call Intel iHD driver
>> > >
>> > > On 10/25/18 2:52 AM, Zachary Zhou wrote:
>> > > > It supports clockwise rotation by 0/90/180/270 degrees defined in
>> > > > va/va_vpp.h, tested following command line on SKL platform
>> > > >
>> > > > dir=0 for 0   degree
>> > > > dir=1 for 90  degree
>> > > > dir=2 for 180 degree
>> > > > dir=3 for 270 degree
>> > > >
>> > > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>> > > > -hwaccel_output_format vaapi -i input.264 -vf
>> > > > "rotation_vaapi=dir=1"
>> > > > -c:v h264_vaapi output.h264
>> > > >
>> > > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
>> > > > ---
>> > > >   configure                     |   3 +
>> > > >   libavfilter/Makefile          |   1 +
>> > > >   libavfilter/allfilters.c      |   1 +
>> > > >   libavfilter/vaapi_vpp.h       |   1 +
>> > > >   libavfilter/vf_rotate_vaapi.c | 252
>> > ++++++++++++++++++++++++++++++++++
>> > > >   5 files changed, 258 insertions(+)
>> > > >   create mode 100644 libavfilter/vf_rotate_vaapi.c
>> > > >
>> > > > diff --git a/configure b/configure index 85d5dd5962..33aced3d78
>> > > > 100755
>> > > > --- a/configure
>> > > > +++ b/configure
>> > > > @@ -6390,6 +6390,9 @@ if enabled vaapi; then
>> > > >       fi
>> > > >
>> > > >       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0,
>> 0)"
>> > > > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"
>> > rotation_flags;
>> > > then
>> > > > +        disable rotation_vaapi_filter
>> > > > +    fi
>> > > >   fi
>> > > >
>> > > >   if enabled_all opencl libdrm ; then diff --git
>> > > > a/libavfilter/Makefile b/libavfilter/Makefile index
>> > > > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c
>> > > > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index
>> > > > 0000000000..34c270e9c7
>> > > > --- /dev/null
>> > > > +++ b/libavfilter/vf_rotate_vaapi.c
>> > > > @@ -0,0 +1,252 @@
>> > > > +/*
>> > > > + * This file is part of FFmpeg.
>> > > > + *
>> > > > + * FFmpeg 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.
>> > > > + *
>> > > > + * FFmpeg 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 FFmpeg; if not, write to the Free Software
>> > > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> > > > +02110-1301 USA  */ #include <string.h>
>> > > > +
>> > > > +#include "libavutil/avassert.h"
>> > > > +#include "libavutil/mem.h"
>> > > > +#include "libavutil/opt.h"
>> > > > +#include "libavutil/pixdesc.h"
>> > > > +
>> > > > +#include "avfilter.h"
>> > > > +#include "formats.h"
>> > > > +#include "internal.h"
>> > > > +#include "vaapi_vpp.h"
>> > > > +
>> > > > +// Rotation angle values
>> > > > +enum RotationAngle {
>> > > > +    ROTATION_0   = 0,
>> > > > +    ROTATION_90  = 1,
>> > > > +    ROTATION_180 = 2,
>> > > > +    ROTATION_270 = 3,
>> > > > +
>> > > > +    ROTATION_MIN     = ROTATION_0,
>> > > > +    ROTATION_MAX     = ROTATION_270,
>> > > > +    ROTATION_DEFAULT = ROTATION_0, };
>> > > > +
>> > > > +typedef struct RotationVAAPIContext {
>> > > > +    VAAPIVPPContext vpp_ctx; // must be the first field
>> > > > +
>> > > > +    int rotation;        // enable rotation.
>> > > > +} RotationVAAPIContext;
>> > > > +
>> > > > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,
>> > > > +AVFrame
>> > > > +*input_frame) {
>> > > > +    AVFilterContext *avctx   = inlink->dst;
>> > > > +    AVFilterLink *outlink    = avctx->outputs[0];
>> > > > +    VAAPIVPPContext *vpp_ctx = avctx->priv;
>> > > > +    AVFrame *output_frame    = NULL;
>> > > > +    VASurfaceID input_surface, output_surface;
>> > > > +    VARectangle input_region;
>> > > > +
>> > > > +    VAProcPipelineParameterBuffer params;
>> > > > +    int err;
>> > > > +
>> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u
>> > (%"PRId64").\n",
>> > > > +           av_get_pix_fmt_name(input_frame->format),
>> > > > +           input_frame->width, input_frame->height,
>> > > > + input_frame->pts);
>> > > > +
>> > > > +    if (vpp_ctx->va_context == VA_INVALID_ID)
>> > > > +        return AVERROR(EINVAL);
>> > > > +
>> > > > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
>> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
>> > input.\n",
>> > > > +           input_surface);
>> > > > +
>> > > > +    output_frame = ff_get_video_buffer(outlink,
>> > > > vpp_ctx->output_width,
>> > > > +                                       vpp_ctx->output_height);
>> > > > +    if (!output_frame) {
>> > > > +        err = AVERROR(ENOMEM);
>> > > > +        goto fail;
>> > > > +    }
>> > > > +
>> > > > +    output_surface =
>> > > > (VASurfaceID)(uintptr_t)output_frame->data[3];
>> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
>> > > output.\n",
>> > > > +           output_surface);
>> > > > +    memset(&params, 0, sizeof(params));
>> > > > +    input_region = (VARectangle) {
>> > > > +        .x      = 0,
>> > > > +        .y      = 0,
>> > > > +        .width  = input_frame->width,
>> > > > +        .height = input_frame->height,
>> > > > +    };
>> > > > +
>> > > > +    switch (vpp_ctx->rotation_state) {
>> > > > +    case VA_ROTATION_NONE:
>> > > > +    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;
>> > > > +    }
>> > > > +    params.surface = input_surface;
>> > > > +    params.surface_region = &input_region;
>> > > > +    params.surface_color_standard =
>> > > > +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
>> > > > +
>> > > > +    params.output_region = NULL;
>> > > > +    params.output_background_color = 0xff000000;
>> > > > +    params.output_color_standard = params.surface_color_standard;
>> > > > +
>> > > > +    params.pipeline_flags = 0;
>> > > > +    params.filter_flags = VA_FRAME_PICTURE;
>> > > > +
>> > > > +    err = ff_vaapi_vpp_render_picture(avctx, &params,
>> > > > output_surface);
>> > > > +    if (err < 0)
>> > > > +        goto fail;
>> > > > +
>> > > > +    err = av_frame_copy_props(output_frame, input_frame);
>> > > > +    if (err < 0)
>> > > > +        goto fail;
>> > > > +    av_frame_free(&input_frame);
>> > > > +
>> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u
>> > > (%"PRId64").\n",
>> > > > +           av_get_pix_fmt_name(output_frame->format),
>> > > > +           output_frame->width, output_frame->height,
>> > > > + output_frame->pts);
>> > > > +
>> > > > +    return ff_filter_frame(outlink, output_frame);
>> > > > +
>> > > > +fail:
>> > > > +    av_frame_free(&input_frame);
>> > > > +    av_frame_free(&output_frame);
>> > > > +    return err;
>> > > > +}
>> > > > +
>> > > > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define
>> > > > +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |
>> AV_OPT_FLAG_FILTERING_PARAM)
>> > > > +static
>> > > const
>> > > > +AVOption rotation_vaapi_options[] = {
>> > > > +    { "dir", "set roation direction", ROFFSET(rotation),
>> > AV_OPT_TYPE_INT,
>> > > { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
>> > > > +        { "clock_0",   "rotate clockwise 0 degrees",   0,
>> > AV_OPT_TYPE_CONST,
>> > > { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
>> > > > +        { "clock_90",  "rotate clockwise 90 degrees",  0,
>> > AV_OPT_TYPE_CONST,
>> > > { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
>> > > > +        { "clock_180", "rotate clockwise 180 degrees", 0,
>> > AV_OPT_TYPE_CONST,
>> > > { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
>> > > > +        { "clock_270", "rotate clockwise 270 degrees", 0,
>> > AV_OPT_TYPE_CONST,
>> > > { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
>> > > > +    { NULL },
>> > > > +};
>> > > > +
>> > > > +AVFILTER_DEFINE_CLASS(rotation_vaapi);
>> > > > +
>> > > > +static const AVFilterPad rotation_vaapi_inputs[] = {
>> > > > +    {
>> > > > +        .name         = "default",
>> > > > +        .type         = AVMEDIA_TYPE_VIDEO,
>> > > > +        .filter_frame = &rotation_vaapi_filter_frame,
>> > > > +        .config_props = &ff_vaapi_vpp_config_input,
>> > > > +    },
>> > > > +    { NULL }
>> > > > +};
>> > > > +
>> > > > +static const AVFilterPad rotation_vaapi_outputs[] = {
>> > > > +    {
>> > > > +        .name = "default",
>> > > > +        .type = AVMEDIA_TYPE_VIDEO,
>> > > > +        .config_props = &ff_vaapi_vpp_config_output,
>> > > > +    },
>> > > > +    { NULL }
>> > > > +};
>> > > > +
>> > > > +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        = rotation_vaapi_inputs,
>> > > > +    .outputs       = rotation_vaapi_outputs,
>> > > > +    .priv_class    = &rotation_vaapi_class,
>> > > > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };
>> > > >
>> > > How about:
>> > >
>> > > deg=0 for 0   degree
>> > > deg=90 for 90  degree
>> > > deg=180 for 180 degree
>> > > deg=270 for 270 degree
>> > >
>> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>> > >   -hwaccel_output_format vaapi -i input.264 -vf
>> > > "rotation_vaapi=deg=90"
>> > >   -c:v h264_vaapi output.h264
>> > >
>> > > The rotation is in degrees , not direction. And using the actual
>> > > degrees
>> > instead
>> > > of magic numbers makes it more obvious for the user.
>> >
>> >
>> > My first version of the
>> > patch(https://patchwork.ffmpeg.org/patch/10754/)
>> > just like this.
>> >
>> > 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
>> >
>> > And I got comments to add sub-options. the sub-options are clock_0,
>> > clock_90, clock_180, clock_270, the command line likes this.
>> >
>> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=
>> > clock_270"
>> > -c:v h264_vaapi output.h264
>> >
>> >
>> > >
>> > > _______________________________________________
>> > > ffmpeg-devel mailing list
>> > > ffmpeg-devel@ffmpeg.org
>> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>> > _______________________________________________
>> > ffmpeg-devel mailing list
>> > ffmpeg-devel@ffmpeg.org
>> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>>
>> Please, call it transpose_vaapi, and make it accept the same options as
>> the
>> transpose filter we have.
>> transpose != rotation.
>
> Actually, I want to change back to "rotation_vaapi=angle=90", I agree  "sean
> darcy <seandarcy2@gmail.com>" comments, and I think this filter is different
> with transpose.
>
> 1. This filter no vflip/hflip support, but transpose has vflip/hflip, in
> VAAPI another feature Mirroring, hflip/vflip are supported by using
> VAProcPipelineParameterBuffer::mirror_state. I was planning enable VAAPI
> mirroring in another patch.
> 2. Currently VAAPI rotation only support 0/90/180/270 degrees, not sure
> VAAPI will add more degrees in future, so I want to keep the name
> rotation_vaapi to align VAAPI.
> 3. I don't want to put VAAPI rotation and VAAPI mirroring together to enable
> a similar but not same with transpose currently, Because the same options
> and the different functions may call people confuse.
>
> My first version patch has already included  the discussion regarding the
> filter name and options. https://patchwork.ffmpeg.org/patch/10754/
>

Why we need yet another rotation filter that does not do rotation but
does rotation in 4 fixed ways?
Seriously? This needs some serious quality control.
sean darcy Oct. 26, 2018, 7:07 p.m. UTC | #6
On 10/26/18 11:18 AM, Paul B Mahol wrote:
> On 10/26/18, Zhou, Zachary <zachary.zhou@intel.com> wrote:
>>
>>
>>> -----Original Message-----
>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
>>> Rostislav Pehlivanov
>>> Sent: Friday, October 26, 2018 9:02 PM
>>> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
>>> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi
>>> rotation feature via call Intel iHD driver
>>>
>>> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com>
>>> wrote:
>>>
>>>>
>>>>
>>>>> -----Original Message-----
>>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On
>>>>> Behalf Of sean darcy
>>>>> Sent: Thursday, October 25, 2018 11:51 PM
>>>>> To: ffmpeg-devel@ffmpeg.org
>>>>> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable
>>>>> vaapi rotation feature via call Intel iHD driver
>>>>>
>>>>> On 10/25/18 2:52 AM, Zachary Zhou wrote:
>>>>>> It supports clockwise rotation by 0/90/180/270 degrees defined in
>>>>>> va/va_vpp.h, tested following command line on SKL platform
>>>>>>
>>>>>> dir=0 for 0   degree
>>>>>> dir=1 for 90  degree
>>>>>> dir=2 for 180 degree
>>>>>> dir=3 for 270 degree
>>>>>>
>>>>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>>>>>> -hwaccel_output_format vaapi -i input.264 -vf
>>>>>> "rotation_vaapi=dir=1"
>>>>>> -c:v h264_vaapi output.h264
>>>>>>
>>>>>> Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
>>>>>> ---
>>>>>>    configure                     |   3 +
>>>>>>    libavfilter/Makefile          |   1 +
>>>>>>    libavfilter/allfilters.c      |   1 +
>>>>>>    libavfilter/vaapi_vpp.h       |   1 +
>>>>>>    libavfilter/vf_rotate_vaapi.c | 252
>>>> ++++++++++++++++++++++++++++++++++
>>>>>>    5 files changed, 258 insertions(+)
>>>>>>    create mode 100644 libavfilter/vf_rotate_vaapi.c
>>>>>>
>>>>>> diff --git a/configure b/configure index 85d5dd5962..33aced3d78
>>>>>> 100755
>>>>>> --- a/configure
>>>>>> +++ b/configure
>>>>>> @@ -6390,6 +6390,9 @@ if enabled vaapi; then
>>>>>>        fi
>>>>>>
>>>>>>        check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0,
>>> 0)"
>>>>>> +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"
>>>> rotation_flags;
>>>>> then
>>>>>> +        disable rotation_vaapi_filter
>>>>>> +    fi
>>>>>>    fi
>>>>>>
>>>>>>    if enabled_all opencl libdrm ; then diff --git
>>>>>> a/libavfilter/Makefile b/libavfilter/Makefile index
>>>>>> 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c
>>>>>> b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index
>>>>>> 0000000000..34c270e9c7
>>>>>> --- /dev/null
>>>>>> +++ b/libavfilter/vf_rotate_vaapi.c
>>>>>> @@ -0,0 +1,252 @@
>>>>>> +/*
>>>>>> + * This file is part of FFmpeg.
>>>>>> + *
>>>>>> + * FFmpeg 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.
>>>>>> + *
>>>>>> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
>>>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>>>>>> +02110-1301 USA  */ #include <string.h>
>>>>>> +
>>>>>> +#include "libavutil/avassert.h"
>>>>>> +#include "libavutil/mem.h"
>>>>>> +#include "libavutil/opt.h"
>>>>>> +#include "libavutil/pixdesc.h"
>>>>>> +
>>>>>> +#include "avfilter.h"
>>>>>> +#include "formats.h"
>>>>>> +#include "internal.h"
>>>>>> +#include "vaapi_vpp.h"
>>>>>> +
>>>>>> +// Rotation angle values
>>>>>> +enum RotationAngle {
>>>>>> +    ROTATION_0   = 0,
>>>>>> +    ROTATION_90  = 1,
>>>>>> +    ROTATION_180 = 2,
>>>>>> +    ROTATION_270 = 3,
>>>>>> +
>>>>>> +    ROTATION_MIN     = ROTATION_0,
>>>>>> +    ROTATION_MAX     = ROTATION_270,
>>>>>> +    ROTATION_DEFAULT = ROTATION_0, };
>>>>>> +
>>>>>> +typedef struct RotationVAAPIContext {
>>>>>> +    VAAPIVPPContext vpp_ctx; // must be the first field
>>>>>> +
>>>>>> +    int rotation;        // enable rotation.
>>>>>> +} RotationVAAPIContext;
>>>>>> +
>>>>>> +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,
>>>>>> +AVFrame
>>>>>> +*input_frame) {
>>>>>> +    AVFilterContext *avctx   = inlink->dst;
>>>>>> +    AVFilterLink *outlink    = avctx->outputs[0];
>>>>>> +    VAAPIVPPContext *vpp_ctx = avctx->priv;
>>>>>> +    AVFrame *output_frame    = NULL;
>>>>>> +    VASurfaceID input_surface, output_surface;
>>>>>> +    VARectangle input_region;
>>>>>> +
>>>>>> +    VAProcPipelineParameterBuffer params;
>>>>>> +    int err;
>>>>>> +
>>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u
>>>> (%"PRId64").\n",
>>>>>> +           av_get_pix_fmt_name(input_frame->format),
>>>>>> +           input_frame->width, input_frame->height,
>>>>>> + input_frame->pts);
>>>>>> +
>>>>>> +    if (vpp_ctx->va_context == VA_INVALID_ID)
>>>>>> +        return AVERROR(EINVAL);
>>>>>> +
>>>>>> +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
>>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
>>>> input.\n",
>>>>>> +           input_surface);
>>>>>> +
>>>>>> +    output_frame = ff_get_video_buffer(outlink,
>>>>>> vpp_ctx->output_width,
>>>>>> +                                       vpp_ctx->output_height);
>>>>>> +    if (!output_frame) {
>>>>>> +        err = AVERROR(ENOMEM);
>>>>>> +        goto fail;
>>>>>> +    }
>>>>>> +
>>>>>> +    output_surface =
>>>>>> (VASurfaceID)(uintptr_t)output_frame->data[3];
>>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
>>>>> output.\n",
>>>>>> +           output_surface);
>>>>>> +    memset(&params, 0, sizeof(params));
>>>>>> +    input_region = (VARectangle) {
>>>>>> +        .x      = 0,
>>>>>> +        .y      = 0,
>>>>>> +        .width  = input_frame->width,
>>>>>> +        .height = input_frame->height,
>>>>>> +    };
>>>>>> +
>>>>>> +    switch (vpp_ctx->rotation_state) {
>>>>>> +    case VA_ROTATION_NONE:
>>>>>> +    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;
>>>>>> +    }
>>>>>> +    params.surface = input_surface;
>>>>>> +    params.surface_region = &input_region;
>>>>>> +    params.surface_color_standard =
>>>>>> +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
>>>>>> +
>>>>>> +    params.output_region = NULL;
>>>>>> +    params.output_background_color = 0xff000000;
>>>>>> +    params.output_color_standard = params.surface_color_standard;
>>>>>> +
>>>>>> +    params.pipeline_flags = 0;
>>>>>> +    params.filter_flags = VA_FRAME_PICTURE;
>>>>>> +
>>>>>> +    err = ff_vaapi_vpp_render_picture(avctx, &params,
>>>>>> output_surface);
>>>>>> +    if (err < 0)
>>>>>> +        goto fail;
>>>>>> +
>>>>>> +    err = av_frame_copy_props(output_frame, input_frame);
>>>>>> +    if (err < 0)
>>>>>> +        goto fail;
>>>>>> +    av_frame_free(&input_frame);
>>>>>> +
>>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u
>>>>> (%"PRId64").\n",
>>>>>> +           av_get_pix_fmt_name(output_frame->format),
>>>>>> +           output_frame->width, output_frame->height,
>>>>>> + output_frame->pts);
>>>>>> +
>>>>>> +    return ff_filter_frame(outlink, output_frame);
>>>>>> +
>>>>>> +fail:
>>>>>> +    av_frame_free(&input_frame);
>>>>>> +    av_frame_free(&output_frame);
>>>>>> +    return err;
>>>>>> +}
>>>>>> +
>>>>>> +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define
>>>>>> +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |
>>> AV_OPT_FLAG_FILTERING_PARAM)
>>>>>> +static
>>>>> const
>>>>>> +AVOption rotation_vaapi_options[] = {
>>>>>> +    { "dir", "set roation direction", ROFFSET(rotation),
>>>> AV_OPT_TYPE_INT,
>>>>> { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
>>>>>> +        { "clock_0",   "rotate clockwise 0 degrees",   0,
>>>> AV_OPT_TYPE_CONST,
>>>>> { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
>>>>>> +        { "clock_90",  "rotate clockwise 90 degrees",  0,
>>>> AV_OPT_TYPE_CONST,
>>>>> { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
>>>>>> +        { "clock_180", "rotate clockwise 180 degrees", 0,
>>>> AV_OPT_TYPE_CONST,
>>>>> { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
>>>>>> +        { "clock_270", "rotate clockwise 270 degrees", 0,
>>>> AV_OPT_TYPE_CONST,
>>>>> { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
>>>>>> +    { NULL },
>>>>>> +};
>>>>>> +
>>>>>> +AVFILTER_DEFINE_CLASS(rotation_vaapi);
>>>>>> +
>>>>>> +static const AVFilterPad rotation_vaapi_inputs[] = {
>>>>>> +    {
>>>>>> +        .name         = "default",
>>>>>> +        .type         = AVMEDIA_TYPE_VIDEO,
>>>>>> +        .filter_frame = &rotation_vaapi_filter_frame,
>>>>>> +        .config_props = &ff_vaapi_vpp_config_input,
>>>>>> +    },
>>>>>> +    { NULL }
>>>>>> +};
>>>>>> +
>>>>>> +static const AVFilterPad rotation_vaapi_outputs[] = {
>>>>>> +    {
>>>>>> +        .name = "default",
>>>>>> +        .type = AVMEDIA_TYPE_VIDEO,
>>>>>> +        .config_props = &ff_vaapi_vpp_config_output,
>>>>>> +    },
>>>>>> +    { NULL }
>>>>>> +};
>>>>>> +
>>>>>> +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        = rotation_vaapi_inputs,
>>>>>> +    .outputs       = rotation_vaapi_outputs,
>>>>>> +    .priv_class    = &rotation_vaapi_class,
>>>>>> +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };
>>>>>>
>>>>> How about:
>>>>>
>>>>> deg=0 for 0   degree
>>>>> deg=90 for 90  degree
>>>>> deg=180 for 180 degree
>>>>> deg=270 for 270 degree
>>>>>
>>>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>>>>>    -hwaccel_output_format vaapi -i input.264 -vf
>>>>> "rotation_vaapi=deg=90"
>>>>>    -c:v h264_vaapi output.h264
>>>>>
>>>>> The rotation is in degrees , not direction. And using the actual
>>>>> degrees
>>>> instead
>>>>> of magic numbers makes it more obvious for the user.
>>>>
>>>>
>>>> My first version of the
>>>> patch(https://patchwork.ffmpeg.org/patch/10754/)
>>>> just like this.
>>>>
>>>> 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
>>>>
>>>> And I got comments to add sub-options. the sub-options are clock_0,
>>>> clock_90, clock_180, clock_270, the command line likes this.
>>>>
>>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
>>>> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=
>>>> clock_270"
>>>> -c:v h264_vaapi output.h264
>>>>
>>>>
>>>>>
>>>>> _______________________________________________
>>>>> ffmpeg-devel mailing list
>>>>> ffmpeg-devel@ffmpeg.org
>>>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>> _______________________________________________
>>>> ffmpeg-devel mailing list
>>>> ffmpeg-devel@ffmpeg.org
>>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>>>
>>> Please, call it transpose_vaapi, and make it accept the same options as
>>> the
>>> transpose filter we have.
>>> transpose != rotation.
>>
>> Actually, I want to change back to "rotation_vaapi=angle=90", I agree  "sean
>> darcy <seandarcy2@gmail.com>" comments, and I think this filter is different
>> with transpose.
>>
>> 1. This filter no vflip/hflip support, but transpose has vflip/hflip, in
>> VAAPI another feature Mirroring, hflip/vflip are supported by using
>> VAProcPipelineParameterBuffer::mirror_state. I was planning enable VAAPI
>> mirroring in another patch.
>> 2. Currently VAAPI rotation only support 0/90/180/270 degrees, not sure
>> VAAPI will add more degrees in future, so I want to keep the name
>> rotation_vaapi to align VAAPI.
>> 3. I don't want to put VAAPI rotation and VAAPI mirroring together to enable
>> a similar but not same with transpose currently, Because the same options
>> and the different functions may call people confuse.
>>
>> My first version patch has already included  the discussion regarding the
>> filter name and options. https://patchwork.ffmpeg.org/patch/10754/
>>
> 
> Why we need yet another rotation filter that does not do rotation but
> does rotation in 4 fixed ways?
> Seriously? This needs some serious quality control.
> _______________________________________________

Not sure I understand this. I think Zachary is saying:

Right now vaapi only does 0,90,180,270 rotations. It may do other 
rotations in the future. It would be straightforward to then allow 45 
degrees: rotation_vaapi=angle=45 . If we use the transpose option set, 
that would be much more awkward.

Or am I missing your point ?
Michael Niedermayer Oct. 26, 2018, 9:15 p.m. UTC | #7
On Thu, Oct 25, 2018 at 02:52:01PM +0800, Zachary Zhou wrote:
> It supports clockwise rotation by 0/90/180/270 degrees defined in
> va/va_vpp.h, tested following command line on SKL platform
> 
> dir=0 for 0   degree
> dir=1 for 90  degree
> dir=2 for 180 degree
> dir=3 for 270 degree
> 
> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"
> -c:v h264_vaapi output.h264
> 
> Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
> ---
>  configure                     |   3 +
>  libavfilter/Makefile          |   1 +
>  libavfilter/allfilters.c      |   1 +
>  libavfilter/vaapi_vpp.h       |   1 +
>  libavfilter/vf_rotate_vaapi.c | 252 ++++++++++++++++++++++++++++++++++
>  5 files changed, 258 insertions(+)
>  create mode 100644 libavfilter/vf_rotate_vaapi.c

still fails to build on 32bit x86

src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_build_filter_params’:
src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’ has no member named ‘rotation_flags’
     if (!pipeline_caps.rotation_flags) {
                       ^
src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’ has no member named ‘rotation_flags’
     support_flag = pipeline_caps.rotation_flags &
                                 ^
src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:
src/libavfilter/vf_rotate_vaapi.c:152:15: error: ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’
         params.rotation_state = vpp_ctx->rotation_state;
               ^
make: *** [libavfilter/vf_rotate_vaapi.o] Error 1
make: *** Waiting for unfinished jobs....

grep VAAPI ffbuild/config.mak 
!HAVE_VAAPI_DRM=yes
!HAVE_VAAPI_X11=yes
!HAVE_OPENCL_VAAPI_BEIGNET=yes
!HAVE_OPENCL_VAAPI_INTEL_MEDIA=yes
!CONFIG_VAAPI_ENCODE_EXAMPLE=yes
!CONFIG_VAAPI_TRANSCODE_EXAMPLE=yes
!CONFIG_VAAPI=yes
!CONFIG_VAAPI_1=yes
!CONFIG_VAAPI_ENCODE=yes
!CONFIG_H264_VAAPI_ENCODER=yes
!CONFIG_HEVC_VAAPI_ENCODER=yes
!CONFIG_MJPEG_VAAPI_ENCODER=yes
!CONFIG_MPEG2_VAAPI_ENCODER=yes
!CONFIG_VP8_VAAPI_ENCODER=yes
!CONFIG_VP9_VAAPI_ENCODER=yes
!CONFIG_H263_VAAPI_HWACCEL=yes
!CONFIG_H264_VAAPI_HWACCEL=yes
!CONFIG_HEVC_VAAPI_HWACCEL=yes
!CONFIG_MJPEG_VAAPI_HWACCEL=yes
!CONFIG_MPEG2_VAAPI_HWACCEL=yes
!CONFIG_MPEG4_VAAPI_HWACCEL=yes
!CONFIG_VC1_VAAPI_HWACCEL=yes
!CONFIG_VP8_VAAPI_HWACCEL=yes
!CONFIG_VP9_VAAPI_HWACCEL=yes
!CONFIG_WMV3_VAAPI_HWACCEL=yes
!CONFIG_DEINTERLACE_VAAPI_FILTER=yes
!CONFIG_DENOISE_VAAPI_FILTER=yes
!CONFIG_PROCAMP_VAAPI_FILTER=yes
!CONFIG_SCALE_VAAPI_FILTER=yes
!CONFIG_SHARPNESS_VAAPI_FILTER=yes
CONFIG_ROTATION_VAAPI_FILTER=yes

[...]
Zachary Zhou Oct. 29, 2018, 1:42 a.m. UTC | #8
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> Michael Niedermayer

> Sent: Saturday, October 27, 2018 5:16 AM

> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On Thu, Oct 25, 2018 at 02:52:01PM +0800, Zachary Zhou wrote:

> > It supports clockwise rotation by 0/90/180/270 degrees defined in

> > va/va_vpp.h, tested following command line on SKL platform

> >

> > dir=0 for 0   degree

> > dir=1 for 90  degree

> > dir=2 for 180 degree

> > dir=3 for 270 degree

> >

> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"

> > -c:v h264_vaapi output.h264

> >

> > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> > ---

> >  configure                     |   3 +

> >  libavfilter/Makefile          |   1 +

> >  libavfilter/allfilters.c      |   1 +

> >  libavfilter/vaapi_vpp.h       |   1 +

> >  libavfilter/vf_rotate_vaapi.c | 252

> > ++++++++++++++++++++++++++++++++++

> >  5 files changed, 258 insertions(+)

> >  create mode 100644 libavfilter/vf_rotate_vaapi.c

> 

> still fails to build on 32bit x86

> 

> src/libavfilter/vf_rotate_vaapi.c: In function

> ‘rotation_vaapi_build_filter_params’:

> src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’ has no

> member named ‘rotation_flags’

>      if (!pipeline_caps.rotation_flags) {

>                        ^

> src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’ has no

> member named ‘rotation_flags’

>      support_flag = pipeline_caps.rotation_flags &

>                                  ^

> src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:

> src/libavfilter/vf_rotate_vaapi.c:152:15: error:

> ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’

>          params.rotation_state = vpp_ctx->rotation_state;

>                ^

> make: *** [libavfilter/vf_rotate_vaapi.o] Error 1

> make: *** Waiting for unfinished jobs....

> 

> grep VAAPI ffbuild/config.mak

> !HAVE_VAAPI_DRM=yes

> !HAVE_VAAPI_X11=yes

> !HAVE_OPENCL_VAAPI_BEIGNET=yes

> !HAVE_OPENCL_VAAPI_INTEL_MEDIA=yes

> !CONFIG_VAAPI_ENCODE_EXAMPLE=yes

> !CONFIG_VAAPI_TRANSCODE_EXAMPLE=yes

> !CONFIG_VAAPI=yes

> !CONFIG_VAAPI_1=yes

> !CONFIG_VAAPI_ENCODE=yes

> !CONFIG_H264_VAAPI_ENCODER=yes

> !CONFIG_HEVC_VAAPI_ENCODER=yes

> !CONFIG_MJPEG_VAAPI_ENCODER=yes

> !CONFIG_MPEG2_VAAPI_ENCODER=yes

> !CONFIG_VP8_VAAPI_ENCODER=yes

> !CONFIG_VP9_VAAPI_ENCODER=yes

> !CONFIG_H263_VAAPI_HWACCEL=yes

> !CONFIG_H264_VAAPI_HWACCEL=yes

> !CONFIG_HEVC_VAAPI_HWACCEL=yes

> !CONFIG_MJPEG_VAAPI_HWACCEL=yes

> !CONFIG_MPEG2_VAAPI_HWACCEL=yes

> !CONFIG_MPEG4_VAAPI_HWACCEL=yes

> !CONFIG_VC1_VAAPI_HWACCEL=yes

> !CONFIG_VP8_VAAPI_HWACCEL=yes

> !CONFIG_VP9_VAAPI_HWACCEL=yes

> !CONFIG_WMV3_VAAPI_HWACCEL=yes

> !CONFIG_DEINTERLACE_VAAPI_FILTER=yes

> !CONFIG_DENOISE_VAAPI_FILTER=yes

> !CONFIG_PROCAMP_VAAPI_FILTER=yes

> !CONFIG_SCALE_VAAPI_FILTER=yes

> !CONFIG_SHARPNESS_VAAPI_FILTER=yes

> CONFIG_ROTATION_VAAPI_FILTER=yes

> 

> [...]


Thanks Michael, Can you share your command line for the build script configure ?
Do I need more setting on the configure file ?

> --

> Michael     GnuPG fingerprint:

> 9FF2128B147EF6730BADF133611EC787040B0FAB

> 

> If you drop bombs on a foreign country and kill a hundred thousand innocent

> people, expect your government to call the consequence "unprovoked

> inhuman terrorist attacks" and use it to justify dropping more bombs and

> killing more people. The technology changed, the idea is old.
Zachary Zhou Oct. 29, 2018, 1:44 a.m. UTC | #9
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> sean darcy

> Sent: Saturday, October 27, 2018 3:07 AM

> To: ffmpeg-devel@ffmpeg.org

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On 10/26/18 11:18 AM, Paul B Mahol wrote:

> > On 10/26/18, Zhou, Zachary <zachary.zhou@intel.com> wrote:

> >>

> >>

> >>> -----Original Message-----

> >>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> >>> Behalf Of Rostislav Pehlivanov

> >>> Sent: Friday, October 26, 2018 9:02 PM

> >>> To: FFmpeg development discussions and patches

> >>> <ffmpeg-devel@ffmpeg.org>

> >>> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable

> >>> vaapi rotation feature via call Intel iHD driver

> >>>

> >>> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com>

> >>> wrote:

> >>>

> >>>>

> >>>>

> >>>>> -----Original Message-----

> >>>>> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> >>>>> Behalf Of sean darcy

> >>>>> Sent: Thursday, October 25, 2018 11:51 PM

> >>>>> To: ffmpeg-devel@ffmpeg.org

> >>>>> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable

> >>>>> vaapi rotation feature via call Intel iHD driver

> >>>>>

> >>>>> On 10/25/18 2:52 AM, Zachary Zhou wrote:

> >>>>>> It supports clockwise rotation by 0/90/180/270 degrees defined in

> >>>>>> va/va_vpp.h, tested following command line on SKL platform

> >>>>>>

> >>>>>> dir=0 for 0   degree

> >>>>>> dir=1 for 90  degree

> >>>>>> dir=2 for 180 degree

> >>>>>> dir=3 for 270 degree

> >>>>>>

> >>>>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> >>>>>> -hwaccel_output_format vaapi -i input.264 -vf

> >>>>>> "rotation_vaapi=dir=1"

> >>>>>> -c:v h264_vaapi output.h264

> >>>>>>

> >>>>>> Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> >>>>>> ---

> >>>>>>    configure                     |   3 +

> >>>>>>    libavfilter/Makefile          |   1 +

> >>>>>>    libavfilter/allfilters.c      |   1 +

> >>>>>>    libavfilter/vaapi_vpp.h       |   1 +

> >>>>>>    libavfilter/vf_rotate_vaapi.c | 252

> >>>> ++++++++++++++++++++++++++++++++++

> >>>>>>    5 files changed, 258 insertions(+)

> >>>>>>    create mode 100644 libavfilter/vf_rotate_vaapi.c

> >>>>>>

> >>>>>> diff --git a/configure b/configure index 85d5dd5962..33aced3d78

> >>>>>> 100755

> >>>>>> --- a/configure

> >>>>>> +++ b/configure

> >>>>>> @@ -6390,6 +6390,9 @@ if enabled vaapi; then

> >>>>>>        fi

> >>>>>>

> >>>>>>        check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1,

> >>>>>> 0,

> >>> 0)"

> >>>>>> +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"

> >>>> rotation_flags;

> >>>>> then

> >>>>>> +        disable rotation_vaapi_filter

> >>>>>> +    fi

> >>>>>>    fi

> >>>>>>

> >>>>>>    if enabled_all opencl libdrm ; then diff --git

> >>>>>> a/libavfilter/Makefile b/libavfilter/Makefile index

> >>>>>> 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c

> >>>>>> b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index

> >>>>>> 0000000000..34c270e9c7

> >>>>>> --- /dev/null

> >>>>>> +++ b/libavfilter/vf_rotate_vaapi.c

> >>>>>> @@ -0,0 +1,252 @@

> >>>>>> +/*

> >>>>>> + * This file is part of FFmpeg.

> >>>>>> + *

> >>>>>> + * FFmpeg 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.

> >>>>>> + *

> >>>>>> + * FFmpeg 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 FFmpeg; if not, write to the Free Software

> >>>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA

> >>>>>> +02110-1301 USA  */ #include <string.h>

> >>>>>> +

> >>>>>> +#include "libavutil/avassert.h"

> >>>>>> +#include "libavutil/mem.h"

> >>>>>> +#include "libavutil/opt.h"

> >>>>>> +#include "libavutil/pixdesc.h"

> >>>>>> +

> >>>>>> +#include "avfilter.h"

> >>>>>> +#include "formats.h"

> >>>>>> +#include "internal.h"

> >>>>>> +#include "vaapi_vpp.h"

> >>>>>> +

> >>>>>> +// Rotation angle values

> >>>>>> +enum RotationAngle {

> >>>>>> +    ROTATION_0   = 0,

> >>>>>> +    ROTATION_90  = 1,

> >>>>>> +    ROTATION_180 = 2,

> >>>>>> +    ROTATION_270 = 3,

> >>>>>> +

> >>>>>> +    ROTATION_MIN     = ROTATION_0,

> >>>>>> +    ROTATION_MAX     = ROTATION_270,

> >>>>>> +    ROTATION_DEFAULT = ROTATION_0, };

> >>>>>> +

> >>>>>> +typedef struct RotationVAAPIContext {

> >>>>>> +    VAAPIVPPContext vpp_ctx; // must be the first field

> >>>>>> +

> >>>>>> +    int rotation;        // enable rotation.

> >>>>>> +} RotationVAAPIContext;

> >>>>>> +

> >>>>>> +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,

> >>>>>> +AVFrame

> >>>>>> +*input_frame) {

> >>>>>> +    AVFilterContext *avctx   = inlink->dst;

> >>>>>> +    AVFilterLink *outlink    = avctx->outputs[0];

> >>>>>> +    VAAPIVPPContext *vpp_ctx = avctx->priv;

> >>>>>> +    AVFrame *output_frame    = NULL;

> >>>>>> +    VASurfaceID input_surface, output_surface;

> >>>>>> +    VARectangle input_region;

> >>>>>> +

> >>>>>> +    VAProcPipelineParameterBuffer params;

> >>>>>> +    int err;

> >>>>>> +

> >>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u

> >>>> (%"PRId64").\n",

> >>>>>> +           av_get_pix_fmt_name(input_frame->format),

> >>>>>> +           input_frame->width, input_frame->height,

> >>>>>> + input_frame->pts);

> >>>>>> +

> >>>>>> +    if (vpp_ctx->va_context == VA_INVALID_ID)

> >>>>>> +        return AVERROR(EINVAL);

> >>>>>> +

> >>>>>> +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];

> >>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp

> >>>> input.\n",

> >>>>>> +           input_surface);

> >>>>>> +

> >>>>>> +    output_frame = ff_get_video_buffer(outlink,

> >>>>>> vpp_ctx->output_width,

> >>>>>> +                                       vpp_ctx->output_height);

> >>>>>> +    if (!output_frame) {

> >>>>>> +        err = AVERROR(ENOMEM);

> >>>>>> +        goto fail;

> >>>>>> +    }

> >>>>>> +

> >>>>>> +    output_surface =

> >>>>>> (VASurfaceID)(uintptr_t)output_frame->data[3];

> >>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp

> >>>>> output.\n",

> >>>>>> +           output_surface);

> >>>>>> +    memset(&params, 0, sizeof(params));

> >>>>>> +    input_region = (VARectangle) {

> >>>>>> +        .x      = 0,

> >>>>>> +        .y      = 0,

> >>>>>> +        .width  = input_frame->width,

> >>>>>> +        .height = input_frame->height,

> >>>>>> +    };

> >>>>>> +

> >>>>>> +    switch (vpp_ctx->rotation_state) {

> >>>>>> +    case VA_ROTATION_NONE:

> >>>>>> +    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;

> >>>>>> +    }

> >>>>>> +    params.surface = input_surface;

> >>>>>> +    params.surface_region = &input_region;

> >>>>>> +    params.surface_color_standard =

> >>>>>> +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);

> >>>>>> +

> >>>>>> +    params.output_region = NULL;

> >>>>>> +    params.output_background_color = 0xff000000;

> >>>>>> +    params.output_color_standard =

> >>>>>> + params.surface_color_standard;

> >>>>>> +

> >>>>>> +    params.pipeline_flags = 0;

> >>>>>> +    params.filter_flags = VA_FRAME_PICTURE;

> >>>>>> +

> >>>>>> +    err = ff_vaapi_vpp_render_picture(avctx, &params,

> >>>>>> output_surface);

> >>>>>> +    if (err < 0)

> >>>>>> +        goto fail;

> >>>>>> +

> >>>>>> +    err = av_frame_copy_props(output_frame, input_frame);

> >>>>>> +    if (err < 0)

> >>>>>> +        goto fail;

> >>>>>> +    av_frame_free(&input_frame);

> >>>>>> +

> >>>>>> +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u

> >>>>> (%"PRId64").\n",

> >>>>>> +           av_get_pix_fmt_name(output_frame->format),

> >>>>>> +           output_frame->width, output_frame->height,

> >>>>>> + output_frame->pts);

> >>>>>> +

> >>>>>> +    return ff_filter_frame(outlink, output_frame);

> >>>>>> +

> >>>>>> +fail:

> >>>>>> +    av_frame_free(&input_frame);

> >>>>>> +    av_frame_free(&output_frame);

> >>>>>> +    return err;

> >>>>>> +}

> >>>>>> +

> >>>>>> +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define

> >>>>>> +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |

> >>> AV_OPT_FLAG_FILTERING_PARAM)

> >>>>>> +static

> >>>>> const

> >>>>>> +AVOption rotation_vaapi_options[] = {

> >>>>>> +    { "dir", "set roation direction", ROFFSET(rotation),

> >>>> AV_OPT_TYPE_INT,

> >>>>> { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS,

> "dir"

> >>>>> },

> >>>>>> +        { "clock_0",   "rotate clockwise 0 degrees",   0,

> >>>> AV_OPT_TYPE_CONST,

> >>>>> { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },

> >>>>>> +        { "clock_90",  "rotate clockwise 90 degrees",  0,

> >>>> AV_OPT_TYPE_CONST,

> >>>>> { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },

> >>>>>> +        { "clock_180", "rotate clockwise 180 degrees", 0,

> >>>> AV_OPT_TYPE_CONST,

> >>>>> { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },

> >>>>>> +        { "clock_270", "rotate clockwise 270 degrees", 0,

> >>>> AV_OPT_TYPE_CONST,

> >>>>> { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },

> >>>>>> +    { NULL },

> >>>>>> +};

> >>>>>> +

> >>>>>> +AVFILTER_DEFINE_CLASS(rotation_vaapi);

> >>>>>> +

> >>>>>> +static const AVFilterPad rotation_vaapi_inputs[] = {

> >>>>>> +    {

> >>>>>> +        .name         = "default",

> >>>>>> +        .type         = AVMEDIA_TYPE_VIDEO,

> >>>>>> +        .filter_frame = &rotation_vaapi_filter_frame,

> >>>>>> +        .config_props = &ff_vaapi_vpp_config_input,

> >>>>>> +    },

> >>>>>> +    { NULL }

> >>>>>> +};

> >>>>>> +

> >>>>>> +static const AVFilterPad rotation_vaapi_outputs[] = {

> >>>>>> +    {

> >>>>>> +        .name = "default",

> >>>>>> +        .type = AVMEDIA_TYPE_VIDEO,

> >>>>>> +        .config_props = &ff_vaapi_vpp_config_output,

> >>>>>> +    },

> >>>>>> +    { NULL }

> >>>>>> +};

> >>>>>> +

> >>>>>> +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        = rotation_vaapi_inputs,

> >>>>>> +    .outputs       = rotation_vaapi_outputs,

> >>>>>> +    .priv_class    = &rotation_vaapi_class,

> >>>>>> +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };

> >>>>>>

> >>>>> How about:

> >>>>>

> >>>>> deg=0 for 0   degree

> >>>>> deg=90 for 90  degree

> >>>>> deg=180 for 180 degree

> >>>>> deg=270 for 270 degree

> >>>>>

> >>>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> >>>>>    -hwaccel_output_format vaapi -i input.264 -vf

> >>>>> "rotation_vaapi=deg=90"

> >>>>>    -c:v h264_vaapi output.h264

> >>>>>

> >>>>> The rotation is in degrees , not direction. And using the actual

> >>>>> degrees

> >>>> instead

> >>>>> of magic numbers makes it more obvious for the user.

> >>>>

> >>>>

> >>>> My first version of the

> >>>> patch(https://patchwork.ffmpeg.org/patch/10754/)

> >>>> just like this.

> >>>>

> >>>> 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

> >>>>

> >>>> And I got comments to add sub-options. the sub-options are clock_0,

> >>>> clock_90, clock_180, clock_270, the command line likes this.

> >>>>

> >>>> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> >>>> -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=

> >>>> clock_270"

> >>>> -c:v h264_vaapi output.h264

> >>>>

> >>>>

> >>>>>

> >>>>> _______________________________________________

> >>>>> ffmpeg-devel mailing list

> >>>>> ffmpeg-devel@ffmpeg.org

> >>>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> >>>> _______________________________________________

> >>>> ffmpeg-devel mailing list

> >>>> ffmpeg-devel@ffmpeg.org

> >>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> >>>

> >>>

> >>> Please, call it transpose_vaapi, and make it accept the same options

> >>> as the transpose filter we have.

> >>> transpose != rotation.

> >>

> >> Actually, I want to change back to "rotation_vaapi=angle=90", I agree

> >> "sean darcy <seandarcy2@gmail.com>" comments, and I think this filter

> >> is different with transpose.

> >>

> >> 1. This filter no vflip/hflip support, but transpose has vflip/hflip,

> >> in VAAPI another feature Mirroring, hflip/vflip are supported by

> >> using VAProcPipelineParameterBuffer::mirror_state. I was planning

> >> enable VAAPI mirroring in another patch.

> >> 2. Currently VAAPI rotation only support 0/90/180/270 degrees, not

> >> sure VAAPI will add more degrees in future, so I want to keep the

> >> name rotation_vaapi to align VAAPI.

> >> 3. I don't want to put VAAPI rotation and VAAPI mirroring together to

> >> enable a similar but not same with transpose currently, Because the

> >> same options and the different functions may call people confuse.

> >>

> >> My first version patch has already included  the discussion regarding

> >> the filter name and options.

> >> https://patchwork.ffmpeg.org/patch/10754/

> >>

> >

> > Why we need yet another rotation filter that does not do rotation but

> > does rotation in 4 fixed ways?

> > Seriously? This needs some serious quality control.

> > _______________________________________________

> 

> Not sure I understand this. I think Zachary is saying:

> 

> Right now vaapi only does 0,90,180,270 rotations. It may do other rotations in

> the future. It would be straightforward to then allow 45

> degrees: rotation_vaapi=angle=45 . If we use the transpose option set, that

> would be much more awkward.

> 

> Or am I missing your point ?


Thanks Sean, you got my point.

> 

> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
mypopy@gmail.com Oct. 29, 2018, 1:58 a.m. UTC | #10
On Fri, Oct 26, 2018 at 11:26 PM Paul B Mahol <onemda@gmail.com> wrote:
>
> On 10/26/18, Zhou, Zachary <zachary.zhou@intel.com> wrote:
> >
> >
> >> -----Original Message-----
> >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
> >> Rostislav Pehlivanov
> >> Sent: Friday, October 26, 2018 9:02 PM
> >> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> >> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi
> >> rotation feature via call Intel iHD driver
> >>
> >> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary <zachary.zhou@intel.com>
> >> wrote:
> >>
> >> >
> >> >
> >> > > -----Original Message-----
> >> > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On
> >> > > Behalf Of sean darcy
> >> > > Sent: Thursday, October 25, 2018 11:51 PM
> >> > > To: ffmpeg-devel@ffmpeg.org
> >> > > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable
> >> > > vaapi rotation feature via call Intel iHD driver
> >> > >
> >> > > On 10/25/18 2:52 AM, Zachary Zhou wrote:
> >> > > > It supports clockwise rotation by 0/90/180/270 degrees defined in
> >> > > > va/va_vpp.h, tested following command line on SKL platform
> >> > > >
> >> > > > dir=0 for 0   degree
> >> > > > dir=1 for 90  degree
> >> > > > dir=2 for 180 degree
> >> > > > dir=3 for 270 degree
> >> > > >
> >> > > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> >> > > > -hwaccel_output_format vaapi -i input.264 -vf
> >> > > > "rotation_vaapi=dir=1"
> >> > > > -c:v h264_vaapi output.h264
> >> > > >
> >> > > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
> >> > > > ---
> >> > > >   configure                     |   3 +
> >> > > >   libavfilter/Makefile          |   1 +
> >> > > >   libavfilter/allfilters.c      |   1 +
> >> > > >   libavfilter/vaapi_vpp.h       |   1 +
> >> > > >   libavfilter/vf_rotate_vaapi.c | 252
> >> > ++++++++++++++++++++++++++++++++++
> >> > > >   5 files changed, 258 insertions(+)
> >> > > >   create mode 100644 libavfilter/vf_rotate_vaapi.c
> >> > > >
> >> > > > diff --git a/configure b/configure index 85d5dd5962..33aced3d78
> >> > > > 100755
> >> > > > --- a/configure
> >> > > > +++ b/configure
> >> > > > @@ -6390,6 +6390,9 @@ if enabled vaapi; then
> >> > > >       fi
> >> > > >
> >> > > >       check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0,
> >> 0)"
> >> > > > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"
> >> > rotation_flags;
> >> > > then
> >> > > > +        disable rotation_vaapi_filter
> >> > > > +    fi
> >> > > >   fi
> >> > > >
> >> > > >   if enabled_all opencl libdrm ; then diff --git
> >> > > > a/libavfilter/Makefile b/libavfilter/Makefile index
> >> > > > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c
> >> > > > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index
> >> > > > 0000000000..34c270e9c7
> >> > > > --- /dev/null
> >> > > > +++ b/libavfilter/vf_rotate_vaapi.c
> >> > > > @@ -0,0 +1,252 @@
> >> > > > +/*
> >> > > > + * This file is part of FFmpeg.
> >> > > > + *
> >> > > > + * FFmpeg 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.
> >> > > > + *
> >> > > > + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> >> > > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> >> > > > +02110-1301 USA  */ #include <string.h>
> >> > > > +
> >> > > > +#include "libavutil/avassert.h"
> >> > > > +#include "libavutil/mem.h"
> >> > > > +#include "libavutil/opt.h"
> >> > > > +#include "libavutil/pixdesc.h"
> >> > > > +
> >> > > > +#include "avfilter.h"
> >> > > > +#include "formats.h"
> >> > > > +#include "internal.h"
> >> > > > +#include "vaapi_vpp.h"
> >> > > > +
> >> > > > +// Rotation angle values
> >> > > > +enum RotationAngle {
> >> > > > +    ROTATION_0   = 0,
> >> > > > +    ROTATION_90  = 1,
> >> > > > +    ROTATION_180 = 2,
> >> > > > +    ROTATION_270 = 3,
> >> > > > +
> >> > > > +    ROTATION_MIN     = ROTATION_0,
> >> > > > +    ROTATION_MAX     = ROTATION_270,
> >> > > > +    ROTATION_DEFAULT = ROTATION_0, };
> >> > > > +
> >> > > > +typedef struct RotationVAAPIContext {
> >> > > > +    VAAPIVPPContext vpp_ctx; // must be the first field
> >> > > > +
> >> > > > +    int rotation;        // enable rotation.
> >> > > > +} RotationVAAPIContext;
> >> > > > +
> >> > > > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,
> >> > > > +AVFrame
> >> > > > +*input_frame) {
> >> > > > +    AVFilterContext *avctx   = inlink->dst;
> >> > > > +    AVFilterLink *outlink    = avctx->outputs[0];
> >> > > > +    VAAPIVPPContext *vpp_ctx = avctx->priv;
> >> > > > +    AVFrame *output_frame    = NULL;
> >> > > > +    VASurfaceID input_surface, output_surface;
> >> > > > +    VARectangle input_region;
> >> > > > +
> >> > > > +    VAProcPipelineParameterBuffer params;
> >> > > > +    int err;
> >> > > > +
> >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u
> >> > (%"PRId64").\n",
> >> > > > +           av_get_pix_fmt_name(input_frame->format),
> >> > > > +           input_frame->width, input_frame->height,
> >> > > > + input_frame->pts);
> >> > > > +
> >> > > > +    if (vpp_ctx->va_context == VA_INVALID_ID)
> >> > > > +        return AVERROR(EINVAL);
> >> > > > +
> >> > > > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
> >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
> >> > input.\n",
> >> > > > +           input_surface);
> >> > > > +
> >> > > > +    output_frame = ff_get_video_buffer(outlink,
> >> > > > vpp_ctx->output_width,
> >> > > > +                                       vpp_ctx->output_height);
> >> > > > +    if (!output_frame) {
> >> > > > +        err = AVERROR(ENOMEM);
> >> > > > +        goto fail;
> >> > > > +    }
> >> > > > +
> >> > > > +    output_surface =
> >> > > > (VASurfaceID)(uintptr_t)output_frame->data[3];
> >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp
> >> > > output.\n",
> >> > > > +           output_surface);
> >> > > > +    memset(&params, 0, sizeof(params));
> >> > > > +    input_region = (VARectangle) {
> >> > > > +        .x      = 0,
> >> > > > +        .y      = 0,
> >> > > > +        .width  = input_frame->width,
> >> > > > +        .height = input_frame->height,
> >> > > > +    };
> >> > > > +
> >> > > > +    switch (vpp_ctx->rotation_state) {
> >> > > > +    case VA_ROTATION_NONE:
> >> > > > +    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;
> >> > > > +    }
> >> > > > +    params.surface = input_surface;
> >> > > > +    params.surface_region = &input_region;
> >> > > > +    params.surface_color_standard =
> >> > > > +        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
> >> > > > +
> >> > > > +    params.output_region = NULL;
> >> > > > +    params.output_background_color = 0xff000000;
> >> > > > +    params.output_color_standard = params.surface_color_standard;
> >> > > > +
> >> > > > +    params.pipeline_flags = 0;
> >> > > > +    params.filter_flags = VA_FRAME_PICTURE;
> >> > > > +
> >> > > > +    err = ff_vaapi_vpp_render_picture(avctx, &params,
> >> > > > output_surface);
> >> > > > +    if (err < 0)
> >> > > > +        goto fail;
> >> > > > +
> >> > > > +    err = av_frame_copy_props(output_frame, input_frame);
> >> > > > +    if (err < 0)
> >> > > > +        goto fail;
> >> > > > +    av_frame_free(&input_frame);
> >> > > > +
> >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u
> >> > > (%"PRId64").\n",
> >> > > > +           av_get_pix_fmt_name(output_frame->format),
> >> > > > +           output_frame->width, output_frame->height,
> >> > > > + output_frame->pts);
> >> > > > +
> >> > > > +    return ff_filter_frame(outlink, output_frame);
> >> > > > +
> >> > > > +fail:
> >> > > > +    av_frame_free(&input_frame);
> >> > > > +    av_frame_free(&output_frame);
> >> > > > +    return err;
> >> > > > +}
> >> > > > +
> >> > > > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define
> >> > > > +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |
> >> AV_OPT_FLAG_FILTERING_PARAM)
> >> > > > +static
> >> > > const
> >> > > > +AVOption rotation_vaapi_options[] = {
> >> > > > +    { "dir", "set roation direction", ROFFSET(rotation),
> >> > AV_OPT_TYPE_INT,
> >> > > { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
> >> > > > +        { "clock_0",   "rotate clockwise 0 degrees",   0,
> >> > AV_OPT_TYPE_CONST,
> >> > > { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
> >> > > > +        { "clock_90",  "rotate clockwise 90 degrees",  0,
> >> > AV_OPT_TYPE_CONST,
> >> > > { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
> >> > > > +        { "clock_180", "rotate clockwise 180 degrees", 0,
> >> > AV_OPT_TYPE_CONST,
> >> > > { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
> >> > > > +        { "clock_270", "rotate clockwise 270 degrees", 0,
> >> > AV_OPT_TYPE_CONST,
> >> > > { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
> >> > > > +    { NULL },
> >> > > > +};
> >> > > > +
> >> > > > +AVFILTER_DEFINE_CLASS(rotation_vaapi);
> >> > > > +
> >> > > > +static const AVFilterPad rotation_vaapi_inputs[] = {
> >> > > > +    {
> >> > > > +        .name         = "default",
> >> > > > +        .type         = AVMEDIA_TYPE_VIDEO,
> >> > > > +        .filter_frame = &rotation_vaapi_filter_frame,
> >> > > > +        .config_props = &ff_vaapi_vpp_config_input,
> >> > > > +    },
> >> > > > +    { NULL }
> >> > > > +};
> >> > > > +
> >> > > > +static const AVFilterPad rotation_vaapi_outputs[] = {
> >> > > > +    {
> >> > > > +        .name = "default",
> >> > > > +        .type = AVMEDIA_TYPE_VIDEO,
> >> > > > +        .config_props = &ff_vaapi_vpp_config_output,
> >> > > > +    },
> >> > > > +    { NULL }
> >> > > > +};
> >> > > > +
> >> > > > +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        = rotation_vaapi_inputs,
> >> > > > +    .outputs       = rotation_vaapi_outputs,
> >> > > > +    .priv_class    = &rotation_vaapi_class,
> >> > > > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };
> >> > > >
> >> > > How about:
> >> > >
> >> > > deg=0 for 0   degree
> >> > > deg=90 for 90  degree
> >> > > deg=180 for 180 degree
> >> > > deg=270 for 270 degree
> >> > >
> >> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> >> > >   -hwaccel_output_format vaapi -i input.264 -vf
> >> > > "rotation_vaapi=deg=90"
> >> > >   -c:v h264_vaapi output.h264
> >> > >
> >> > > The rotation is in degrees , not direction. And using the actual
> >> > > degrees
> >> > instead
> >> > > of magic numbers makes it more obvious for the user.
> >> >
> >> >
> >> > My first version of the
> >> > patch(https://patchwork.ffmpeg.org/patch/10754/)
> >> > just like this.
> >> >
> >> > 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
> >> >
> >> > And I got comments to add sub-options. the sub-options are clock_0,
> >> > clock_90, clock_180, clock_270, the command line likes this.
> >> >
> >> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> >> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=
> >> > clock_270"
> >> > -c:v h264_vaapi output.h264
> >> >
> >> >
> >> > >
> >> > > _______________________________________________
> >> > > ffmpeg-devel mailing list
> >> > > ffmpeg-devel@ffmpeg.org
> >> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >> > _______________________________________________
> >> > ffmpeg-devel mailing list
> >> > ffmpeg-devel@ffmpeg.org
> >> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>
> >>
> >> Please, call it transpose_vaapi, and make it accept the same options as
> >> the
> >> transpose filter we have.
> >> transpose != rotation.
> >
> > Actually, I want to change back to "rotation_vaapi=angle=90", I agree  "sean
> > darcy <seandarcy2@gmail.com>" comments, and I think this filter is different
> > with transpose.
> >
> > 1. This filter no vflip/hflip support, but transpose has vflip/hflip, in
> > VAAPI another feature Mirroring, hflip/vflip are supported by using
> > VAProcPipelineParameterBuffer::mirror_state. I was planning enable VAAPI
> > mirroring in another patch.
> > 2. Currently VAAPI rotation only support 0/90/180/270 degrees, not sure
> > VAAPI will add more degrees in future, so I want to keep the name
> > rotation_vaapi to align VAAPI.
> > 3. I don't want to put VAAPI rotation and VAAPI mirroring together to enable
> > a similar but not same with transpose currently, Because the same options
> > and the different functions may call people confuse.
> >
> > My first version patch has already included  the discussion regarding the
> > filter name and options. https://patchwork.ffmpeg.org/patch/10754/
> >
>
> Why we need yet another rotation filter that does not do rotation but
> does rotation in 4 fixed ways?
> Seriously? This needs some serious quality control.
> _______________________________________________
>
I know Mark have given a openCL rotation filter implement with any
angle support, so I didn't submitted the patch even I have implement
the VA-API rotation filter in last year.
Zachary Zhou Oct. 29, 2018, 8:09 a.m. UTC | #11
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> mypopy@gmail.com

> Sent: Monday, October 29, 2018 9:58 AM

> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On Fri, Oct 26, 2018 at 11:26 PM Paul B Mahol <onemda@gmail.com> wrote:

> >

> > On 10/26/18, Zhou, Zachary <zachary.zhou@intel.com> wrote:

> > >

> > >

> > >> -----Original Message-----

> > >> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> > >> Behalf Of Rostislav Pehlivanov

> > >> Sent: Friday, October 26, 2018 9:02 PM

> > >> To: FFmpeg development discussions and patches

> > >> <ffmpeg-devel@ffmpeg.org>

> > >> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable

> > >> vaapi rotation feature via call Intel iHD driver

> > >>

> > >> On Fri, 26 Oct 2018 at 04:10, Zhou, Zachary

> > >> <zachary.zhou@intel.com>

> > >> wrote:

> > >>

> > >> >

> > >> >

> > >> > > -----Original Message-----

> > >> > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> > >> > > Behalf Of sean darcy

> > >> > > Sent: Thursday, October 25, 2018 11:51 PM

> > >> > > To: ffmpeg-devel@ffmpeg.org

> > >> > > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi:

> > >> > > enable vaapi rotation feature via call Intel iHD driver

> > >> > >

> > >> > > On 10/25/18 2:52 AM, Zachary Zhou wrote:

> > >> > > > It supports clockwise rotation by 0/90/180/270 degrees

> > >> > > > defined in va/va_vpp.h, tested following command line on SKL

> > >> > > > platform

> > >> > > >

> > >> > > > dir=0 for 0   degree

> > >> > > > dir=1 for 90  degree

> > >> > > > dir=2 for 180 degree

> > >> > > > dir=3 for 270 degree

> > >> > > >

> > >> > > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > >> > > > -hwaccel_output_format vaapi -i input.264 -vf

> > >> > > > "rotation_vaapi=dir=1"

> > >> > > > -c:v h264_vaapi output.h264

> > >> > > >

> > >> > > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> > >> > > > ---

> > >> > > >   configure                     |   3 +

> > >> > > >   libavfilter/Makefile          |   1 +

> > >> > > >   libavfilter/allfilters.c      |   1 +

> > >> > > >   libavfilter/vaapi_vpp.h       |   1 +

> > >> > > >   libavfilter/vf_rotate_vaapi.c | 252

> > >> > ++++++++++++++++++++++++++++++++++

> > >> > > >   5 files changed, 258 insertions(+)

> > >> > > >   create mode 100644 libavfilter/vf_rotate_vaapi.c

> > >> > > >

> > >> > > > diff --git a/configure b/configure index

> > >> > > > 85d5dd5962..33aced3d78

> > >> > > > 100755

> > >> > > > --- a/configure

> > >> > > > +++ b/configure

> > >> > > > @@ -6390,6 +6390,9 @@ if enabled vaapi; then

> > >> > > >       fi

> > >> > > >

> > >> > > >       check_cpp_condition vaapi_1 "va/va.h"

> > >> > > > "VA_CHECK_VERSION(1, 0,

> > >> 0)"

> > >> > > > +    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps"

> > >> > rotation_flags;

> > >> > > then

> > >> > > > +        disable rotation_vaapi_filter

> > >> > > > +    fi

> > >> > > >   fi

> > >> > > >

> > >> > > >   if enabled_all opencl libdrm ; then diff --git

> > >> > > > a/libavfilter/Makefile b/libavfilter/Makefile index

> > >> > > > 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c

> > >> > > > b/libavfilter/vf_rotate_vaapi.c new file mode 100644 index

> > >> > > > 0000000000..34c270e9c7

> > >> > > > --- /dev/null

> > >> > > > +++ b/libavfilter/vf_rotate_vaapi.c

> > >> > > > @@ -0,0 +1,252 @@

> > >> > > > +/*

> > >> > > > + * This file is part of FFmpeg.

> > >> > > > + *

> > >> > > > + * FFmpeg 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.

> > >> > > > + *

> > >> > > > + * FFmpeg 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 FFmpeg; if not, write to the Free

> > >> > > > +Software

> > >> > > > + * Foundation, Inc., 51 Franklin Street, Fifth Floor,

> > >> > > > +Boston, MA

> > >> > > > +02110-1301 USA  */ #include <string.h>

> > >> > > > +

> > >> > > > +#include "libavutil/avassert.h"

> > >> > > > +#include "libavutil/mem.h"

> > >> > > > +#include "libavutil/opt.h"

> > >> > > > +#include "libavutil/pixdesc.h"

> > >> > > > +

> > >> > > > +#include "avfilter.h"

> > >> > > > +#include "formats.h"

> > >> > > > +#include "internal.h"

> > >> > > > +#include "vaapi_vpp.h"

> > >> > > > +

> > >> > > > +// Rotation angle values

> > >> > > > +enum RotationAngle {

> > >> > > > +    ROTATION_0   = 0,

> > >> > > > +    ROTATION_90  = 1,

> > >> > > > +    ROTATION_180 = 2,

> > >> > > > +    ROTATION_270 = 3,

> > >> > > > +

> > >> > > > +    ROTATION_MIN     = ROTATION_0,

> > >> > > > +    ROTATION_MAX     = ROTATION_270,

> > >> > > > +    ROTATION_DEFAULT = ROTATION_0, };

> > >> > > > +

> > >> > > > +typedef struct RotationVAAPIContext {

> > >> > > > +    VAAPIVPPContext vpp_ctx; // must be the first field

> > >> > > > +

> > >> > > > +    int rotation;        // enable rotation.

> > >> > > > +} RotationVAAPIContext;

> > >> > > > +

> > >> > > > +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 rotation_vaapi_filter_frame(AVFilterLink *inlink,

> > >> > > > +AVFrame

> > >> > > > +*input_frame) {

> > >> > > > +    AVFilterContext *avctx   = inlink->dst;

> > >> > > > +    AVFilterLink *outlink    = avctx->outputs[0];

> > >> > > > +    VAAPIVPPContext *vpp_ctx = avctx->priv;

> > >> > > > +    AVFrame *output_frame    = NULL;

> > >> > > > +    VASurfaceID input_surface, output_surface;

> > >> > > > +    VARectangle input_region;

> > >> > > > +

> > >> > > > +    VAProcPipelineParameterBuffer params;

> > >> > > > +    int err;

> > >> > > > +

> > >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u

> > >> > (%"PRId64").\n",

> > >> > > > +           av_get_pix_fmt_name(input_frame->format),

> > >> > > > +           input_frame->width, input_frame->height,

> > >> > > > + input_frame->pts);

> > >> > > > +

> > >> > > > +    if (vpp_ctx->va_context == VA_INVALID_ID)

> > >> > > > +        return AVERROR(EINVAL);

> > >> > > > +

> > >> > > > +    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];

> > >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc

> > >> > > > + vpp

> > >> > input.\n",

> > >> > > > +           input_surface);

> > >> > > > +

> > >> > > > +    output_frame = ff_get_video_buffer(outlink,

> > >> > > > vpp_ctx->output_width,

> > >> > > > +                                       vpp_ctx->output_height);

> > >> > > > +    if (!output_frame) {

> > >> > > > +        err = AVERROR(ENOMEM);

> > >> > > > +        goto fail;

> > >> > > > +    }

> > >> > > > +

> > >> > > > +    output_surface =

> > >> > > > (VASurfaceID)(uintptr_t)output_frame->data[3];

> > >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc

> > >> > > > + vpp

> > >> > > output.\n",

> > >> > > > +           output_surface);

> > >> > > > +    memset(&params, 0, sizeof(params));

> > >> > > > +    input_region = (VARectangle) {

> > >> > > > +        .x      = 0,

> > >> > > > +        .y      = 0,

> > >> > > > +        .width  = input_frame->width,

> > >> > > > +        .height = input_frame->height,

> > >> > > > +    };

> > >> > > > +

> > >> > > > +    switch (vpp_ctx->rotation_state) {

> > >> > > > +    case VA_ROTATION_NONE:

> > >> > > > +    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;

> > >> > > > +    }

> > >> > > > +    params.surface = input_surface;

> > >> > > > +    params.surface_region = &input_region;

> > >> > > > +    params.surface_color_standard =

> > >> > > > +

> > >> > > > + ff_vaapi_vpp_colour_standard(input_frame->colorspace);

> > >> > > > +

> > >> > > > +    params.output_region = NULL;

> > >> > > > +    params.output_background_color = 0xff000000;

> > >> > > > +    params.output_color_standard =

> > >> > > > + params.surface_color_standard;

> > >> > > > +

> > >> > > > +    params.pipeline_flags = 0;

> > >> > > > +    params.filter_flags = VA_FRAME_PICTURE;

> > >> > > > +

> > >> > > > +    err = ff_vaapi_vpp_render_picture(avctx, &params,

> > >> > > > output_surface);

> > >> > > > +    if (err < 0)

> > >> > > > +        goto fail;

> > >> > > > +

> > >> > > > +    err = av_frame_copy_props(output_frame, input_frame);

> > >> > > > +    if (err < 0)

> > >> > > > +        goto fail;

> > >> > > > +    av_frame_free(&input_frame);

> > >> > > > +

> > >> > > > +    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u

> > >> > > (%"PRId64").\n",

> > >> > > > +           av_get_pix_fmt_name(output_frame->format),

> > >> > > > +           output_frame->width, output_frame->height,

> > >> > > > + output_frame->pts);

> > >> > > > +

> > >> > > > +    return ff_filter_frame(outlink, output_frame);

> > >> > > > +

> > >> > > > +fail:

> > >> > > > +    av_frame_free(&input_frame);

> > >> > > > +    av_frame_free(&output_frame);

> > >> > > > +    return err;

> > >> > > > +}

> > >> > > > +

> > >> > > > +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 ROFFSET(x) offsetof(RotationVAAPIContext, x) #define

> > >> > > > +FLAGS (AV_OPT_FLAG_VIDEO_PARAM |

> > >> AV_OPT_FLAG_FILTERING_PARAM)

> > >> > > > +static

> > >> > > const

> > >> > > > +AVOption rotation_vaapi_options[] = {

> > >> > > > +    { "dir", "set roation direction", ROFFSET(rotation),

> > >> > AV_OPT_TYPE_INT,

> > >> > > { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS,

> > >> > > "dir" },

> > >> > > > +        { "clock_0",   "rotate clockwise 0 degrees",   0,

> > >> > AV_OPT_TYPE_CONST,

> > >> > > { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },

> > >> > > > +        { "clock_90",  "rotate clockwise 90 degrees",  0,

> > >> > AV_OPT_TYPE_CONST,

> > >> > > { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },

> > >> > > > +        { "clock_180", "rotate clockwise 180 degrees", 0,

> > >> > AV_OPT_TYPE_CONST,

> > >> > > { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },

> > >> > > > +        { "clock_270", "rotate clockwise 270 degrees", 0,

> > >> > AV_OPT_TYPE_CONST,

> > >> > > { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },

> > >> > > > +    { NULL },

> > >> > > > +};

> > >> > > > +

> > >> > > > +AVFILTER_DEFINE_CLASS(rotation_vaapi);

> > >> > > > +

> > >> > > > +static const AVFilterPad rotation_vaapi_inputs[] = {

> > >> > > > +    {

> > >> > > > +        .name         = "default",

> > >> > > > +        .type         = AVMEDIA_TYPE_VIDEO,

> > >> > > > +        .filter_frame = &rotation_vaapi_filter_frame,

> > >> > > > +        .config_props = &ff_vaapi_vpp_config_input,

> > >> > > > +    },

> > >> > > > +    { NULL }

> > >> > > > +};

> > >> > > > +

> > >> > > > +static const AVFilterPad rotation_vaapi_outputs[] = {

> > >> > > > +    {

> > >> > > > +        .name = "default",

> > >> > > > +        .type = AVMEDIA_TYPE_VIDEO,

> > >> > > > +        .config_props = &ff_vaapi_vpp_config_output,

> > >> > > > +    },

> > >> > > > +    { NULL }

> > >> > > > +};

> > >> > > > +

> > >> > > > +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        = rotation_vaapi_inputs,

> > >> > > > +    .outputs       = rotation_vaapi_outputs,

> > >> > > > +    .priv_class    = &rotation_vaapi_class,

> > >> > > > +    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, };

> > >> > > >

> > >> > > How about:

> > >> > >

> > >> > > deg=0 for 0   degree

> > >> > > deg=90 for 90  degree

> > >> > > deg=180 for 180 degree

> > >> > > deg=270 for 270 degree

> > >> > >

> > >> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > >> > >   -hwaccel_output_format vaapi -i input.264 -vf

> > >> > > "rotation_vaapi=deg=90"

> > >> > >   -c:v h264_vaapi output.h264

> > >> > >

> > >> > > The rotation is in degrees , not direction. And using the

> > >> > > actual degrees

> > >> > instead

> > >> > > of magic numbers makes it more obvious for the user.

> > >> >

> > >> >

> > >> > My first version of the

> > >> > patch(https://patchwork.ffmpeg.org/patch/10754/)

> > >> > just like this.

> > >> >

> > >> > 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

> > >> >

> > >> > And I got comments to add sub-options. the sub-options are

> > >> > clock_0, clock_90, clock_180, clock_270, the command line likes this.

> > >> >

> > >> > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > >> > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=

> > >> > clock_270"

> > >> > -c:v h264_vaapi output.h264

> > >> >

> > >> >

> > >> > >

> > >> > > _______________________________________________

> > >> > > ffmpeg-devel mailing list

> > >> > > ffmpeg-devel@ffmpeg.org

> > >> > > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> > >> > _______________________________________________

> > >> > ffmpeg-devel mailing list

> > >> > ffmpeg-devel@ffmpeg.org

> > >> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

> > >>

> > >>

> > >> Please, call it transpose_vaapi, and make it accept the same

> > >> options as the transpose filter we have.

> > >> transpose != rotation.

> > >

> > > Actually, I want to change back to "rotation_vaapi=angle=90", I

> > > agree  "sean darcy <seandarcy2@gmail.com>" comments, and I think

> > > this filter is different with transpose.

> > >

> > > 1. This filter no vflip/hflip support, but transpose has

> > > vflip/hflip, in VAAPI another feature Mirroring, hflip/vflip are

> > > supported by using VAProcPipelineParameterBuffer::mirror_state. I

> > > was planning enable VAAPI mirroring in another patch.

> > > 2. Currently VAAPI rotation only support 0/90/180/270 degrees, not

> > > sure VAAPI will add more degrees in future, so I want to keep the

> > > name rotation_vaapi to align VAAPI.

> > > 3. I don't want to put VAAPI rotation and VAAPI mirroring together

> > > to enable a similar but not same with transpose currently, Because

> > > the same options and the different functions may call people confuse.

> > >

> > > My first version patch has already included  the discussion

> > > regarding the filter name and options.

> > > https://patchwork.ffmpeg.org/patch/10754/

> > >

> >

> > Why we need yet another rotation filter that does not do rotation but

> > does rotation in 4 fixed ways?

> > Seriously? This needs some serious quality control.

> > _______________________________________________

> >

> I know Mark have given a openCL rotation filter implement with any angle

> support, so I didn't submitted the patch even I have implement the VA-API

> rotation filter in last year.


Thank you for comments.
0/90/180/270 are very common angles for filter, these angles can be done by transpose filter.
if transpose do 180 degrees, it should be do two times 90 degree rotation, but VAAPI rotation just do one time parameter setting.  This is one difference between VAAPI rotation and transpose, and it looks like I cannot use transpose options and sub-options directly.

Another, transpose filter support hflip/vflip, VAAPI mirroring can do it. 
We can consider to use VAAPI rotation and VAAPI mirror two filters to simulate transpose filter.
But it is will not the same with transpose filter. Not only how to do 180 degrees rotation, but also
we can find followings in va/va_vpp.h https://github.com/intel/libva/blob/master/va/va_vpp.h 989 line: 
" It is assumed that the rotation operation is always performed before the mirroring operation. "

So, I think VAAPI rotation and VAAP mirroring is useful. I just think if we can keep VAAPI rotation and VAAP mirroring separately is better. 

And I find one issue on VAAPI mirroring currently, I have to wait if I consider to enable VAAPI mirroring filter.


> _______________________________________________

> ffmpeg-devel mailing list

> ffmpeg-devel@ffmpeg.org

> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Michael Niedermayer Oct. 30, 2018, 7:53 p.m. UTC | #12
On Mon, Oct 29, 2018 at 01:42:55AM +0000, Zhou, Zachary wrote:
> 
> 
> > -----Original Message-----
> > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
> > Michael Niedermayer
> > Sent: Saturday, October 27, 2018 5:16 AM
> > To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi
> > rotation feature via call Intel iHD driver
> > 
> > On Thu, Oct 25, 2018 at 02:52:01PM +0800, Zachary Zhou wrote:
> > > It supports clockwise rotation by 0/90/180/270 degrees defined in
> > > va/va_vpp.h, tested following command line on SKL platform
> > >
> > > dir=0 for 0   degree
> > > dir=1 for 90  degree
> > > dir=2 for 180 degree
> > > dir=3 for 270 degree
> > >
> > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
> > > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"
> > > -c:v h264_vaapi output.h264
> > >
> > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>
> > > ---
> > >  configure                     |   3 +
> > >  libavfilter/Makefile          |   1 +
> > >  libavfilter/allfilters.c      |   1 +
> > >  libavfilter/vaapi_vpp.h       |   1 +
> > >  libavfilter/vf_rotate_vaapi.c | 252
> > > ++++++++++++++++++++++++++++++++++
> > >  5 files changed, 258 insertions(+)
> > >  create mode 100644 libavfilter/vf_rotate_vaapi.c
> > 
> > still fails to build on 32bit x86
> > 
> > src/libavfilter/vf_rotate_vaapi.c: In function
> > ‘rotation_vaapi_build_filter_params’:
> > src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’ has no
> > member named ‘rotation_flags’
> >      if (!pipeline_caps.rotation_flags) {
> >                        ^
> > src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’ has no
> > member named ‘rotation_flags’
> >      support_flag = pipeline_caps.rotation_flags &
> >                                  ^
> > src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:
> > src/libavfilter/vf_rotate_vaapi.c:152:15: error:
> > ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’
> >          params.rotation_state = vpp_ctx->rotation_state;
> >                ^
> > make: *** [libavfilter/vf_rotate_vaapi.o] Error 1
> > make: *** Waiting for unfinished jobs....
> > 
> > grep VAAPI ffbuild/config.mak
> > !HAVE_VAAPI_DRM=yes
> > !HAVE_VAAPI_X11=yes
> > !HAVE_OPENCL_VAAPI_BEIGNET=yes
> > !HAVE_OPENCL_VAAPI_INTEL_MEDIA=yes
> > !CONFIG_VAAPI_ENCODE_EXAMPLE=yes
> > !CONFIG_VAAPI_TRANSCODE_EXAMPLE=yes
> > !CONFIG_VAAPI=yes
> > !CONFIG_VAAPI_1=yes
> > !CONFIG_VAAPI_ENCODE=yes
> > !CONFIG_H264_VAAPI_ENCODER=yes
> > !CONFIG_HEVC_VAAPI_ENCODER=yes
> > !CONFIG_MJPEG_VAAPI_ENCODER=yes
> > !CONFIG_MPEG2_VAAPI_ENCODER=yes
> > !CONFIG_VP8_VAAPI_ENCODER=yes
> > !CONFIG_VP9_VAAPI_ENCODER=yes
> > !CONFIG_H263_VAAPI_HWACCEL=yes
> > !CONFIG_H264_VAAPI_HWACCEL=yes
> > !CONFIG_HEVC_VAAPI_HWACCEL=yes
> > !CONFIG_MJPEG_VAAPI_HWACCEL=yes
> > !CONFIG_MPEG2_VAAPI_HWACCEL=yes
> > !CONFIG_MPEG4_VAAPI_HWACCEL=yes
> > !CONFIG_VC1_VAAPI_HWACCEL=yes
> > !CONFIG_VP8_VAAPI_HWACCEL=yes
> > !CONFIG_VP9_VAAPI_HWACCEL=yes
> > !CONFIG_WMV3_VAAPI_HWACCEL=yes
> > !CONFIG_DEINTERLACE_VAAPI_FILTER=yes
> > !CONFIG_DENOISE_VAAPI_FILTER=yes
> > !CONFIG_PROCAMP_VAAPI_FILTER=yes
> > !CONFIG_SCALE_VAAPI_FILTER=yes
> > !CONFIG_SHARPNESS_VAAPI_FILTER=yes
> > CONFIG_ROTATION_VAAPI_FILTER=yes
> > 
> > [...]
> 
> Thanks Michael, Can you share your command line for the build script configure ?
> Do I need more setting on the configure file ?

i simplified it a bit, this can still reproduce it:
make distclean ; ../configure   --cc='ccache gcc -m32'   && make -j12


src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_build_filter_params’:
src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’ has no member named ‘rotation_flags’
     if (!pipeline_caps.rotation_flags) {
                       ^
src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’ has no member named ‘rotation_flags’
     support_flag = pipeline_caps.rotation_flags &
                                 ^
src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:
src/libavfilter/vf_rotate_vaapi.c:152:15: error: ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’
         params.rotation_state = vpp_ctx->rotation_state;
               ^
make: *** [libavfilter/vf_rotate_vaapi.o] Error 1
make: *** Waiting for unfinished jobs....

[...]
Zachary Zhou Oct. 31, 2018, 2:46 a.m. UTC | #13
> -----Original Message-----

> From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of

> Michael Niedermayer

> Sent: Wednesday, October 31, 2018 3:53 AM

> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>

> Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable vaapi

> rotation feature via call Intel iHD driver

> 

> On Mon, Oct 29, 2018 at 01:42:55AM +0000, Zhou, Zachary wrote:

> >

> >

> > > -----Original Message-----

> > > From: ffmpeg-devel [mailto:ffmpeg-devel-bounces@ffmpeg.org] On

> > > Behalf Of Michael Niedermayer

> > > Sent: Saturday, October 27, 2018 5:16 AM

> > > To: FFmpeg development discussions and patches

> > > <ffmpeg-devel@ffmpeg.org>

> > > Subject: Re: [FFmpeg-devel] [PATCH V2] libavfilter/vaapi: enable

> > > vaapi rotation feature via call Intel iHD driver

> > >

> > > On Thu, Oct 25, 2018 at 02:52:01PM +0800, Zachary Zhou wrote:

> > > > It supports clockwise rotation by 0/90/180/270 degrees defined in

> > > > va/va_vpp.h, tested following command line on SKL platform

> > > >

> > > > dir=0 for 0   degree

> > > > dir=1 for 90  degree

> > > > dir=2 for 180 degree

> > > > dir=3 for 270 degree

> > > >

> > > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128

> > > > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=dir=1"

> > > > -c:v h264_vaapi output.h264

> > > >

> > > > Signed-off-by: Zachary Zhou <zachary.zhou@intel.com>

> > > > ---

> > > >  configure                     |   3 +

> > > >  libavfilter/Makefile          |   1 +

> > > >  libavfilter/allfilters.c      |   1 +

> > > >  libavfilter/vaapi_vpp.h       |   1 +

> > > >  libavfilter/vf_rotate_vaapi.c | 252

> > > > ++++++++++++++++++++++++++++++++++

> > > >  5 files changed, 258 insertions(+)  create mode 100644

> > > > libavfilter/vf_rotate_vaapi.c

> > >

> > > still fails to build on 32bit x86

> > >

> > > src/libavfilter/vf_rotate_vaapi.c: In function

> > > ‘rotation_vaapi_build_filter_params’:

> > > src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’

> > > has no member named ‘rotation_flags’

> > >      if (!pipeline_caps.rotation_flags) {

> > >                        ^

> > > src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’

> > > has no member named ‘rotation_flags’

> > >      support_flag = pipeline_caps.rotation_flags &

> > >                                  ^

> > > src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:

> > > src/libavfilter/vf_rotate_vaapi.c:152:15: error:

> > > ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’

> > >          params.rotation_state = vpp_ctx->rotation_state;

> > >                ^

> > > make: *** [libavfilter/vf_rotate_vaapi.o] Error 1

> > > make: *** Waiting for unfinished jobs....

> > >

> > > grep VAAPI ffbuild/config.mak

> > > !HAVE_VAAPI_DRM=yes

> > > !HAVE_VAAPI_X11=yes

> > > !HAVE_OPENCL_VAAPI_BEIGNET=yes

> > > !HAVE_OPENCL_VAAPI_INTEL_MEDIA=yes

> > > !CONFIG_VAAPI_ENCODE_EXAMPLE=yes

> > > !CONFIG_VAAPI_TRANSCODE_EXAMPLE=yes

> > > !CONFIG_VAAPI=yes

> > > !CONFIG_VAAPI_1=yes

> > > !CONFIG_VAAPI_ENCODE=yes

> > > !CONFIG_H264_VAAPI_ENCODER=yes

> > > !CONFIG_HEVC_VAAPI_ENCODER=yes

> > > !CONFIG_MJPEG_VAAPI_ENCODER=yes

> > > !CONFIG_MPEG2_VAAPI_ENCODER=yes

> > > !CONFIG_VP8_VAAPI_ENCODER=yes

> > > !CONFIG_VP9_VAAPI_ENCODER=yes

> > > !CONFIG_H263_VAAPI_HWACCEL=yes

> > > !CONFIG_H264_VAAPI_HWACCEL=yes

> > > !CONFIG_HEVC_VAAPI_HWACCEL=yes

> > > !CONFIG_MJPEG_VAAPI_HWACCEL=yes

> > > !CONFIG_MPEG2_VAAPI_HWACCEL=yes

> > > !CONFIG_MPEG4_VAAPI_HWACCEL=yes

> > > !CONFIG_VC1_VAAPI_HWACCEL=yes

> > > !CONFIG_VP8_VAAPI_HWACCEL=yes

> > > !CONFIG_VP9_VAAPI_HWACCEL=yes

> > > !CONFIG_WMV3_VAAPI_HWACCEL=yes

> > > !CONFIG_DEINTERLACE_VAAPI_FILTER=yes

> > > !CONFIG_DENOISE_VAAPI_FILTER=yes

> > > !CONFIG_PROCAMP_VAAPI_FILTER=yes

> > > !CONFIG_SCALE_VAAPI_FILTER=yes

> > > !CONFIG_SHARPNESS_VAAPI_FILTER=yes

> > > CONFIG_ROTATION_VAAPI_FILTER=yes

> > >

> > > [...]

> >

> > Thanks Michael, Can you share your command line for the build script

> configure ?

> > Do I need more setting on the configure file ?

> 

> i simplified it a bit, this can still reproduce it:

> make distclean ; ../configure   --cc='ccache gcc -m32'   && make -j12

> 

> 

> src/libavfilter/vf_rotate_vaapi.c: In function

> ‘rotation_vaapi_build_filter_params’:

> src/libavfilter/vf_rotate_vaapi.c:69:23: error: ‘VAProcPipelineCaps’ has no

> member named ‘rotation_flags’

>      if (!pipeline_caps.rotation_flags) {

>                        ^

> src/libavfilter/vf_rotate_vaapi.c:95:33: error: ‘VAProcPipelineCaps’ has no

> member named ‘rotation_flags’

>      support_flag = pipeline_caps.rotation_flags &

>                                  ^

> src/libavfilter/vf_rotate_vaapi.c: In function ‘rotation_vaapi_filter_frame’:

> src/libavfilter/vf_rotate_vaapi.c:152:15: error:

> ‘VAProcPipelineParameterBuffer’ has no member named ‘rotation_state’

>          params.rotation_state = vpp_ctx->rotation_state;

>                ^

> make: *** [libavfilter/vf_rotate_vaapi.o] Error 1

> make: *** Waiting for unfinished jobs....

> 

> [...]


Thank you Michael, I have reproduced this issue, and fixed this issue in the new version the patch by changed configure file.
https://patchwork.ffmpeg.org/patch/10858/

> 

> --

> Michael     GnuPG fingerprint:

> 9FF2128B147EF6730BADF133611EC787040B0FAB

> 

> The worst form of inequality is to try to make unequal things equal.

> -- Aristotle
Mark Thompson Oct. 31, 2018, 11:38 p.m. UTC | #14
On 29/10/18 01:58, mypopy@gmail.com wrote:
>> ... lots of other stuff ...
> I know Mark have given a openCL rotation filter implement with any
> angle support, so I didn't submitted the patch even I have implement
> the VA-API rotation filter in last year.

I never wrote a standalone filter for it, but the relevant code is in the program_opencl examples (changing it to rotate by some specific angle is trivial).

- Mark
diff mbox

Patch

diff --git a/configure b/configure
index 85d5dd5962..33aced3d78 100755
--- a/configure
+++ b/configure
@@ -6390,6 +6390,9 @@  if enabled vaapi; then
     fi
 
     check_cpp_condition vaapi_1 "va/va.h" "VA_CHECK_VERSION(1, 0, 0)"
+    if ! check_struct "va/va.h" "struct _VAProcPipelineCaps" rotation_flags; then
+        disable rotation_vaapi_filter
+    fi
 fi
 
 if enabled_all opencl libdrm ; then
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 108a2f87d7..534650364a 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_rotate_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_rotate_vaapi.c b/libavfilter/vf_rotate_vaapi.c
new file mode 100644
index 0000000000..34c270e9c7
--- /dev/null
+++ b/libavfilter/vf_rotate_vaapi.c
@@ -0,0 +1,252 @@ 
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "vaapi_vpp.h"
+
+// Rotation angle values
+enum RotationAngle {
+    ROTATION_0   = 0,
+    ROTATION_90  = 1,
+    ROTATION_180 = 2,
+    ROTATION_270 = 3,
+
+    ROTATION_MIN     = ROTATION_0,
+    ROTATION_MAX     = ROTATION_270,
+    ROTATION_DEFAULT = ROTATION_0,
+};
+
+typedef struct RotationVAAPIContext {
+    VAAPIVPPContext vpp_ctx; // must be the first field
+
+    int rotation;        // enable rotation.
+} RotationVAAPIContext;
+
+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 rotation_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
+{
+    AVFilterContext *avctx   = inlink->dst;
+    AVFilterLink *outlink    = avctx->outputs[0];
+    VAAPIVPPContext *vpp_ctx = avctx->priv;
+    AVFrame *output_frame    = NULL;
+    VASurfaceID input_surface, output_surface;
+    VARectangle input_region;
+
+    VAProcPipelineParameterBuffer params;
+    int err;
+
+    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
+           av_get_pix_fmt_name(input_frame->format),
+           input_frame->width, input_frame->height, input_frame->pts);
+
+    if (vpp_ctx->va_context == VA_INVALID_ID)
+        return AVERROR(EINVAL);
+
+    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
+    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp input.\n",
+           input_surface);
+
+    output_frame = ff_get_video_buffer(outlink, vpp_ctx->output_width,
+                                       vpp_ctx->output_height);
+    if (!output_frame) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];
+    av_log(avctx, AV_LOG_DEBUG, "Using surface %#x for misc vpp output.\n",
+           output_surface);
+    memset(&params, 0, sizeof(params));
+    input_region = (VARectangle) {
+        .x      = 0,
+        .y      = 0,
+        .width  = input_frame->width,
+        .height = input_frame->height,
+    };
+
+    switch (vpp_ctx->rotation_state) {
+    case VA_ROTATION_NONE:
+    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;
+    }
+    params.surface = input_surface;
+    params.surface_region = &input_region;
+    params.surface_color_standard =
+        ff_vaapi_vpp_colour_standard(input_frame->colorspace);
+
+    params.output_region = NULL;
+    params.output_background_color = 0xff000000;
+    params.output_color_standard = params.surface_color_standard;
+
+    params.pipeline_flags = 0;
+    params.filter_flags = VA_FRAME_PICTURE;
+
+    err = ff_vaapi_vpp_render_picture(avctx, &params, output_surface);
+    if (err < 0)
+        goto fail;
+
+    err = av_frame_copy_props(output_frame, input_frame);
+    if (err < 0)
+        goto fail;
+    av_frame_free(&input_frame);
+
+    av_log(avctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n",
+           av_get_pix_fmt_name(output_frame->format),
+           output_frame->width, output_frame->height, output_frame->pts);
+
+    return ff_filter_frame(outlink, output_frame);
+
+fail:
+    av_frame_free(&input_frame);
+    av_frame_free(&output_frame);
+    return err;
+}
+
+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 ROFFSET(x) offsetof(RotationVAAPIContext, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
+static const AVOption rotation_vaapi_options[] = {
+    { "dir", "set roation direction", ROFFSET(rotation), AV_OPT_TYPE_INT, { .i64 = ROTATION_MIN }, ROTATION_MIN, ROTATION_MAX, FLAGS, "dir" },
+        { "clock_0",   "rotate clockwise 0 degrees",   0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_0 },   .flags=FLAGS, .unit = "dir" },
+        { "clock_90",  "rotate clockwise 90 degrees",  0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_90},   .flags=FLAGS, .unit = "dir" },
+        { "clock_180", "rotate clockwise 180 degrees", 0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_180 }, .flags=FLAGS, .unit = "dir" },
+        { "clock_270", "rotate clockwise 270 degrees", 0, AV_OPT_TYPE_CONST, { .i64 = ROTATION_270 }, .flags=FLAGS, .unit = "dir" },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(rotation_vaapi);
+
+static const AVFilterPad rotation_vaapi_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &rotation_vaapi_filter_frame,
+        .config_props = &ff_vaapi_vpp_config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad rotation_vaapi_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &ff_vaapi_vpp_config_output,
+    },
+    { NULL }
+};
+
+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        = rotation_vaapi_inputs,
+    .outputs       = rotation_vaapi_outputs,
+    .priv_class    = &rotation_vaapi_class,
+    .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
+};