diff --git a/configure b/configure index 37a738a0dd..d068b11073 100755 --- a/configure +++ b/configure @@ -3697,6 +3697,7 @@ transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" +vflip_vulkan_filter_deps="vulkan spirv_compiler" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" libvmaf_filter_deps="libvmaf pthreads" diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 7ac29e2114..0e27aeeff6 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -298,7 +298,7 @@ OBJS-$(CONFIG_GREYEDGE_FILTER) += vf_colorconstancy.o OBJS-$(CONFIG_GUIDED_FILTER) += vf_guided.o OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o framesync.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o -OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_hflip_vulkan.o vulkan.o +OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o @@ -493,6 +493,7 @@ OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VARBLUR_FILTER) += vf_varblur.o framesync.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o +OBJS-$(CONFIG_VFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_VFRDET_FILTER) += vf_vfrdet.o OBJS-$(CONFIG_VIBRANCE_FILTER) += vf_vibrance.o OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 82c50cba49..4bf17ef292 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -470,6 +470,7 @@ extern const AVFilter ff_vf_vaguedenoiser; extern const AVFilter ff_vf_varblur; extern const AVFilter ff_vf_vectorscope; extern const AVFilter ff_vf_vflip; +extern const AVFilter ff_vf_vflip_vulkan; extern const AVFilter ff_vf_vfrdet; extern const AVFilter ff_vf_vibrance; extern const AVFilter ff_vf_vidstabdetect; diff --git a/libavfilter/vf_hflip_vulkan.c b/libavfilter/vf_flip_vulkan.c similarity index 76% rename from libavfilter/vf_hflip_vulkan.c rename to libavfilter/vf_flip_vulkan.c index b3a3d0b2aa..e9e04db91b 100644 --- a/libavfilter/vf_hflip_vulkan.c +++ b/libavfilter/vf_flip_vulkan.c @@ -24,7 +24,12 @@ #define CGS 32 -typedef struct HFlipVulkanContext { +enum FlipType { + FLIP_VERTICAL, + FLIP_HORIZONTAL +}; + +typedef struct FlipVulkanContext { FFVulkanContext vkctx; FFVkQueueFamilyCtx qf; FFVkExecContext *exec; @@ -34,13 +39,13 @@ typedef struct HFlipVulkanContext { VkDescriptorImageInfo output_images[3]; int initialized; -} HFlipVulkanContext; +} FlipVulkanContext; -static av_cold int init_filter(AVFilterContext *avctx, AVFrame *in) +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type) { int err = 0; FFVkSPIRVShader *shd; - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = ctx->priv; FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); @@ -76,26 +81,37 @@ static av_cold int init_filter(AVFilterContext *avctx, AVFrame *in) if (!s->pl) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(s->pl, "hflip_compute", image_descs[0].stages); + shd = ff_vk_init_shader(s->pl, "flip_compute", image_descs[0].stages); if (!shd) return AVERROR(ENOMEM); ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 size; ); - GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); for (int i = 0; i < planes; i++) { - GLSLC(0, ); - GLSLF(1, size = imageSize(output_image[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); - GLSLF(2, imageStore(output_image[%i], pos, res); ,i); - GLSLC(1, } ); + GLSLC(0, ); + GLSLF(1, size = imageSize(output_image[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + switch (type) + { + case FLIP_HORIZONTAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); + break; + case FLIP_VERTICAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i); + break; + default: + GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); + break; + } + GLSLF(2, imageStore(output_image[%i], pos, res); ,i); + GLSLC(1, } ); } - GLSLC(0, } ); + GLSLC(0, } ); RET(ff_vk_compile_shader(vkctx, shd, "main")); RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); @@ -109,9 +125,9 @@ fail: return err; } -static av_cold void hflip_vulkan_uninit(AVFilterContext *avctx) +static av_cold void flip_vulkan_uninit(AVFilterContext *avctx) { - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = avctx->priv; ff_vk_uninit(&s->vkctx); s->initialized = 0; @@ -121,7 +137,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in { int err = 0; VkCommandBuffer cmd_buf; - HFlipVulkanContext *s = avctx->priv; + FlipVulkanContext *s = avctx->priv; FFVulkanContext *vkctx = &s->vkctx; FFVulkanFunctions *vk = &s->vkctx.vkfn; AVVkFrame *in = (AVVkFrame *)inframe->data[0]; @@ -210,12 +226,12 @@ fail: return err; } -static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) { int err; AVFrame *out = NULL; AVFilterContext *ctx = link->dst; - HFlipVulkanContext *s = ctx->priv; + FlipVulkanContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -225,7 +241,7 @@ static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) } if (!s->initialized) - RET(init_filter(ctx, in)); + RET(init_filter(ctx, in, type)); RET(process_frames(ctx, out, in)); @@ -241,6 +257,16 @@ fail: return err; } +static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return flip_vulkan_filter_frame(link, in, FLIP_HORIZONTAL); +} + +static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return flip_vulkan_filter_frame(link, in, FLIP_VERTICAL); +} + static const AVOption hflip_vulkan_options[] = { { NULL }, }; @@ -256,7 +282,7 @@ static const AVFilterPad hflip_vulkan_inputs[] = { } }; -static const AVFilterPad hflip_vulkan_outputs[] = { +static const AVFilterPad flip_vulkan_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, @@ -267,12 +293,40 @@ static const AVFilterPad hflip_vulkan_outputs[] = { const AVFilter ff_vf_hflip_vulkan = { .name = "hflip_vulkan", .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"), - .priv_size = sizeof(HFlipVulkanContext), + .priv_size = sizeof(FlipVulkanContext), .init = &ff_vk_filter_init, - .uninit = &hflip_vulkan_uninit, + .uninit = &flip_vulkan_uninit, FILTER_INPUTS(hflip_vulkan_inputs), - FILTER_OUTPUTS(hflip_vulkan_outputs), + FILTER_OUTPUTS(flip_vulkan_outputs), FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), .priv_class = &hflip_vulkan_class, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +static const AVOption vflip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(vflip_vulkan); + +static const AVFilterPad vflip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &vflip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_vflip_vulkan = { + .name = "vflip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Vertically flip the input video in Vulkan"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(vflip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &vflip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +};