FFmpeg
Loading...
Searching...
No Matches
vf_overlay_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/opt.h"
22#include "vulkan_filter.h"
23
24#include "filters.h"
25#include "framesync.h"
26#include "video.h"
27
28extern const unsigned char ff_overlay_comp_spv_data[];
29extern const unsigned int ff_overlay_comp_spv_len;
30
51
53{
54 int err;
55 OverlayVulkanContext *s = ctx->priv;
56 FFVulkanContext *vkctx = &s->vkctx;
57 const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
58 const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA;
59 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(s->vkctx.output_format);
60 FFVulkanShader *shd = &s->shd;
61
62 s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
63 if (!s->qf) {
64 av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
65 err = AVERROR(ENOTSUP);
66 goto fail;
67 }
68
69 RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, FF_VK_DEFAULT_EXEC_CONTEXTS, 0, 0, 0, NULL));
70
71 SPEC_LIST_CREATE(sl, 2, 2*sizeof(uint32_t))
72 SPEC_LIST_ADD(sl, 0, 32, planes);
73 SPEC_LIST_ADD(sl, 1, 32, ialpha);
74
75 ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, sl,
76 (int []) { 32, 32, 1 }, 0);
77
78 ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts),
79 VK_SHADER_STAGE_COMPUTE_BIT);
80
82 { /* main_img */
83 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
84 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
85 .elems = planes,
86 },
87 { /* overlay_img */
88 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
89 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
90 .elems = planes,
91 },
92 { /* output_img */
93 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
94 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
95 .elems = planes,
96 },
97 };
98 ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 3, 0);
99
100 RET(ff_vk_shader_link(vkctx, shd,
102 ff_overlay_comp_spv_len, "main"));
103
104 RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
105
106 s->opts.o_offset[0] = s->overlay_x;
107 s->opts.o_offset[1] = s->overlay_y;
108 s->opts.o_offset[2] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
109 s->opts.o_offset[3] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
110 s->opts.o_offset[4] = s->opts.o_offset[0] >> pix_desc->log2_chroma_w;
111 s->opts.o_offset[5] = s->opts.o_offset[1] >> pix_desc->log2_chroma_h;
112
113 s->opts.o_size[0] = s->overlay_w;
114 s->opts.o_size[1] = s->overlay_h;
115 s->opts.o_size[2] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
116 s->opts.o_size[3] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
117 s->opts.o_size[4] = s->opts.o_size[0] >> pix_desc->log2_chroma_w;
118 s->opts.o_size[5] = s->opts.o_size[1] >> pix_desc->log2_chroma_h;
119
120 s->initialized = 1;
121
122fail:
123 return err;
124}
125
127{
128 int err;
129 AVFilterContext *ctx = fs->parent;
130 OverlayVulkanContext *s = ctx->priv;
131 AVFilterLink *outlink = ctx->outputs[0];
132 AVFrame *input_main, *input_overlay, *out;
133
134 err = ff_framesync_get_frame(fs, 0, &input_main, 0);
135 if (err < 0)
136 goto fail;
137 err = ff_framesync_get_frame(fs, 1, &input_overlay, 0);
138 if (err < 0)
139 goto fail;
140
141 if (!input_main || !input_overlay)
142 return 0;
143
144 if (!s->initialized) {
145 AVHWFramesContext *main_fc = (AVHWFramesContext*)input_main->hw_frames_ctx->data;
146 AVHWFramesContext *overlay_fc = (AVHWFramesContext*)input_overlay->hw_frames_ctx->data;
147 if (main_fc->sw_format != overlay_fc->sw_format) {
148 av_log(ctx, AV_LOG_ERROR, "Mismatching sw formats!\n");
149 return AVERROR(EINVAL);
150 }
151
152 s->overlay_w = input_overlay->width;
153 s->overlay_h = input_overlay->height;
154
156 }
157
158 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
159 if (!out) {
160 err = AVERROR(ENOMEM);
161 goto fail;
162 }
163
164 RET(ff_vk_filter_process_Nin(&s->vkctx, &s->e, &s->shd,
165 out, (AVFrame *[]){ input_main, input_overlay }, 2,
166 VK_NULL_HANDLE, 1, &s->opts, sizeof(s->opts)));
167
168 err = av_frame_copy_props(out, input_main);
169 if (err < 0)
170 goto fail;
171
172 return ff_filter_frame(outlink, out);
173
174fail:
176 return err;
177}
178
180{
181 int err;
182 AVFilterContext *avctx = outlink->src;
183 OverlayVulkanContext *s = avctx->priv;
184
185 err = ff_vk_filter_config_output(outlink);
186 if (err < 0)
187 return err;
188
189 err = ff_framesync_init_dualinput(&s->fs, avctx);
190 if (err < 0)
191 return err;
192
193 return ff_framesync_configure(&s->fs);
194}
195
197{
198 OverlayVulkanContext *s = avctx->priv;
199
200 return ff_framesync_activate(&s->fs);
201}
202
204{
205 OverlayVulkanContext *s = avctx->priv;
206
207 s->fs.on_event = &overlay_vulkan_blend;
208
209 return ff_vk_filter_init(avctx);
210}
211
213{
214 OverlayVulkanContext *s = avctx->priv;
215 FFVulkanContext *vkctx = &s->vkctx;
216
217 ff_vk_exec_pool_free(vkctx, &s->e);
218 ff_vk_shader_free(vkctx, &s->shd);
219
220 ff_vk_uninit(&s->vkctx);
222
223 s->initialized = 0;
224}
225
226#define OFFSET(x) offsetof(OverlayVulkanContext, x)
227#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
229 { "x", "Set horizontal offset", OFFSET(overlay_x), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
230 { "y", "Set vertical offset", OFFSET(overlay_y), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, .flags = FLAGS },
231 { NULL },
232};
233
234AVFILTER_DEFINE_CLASS(overlay_vulkan);
235
237 {
238 .name = "main",
239 .type = AVMEDIA_TYPE_VIDEO,
240 .config_props = &ff_vk_filter_config_input,
241 },
242 {
243 .name = "overlay",
244 .type = AVMEDIA_TYPE_VIDEO,
245 .config_props = &ff_vk_filter_config_input,
246 },
247};
248
250 {
251 .name = "default",
252 .type = AVMEDIA_TYPE_VIDEO,
253 .config_props = &overlay_vulkan_config_output,
254 },
255};
256
258 .p.name = "overlay_vulkan",
259 .p.description = NULL_IF_CONFIG_SMALL("Overlay a source on top of another"),
260 .p.priv_class = &overlay_vulkan_class,
261 .p.flags = AVFILTER_FLAG_HWDEVICE,
262 .priv_size = sizeof(OverlayVulkanContext),
269 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
270};
const FFFilter ff_vf_overlay_vulkan
int32_t
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
#define s(width, name)
Definition cbs_vp9.c:198
#define fs(width, name, subs,...)
Definition cbs_vp9.c:200
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
Definition framesync.c:137
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
Definition framesync.c:352
int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, unsigned get)
Get the current frame in an input.
Definition framesync.c:269
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
Definition framesync.c:372
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
Definition framesync.c:301
#define fail
Definition test.h:479
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
Definition avfilter.h:187
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#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
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
Definition filters.h:254
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
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:2240
void ff_vk_shader_add_descriptor_set(FFVulkanContext *s, FFVulkanShader *shd, const FFVulkanDescriptorSetBinding *desc, int nb, int singular)
Add descriptor to a shader.
Definition vulkan.c:2543
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:331
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:395
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1613
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2808
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2784
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2577
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:316
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:2437
const char * desc
Definition libsvtav1.c:83
static const struct @257111027162314367033347246032313251342043035002 planes[]
AVOptions.
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition pixdesc.h:147
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
uint8_t * data
The data buffer.
Definition buffer.h:90
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int width
Definition frame.h:544
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition frame.h:769
int height
Definition frame.h:544
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition pixdesc.h:80
uint64_t flags
Combination of AV_PIX_FMT_FLAG_... flags.
Definition pixdesc.h:94
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition pixdesc.h:89
Frame sync structure.
Definition framesync.h:168
AVVulkanDeviceQueueFamily * qf
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
static AVDictionary * opts
Definition movenc.c:51
static const AVOption overlay_vulkan_options[]
static void overlay_vulkan_uninit(AVFilterContext *avctx)
static av_cold int init_filter(AVFilterContext *ctx)
const unsigned int ff_overlay_comp_spv_len
static av_cold int overlay_vulkan_init(AVFilterContext *avctx)
static int overlay_vulkan_blend(FFFrameSync *fs)
static const AVFilterPad overlay_vulkan_outputs[]
static int overlay_vulkan_config_output(AVFilterLink *outlink)
static const AVFilterPad overlay_vulkan_inputs[]
#define OFFSET(x)
const unsigned char ff_overlay_comp_spv_data[]
static int overlay_vulkan_activate(AVFilterContext *avctx)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89
#define FF_VK_DEFAULT_EXEC_CONTEXTS
Definition vulkan.h:121
#define RET(x)
Definition vulkan.h:37
#define SPEC_LIST_ADD(name, idx, val_bits, val)
Definition vulkan.h:55
#define SPEC_LIST_CREATE(name, max_length, max_size)
Definition vulkan.h:45
int ff_vk_filter_config_input(AVFilterLink *inlink)
int ff_vk_filter_config_output(AVFilterLink *outlink)
int ff_vk_filter_process_Nin(FFVulkanContext *vkctx, FFVkExecPool *e, FFVulkanShader *shd, AVFrame *out, AVFrame *in[], int nb_in, VkSampler sampler, uint32_t wgc_z, void *push_src, size_t push_size)
Up to 16 inputs, one output.
int ff_vk_filter_init(AVFilterContext *avctx)
General lavfi IO functions.