FFmpeg
vf_bwdif_vulkan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Lynne
3  * Copyright (C) 2018 Philip Langdale <philipl@overt.org>
4  * Copyright (C) 2016 Thomas Mundt <loudmax@yahoo.de>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavutil/random_seed.h"
24 #include "libavutil/opt.h"
25 #include "vulkan_filter.h"
26 #include "yadif.h"
27 #include "filters.h"
28 
29 typedef struct BWDIFVulkanContext {
32 
38 
39 typedef struct BWDIFParameters {
40  int parity;
41  int tff;
44 
45 extern const unsigned char ff_bwdif_comp_spv_data[];
46 extern const unsigned int ff_bwdif_comp_spv_len;
47 
49 {
50  int err;
51  BWDIFVulkanContext *s = ctx->priv;
52  FFVulkanContext *vkctx = &s->vkctx;
53  const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
55 
56  s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
57  if (!s->qf) {
58  av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
59  err = AVERROR(ENOTSUP);
60  goto fail;
61  }
62 
63  RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
64 
65  ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
66  (uint32_t [3]) { 1, 64, planes }, 0);
67 
69  {
70  .name = "prev",
71  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
72  .elems = planes,
73  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
74  },
75  {
76  .name = "cur",
77  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
78  .elems = planes,
79  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
80  },
81  {
82  .name = "next",
83  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
84  .elems = planes,
85  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
86  },
87  {
88  .name = "dst",
89  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
90  .elems = planes,
91  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
92  },
93  };
94 
95  ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 4, 0, 0);
96 
98  VK_SHADER_STAGE_COMPUTE_BIT);
99 
100  RET(ff_vk_shader_link(vkctx, &s->shd,
102  ff_bwdif_comp_spv_len, "main"));
103  RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
104 
105  s->initialized = 1;
106 
107 fail:
108  return err;
109 }
110 
112  int parity, int tff)
113 {
114  BWDIFVulkanContext *s = ctx->priv;
115  YADIFContext *y = &s->yadif;
116  BWDIFParameters params = {
117  .parity = parity,
118  .tff = tff,
119  .current_field = y->current_field,
120  };
121 
122  ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, dst,
123  (AVFrame *[]){ y->prev, y->cur, y->next }, 3,
124  VK_NULL_HANDLE, &params, sizeof(params));
125 
126  if (y->current_field == YADIF_FIELD_END)
128 }
129 
131 {
132  BWDIFVulkanContext *s = avctx->priv;
133  FFVulkanContext *vkctx = &s->vkctx;
134 
135  ff_vk_exec_pool_free(vkctx, &s->e);
136  ff_vk_shader_free(vkctx, &s->shd);
137 
138  ff_vk_uninit(&s->vkctx);
139 
140  ff_yadif_uninit(avctx);
141 
142  s->initialized = 0;
143 }
144 
146 {
148  AVHWFramesContext *input_frames;
149  AVFilterContext *avctx = inlink->dst;
150  BWDIFVulkanContext *s = avctx->priv;
151  FFVulkanContext *vkctx = &s->vkctx;
152 
153  if (!l->hw_frames_ctx) {
154  av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
155  "hardware frames context on the input.\n");
156  return AVERROR(EINVAL);
157  }
158 
159  input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
160  if (input_frames->format != AV_PIX_FMT_VULKAN)
161  return AVERROR(EINVAL);
162 
163  /* Extract the device and default output format from the first input. */
164  if (avctx->inputs[0] != inlink)
165  return 0;
166 
167  /* Save the ref, without reffing it */
168  vkctx->input_frames_ref = l->hw_frames_ctx;
169 
170  /* Defaults */
171  vkctx->output_format = input_frames->sw_format;
172  vkctx->output_width = inlink->w;
173  vkctx->output_height = inlink->h;
174 
175  return 0;
176 }
177 
179 {
180  FilterLink *l = ff_filter_link(outlink);
181  int err;
182  AVFilterContext *avctx = outlink->src;
183  BWDIFVulkanContext *s = avctx->priv;
184  YADIFContext *y = &s->yadif;
185  FFVulkanContext *vkctx = &s->vkctx;
186 
188 
189  err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref,
190  vkctx->output_width, vkctx->output_height,
191  vkctx->output_format);
192  if (err < 0)
193  return err;
194 
195  /* For logging */
196  vkctx->class = y->class;
197 
199  if (!l->hw_frames_ctx)
200  return AVERROR(ENOMEM);
201 
202  err = ff_yadif_config_output_common(outlink);
203  if (err < 0)
204  return err;
205 
206  y->csp = av_pix_fmt_desc_get(vkctx->frames->sw_format);
208 
209  if (AV_CEIL_RSHIFT(outlink->w, y->csp->log2_chroma_w) < 4 || AV_CEIL_RSHIFT(outlink->h, y->csp->log2_chroma_h) < 4) {
210  av_log(avctx, AV_LOG_ERROR, "Video with planes less than 4 columns or lines is not supported\n");
211  return AVERROR(EINVAL);
212  }
213 
214  return init_filter(avctx);
215 }
216 
217 static const AVClass bwdif_vulkan_class = {
218  .class_name = "bwdif_vulkan",
219  .item_name = av_default_item_name,
220  .option = ff_yadif_options,
221  .version = LIBAVUTIL_VERSION_INT,
222  .category = AV_CLASS_CATEGORY_FILTER,
223 };
224 
226  {
227  .name = "default",
228  .type = AVMEDIA_TYPE_VIDEO,
229  .filter_frame = ff_yadif_filter_frame,
230  .config_props = &bwdif_vulkan_config_input,
231  },
232 };
233 
235  {
236  .name = "default",
237  .type = AVMEDIA_TYPE_VIDEO,
238  .request_frame = ff_yadif_request_frame,
239  .config_props = &bwdif_vulkan_config_output,
240  },
241 };
242 
244  .p.name = "bwdif_vulkan",
245  .p.description = NULL_IF_CONFIG_SMALL("Deinterlace Vulkan frames via bwdif"),
246  .p.priv_class = &bwdif_vulkan_class,
247  .p.flags = AVFILTER_FLAG_HWDEVICE |
249  .priv_size = sizeof(BWDIFVulkanContext),
255  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
256 };
YADIFContext::class
const AVClass * class
Definition: yadif.h:52
FFVulkanContext::output_height
int output_height
Definition: vulkan.h:362
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ff_vk_shader_free
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition: vulkan.c:2984
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
RET
#define RET(x)
Definition: vulkan.h:68
ff_vk_exec_pool_init
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
Definition: vulkan.c:366
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:200
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
YADIFContext::csp
const AVPixFmtDescriptor * csp
Definition: yadif.h:76
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:263
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
ff_vk_filter_init
int ff_vk_filter_init(AVFilterContext *avctx)
General lavfi IO functions.
Definition: vulkan_filter.c:233
FFVulkanContext::class
const AVClass * class
Definition: vulkan.h:314
BWDIFParameters::current_field
int current_field
Definition: vf_bwdif_vulkan.c:42
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:3010
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:220
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
ff_vf_bwdif_vulkan
const FFFilter ff_vf_bwdif_vulkan
Definition: vf_bwdif_vulkan.c:243
BWDIFParameters::tff
int tff
Definition: vf_bwdif_vulkan.c:41
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3496
ff_yadif_config_output_common
int ff_yadif_config_output_common(AVFilterLink *outlink)
Definition: yadif_common.c:208
bwdif_vulkan_uninit
static void bwdif_vulkan_uninit(AVFilterContext *avctx)
Definition: vf_bwdif_vulkan.c:130
BWDIFVulkanContext::shd
FFVulkanShader shd
Definition: vf_bwdif_vulkan.c:36
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:289
fail
#define fail()
Definition: checkasm.h:216
vulkan_filter.h
ff_vk_filter_init_context
int ff_vk_filter_init_context(AVFilterContext *avctx, FFVulkanContext *s, AVBufferRef *frames_ref, int width, int height, enum AVPixelFormat sw_format)
Can be called manually, if not using ff_vk_filter_config_output.
Definition: vulkan_filter.c:25
ff_vk_shader_register_exec
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition: vulkan.c:2637
FFVulkanContext::frames_ref
AVBufferRef * frames_ref
Definition: vulkan.h:353
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:39
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
av_cold
#define av_cold
Definition: attributes.h:106
bwdif_vulkan_config_input
static int bwdif_vulkan_config_input(AVFilterLink *inlink)
Definition: vf_bwdif_vulkan.c:145
FFFilter
Definition: filters.h:266
FFVulkanContext::output_width
int output_width
Definition: vulkan.h:361
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AVPixFmtDescriptor::log2_chroma_w
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:80
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:301
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:264
if
if(ret)
Definition: filter_design.txt:179
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
BWDIFVulkanContext::initialized
int initialized
Definition: vf_bwdif_vulkan.c:33
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:76
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:282
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:242
ff_vk_shader_link
int ff_vk_shader_link(FFVulkanContext *s, FFVulkanShader *shd, const char *spirv, size_t spirv_len, const char *entrypoint)
Link a shader into an executable.
Definition: vulkan.c:2393
FFVulkanContext
Definition: vulkan.h:313
bwdif_vulkan_config_output
static int bwdif_vulkan_config_output(AVFilterLink *outlink)
Definition: vf_bwdif_vulkan.c:178
BWDIFParameters::parity
int parity
Definition: vf_bwdif_vulkan.c:40
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:198
AV_CLASS_CATEGORY_FILTER
@ AV_CLASS_CATEGORY_FILTER
Definition: log.h:36
FF_FILTER_FLAG_HWFRAME_AWARE
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition: filters.h:207
ff_yadif_options
const AVOption ff_yadif_options[]
Definition: yadif_common.c:263
ff_vk_filter_process_Nin
int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e, FFVulkanShader *shd, AVFrame *out, AVFrame *in[], int nb_in, VkSampler sampler, void *push_src, size_t push_size)
Up to 16 inputs, one output.
Definition: vulkan_filter.c:407
yadif.h
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:550
FFVulkanDescriptorSetBinding
Definition: vulkan.h:112
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
BWDIFVulkanContext::vkctx
FFVulkanContext vkctx
Definition: vf_bwdif_vulkan.c:31
AVFILTER_FLAG_HWDEVICE
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
Definition: avfilter.h:188
YADIFContext::filter
void(* filter)(AVFilterContext *ctx, AVFrame *dstpic, int parity, int tff)
Definition: yadif.h:65
FFVulkanShader
Definition: vulkan.h:225
parity
mcdeint parity
Definition: vf_mcdeint.c:289
BWDIFVulkanContext::yadif
YADIFContext yadif
Definition: vf_bwdif_vulkan.c:30
FFVulkanContext::output_format
enum AVPixelFormat output_format
Definition: vulkan.h:363
FFVulkanContext::input_frames_ref
AVBufferRef * input_frames_ref
Definition: vulkan.h:352
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
BWDIFVulkanContext
Definition: vf_bwdif_vulkan.c:29
YADIFContext
Definition: yadif.h:51
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:45
BWDIFVulkanContext::e
FFVkExecPool e
Definition: vf_bwdif_vulkan.c:34
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:81
FFVkExecPool
Definition: vulkan.h:291
ff_vk_shader_add_push_const
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition: vulkan.c:1498
ff_vk_qf_find
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition: vulkan.c:288
BWDIFVulkanContext::qf
AVVulkanDeviceQueueFamily * qf
Definition: vf_bwdif_vulkan.c:35
bwdif_vulkan_class
static const AVClass bwdif_vulkan_class
Definition: vf_bwdif_vulkan.c:217
planes
static const struct @549 planes[]
ff_vk_shader_add_descriptor_set
int ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular, int print_to_shader_only)
Add descriptor to a shader.
Definition: vulkan.c:2525
bwdif_vulkan_outputs
static const AVFilterPad bwdif_vulkan_outputs[]
Definition: vf_bwdif_vulkan.c:234
random_seed.h
YADIF_FIELD_END
@ YADIF_FIELD_END
The first or last field in a sequence.
Definition: yadif.h:47
ff_yadif_request_frame
int ff_yadif_request_frame(AVFilterLink *link)
Definition: yadif_common.c:174
ff_bwdif_comp_spv_data
const unsigned char ff_bwdif_comp_spv_data[]
bwdif_vulkan_inputs
static const AVFilterPad bwdif_vulkan_inputs[]
Definition: vf_bwdif_vulkan.c:225
AVFilterContext
An instance of a filter.
Definition: avfilter.h:274
YADIF_FIELD_NORMAL
@ YADIF_FIELD_NORMAL
A normal field in the middle of a sequence.
Definition: yadif.h:48
desc
const char * desc
Definition: libsvtav1.c:78
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
FFFilter::p
AVFilter p
The public AVFilter.
Definition: filters.h:270
ff_yadif_uninit
void ff_yadif_uninit(AVFilterContext *ctx)
Definition: yadif_common.c:248
YADIFContext::current_field
int current_field
YADIFCurrentField.
Definition: yadif.h:88
bwdif_vulkan_filter_frame
static void bwdif_vulkan_filter_frame(AVFilterContext *ctx, AVFrame *dst, int parity, int tff)
Definition: vf_bwdif_vulkan.c:111
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition: avfilter.h:205
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
init_filter
static av_cold int init_filter(AVFilterContext *ctx)
Definition: vf_bwdif_vulkan.c:48
AVVulkanDeviceQueueFamily
Definition: hwcontext_vulkan.h:33
BWDIFParameters
Definition: vf_bwdif_vulkan.c:39
FFVulkanContext::frames
AVHWFramesContext * frames
Definition: vulkan.h:354
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: filters.h:253
ff_bwdif_comp_spv_len
const unsigned int ff_bwdif_comp_spv_len
ff_vk_shader_load
int ff_vk_shader_load(FFVulkanShader *shd, VkPipelineStageFlags stage, VkSpecializationInfo *spec, uint32_t wg_size[3], uint32_t required_subgroup_size)
Initialize a shader object.
Definition: vulkan.c:2091
AVPixFmtDescriptor::log2_chroma_h
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:89
ff_yadif_filter_frame
int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame)
Definition: yadif_common.c:99