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);
54 
55  s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
56  if (!s->qf) {
57  av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
58  err = AVERROR(ENOTSUP);
59  goto fail;
60  }
61 
62  RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
63 
64  ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
65  (uint32_t [3]) { 1, 64, planes }, 0);
66 
67  const FFVulkanDescriptorSetBinding desc_set[] = {
68  { /* prev */
69  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
70  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
71  .elems = planes,
72  },
73  { /* cur */
74  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
75  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
76  .elems = planes,
77  },
78  { /* next */
79  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
80  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
81  .elems = planes,
82  },
83  { /* dst */
84  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
85  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
86  .elems = planes,
87  },
88  };
89  ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc_set, 4, 0, 0);
90 
92  VK_SHADER_STAGE_COMPUTE_BIT);
93 
94  RET(ff_vk_shader_link(vkctx, &s->shd,
96  ff_bwdif_comp_spv_len, "main"));
97  RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
98 
99  s->initialized = 1;
100 
101 fail:
102  return err;
103 }
104 
106  int parity, int tff)
107 {
108  BWDIFVulkanContext *s = ctx->priv;
109  YADIFContext *y = &s->yadif;
110  BWDIFParameters params = {
111  .parity = parity,
112  .tff = tff,
113  .current_field = y->current_field,
114  };
115 
116  ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd, dst,
117  (AVFrame *[]){ y->prev, y->cur, y->next }, 3,
118  VK_NULL_HANDLE, &params, sizeof(params));
119 
120  if (y->current_field == YADIF_FIELD_END)
122 }
123 
125 {
126  BWDIFVulkanContext *s = avctx->priv;
127  FFVulkanContext *vkctx = &s->vkctx;
128 
129  ff_vk_exec_pool_free(vkctx, &s->e);
130  ff_vk_shader_free(vkctx, &s->shd);
131 
132  ff_vk_uninit(&s->vkctx);
133 
134  ff_yadif_uninit(avctx);
135 
136  s->initialized = 0;
137 }
138 
140 {
142  AVHWFramesContext *input_frames;
143  AVFilterContext *avctx = inlink->dst;
144  BWDIFVulkanContext *s = avctx->priv;
145  FFVulkanContext *vkctx = &s->vkctx;
146 
147  if (!l->hw_frames_ctx) {
148  av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
149  "hardware frames context on the input.\n");
150  return AVERROR(EINVAL);
151  }
152 
153  input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
154  if (input_frames->format != AV_PIX_FMT_VULKAN)
155  return AVERROR(EINVAL);
156 
157  /* Extract the device and default output format from the first input. */
158  if (avctx->inputs[0] != inlink)
159  return 0;
160 
161  /* Save the ref, without reffing it */
162  vkctx->input_frames_ref = l->hw_frames_ctx;
163 
164  /* Defaults */
165  vkctx->output_format = input_frames->sw_format;
166  vkctx->output_width = inlink->w;
167  vkctx->output_height = inlink->h;
168 
169  return 0;
170 }
171 
173 {
174  FilterLink *l = ff_filter_link(outlink);
175  int err;
176  AVFilterContext *avctx = outlink->src;
177  BWDIFVulkanContext *s = avctx->priv;
178  YADIFContext *y = &s->yadif;
179  FFVulkanContext *vkctx = &s->vkctx;
180 
182 
183  err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref,
184  vkctx->output_width, vkctx->output_height,
185  vkctx->output_format);
186  if (err < 0)
187  return err;
188 
189  /* For logging */
190  vkctx->class = y->class;
191 
193  if (!l->hw_frames_ctx)
194  return AVERROR(ENOMEM);
195 
196  err = ff_yadif_config_output_common(outlink);
197  if (err < 0)
198  return err;
199 
200  y->csp = av_pix_fmt_desc_get(vkctx->frames->sw_format);
202 
203  if (AV_CEIL_RSHIFT(outlink->w, y->csp->log2_chroma_w) < 4 || AV_CEIL_RSHIFT(outlink->h, y->csp->log2_chroma_h) < 4) {
204  av_log(avctx, AV_LOG_ERROR, "Video with planes less than 4 columns or lines is not supported\n");
205  return AVERROR(EINVAL);
206  }
207 
208  return init_filter(avctx);
209 }
210 
211 static const AVClass bwdif_vulkan_class = {
212  .class_name = "bwdif_vulkan",
213  .item_name = av_default_item_name,
214  .option = ff_yadif_options,
215  .version = LIBAVUTIL_VERSION_INT,
216  .category = AV_CLASS_CATEGORY_FILTER,
217 };
218 
220  {
221  .name = "default",
222  .type = AVMEDIA_TYPE_VIDEO,
223  .filter_frame = ff_yadif_filter_frame,
224  .config_props = &bwdif_vulkan_config_input,
225  },
226 };
227 
229  {
230  .name = "default",
231  .type = AVMEDIA_TYPE_VIDEO,
232  .request_frame = ff_yadif_request_frame,
233  .config_props = &bwdif_vulkan_config_output,
234  },
235 };
236 
238  .p.name = "bwdif_vulkan",
239  .p.description = NULL_IF_CONFIG_SMALL("Deinterlace Vulkan frames via bwdif"),
240  .p.priv_class = &bwdif_vulkan_class,
241  .p.flags = AVFILTER_FLAG_HWDEVICE |
243  .priv_size = sizeof(BWDIFVulkanContext),
249  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
250 };
YADIFContext::class
const AVClass * class
Definition: yadif.h:52
FFVulkanContext::output_height
int output_height
Definition: vulkan.h:361
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:2789
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:355
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:264
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:313
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:2815
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:237
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:124
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:218
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:2582
FFVulkanContext::frames_ref
AVBufferRef * frames_ref
Definition: vulkan.h:352
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:40
FFVulkanDescriptorSetBinding::type
VkDescriptorType type
Definition: vulkan.h:114
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:139
FFFilter
Definition: filters.h:267
FFVulkanContext::output_width
int output_width
Definition: vulkan.h:360
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
static 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:299
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:265
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:2355
FFVulkanContext
Definition: vulkan.h:312
bwdif_vulkan_config_output
static int bwdif_vulkan_config_output(AVFilterLink *outlink)
Definition: vf_bwdif_vulkan.c:172
BWDIFParameters::parity
int parity
Definition: vf_bwdif_vulkan.c:40
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:199
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:208
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:362
FFVulkanContext::input_frames_ref
AVBufferRef * input_frames_ref
Definition: vulkan.h:351
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:46
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:290
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:1479
ff_vk_qf_find
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition: vulkan.c:286
BWDIFVulkanContext::qf
AVVulkanDeviceQueueFamily * qf
Definition: vf_bwdif_vulkan.c:35
bwdif_vulkan_class
static const AVClass bwdif_vulkan_class
Definition: vf_bwdif_vulkan.c:211
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:2482
bwdif_vulkan_outputs
static const AVFilterPad bwdif_vulkan_outputs[]
Definition: vf_bwdif_vulkan.c:228
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:219
planes
static const struct @554 planes[]
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
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
FFFilter::p
AVFilter p
The public AVFilter.
Definition: filters.h:271
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:105
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:353
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: filters.h:254
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:2072
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