[FFmpeg-devel] [PATCH v3] libavfilter: add a gblur_vulkan filter

Chen, Wenbin wenbin.chen at intel.com
Mon Nov 8 03:43:34 EET 2021


> 9 Sept 2021, 07:44 by jianhua.wu at intel.com:
> 
> > This commit adds a powerful and customizable gblur Vulkan filter,
> > which provides a maximum 127x127 kernel size of Gaussian Filter.
> > The size could be adjusted by requirements on quality or performance.
> >
> > The following command is on how to apply gblur_vulkan filter:
> >
> > ffmpeg -init_hw_device vulkan=vul:0 -filter_hw_device vul -i input.264
> > -vf
> hwupload=extra_hw_frames=16,gblur_vulkan,hwdownload,format=yuv420p
> > output.264
> >
> > Signed-off-by: Wu Jianhua <jianhua.wu at intel.com>
> > ---
> >  configure                     |   1 +
> >  libavfilter/Makefile          |   1 +
> >  libavfilter/allfilters.c      |   1 +
> >  libavfilter/vf_gblur_vulkan.c | 511
> ++++++++++++++++++++++++++++++++++
> >  4 files changed, 514 insertions(+)
> >  create mode 100644 libavfilter/vf_gblur_vulkan.c
> >
> > diff --git a/configure b/configure
> > index af410a9d11..4b9a0d8e07 100755
> > --- a/configure
> > +++ b/configure
> > @@ -3601,6 +3601,7 @@ freezedetect_filter_select="scene_sad"
> >  frei0r_filter_deps="frei0r libdl"
> >  frei0r_src_filter_deps="frei0r libdl"
> >  fspp_filter_deps="gpl"
> > +gblur_vulkan_filter_deps="vulkan_lib libglslang"
> >  histeq_filter_deps="gpl"
> >  hqdn3d_filter_deps="gpl"
> >  interlace_filter_deps="gpl"
> > diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> > index af957a5ac0..5f74e33599 100644
> > --- a/libavfilter/Makefile
> > +++ b/libavfilter/Makefile
> > @@ -286,6 +286,7 @@ OBJS-$(CONFIG_FREEZEFRAMES_FILTER)           +=
> vf_freezeframes.o
> >  OBJS-$(CONFIG_FREI0R_FILTER)                 += vf_frei0r.o
> >  OBJS-$(CONFIG_FSPP_FILTER)                   += vf_fspp.o qp_table.o
> >  OBJS-$(CONFIG_GBLUR_FILTER)                  += vf_gblur.o
> > +OBJS-$(CONFIG_GBLUR_VULKAN_FILTER)           += vf_gblur_vulkan.o
> vulkan.o
> >  OBJS-$(CONFIG_GEQ_FILTER)                    += vf_geq.o
> >  OBJS-$(CONFIG_GRADFUN_FILTER)                += vf_gradfun.o
> >  OBJS-$(CONFIG_GRAPHMONITOR_FILTER)           += f_graphmonitor.o
> > diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> > index 0c6b2347c8..b5576de3af 100644
> > --- a/libavfilter/allfilters.c
> > +++ b/libavfilter/allfilters.c
> > @@ -271,6 +271,7 @@ extern const AVFilter ff_vf_freezeframes;
> >  extern const AVFilter ff_vf_frei0r;
> >  extern const AVFilter ff_vf_fspp;
> >  extern const AVFilter ff_vf_gblur;
> > +extern const AVFilter ff_vf_gblur_vulkan;
> >  extern const AVFilter ff_vf_geq;
> >  extern const AVFilter ff_vf_gradfun;
> >  extern const AVFilter ff_vf_graphmonitor;
> > diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c
> > new file mode 100644
> > index 0000000000..5c072f8971
> > --- /dev/null
> > +++ b/libavfilter/vf_gblur_vulkan.c
> > @@ -0,0 +1,511 @@
> > +/*
> > + * copyright (c) 2021 Wu Jianhua <jianhua.wu at intel.com>
> > + * 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 "libavutil/random_seed.h"
> > +#include "libavutil/opt.h"
> > +#include "vulkan.h"
> > +#include "internal.h"
> > +
> > +#define CGS 32
> > +#define GBLUR_MAX_KERNEL_SIZE 127
> > +
> > +typedef struct GBlurVulkanContext {
> > +    VulkanFilterContext vkctx;
> > +    FFVkExecContext *exec;
> > +    VulkanPipeline *pl_hor;
> > +    VulkanPipeline *pl_ver;
> > +    FFVkBuffer params_buf_hor;
> > +    FFVkBuffer params_buf_ver;
> > +
> > +    VkDescriptorImageInfo input_images[3];
> > +    VkDescriptorImageInfo tmp_images[3];
> > +    VkDescriptorImageInfo output_images[3];
> > +    VkDescriptorBufferInfo params_desc_hor;
> > +    VkDescriptorBufferInfo params_desc_ver;
> > +
> > +    int initialized;
> > +    int size;
> > +    int planes;
> > +    int kernel_size;
> > +    float sigma;
> > +    float sigmaV;
> > +    AVFrame *tmpframe;
> > +} GBlurVulkanContext;
> > +
> > +static const char gblur_horizontal[] = {
> > +    C(0, void gblur(const ivec2 pos, const int index)                                  )
> > +    C(0, {                                                                             )
> > +    C(1,     vec4 sum = texture(input_image[index], pos) *
> kernel[0];                  )
> > +    C(0,                                                                               )
> > +    C(1,     for(int i = 1; i < kernel.length(); i++) {                                )
> > +    C(2,         sum += texture(input_image[index], pos + vec2(i, 0.0)) *
> kernel[i];   )
> > +    C(2,         sum += texture(input_image[index], pos - vec2(i, 0.0)) *
> kernel[i];   )
> > +    C(1,     }                                                                         )
> > +    C(0,                                                                               )
> > +    C(1,     imageStore(output_image[index], pos, sum);                                )
> > +    C(0, }                                                                             )
> > +};
> > +
> > +static const char gblur_vertical[] = {
> > +    C(0, void gblur(const ivec2 pos, const int index)                                  )
> > +    C(0, {                                                                             )
> > +    C(1,     vec4 sum = texture(input_image[index], pos) *
> kernel[0];                  )
> > +    C(0,                                                                               )
> > +    C(1,     for(int i = 1; i < kernel.length(); i++) {                                )
> > +    C(2,         sum += texture(input_image[index], pos + vec2(0.0, i)) *
> kernel[i];   )
> > +    C(2,         sum += texture(input_image[index], pos - vec2(0.0, i)) *
> kernel[i];   )
> > +    C(1,     }                                                                         )
> > +    C(0,                                                                               )
> > +    C(1,     imageStore(output_image[index], pos, sum);                                )
> > +    C(0, }                                                                             )
> > +};
> >
> 
> The reason why avgblur_vulkan is split into horizontal and vertical
> was because you can change the blur radius in either direction.
> This is always going to be square, so to speed it up significantly,
> you can just do it all at once in both directions.
> 
> By the way, I've written a replacement for the synchronization
> system that uses timeline semaphores. The repo is at
> https://github.com/cyanreg/FFmpeg/tree/vulkan
> I'll be pushing it in a few days once someone reviews it.
> You can adapt your patches to that.
> 
> I've CC'd Wenbin Chen here too. I think your single_memory
> flag patch is reasonable, could you rebase it onto the branch and
> resubmit?

Ok, I will resubmit it.


More information about the ffmpeg-devel mailing list