FFmpeg
vf_scale_vulkan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Lynne
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/random_seed.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/vulkan_spirv.h"
24 #include "vulkan_filter.h"
25 #include "scale_eval.h"
26 #include "filters.h"
27 #include "colorspace.h"
28 #include "video.h"
29 #include "libswscale/swscale.h"
30 
31 extern const unsigned char ff_debayer_comp_spv_data[];
32 extern const unsigned int ff_debayer_comp_spv_len;
33 
34 enum ScalerFunc {
37 
39 };
40 
44 
46 };
47 
48 typedef struct ScaleVulkanContext {
51 
56  VkSampler sampler;
57 
58  /* Push constants / options */
59  struct {
60  float yuv_matrix[4][4];
61  int crop_x;
62  int crop_y;
63  int crop_w;
64  int crop_h;
65  } opts;
66 
68  char *w_expr;
69  char *h_expr;
70 
75 
76 static const char scale_bilinear[] = {
77  C(0, vec4 scale_bilinear(int idx, ivec2 pos, vec2 crop_range, vec2 crop_off))
78  C(0, { )
79  C(1, vec2 npos = (vec2(pos) + 0.5f) / imageSize(output_img[idx]); )
80  C(1, npos *= crop_range; /* Reduce the range */ )
81  C(1, npos += crop_off; /* Offset the start */ )
82  C(1, return texture(input_img[idx], npos); )
83  C(0, } )
84 };
85 
86 static const char rgb2yuv[] = {
87  C(0, vec4 rgb2yuv(vec4 src, int fullrange) )
88  C(0, { )
89  C(1, src *= yuv_matrix; )
90  C(1, if (fullrange == 1) { )
91  C(2, src += vec4(0.0, 0.5, 0.5, 0.0); )
92  C(1, } else { )
93  C(2, src *= vec4(219.0 / 255.0, 224.0 / 255.0, 224.0 / 255.0, 1.0); )
94  C(2, src += vec4(16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 0.0); )
95  C(1, } )
96  C(1, return src; )
97  C(0, } )
98 };
99 
100 static const char write_nv12[] = {
101  C(0, void write_nv12(vec4 src, ivec2 pos) )
102  C(0, { )
103  C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); )
104  C(1, pos /= ivec2(2); )
105  C(1, imageStore(output_img[1], pos, vec4(src.g, src.b, 0.0, 0.0)); )
106  C(0, } )
107 };
108 
109 static const char write_420[] = {
110  C(0, void write_420(vec4 src, ivec2 pos) )
111  C(0, { )
112  C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); )
113  C(1, pos /= ivec2(2); )
114  C(1, imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0)); )
115  C(1, imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0)); )
116  C(0, } )
117 };
118 
119 static const char write_444[] = {
120  C(0, void write_444(vec4 src, ivec2 pos) )
121  C(0, { )
122  C(1, imageStore(output_img[0], pos, vec4(src.r, 0.0, 0.0, 0.0)); )
123  C(1, imageStore(output_img[1], pos, vec4(src.g, 0.0, 0.0, 0.0)); )
124  C(1, imageStore(output_img[2], pos, vec4(src.b, 0.0, 0.0, 0.0)); )
125  C(0, } )
126 };
127 
130 {
131  ScaleVulkanContext *s = ctx->priv;
133 
134  if (s->vkctx.output_format != s->vkctx.input_format) {
135  GLSLD( rgb2yuv );
136  }
137 
138  switch (s->vkctx.output_format) {
139  case AV_PIX_FMT_NV12: GLSLD(write_nv12); break;
140  case AV_PIX_FMT_YUV420P: GLSLD( write_420); break;
141  case AV_PIX_FMT_YUV444P: GLSLD( write_444); break;
142  default: break;
143  }
144 
145  GLSLC(0, void main() );
146  GLSLC(0, { );
147  GLSLC(1, ivec2 size; );
148  GLSLC(1, ivec2 pos = ivec2(gl_GlobalInvocationID.xy); );
149  GLSLF(1, vec2 in_d = vec2(%i, %i); ,in->width, in->height);
150  GLSLC(1, vec2 c_r = vec2(crop_w, crop_h) / in_d; );
151  GLSLC(1, vec2 c_o = vec2(crop_x, crop_y) / in_d; );
152  GLSLC(0, );
153 
154  if (s->vkctx.output_format == s->vkctx.input_format) {
155  for (int i = 0; i < desc[1].elems; i++) {
156  GLSLF(1, size = imageSize(output_img[%i]); ,i);
157  GLSLC(1, if (IS_WITHIN(pos, size)) { );
158  switch (s->scaler) {
159  case F_NEAREST:
160  case F_BILINEAR:
161  GLSLF(2, vec4 res = scale_bilinear(%i, pos, c_r, c_o); ,i);
162  GLSLF(2, imageStore(output_img[%i], pos, res); ,i);
163  break;
164  };
165  GLSLC(1, } );
166  }
167  } else {
168  GLSLC(1, vec4 res = scale_bilinear(0, pos, c_r, c_o); );
169  GLSLF(1, res = rgb2yuv(res, %i); ,s->out_range == AVCOL_RANGE_JPEG);
170  switch (s->vkctx.output_format) {
171  case AV_PIX_FMT_NV12: GLSLC(1, write_nv12(res, pos); ); break;
172  case AV_PIX_FMT_YUV420P: GLSLC(1, write_420(res, pos); ); break;
173  case AV_PIX_FMT_YUV444P: GLSLC(1, write_444(res, pos); ); break;
174  default: return AVERROR(EINVAL);
175  }
176  }
177 
178  GLSLC(0, } );
179 
180  if (s->vkctx.output_format != s->vkctx.input_format) {
181  const AVLumaCoefficients *lcoeffs;
182  double tmp_mat[3][3];
183 
185  if (!lcoeffs) {
186  av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n");
187  return AVERROR(EINVAL);
188  }
189 
190  ff_fill_rgb2yuv_table(lcoeffs, tmp_mat);
191 
192  for (int y = 0; y < 3; y++)
193  for (int x = 0; x < 3; x++)
194  s->opts.yuv_matrix[x][y] = tmp_mat[x][y];
195  s->opts.yuv_matrix[3][3] = 1.0;
196  }
197 
198  return 0;
199 }
200 
202 {
203  int err;
204  uint8_t *spv_data;
205  size_t spv_len;
206  void *spv_opaque = NULL;
207  VkFilter sampler_mode;
208  ScaleVulkanContext *s = ctx->priv;
209  FFVulkanContext *vkctx = &s->vkctx;
210  FFVulkanShader *shd = &s->shd;
211  FFVkSPIRVCompiler *spv;
213 
214  int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format);
215 
216  switch (s->scaler) {
217  case F_NEAREST:
218  sampler_mode = VK_FILTER_NEAREST;
219  break;
220  case F_BILINEAR:
221  sampler_mode = VK_FILTER_LINEAR;
222  break;
223  };
224 
225  spv = ff_vk_spirv_init();
226  if (!spv) {
227  av_log(ctx, AV_LOG_ERROR, "Unable to initialize SPIR-V compiler!\n");
228  return AVERROR_EXTERNAL;
229  }
230 
231  RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL));
232 
233  RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode));
234 
235  RET(ff_vk_shader_init(vkctx, &s->shd, "scale",
236  VK_SHADER_STAGE_COMPUTE_BIT,
237  NULL, 0,
238  32, 32, 1,
239  0));
240 
242  {
243  .name = "input_img",
244  .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
245  .mem_layout = NULL,
246  .mem_quali = "readonly",
247  .dimensions = 2,
248  .elems = in_planes,
249  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
250  .samplers = DUP_SAMPLER(s->sampler),
251  },
252  {
253  .name = "output_img",
254  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
255  .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format, FF_VK_REP_FLOAT),
256  .mem_quali = "writeonly",
257  .dimensions = 2,
258  .elems = av_pix_fmt_count_planes(s->vkctx.output_format),
259  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
260  },
261  };
262 
263  RET(ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0));
264 
265  GLSLC(0, layout(push_constant, std430) uniform pushConstants { );
266  GLSLC(1, mat4 yuv_matrix; );
267  GLSLC(1, int crop_x; );
268  GLSLC(1, int crop_y; );
269  GLSLC(1, int crop_w; );
270  GLSLC(1, int crop_h; );
271  GLSLC(0, }; );
272  GLSLC(0, );
273 
274  ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
275  VK_SHADER_STAGE_COMPUTE_BIT);
276 
277  err = init_scale_shader(ctx, shd, desc, in);
278  if (err < 0)
279  goto fail;
280 
281  RET(spv->compile_shader(vkctx, spv, shd, &spv_data, &spv_len, "main",
282  &spv_opaque));
283  RET(ff_vk_shader_link(vkctx, shd, spv_data, spv_len, "main"));
284 
285  RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
286 
287  s->initialized = 1;
288 
289 fail:
290  if (spv_opaque)
291  spv->free_shader(spv, &spv_opaque);
292  if (spv)
293  spv->uninit(&spv);
294 
295  return err;
296 }
297 
299 {
300  int err;
301  ScaleVulkanContext *s = ctx->priv;
302  FFVulkanContext *vkctx = &s->vkctx;
303  FFVulkanShader *shd = &s->shd;
304 
305  RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*2, 0, 0, 0, NULL));
306 
307  SPEC_LIST_CREATE(sl, 1, 1*sizeof(int32_t))
308  SPEC_LIST_ADD(sl, 0, 32, s->debayer);
309  ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
310  (uint32_t []) { 32, 32, 1 }, 0);
311 
312  ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
313  VK_SHADER_STAGE_COMPUTE_BIT);
314 
316  {
317  .name = "src",
318  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
319  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
320  },
321  {
322  .name = "dst",
323  .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
324  .stages = VK_SHADER_STAGE_COMPUTE_BIT,
325  },
326  };
327  ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0, 0);
328 
329  RET(ff_vk_shader_link(vkctx, shd,
331  ff_debayer_comp_spv_len, "main"));
332 
333  RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
334 
335  shd->lg_size[0] <<= 1;
336  shd->lg_size[1] <<= 1;
337 
338  s->initialized = 1;
339 
340 fail:
341  return err;
342 }
343 
345 {
346  int err;
347  AVFilterContext *ctx = link->dst;
348  ScaleVulkanContext *s = ctx->priv;
349  AVFilterLink *outlink = ctx->outputs[0];
350 
351  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
352  if (!out) {
353  err = AVERROR(ENOMEM);
354  goto fail;
355  }
356 
357  s->opts.crop_x = in->crop_left;
358  s->opts.crop_y = in->crop_top;
359  s->opts.crop_w = in->width - (in->crop_left + in->crop_right);
360  s->opts.crop_h = in->height - (in->crop_top + in->crop_bottom);
361 
362  err = av_frame_copy_props(out, in);
363  if (err < 0)
364  goto fail;
365 
366  if (out->width != in->width || out->height != in->height) {
367  av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data,
369  }
370 
371  if (s->out_range != AVCOL_RANGE_UNSPECIFIED)
372  out->color_range = s->out_range;
373  if (s->vkctx.output_format != s->vkctx.input_format)
374  out->chroma_location = AVCHROMA_LOC_TOPLEFT;
375 
376  if (!s->sws) {
377  if (!s->initialized) {
378  s->qf = ff_vk_qf_find(&s->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
379  if (!s->qf) {
380  av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
381  err = AVERROR(ENOTSUP);
382  goto fail;
383  }
384 
385  if (s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16)
386  RET(init_debayer(ctx, in));
387  else
388  RET(init_filter(ctx, in));
389  }
390 
391  RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
392  s->sampler, &s->opts, sizeof(s->opts)));
393  } else {
394  err = sws_scale_frame(s->sws, out, in);
395  if (err < 0)
396  goto fail;
397  }
398 
399  av_frame_free(&in);
400 
401  return ff_filter_frame(outlink, out);
402 
403 fail:
404  av_frame_free(&in);
405  av_frame_free(&out);
406  return err;
407 }
408 
410 {
411  int err;
412  AVFilterContext *avctx = outlink->src;
413  ScaleVulkanContext *s = avctx->priv;
414  FFVulkanContext *vkctx = &s->vkctx;
415  AVFilterLink *inlink = outlink->src->inputs[0];
416 
417  err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
418  &vkctx->output_width,
419  &vkctx->output_height);
420  if (err < 0)
421  return err;
422 
424  SCALE_FORCE_OAR_DISABLE, 1, 1.f);
425 
426  outlink->w = vkctx->output_width;
427  outlink->h = vkctx->output_height;
428 
429  if (s->out_format_string) {
430  s->vkctx.output_format = av_get_pix_fmt(s->out_format_string);
431  if (s->vkctx.output_format == AV_PIX_FMT_NONE) {
432  av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n");
433  return AVERROR(EINVAL);
434  }
435  } else {
436  s->vkctx.output_format = s->vkctx.input_format;
437  }
438 
439  if (s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16) {
440  if (s->vkctx.output_format == s->vkctx.input_format) {
441  s->vkctx.output_format = AV_PIX_FMT_RGBA64;
442  } else if (!ff_vk_mt_is_np_rgb(s->vkctx.output_format)) {
443  av_log(avctx, AV_LOG_ERROR, "Unsupported output format for debayer\n");
444  return AVERROR(EINVAL);
445  }
446  if (inlink->w != outlink->w || inlink->w != outlink->w) {
447  av_log(avctx, AV_LOG_ERROR, "Scaling is not supported with debayering\n");
448  return AVERROR_PATCHWELCOME;
449  }
450  } else if (inlink->w == outlink->w || inlink->w == outlink->w) {
451  s->sws = sws_alloc_context();
452  if (!s->sws)
453  return AVERROR(ENOMEM);
454  av_opt_set(s->sws, "sws_flags", "unstable", 0);
455  } else if (s->vkctx.output_format != s->vkctx.input_format) {
456  if (!ff_vk_mt_is_np_rgb(s->vkctx.input_format)) {
457  av_log(avctx, AV_LOG_ERROR, "Unsupported input format for conversion\n");
458  return AVERROR(EINVAL);
459  }
460  if (s->vkctx.output_format != AV_PIX_FMT_NV12 &&
461  s->vkctx.output_format != AV_PIX_FMT_YUV420P &&
462  s->vkctx.output_format != AV_PIX_FMT_YUV444P) {
463  av_log(avctx, AV_LOG_ERROR, "Unsupported output format\n");
464  return AVERROR(EINVAL);
465  }
466  } else if (s->out_range != AVCOL_RANGE_UNSPECIFIED) {
467  av_log(avctx, AV_LOG_ERROR, "Cannot change range without converting format\n");
468  return AVERROR(EINVAL);
469  }
470 
471  return ff_vk_filter_config_output(outlink);
472 }
473 
475 {
476  ScaleVulkanContext *s = avctx->priv;
477  FFVulkanContext *vkctx = &s->vkctx;
478  FFVulkanFunctions *vk = &vkctx->vkfn;
479 
480  ff_vk_exec_pool_free(vkctx, &s->e);
481  ff_vk_shader_free(vkctx, &s->shd);
482  sws_free_context(&s->sws);
483 
484  if (s->sampler)
485  vk->DestroySampler(vkctx->hwctx->act_dev, s->sampler,
486  vkctx->hwctx->alloc);
487 
488  ff_vk_uninit(&s->vkctx);
489 
490  s->initialized = 0;
491 }
492 
493 #define OFFSET(x) offsetof(ScaleVulkanContext, x)
494 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
495 static const AVOption scale_vulkan_options[] = {
496  { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = FLAGS },
497  { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = FLAGS },
498  { "scaler", "Scaler function", OFFSET(scaler), AV_OPT_TYPE_INT, {.i64 = F_BILINEAR}, 0, F_NB, .flags = FLAGS, .unit = "scaler" },
499  { "bilinear", "Bilinear interpolation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = F_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "scaler" },
500  { "nearest", "Nearest (useful for pixel art)", 0, AV_OPT_TYPE_CONST, {.i64 = F_NEAREST}, 0, 0, .flags = FLAGS, .unit = "scaler" },
501  { "debayer", "Debayer algorithm to use", OFFSET(debayer), AV_OPT_TYPE_INT, {.i64 = DB_BILINEAR_HQ}, 0, DB_NB, .flags = FLAGS, .unit = "debayer" },
502  { "bilinear", "Bilinear debayering (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "debayer" },
503  { "bilinear_hq", "Bilinear debayering (high quality)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR_HQ}, 0, 0, .flags = FLAGS, .unit = "debayer" },
504  { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
505  { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" },
506  { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
507  { "limited", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
508  { "jpeg", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
509  { "mpeg", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
510  { "tv", "Limited range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, .unit = "range" },
511  { "pc", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" },
512  { NULL },
513 };
514 
515 AVFILTER_DEFINE_CLASS(scale_vulkan);
516 
518  {
519  .name = "default",
520  .type = AVMEDIA_TYPE_VIDEO,
521  .filter_frame = &scale_vulkan_filter_frame,
522  .config_props = &ff_vk_filter_config_input,
523  },
524 };
525 
527  {
528  .name = "default",
529  .type = AVMEDIA_TYPE_VIDEO,
530  .config_props = &scale_vulkan_config_output,
531  },
532 };
533 
535  .p.name = "scale_vulkan",
536  .p.description = NULL_IF_CONFIG_SMALL("Scale Vulkan frames"),
537  .p.priv_class = &scale_vulkan_class,
538  .p.flags = AVFILTER_FLAG_HWDEVICE,
539  .priv_size = sizeof(ScaleVulkanContext),
545  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
546 };
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:118
init_debayer
static av_cold int init_debayer(AVFilterContext *ctx, AVFrame *in)
Definition: vf_scale_vulkan.c:298
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:2799
ff_vk_shader_init
int ff_vk_shader_init(FFVulkanContext *s, FFVulkanShader *shd, const char *name, VkPipelineStageFlags stage, const char *extensions[], int nb_extensions, int lg_x, int lg_y, int lg_z, uint32_t required_subgroup_size)
Initialize a shader object, with a specific set of extensions, type+bind, local group size,...
Definition: vulkan.c:2111
out
static FILE * out
Definition: movenc.c:55
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1067
RET
#define RET(x)
Definition: vulkan.h:68
ff_vk_filter_process_simple
int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e, FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f, VkSampler sampler, void *push_src, size_t push_size)
Submit a compute shader with a zero/one input and single out for execution.
Definition: vulkan_filter.c:242
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:357
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
DB_NB
@ DB_NB
Definition: vf_scale_vulkan.c:45
ff_debayer_comp_spv_data
const unsigned char ff_debayer_comp_spv_data[]
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
AVFrame::colorspace
enum AVColorSpace colorspace
YUV colorspace type.
Definition: frame.h:689
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:264
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
OFFSET
#define OFFSET(x)
Definition: vf_scale_vulkan.c:493
AVFrame::width
int width
Definition: frame.h:499
ff_vk_filter_init
int ff_vk_filter_init(AVFilterContext *avctx)
General lavfi IO functions.
Definition: vulkan_filter.c:233
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:777
scale_vulkan_outputs
static const AVFilterPad scale_vulkan_outputs[]
Definition: vf_scale_vulkan.c:526
av_csp_luma_coeffs_from_avcsp
const struct AVLumaCoefficients * av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp)
Retrieves the Luma coefficients necessary to construct a conversion matrix from an enum constant desc...
Definition: csp.c:58
AVOption
AVOption.
Definition: opt.h:429
DB_BILINEAR_HQ
@ DB_BILINEAR_HQ
Definition: vf_scale_vulkan.c:43
scale_vulkan_options
static const AVOption scale_vulkan_options[]
Definition: vf_scale_vulkan.c:495
rgb2yuv
static const char rgb2yuv[]
Definition: vf_scale_vulkan.c:86
write_nv12
static const char write_nv12[]
Definition: vf_scale_vulkan.c:100
ff_scale_eval_dimensions
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
Definition: scale_eval.c:57
AVLumaCoefficients
Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar calculations.
Definition: csp.h:48
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2825
FFVkSPIRVCompiler::uninit
void(* uninit)(struct FFVkSPIRVCompiler **ctx)
Definition: vulkan_spirv.h:32
SPEC_LIST_ADD
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition: vulkan.h:86
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:220
ScaleVulkanContext::sampler
VkSampler sampler
Definition: vf_scale_vulkan.c:56
video.h
ScaleVulkanContext::yuv_matrix
float yuv_matrix[4][4]
Definition: vf_scale_vulkan.c:60
write_420
static const char write_420[]
Definition: vf_scale_vulkan.c:109
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
ScaleVulkanContext::e
FFVkExecPool e
Definition: vf_scale_vulkan.c:53
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(scale_vulkan)
ScalerFunc
ScalerFunc
Definition: vf_scale_vulkan.c:34
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3496
AVVulkanDeviceContext::alloc
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
Definition: hwcontext_vulkan.h:63
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:289
fail
#define fail()
Definition: checkasm.h:221
vulkan_filter.h
colorspace.h
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:2592
DebayerFunc
DebayerFunc
Definition: vf_scale_vulkan.c:41
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:825
AV_SIDE_DATA_PROP_SIZE_DEPENDENT
@ AV_SIDE_DATA_PROP_SIZE_DEPENDENT
Side data depends on the video dimensions.
Definition: frame.h:309
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:40
C
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
Definition: writing_filters.txt:58
GLSLC
#define GLSLC(N, S)
Definition: vulkan.h:45
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:111
main
int main
Definition: dovi_rpuenc.c:38
FFFilter
Definition: filters.h:267
FFVulkanContext::output_width
int output_width
Definition: vulkan.h:360
F_NEAREST
@ F_NEAREST
Definition: vf_scale_vulkan.c:36
s
#define s(width, name)
Definition: cbs_vp9.c:198
F_BILINEAR
@ F_BILINEAR
Definition: vf_scale_vulkan.c:35
scale_vulkan_filter_frame
static int scale_vulkan_filter_frame(AVFilterLink *link, AVFrame *in)
Definition: vf_scale_vulkan.c:344
ScaleVulkanContext::crop_x
int crop_x
Definition: vf_scale_vulkan.c:61
ff_vf_scale_vulkan
const FFFilter ff_vf_scale_vulkan
Definition: vf_scale_vulkan.c:534
filters.h
FF_VK_REP_FLOAT
@ FF_VK_REP_FLOAT
Definition: vulkan.h:451
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
GLSLD
#define GLSLD(D)
Definition: vulkan.h:60
AVFrame::crop_right
size_t crop_right
Definition: frame.h:753
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
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
link
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 link
Definition: filter_design.txt:23
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:529
ff_vk_shader_rep_fmt
const char * ff_vk_shader_rep_fmt(enum AVPixelFormat pix_fmt, enum FFVkShaderRepFormat rep_fmt)
Definition: vulkan.c:1615
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
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:599
DUP_SAMPLER
#define DUP_SAMPLER(x)
Definition: vulkan.h:104
scale_vulkan_uninit
static void scale_vulkan_uninit(AVFilterContext *avctx)
Definition: vf_scale_vulkan.c:474
ScaleVulkanContext::h_expr
char * h_expr
Definition: vf_scale_vulkan.c:69
AVCHROMA_LOC_TOPLEFT
@ AVCHROMA_LOC_TOPLEFT
ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2.
Definition: pixfmt.h:800
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:282
ff_vk_filter_config_output
int ff_vk_filter_config_output(AVFilterLink *outlink)
Definition: vulkan_filter.c:209
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:2365
ScaleVulkanContext::debayer
enum DebayerFunc debayer
Definition: vf_scale_vulkan.c:73
SPEC_LIST_CREATE
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition: vulkan.h:76
ScaleVulkanContext::crop_h
int crop_h
Definition: vf_scale_vulkan.c:64
FFVulkanContext
Definition: vulkan.h:312
ScaleVulkanContext::out_range
enum AVColorRange out_range
Definition: vf_scale_vulkan.c:72
F_NB
@ F_NB
Definition: vf_scale_vulkan.c:38
FLAGS
#define FLAGS
Definition: vf_scale_vulkan.c:494
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:743
ScaleVulkanContext::vkctx
FFVulkanContext vkctx
Definition: vf_scale_vulkan.c:49
AVFrame::crop_bottom
size_t crop_bottom
Definition: frame.h:751
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
AVFrame::crop_left
size_t crop_left
Definition: frame.h:752
ScaleVulkanContext::qf
AVVulkanDeviceQueueFamily * qf
Definition: vf_scale_vulkan.c:54
f
f
Definition: af_crystalizer.c:122
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
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1031
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
AVFILTER_FLAG_HWDEVICE
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
Definition: avfilter.h:188
size
int size
Definition: twinvq_data.h:10344
FFVulkanShader
Definition: vulkan.h:225
ScaleVulkanContext::crop_y
int crop_y
Definition: vf_scale_vulkan.c:62
scale_eval.h
FFVkSPIRVCompiler::compile_shader
int(* compile_shader)(FFVulkanContext *s, struct FFVkSPIRVCompiler *ctx, FFVulkanShader *shd, uint8_t **data, size_t *size, const char *entrypoint, void **opaque)
Definition: vulkan_spirv.h:28
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
ff_vk_mt_is_np_rgb
int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt)
Returns 1 if pixfmt is a usable RGB format.
Definition: vulkan.c:1549
av_frame_side_data_remove_by_props
void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, int props)
Remove and free all side data instances that match any of the given side data properties.
Definition: side_data.c:117
FFVkSPIRVCompiler
Definition: vulkan_spirv.h:26
layout
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 layout
Definition: filter_design.txt:18
ScaleVulkanContext::scaler
enum ScalerFunc scaler
Definition: vf_scale_vulkan.c:71
uninit
static void uninit(AVBSFContext *ctx)
Definition: pcm_rechunk.c:68
ff_fill_rgb2yuv_table
void ff_fill_rgb2yuv_table(const AVLumaCoefficients *coeffs, double rgb2yuv[3][3])
Definition: colorspace.c:125
ScaleVulkanContext::w_expr
char * w_expr
Definition: vf_scale_vulkan.c:68
scale_bilinear
static const char scale_bilinear[]
Definition: vf_scale_vulkan.c:76
write_444
static const char write_444[]
Definition: vf_scale_vulkan.c:119
vulkan_spirv.h
scale_vulkan_inputs
static const AVFilterPad scale_vulkan_inputs[]
Definition: vf_scale_vulkan.c:517
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:46
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:760
FFVkSPIRVCompiler::free_shader
void(* free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque)
Definition: vulkan_spirv.h:31
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
FFVulkanContext::vkfn
FFVulkanFunctions vkfn
Definition: vulkan.h:316
FFVkExecPool
Definition: vulkan.h:290
pos
unsigned int pos
Definition: spdifenc.c:414
ScaleVulkanContext::shd
FFVulkanShader shd
Definition: vf_scale_vulkan.c:55
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:1489
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
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:3388
AVFrame::height
int height
Definition: frame.h:499
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:2492
random_seed.h
ScaleVulkanContext::initialized
int initialized
Definition: vf_scale_vulkan.c:52
GLSLF
#define GLSLF(N, S,...)
Definition: vulkan.h:55
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
ScaleVulkanContext::opts
struct ScaleVulkanContext::@421 opts
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
ScaleVulkanContext::sws
SwsContext * sws
Definition: vf_scale_vulkan.c:50
FFVulkanShader::lg_size
uint32_t lg_size[3]
Definition: vulkan.h:237
ScaleVulkanContext::crop_w
int crop_w
Definition: vf_scale_vulkan.c:63
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AVFilterContext
An instance of a filter.
Definition: avfilter.h:274
ScaleVulkanContext
Definition: vf_scale_vulkan.c:48
desc
const char * desc
Definition: libsvtav1.c:82
ff_vk_filter_config_input
int ff_vk_filter_config_input(AVFilterLink *inlink)
Definition: vulkan_filter.c:176
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
FFFilter::p
AVFilter p
The public AVFilter.
Definition: filters.h:271
FFVulkanContext::hwctx
AVVulkanDeviceContext * hwctx
Definition: vulkan.h:349
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
ff_vk_init_sampler
int ff_vk_init_sampler(FFVulkanContext *s, VkSampler *sampler, int unnorm_coords, VkFilter filt)
Create a sampler.
Definition: vulkan.c:1500
AVFrame::crop_top
size_t crop_top
Definition: frame.h:750
SCALE_FORCE_OAR_DISABLE
@ SCALE_FORCE_OAR_DISABLE
Definition: scale_eval.h:25
sws_free_context
void sws_free_context(SwsContext **ctx)
Free the context and everything associated with it, and write NULL to the provided pointer.
Definition: utils.c:2368
int32_t
int32_t
Definition: audioconvert.c:56
scale_vulkan_config_output
static int scale_vulkan_config_output(AVFilterLink *outlink)
Definition: vf_scale_vulkan.c:409
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVVulkanDeviceQueueFamily
Definition: hwcontext_vulkan.h:33
DB_BILINEAR
@ DB_BILINEAR
Definition: vf_scale_vulkan.c:42
init_filter
static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
Definition: vf_scale_vulkan.c:201
sws_scale_frame
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image dimensions or settings change in any way sws_scale_frame() is itself just a light-weight wrapper that runs ff_sws_graph_create() whenever the format changes
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
AV_PIX_FMT_BAYER_RGGB16
#define AV_PIX_FMT_BAYER_RGGB16
Definition: pixfmt.h:572
AVColorRange
AVColorRange
Visual content value range.
Definition: pixfmt.h:742
SwsContext
Main external API structure.
Definition: swscale.h:206
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
FILTER_SINGLE_PIXFMT
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition: filters.h:254
FFVulkanFunctions
Definition: vulkan_functions.h:274
ff_scale_adjust_dimensions
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by, double w_adj)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
Definition: scale_eval.c:122
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:2082
init_scale_shader
static int init_scale_shader(AVFilterContext *ctx, FFVulkanShader *shd, FFVulkanDescriptorSetBinding *desc, AVFrame *in)
Definition: vf_scale_vulkan.c:128
ScaleVulkanContext::out_format_string
char * out_format_string
Definition: vf_scale_vulkan.c:67
src
#define src
Definition: vp8dsp.c:248
swscale.h
ff_debayer_comp_spv_len
const unsigned int ff_debayer_comp_spv_len