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. +} 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: + 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", + 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel