> From: ffmpeg-devel [mailto:ffmpeg-devel-boun...@ffmpeg.org] On Behalf > Of Zachary Zhou > Sent: Tuesday, October 23, 2018 3:53 PM > To: ffmpeg-devel@ffmpeg.org > Cc: Zhou, Zachary <zachary.z...@intel.com> > Subject: [FFmpeg-devel] [PATCH] libavfilter/vaapi: enable vaapi rotation > feature via call Intel iHD driver > > It supports clockwise rotation by 0/90/180/270 degrees defined in > va/va_vpp.h, tested following command line on SKL platform > > ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 > -hwaccel_output_format vaapi -i input.264 -vf "rotation_vaapi=angle=90" > -c:v h264_vaapi output.h264 > --- > libavfilter/Makefile | 1 + > libavfilter/allfilters.c | 1 + > libavfilter/vaapi_vpp.h | 1 + > libavfilter/vf_misc_vaapi.c | 122 > ++++++++++++++++++++++++++++++++++++ > 4 files changed, 125 insertions(+) > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile index > 108a2f87d7..81afc100dc 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -349,6 +349,7 @@ OBJS-$(CONFIG_SETRANGE_FILTER) > += vf_setparams.o > OBJS-$(CONFIG_SETSAR_FILTER) += vf_aspect.o > OBJS-$(CONFIG_SETTB_FILTER) += settb.o > OBJS-$(CONFIG_SHARPNESS_VAAPI_FILTER) += vf_misc_vaapi.o > vaapi_vpp.o > +OBJS-$(CONFIG_ROTATION_VAAPI_FILTER) += vf_misc_vaapi.o > vaapi_vpp.o > OBJS-$(CONFIG_SHOWINFO_FILTER) += vf_showinfo.o > OBJS-$(CONFIG_SHOWPALETTE_FILTER) += > vf_showpalette.o > OBJS-$(CONFIG_SHUFFLEFRAMES_FILTER) += > vf_shuffleframes.o > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index > 557590850b..4b90a7f440 100644 > --- a/libavfilter/allfilters.c > +++ b/libavfilter/allfilters.c > @@ -333,6 +333,7 @@ extern AVFilter ff_vf_setrange; extern AVFilter > ff_vf_setsar; extern AVFilter ff_vf_settb; extern AVFilter > ff_vf_sharpness_vaapi; > +extern AVFilter ff_vf_rotation_vaapi; > extern AVFilter ff_vf_showinfo; > extern AVFilter ff_vf_showpalette; > extern AVFilter ff_vf_shuffleframes; > diff --git a/libavfilter/vaapi_vpp.h b/libavfilter/vaapi_vpp.h index > 0bc31018d4..cfe19b689f 100644 > --- a/libavfilter/vaapi_vpp.h > +++ b/libavfilter/vaapi_vpp.h > @@ -44,6 +44,7 @@ typedef struct VAAPIVPPContext { > int output_width; // computed width > int output_height; // computed height > > + int rotation_state; > VABufferID filter_buffers[VAProcFilterCount]; > int nb_filter_buffers; > > diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c index > 30b808a993..e5d354e3dc 100644 > --- a/libavfilter/vf_misc_vaapi.c > +++ b/libavfilter/vf_misc_vaapi.c > @@ -37,6 +37,18 @@ > #define SHARPNESS_MAX 64 > #define SHARPNESS_DEFAULT 44 > > +// Rotation angle values > +enum RotationAngle { > + ROTATION_0 = 0, > + ROTATION_90 = 90, > + ROTATION_180 = 180, > + ROTATION_270 = 270, > + > + ROTATION_MIN = ROTATION_0, > + ROTATION_MAX = ROTATION_270, > + ROTATION_DEFAULT = ROTATION_0, > +}; > + > typedef struct DenoiseVAAPIContext { > VAAPIVPPContext vpp_ctx; // must be the first field > > @@ -49,6 +61,12 @@ typedef struct SharpnessVAAPIContext { > int sharpness; // enable sharpness. > } SharpnessVAAPIContext; > > +typedef struct RotationVAAPIContext { > + VAAPIVPPContext vpp_ctx; // must be the first field > + > + int rotation; // enable rotation.
Looks like it means rotation degree, not a flag to enable/disable rotation. So the comment here may be not precise. > +} RotationVAAPIContext; > + > static float map(int x, int in_min, int in_max, float out_min, float out_max) > { > double slope, output; > @@ -123,6 +141,64 @@ static int > sharpness_vaapi_build_filter_params(AVFilterContext *avctx) > return 0; > } > > +static int rotation_vaapi_build_filter_params(AVFilterContext *avctx) { > + VAAPIVPPContext *vpp_ctx = avctx->priv; > + RotationVAAPIContext *ctx = avctx->priv; > + > + VAStatus vas; > + int support_flag; > + > + VAProcPipelineCaps pipeline_caps; > + > + memset(&pipeline_caps, 0, sizeof(pipeline_caps)); > + vas = vaQueryVideoProcPipelineCaps(vpp_ctx->hwctx->display, > + vpp_ctx->va_context, > + NULL, 0, > + &pipeline_caps); > + if (vas != VA_STATUS_SUCCESS) { > + av_log(avctx, AV_LOG_ERROR, "Failed to query pipeline " > + "caps: %d (%s).\n", vas, vaErrorStr(vas)); > + return AVERROR(EIO); > + } > + > + if (!pipeline_caps.rotation_flags) { > + av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't support > rotation\n"); > + return AVERROR(EINVAL); > + } > + > + switch (ctx->rotation) { > + case ROTATION_0: > + vpp_ctx->rotation_state = VA_ROTATION_NONE; > + break; > + case ROTATION_90: > + vpp_ctx->rotation_state = VA_ROTATION_90; > + break; > + case ROTATION_180: > + vpp_ctx->rotation_state = VA_ROTATION_180; > + break; > + case ROTATION_270: > + vpp_ctx->rotation_state = VA_ROTATION_270; > + break; > + default: > + av_log(avctx, AV_LOG_ERROR, "Failed to set rotation_state > to %d. " > + "Clockwise %d, %d, %d and %d are only supported\n", > + ctx->rotation, > + ROTATION_0, ROTATION_90, ROTATION_180, > ROTATION_270); > + return AVERROR(EINVAL); > + } > + > + support_flag = pipeline_caps.rotation_flags & > + (1 << vpp_ctx->rotation_state); > + if (!support_flag) { > + av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't > support %d\n", > + ctx->rotation); > + return AVERROR(EINVAL); > + } > + > + return 0; > +} > + > static int misc_vaapi_filter_frame(AVFilterLink *inlink, AVFrame > *input_frame) { > AVFilterContext *avctx = inlink->dst; > @@ -164,6 +240,19 @@ static int misc_vaapi_filter_frame(AVFilterLink > *inlink, AVFrame *input_frame) > .height = input_frame->height, > }; > > + switch (vpp_ctx->rotation_state) { > + case VA_ROTATION_NONE: Should be this case by-passed? I guess can bring a little performance benefit. > + case VA_ROTATION_90: > + case VA_ROTATION_180: > + case VA_ROTATION_270: > + params.rotation_state = vpp_ctx->rotation_state; > + break; > + default: > + av_log(avctx, AV_LOG_ERROR, "VAAPI doesn't support %d\n", > + vpp_ctx->rotation_state); > + goto fail; > + } > + > if (vpp_ctx->nb_filter_buffers) { > params.filters = &vpp_ctx->filter_buffers[0]; > params.num_filters = vpp_ctx->nb_filter_buffers; @@ -225,6 > +314,18 @@ static av_cold int sharpness_vaapi_init(AVFilterContext *avctx) > return 0; > } > > +static av_cold int rotation_vaapi_init(AVFilterContext *avctx) { > + VAAPIVPPContext *vpp_ctx = avctx->priv; > + > + ff_vaapi_vpp_ctx_init(avctx); > + vpp_ctx->pipeline_uninit = ff_vaapi_vpp_pipeline_uninit; > + vpp_ctx->build_filter_params = rotation_vaapi_build_filter_params; > + vpp_ctx->output_format = AV_PIX_FMT_NONE; > + > + return 0; > +} > + > #define DOFFSET(x) offsetof(DenoiseVAAPIContext, x) #define FLAGS > (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) static > const AVOption denoise_vaapi_options[] = { @@ -240,8 +341,16 @@ static > const AVOption sharpness_vaapi_options[] = { > { NULL }, > }; > > +#define ROFFSET(x) offsetof(RotationVAAPIContext, x) static const > +AVOption rotation_vaapi_options[] = { > + { "angle", "clockwise rotation angle 0/90/180/270 are only > supported", Should be better if sub-options can be added, just like cclock_flip option in transpose_options. > + ROFFSET(rotation), AV_OPT_TYPE_INT, { .i64 = > ROTATION_DEFAULT }, ROTATION_MIN, ROTATION_MAX, .flags = FLAGS }, > + { NULL }, > +}; > + > AVFILTER_DEFINE_CLASS(denoise_vaapi); > AVFILTER_DEFINE_CLASS(sharpness_vaapi); > +AVFILTER_DEFINE_CLASS(rotation_vaapi); > > static const AVFilterPad misc_vaapi_inputs[] = { > { > @@ -287,3 +396,16 @@ AVFilter ff_vf_sharpness_vaapi = { > .priv_class = &sharpness_vaapi_class, > .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; > + > +AVFilter ff_vf_rotation_vaapi = { > + .name = "rotation_vaapi", > + .description = NULL_IF_CONFIG_SMALL("VAAPI VPP for rotation"), > + .priv_size = sizeof(RotationVAAPIContext), > + .init = &rotation_vaapi_init, > + .uninit = &ff_vaapi_vpp_ctx_uninit, > + .query_formats = &ff_vaapi_vpp_query_formats, > + .inputs = misc_vaapi_inputs, > + .outputs = misc_vaapi_outputs, > + .priv_class = &rotation_vaapi_class, > + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; > -- > 2.17.1 The rest LGTM. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel