FFmpeg
vf_blend_vulkan.c
Go to the documentation of this file.
1 /*
2  * copyright (c) 2021-2022 Wu Jianhua <jianhua.wu@intel.com>
3  * The blend modes are based on the blend.c.
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/random_seed.h"
23 #include "libavutil/opt.h"
24 #include "vulkan_filter.h"
25 #include "internal.h"
26 #include "framesync.h"
27 #include "blend.h"
28 
29 #define CGS 32
30 
31 #define IN_TOP 0
32 #define IN_BOTTOM 1
33 
34 typedef struct FilterParamsVulkan {
35  const char *blend;
36  const char *blend_func;
37  double opacity;
40 
41 typedef struct BlendVulkanContext {
47 
48  VkDescriptorImageInfo top_images[3];
49  VkDescriptorImageInfo bottom_images[3];
50  VkDescriptorImageInfo output_images[3];
51 
53  double all_opacity;
55 
58 
59 #define DEFINE_BLEND_MODE(MODE, EXPR) \
60 static const char blend_##MODE[] = "blend_"#MODE; \
61 static const char blend_##MODE##_func[] = { \
62  C(0, vec4 blend_##MODE(vec4 top, vec4 bottom, float opacity) { ) \
63  C(1, vec4 dst = EXPR; ) \
64  C(1, return dst; ) \
65  C(0, } ) \
66 };
67 
68 #define A top
69 #define B bottom
70 
71 #define FN(EXPR) A + ((EXPR) - A) * opacity
72 
73 DEFINE_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity))
74 DEFINE_BLEND_MODE(MULTIPLY, FN(1.0f * A * B / 1.0f))
75 
76 static inline void init_blend_func(FilterParamsVulkan *param)
77 {
78 #define CASE(MODE) case BLEND_##MODE: \
79  param->blend = blend_##MODE;\
80  param->blend_func = blend_##MODE##_func; \
81  break;
82 
83  switch (param->mode) {
84  CASE(NORMAL)
85  CASE(MULTIPLY)
86  default: param->blend = NULL; break;
87  }
88 
89 #undef CASE
90 }
91 
92 static int config_params(AVFilterContext *avctx)
93 {
94  BlendVulkanContext *s = avctx->priv;
95 
96  for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) {
97  FilterParamsVulkan *param = &s->params[plane];
98 
99  if (s->all_mode >= 0)
100  param->mode = s->all_mode;
101  if (s->all_opacity < 1)
102  param->opacity = s->all_opacity;
103 
104  init_blend_func(param);
105  if (!param->blend) {
106  av_log(avctx, AV_LOG_ERROR,
107  "Currently the blend mode specified is not supported yet.\n");
108  return AVERROR(EINVAL);
109  }
110  }
111 
112  return 0;
113 }
114 
115 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
116  char *res, int res_len, int flags)
117 {
118  int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
119  if (ret < 0)
120  return ret;
121 
122  return config_params(ctx);
123 }
124 
126 {
127  int err = 0;
128  FFVkSampler *sampler;
129  FFVkSPIRVShader *shd;
130  BlendVulkanContext *s = avctx->priv;
131  FFVulkanContext *vkctx = &s->vkctx;
132  const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
133 
134  ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0);
135 
136  sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR);
137  if (!sampler)
138  return AVERROR_EXTERNAL;
139 
140  s->pl = ff_vk_create_pipeline(vkctx, &s->qf);
141  if (!s->pl)
142  return AVERROR(ENOMEM);
143 
144  {
145  FFVulkanDescriptorSetBinding image_descs[] = {
146  {
147  .name = "top_images",
148  .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
149  .dimensions = 2,
150  .elems = planes,
151  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
152  .updater = s->top_images,
153  .sampler = sampler,
154  },
155  {
156  .name = "bottom_images",
157  .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
158  .dimensions = 2,
159  .elems = planes,
160  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
161  .updater = s->bottom_images,
162  .sampler = sampler,
163  },
164  {
165  .name = "output_images",
166  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
167  .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format),
168  .mem_quali = "writeonly",
169  .dimensions = 2,
170  .elems = planes,
171  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
172  .updater = s->output_images,
173  },
174  };
175 
176  shd = ff_vk_init_shader(s->pl, "blend_compute", image_descs[0].stages);
177  if (!shd)
178  return AVERROR(ENOMEM);
179 
180  ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 });
181  RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0));
182 
183  for (int i = 0, j = 0; i < planes; i++) {
184  for (j = 0; j < i; j++)
185  if (s->params[i].blend_func == s->params[j].blend_func)
186  break;
187  /* note: the bracket is needed, for GLSLD is a macro with multiple statements. */
188  if (j == i) {
189  GLSLD(s->params[i].blend_func);
190  }
191  }
192 
193  GLSLC(0, void main() );
194  GLSLC(0, { );
195  GLSLC(1, ivec2 size; );
196  GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); );
197  for (int i = 0; i < planes; i++) {
198  GLSLC(0, );
199  GLSLF(1, size = imageSize(output_images[%i]); ,i);
200  GLSLC(1, if (IS_WITHIN(pos, size)) { );
201  GLSLF(2, const vec4 top = texture(top_images[%i], pos); ,i);
202  GLSLF(2, const vec4 bottom = texture(bottom_images[%i], pos); ,i);
203  GLSLF(2, const float opacity = %f; ,s->params[i].opacity);
204  GLSLF(2, vec4 dst = %s(top, bottom, opacity); ,s->params[i].blend);
205  GLSLC(0, );
206  GLSLF(2, imageStore(output_images[%i], pos, dst); ,i);
207  GLSLC(1, } );
208  }
209  GLSLC(0, } );
210 
211  RET(ff_vk_compile_shader(vkctx, shd, "main"));
212  RET(ff_vk_init_pipeline_layout(vkctx, s->pl));
213  RET(ff_vk_init_compute_pipeline(vkctx, s->pl));
214  }
215 
216  RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf));
217 
218  s->initialized = 1;
219 
220 fail:
221  return err;
222 }
223 
224 static int process_frames(AVFilterContext *avctx, AVFrame *out_frame, AVFrame *top_frame, AVFrame *bottom_frame)
225 {
226  int err = 0;
227  VkCommandBuffer cmd_buf;
228  BlendVulkanContext *s = avctx->priv;
229  FFVulkanContext *vkctx = &s->vkctx;
230  FFVulkanFunctions *vk = &s->vkctx.vkfn;
231  const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
232 
233  AVVkFrame *out = (AVVkFrame *)out_frame->data[0];
234  AVVkFrame *top = (AVVkFrame *)top_frame->data[0];
235  AVVkFrame *bottom = (AVVkFrame *)bottom_frame->data[0];
236 
237  AVHWFramesContext *top_fc = (AVHWFramesContext*)top_frame->hw_frames_ctx->data;
238  AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom_frame->hw_frames_ctx->data;
239 
240  const VkFormat *top_formats = av_vkfmt_from_pixfmt(top_fc->sw_format);
241  const VkFormat *bottom_formats = av_vkfmt_from_pixfmt(bottom_fc->sw_format);
242  const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);
243 
244  ff_vk_start_exec_recording(vkctx, s->exec);
245  cmd_buf = ff_vk_get_exec_buf(s->exec);
246 
247  for (int i = 0; i < planes; i++) {
248  RET(ff_vk_create_imageview(vkctx, s->exec,
249  &s->top_images[i].imageView, top->img[i],
250  top_formats[i],
252 
253  RET(ff_vk_create_imageview(vkctx, s->exec,
254  &s->bottom_images[i].imageView, bottom->img[i],
255  bottom_formats[i],
257 
258  RET(ff_vk_create_imageview(vkctx, s->exec,
259  &s->output_images[i].imageView, out->img[i],
260  output_formats[i],
262 
263  s->top_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
264  s->bottom_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
265  s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
266  }
267 
268  ff_vk_update_descriptor_set(vkctx, s->pl, 0);
269 
270  for (int i = 0; i < planes; i++) {
271  VkImageMemoryBarrier barriers[] = {
272  {
273  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
274  .srcAccessMask = 0,
275  .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
276  .oldLayout = top->layout[i],
277  .newLayout = s->top_images[i].imageLayout,
278  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
279  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
280  .image = top->img[i],
281  .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
282  .subresourceRange.levelCount = 1,
283  .subresourceRange.layerCount = 1,
284  },
285  {
286  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
287  .srcAccessMask = 0,
288  .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
289  .oldLayout = bottom->layout[i],
290  .newLayout = s->bottom_images[i].imageLayout,
291  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
292  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
293  .image = bottom->img[i],
294  .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
295  .subresourceRange.levelCount = 1,
296  .subresourceRange.layerCount = 1,
297  },
298  {
299  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
300  .srcAccessMask = 0,
301  .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
302  .oldLayout = out->layout[i],
303  .newLayout = s->output_images[i].imageLayout,
304  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
305  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
306  .image = out->img[i],
307  .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
308  .subresourceRange.levelCount = 1,
309  .subresourceRange.layerCount = 1,
310  },
311  };
312 
313  vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
314  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
315  0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers);
316 
317  top->layout[i] = barriers[0].newLayout;
318  top->access[i] = barriers[0].dstAccessMask;
319 
320  bottom->layout[i] = barriers[1].newLayout;
321  bottom->access[i] = barriers[1].dstAccessMask;
322 
323  out->layout[i] = barriers[2].newLayout;
324  out->access[i] = barriers[2].dstAccessMask;
325  }
326 
327  ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);
328  vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS) / CGS,
329  FFALIGN(s->vkctx.output_height, CGS) / CGS, 1);
330 
331  ff_vk_add_exec_dep(vkctx, s->exec, top_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
332  ff_vk_add_exec_dep(vkctx, s->exec, bottom_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
333  ff_vk_add_exec_dep(vkctx, s->exec, out_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
334 
335  err = ff_vk_submit_exec_queue(vkctx, s->exec);
336  if (err)
337  return err;
338 
339  ff_vk_qf_rotate(&s->qf);
340 
341  return 0;
342 
343 fail:
344  ff_vk_discard_exec_deps(s->exec);
345  return err;
346 }
347 
349 {
350  int err;
351  AVFilterContext *avctx = fs->parent;
352  BlendVulkanContext *s = avctx->priv;
353  AVFilterLink *outlink = avctx->outputs[0];
354  AVFrame *top, *bottom, *out;
355 
356  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
357  if (!out) {
358  err = AVERROR(ENOMEM);
359  goto fail;
360  }
361 
362  RET(ff_framesync_get_frame(fs, IN_TOP, &top, 0));
363  RET(ff_framesync_get_frame(fs, IN_BOTTOM, &bottom, 0));
364 
365  RET(av_frame_copy_props(out, top));
366 
367  if (!s->initialized) {
369  AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom->hw_frames_ctx->data;
370  if (top_fc->sw_format != bottom_fc->sw_format) {
371  av_log(avctx, AV_LOG_ERROR,
372  "Currently the sw format of the bottom video need to match the top!\n");
373  return AVERROR(EINVAL);
374  }
375  RET(init_filter(avctx));
376  }
377 
378  RET(process_frames(avctx, out, top, bottom));
379 
380  return ff_filter_frame(outlink, out);
381 
382 fail:
383  av_frame_free(&out);
384  return err;
385 }
386 
387 static av_cold int init(AVFilterContext *avctx)
388 {
389  BlendVulkanContext *s = avctx->priv;
390 
391  s->fs.on_event = blend_frame;
392 
393  return ff_vk_filter_init(avctx);
394 }
395 
396 static av_cold void uninit(AVFilterContext *avctx)
397 {
398  BlendVulkanContext *s = avctx->priv;
399 
400  ff_framesync_uninit(&s->fs);
401 
402  ff_vk_uninit(&s->vkctx);
403 
404  s->initialized = 0;
405 }
406 
407 static int config_props_output(AVFilterLink *outlink)
408 {
409  int err;
410  AVFilterContext *avctx = outlink->src;
411  BlendVulkanContext *s = avctx->priv;
412  AVFilterLink *toplink = avctx->inputs[IN_TOP];
413  AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM];
414 
415  if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) {
416  av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
417  "(size %dx%d) do not match the corresponding "
418  "second input link %s parameters (size %dx%d)\n",
419  avctx->input_pads[IN_TOP].name, toplink->w, toplink->h,
420  avctx->input_pads[IN_BOTTOM].name, bottomlink->w, bottomlink->h);
421  return AVERROR(EINVAL);
422  }
423 
424  outlink->sample_aspect_ratio = toplink->sample_aspect_ratio;
425  outlink->frame_rate = toplink->frame_rate;
426 
428 
429  RET(ff_framesync_init_dualinput(&s->fs, avctx));
430 
432  outlink->time_base = s->fs.time_base;
433 
434  RET(config_params(avctx));
435 
436 fail:
437  return err;
438 }
439 
440 static int activate(AVFilterContext *avctx)
441 {
442  BlendVulkanContext *s = avctx->priv;
443  return ff_framesync_activate(&s->fs);
444 }
445 
446 #define OFFSET(x) offsetof(BlendVulkanContext, x)
447 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
448 
449 static const AVOption blend_vulkan_options[] = {
450  { "c0_mode", "set component #0 blend mode", OFFSET(params[0].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" },
451  { "c1_mode", "set component #1 blend mode", OFFSET(params[1].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" },
452  { "c2_mode", "set component #2 blend mode", OFFSET(params[2].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" },
453  { "c3_mode", "set component #3 blend mode", OFFSET(params[3].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" },
454  { "all_mode", "set blend mode for all components", OFFSET(all_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, BLEND_NB - 1, FLAGS, "mode" },
455  { "normal", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_NORMAL }, 0, 0, FLAGS, "mode" },
456  { "multiply", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_MULTIPLY }, 0, 0, FLAGS, "mode" },
457 
458  { "c0_opacity", "set color component #0 opacity", OFFSET(params[0].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
459  { "c1_opacity", "set color component #1 opacity", OFFSET(params[1].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
460  { "c2_opacity", "set color component #2 opacity", OFFSET(params[2].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
461  { "c3_opacity", "set color component #3 opacity", OFFSET(params[3].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
462  { "all_opacity", "set opacity for all color components", OFFSET(all_opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS },
463 
464  { NULL }
465 };
466 
467 AVFILTER_DEFINE_CLASS(blend_vulkan);
468 
470  {
471  .name = "top",
472  .type = AVMEDIA_TYPE_VIDEO,
473  .config_props = &ff_vk_filter_config_input,
474  },
475  {
476  .name = "bottom",
477  .type = AVMEDIA_TYPE_VIDEO,
478  .config_props = &ff_vk_filter_config_input,
479  },
480 };
481 
482 
484  {
485  .name = "default",
486  .type = AVMEDIA_TYPE_VIDEO,
487  .config_props = &config_props_output,
488  }
489 };
490 
492  .name = "blend_vulkan",
493  .description = NULL_IF_CONFIG_SMALL("Blend two video frames in Vulkan"),
494  .priv_size = sizeof(BlendVulkanContext),
495  .init = &init,
496  .uninit = &uninit,
497  .activate = &activate,
501  .priv_class = &blend_vulkan_class,
502  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
503  .process_command = &process_command,
504 };
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:101
ff_framesync_configure
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition: framesync.c:134
planes
static const struct @346 planes[]
BlendVulkanContext::pl
FFVulkanPipeline * pl
Definition: vf_blend_vulkan.c:45
ff_vf_blend_vulkan
const AVFilter ff_vf_blend_vulkan
Definition: vf_blend_vulkan.c:491
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_comp_identity_map
const VkComponentMapping ff_comp_identity_map
Definition: vulkan.c:51
ff_framesync_uninit
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition: framesync.c:304
out
FILE * out
Definition: movenc.c:54
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: internal.h:374
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:969
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
ff_framesync_get_frame
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition: framesync.c:267
config_props_output
static int config_props_output(AVFilterLink *outlink)
Definition: vf_blend_vulkan.c:407
ff_vk_bind_pipeline_exec
void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, FFVulkanPipeline *pl)
Add a command to bind the completed pipeline and its descriptor sets.
Definition: vulkan.c:1264
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:99
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
FFVulkanDescriptorSetBinding::stages
VkShaderStageFlags stages
Definition: vulkan.h:86
init_blend_func
static void init_blend_func(FilterParamsVulkan *param)
Definition: vf_blend_vulkan.c:76
ff_vk_filter_init
int ff_vk_filter_init(AVFilterContext *avctx)
General lavfi IO functions.
Definition: vulkan_filter.c:184
B
#define B
Definition: vf_blend_vulkan.c:69
AVOption
AVOption.
Definition: opt.h:251
ff_vk_compile_shader
int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, const char *entrypoint)
Compiles the shader, entrypoint must be set to "main".
Definition: vulkan.c:849
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees the main Vulkan context.
Definition: vulkan.c:1379
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:165
FFFrameSync
Frame sync structure.
Definition: framesync.h:168
MULTIPLY
#define MULTIPLY(var, const)
Definition: 4xm.c:164
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:376
FFVkSampler
Definition: vulkan.h:74
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:351
BLEND_NB
@ BLEND_NB
Definition: blend.h:69
ff_vk_add_exec_dep
int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag)
Adds a frame as a queue dependency.
Definition: vulkan.c:509
ff_vk_get_exec_buf
VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e)
Gets the command buffer to use for this submission from the exe context.
Definition: vulkan.c:504
BlendVulkanContext::all_opacity
double all_opacity
Definition: vf_blend_vulkan.c:53
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2928
CGS
#define CGS
Definition: vf_blend_vulkan.c:29
BlendVulkanContext::fs
FFFrameSync fs
Definition: vf_blend_vulkan.c:46
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:217
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:407
fail
#define fail()
Definition: checkasm.h:134
init
static av_cold int init(AVFilterContext *avctx)
Definition: vf_blend_vulkan.c:387
BlendVulkanContext::params
FilterParamsVulkan params[4]
Definition: vf_blend_vulkan.c:52
vulkan_filter.h
blend_vulkan_outputs
static const AVFilterPad blend_vulkan_outputs[]
Definition: vf_blend_vulkan.c:483
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:49
OFFSET
#define OFFSET(x)
Definition: vf_blend_vulkan.c:446
AVFilterContext::input_pads
AVFilterPad * input_pads
array of input pads
Definition: avfilter.h:399
ff_vk_qf_init
void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits dev_family, int nb_queues)
Initialize a queue family with a specific number of queues.
Definition: vulkan.c:96
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
ff_vk_create_imageview
int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, VkImageView *v, VkImage img, VkFormat fmt, const VkComponentMapping map)
Create an imageview.
Definition: vulkan.c:742
blend_vulkan_inputs
static const AVFilterPad blend_vulkan_inputs[]
Definition: vf_blend_vulkan.c:469
s
#define s(width, name)
Definition: cbs_vp9.c:256
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Definition: opt.h:227
FilterParamsVulkan
Definition: vf_blend_vulkan.c:34
ff_vk_init_shader
FFVkSPIRVShader * ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, VkShaderStageFlags stage)
Inits a shader for a specific pipeline.
Definition: vulkan.c:795
ctx
AVFormatContext * ctx
Definition: movenc.c:48
BlendVulkanContext::bottom_images
VkDescriptorImageInfo bottom_images[3]
Definition: vf_blend_vulkan.c:49
activate
static int activate(AVFilterContext *avctx)
Definition: vf_blend_vulkan.c:440
init_filter
static av_cold int init_filter(AVFilterContext *avctx)
Definition: vf_blend_vulkan.c:125
BlendVulkanContext::initialized
int initialized
Definition: vf_blend_vulkan.c:56
BlendVulkanContext::exec
FFVkExecContext * exec
Definition: vf_blend_vulkan.c:44
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: internal.h:194
ff_vk_update_descriptor_set
void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, int set_id)
Updates a descriptor set via the updaters defined.
Definition: vulkan.c:1080
ff_vk_start_exec_recording
int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e)
Begin recording to the command buffer.
Definition: vulkan.c:463
BlendVulkanContext::qf
FFVkQueueFamilyCtx qf
Definition: vf_blend_vulkan.c:43
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:222
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:594
BLEND_MULTIPLY
@ BLEND_MULTIPLY
Definition: blend.h:42
GLSLD
#define GLSLD(D)
Definition: vulkan.h:47
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:258
BlendMode
BlendMode
Definition: blend.h:27
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:400
BlendVulkanContext::output_images
VkDescriptorImageInfo output_images[3]
Definition: vf_blend_vulkan.c:50
ff_vk_create_exec_ctx
int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, FFVkQueueFamilyCtx *qf)
Init an execution context for command recording and queue submission.
Definition: vulkan.c:385
ff_vk_filter_config_output
int ff_vk_filter_config_output(AVFilterLink *outlink)
Definition: vulkan_filter.c:133
ff_vk_qf_rotate
void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf)
Rotate through the queues in a queue family.
Definition: vulkan.c:132
config_params
static int config_params(AVFilterContext *avctx)
Definition: vf_blend_vulkan.c:92
blend_vulkan_options
static const AVOption blend_vulkan_options[]
Definition: vf_blend_vulkan.c:449
FFVulkanContext
Definition: vulkan.h:188
BlendVulkanContext
Definition: vf_blend_vulkan.c:41
A
#define A
Definition: vf_blend_vulkan.c:68
FFVulkanPipeline
Definition: vulkan.h:104
ff_vk_discard_exec_deps
void ff_vk_discard_exec_deps(FFVkExecContext *e)
Discards all queue dependencies.
Definition: vulkan.c:447
main
int main(int argc, char **argv)
Definition: avio_http_serve_files.c:99
FLAGS
#define FLAGS
Definition: vf_blend_vulkan.c:447
f
f
Definition: af_crystalizer.c:122
AVVkFrame::access
VkAccessFlagBits access[AV_NUM_DATA_POINTERS]
Updated after every barrier.
Definition: hwcontext_vulkan.h:240
FFVulkanDescriptorSetBinding
Definition: vulkan.h:78
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:115
ff_framesync_init_dualinput
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition: framesync.c:372
blend_frame
static int blend_frame(FFFrameSync *fs)
Definition: vf_blend_vulkan.c:348
AVVkFrame
Definition: hwcontext_vulkan.h:213
IN_TOP
#define IN_TOP
Definition: vf_blend_vulkan.c:31
ff_vk_init_pipeline_layout
int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl)
Initializes the pipeline layout after all shaders and descriptor sets have been finished.
Definition: vulkan.c:1116
size
int size
Definition: twinvq_data.h:10344
FFVkQueueFamilyCtx
Definition: vulkan.h:97
FilterParamsVulkan::opacity
double opacity
Definition: vf_blend_vulkan.c:37
IN_BOTTOM
#define IN_BOTTOM
Definition: vf_blend_vulkan.c:32
FilterParamsVulkan::blend_func
const char * blend_func
Definition: vf_blend_vulkan.c:36
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:842
ff_vk_submit_exec_queue
int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e)
Submits a command buffer to the queue for execution.
Definition: vulkan.c:590
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
FFVkExecContext
Definition: vulkan.h:154
FFVulkanDescriptorSetBinding::name
const char * name
Definition: vulkan.h:79
internal.h
av_vkfmt_from_pixfmt
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the format of each image up to the number of planes for a given sw_format.
Definition: hwcontext_stub.c:30
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: internal.h:184
CASE
#define CASE(MODE)
ff_vk_init_compute_pipeline
int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl)
Initializes a compute pipeline.
Definition: vulkan.c:1229
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
BlendVulkanContext::vkctx
FFVulkanContext vkctx
Definition: vf_blend_vulkan.c:42
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
blend.h
ff_vk_shader_rep_fmt
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt)
Gets the glsl format string for a pixel format.
Definition: vulkan.c:721
BlendVulkanContext::all_mode
enum BlendMode all_mode
Definition: vf_blend_vulkan.c:54
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:55
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:46
ff_vk_create_pipeline
FFVulkanPipeline * ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf)
Inits a pipeline.
Definition: vulkan.c:1220
AVFilter
Filter definition.
Definition: avfilter.h:161
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
ret
ret
Definition: filter_design.txt:187
pos
unsigned int pos
Definition: spdifenc.c:413
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:678
BlendVulkanContext::top_images
VkDescriptorImageInfo top_images[3]
Definition: vf_blend_vulkan.c:48
ff_vk_add_descriptor_set
int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, int num, int only_print_to_shader)
Adds a descriptor set to the shader and registers them in the pipeline.
Definition: vulkan.c:923
random_seed.h
framesync.h
uninit
static av_cold void uninit(AVFilterContext *avctx)
Definition: vf_blend_vulkan.c:396
FFVkSPIRVShader
Definition: vulkan.h:58
mode
mode
Definition: ebur128.h:83
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: vf_blend_vulkan.c:115
ff_vk_init_sampler
FFVkSampler * ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords, VkFilter filt)
Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit()
Definition: vulkan.c:670
DEFINE_BLEND_MODE
#define DEFINE_BLEND_MODE(MODE, EXPR)
Definition: vf_blend_vulkan.c:59
AVFilterContext
An instance of a filter.
Definition: avfilter.h:392
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:44
ff_vk_filter_config_input
int ff_vk_filter_config_input(AVFilterLink *inlink)
Definition: vulkan_filter.c:52
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
FilterParamsVulkan::mode
enum BlendMode mode
Definition: vf_blend_vulkan.c:38
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:241
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: internal.h:195
FilterParamsVulkan::blend
const char * blend
Definition: vf_blend_vulkan.c:35
ff_vk_set_compute_shader_sizes
void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3])
Writes the workgroup size for a shader.
Definition: vulkan.c:816
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FN
#define FN(EXPR)
Definition: vf_blend_vulkan.c:71
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(blend_vulkan)
ff_framesync_activate
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition: framesync.c:355
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234
RET
#define RET(x)
Definition: vulkan.h:52
FFVulkanFunctions
Definition: vulkan_functions.h:175
BLEND_NORMAL
@ BLEND_NORMAL
Definition: blend.h:29
process_frames
static int process_frames(AVFilterContext *avctx, AVFrame *out_frame, AVFrame *top_frame, AVFrame *bottom_frame)
Definition: vf_blend_vulkan.c:224
AVFilterContext::outputs
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:404