FFmpeg
Loading...
Searching...
No Matches
vf_transpose_vulkan.c
Go to the documentation of this file.
1/*
2 * copyright (c) 2021 Wu Jianhua <jianhua.wu@intel.com>
3 * Copyright (c) Lynne
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/opt.h"
23#include "vulkan_filter.h"
24
25#include "filters.h"
26#include "transpose.h"
27#include "video.h"
28
29extern const unsigned char ff_transpose_comp_spv_data[];
30extern const unsigned int ff_transpose_comp_spv_len;
31
43
45{
46 int err;
48 FFVulkanContext *vkctx = &s->vkctx;
49 const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
50
51 s->qf = ff_vk_qf_find(vkctx, VK_QUEUE_COMPUTE_BIT, 0);
52 if (!s->qf) {
53 av_log(ctx, AV_LOG_ERROR, "Device has no compute queues\n");
54 err = AVERROR(ENOTSUP);
55 goto fail;
56 }
57
58 RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, FF_VK_DEFAULT_EXEC_CONTEXTS, 0, 0, 0, NULL));
59
60 ff_vk_shader_load(&s->shd, VK_SHADER_STAGE_COMPUTE_BIT, NULL,
61 (uint32_t []) { 32, 1, planes }, 0);
62
63 ff_vk_shader_add_push_const(&s->shd, 0, sizeof(int),
64 VK_SHADER_STAGE_COMPUTE_BIT);
65
67 { /* input_img */
68 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
69 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
70 .elems = planes,
71 },
72 { /* output_img */
73 .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
74 .stages = VK_SHADER_STAGE_COMPUTE_BIT,
75 .elems = planes,
76 },
77 };
78 ff_vk_shader_add_descriptor_set(vkctx, &s->shd, desc, 2, 0);
79
80 RET(ff_vk_shader_link(vkctx, &s->shd,
83
84 RET(ff_vk_shader_register_exec(vkctx, &s->e, &s->shd));
85
86 s->initialized = 1;
87
88fail:
89 return err;
90}
91
92static int filter_frame(AVFilterLink *inlink, AVFrame *in)
93{
94 int err;
95 AVFrame *out = NULL;
96 AVFilterContext *ctx = inlink->dst;
98 AVFilterLink *outlink = ctx->outputs[0];
99
100 if (s->passthrough)
101 return ff_filter_frame(outlink, in);
102
103 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
104 if (!out) {
105 err = AVERROR(ENOMEM);
106 goto fail;
107 }
108
109 if (!s->initialized)
110 RET(init_filter(ctx, in));
111
112 RET(ff_vk_filter_process_simple(&s->vkctx, &s->e, &s->shd, out, in,
113 VK_NULL_HANDLE, 1, &s->dir, sizeof(int)));
114
116
117 if (in->sample_aspect_ratio.num)
118 out->sample_aspect_ratio = in->sample_aspect_ratio;
119 else {
120 out->sample_aspect_ratio.num = in->sample_aspect_ratio.den;
121 out->sample_aspect_ratio.den = in->sample_aspect_ratio.num;
122 }
123
124 av_frame_free(&in);
125
126 return ff_filter_frame(outlink, out);
127
128fail:
129 av_frame_free(&in);
131 return err;
132}
133
135{
136 TransposeVulkanContext *s = avctx->priv;
137 FFVulkanContext *vkctx = &s->vkctx;
138
139 ff_vk_exec_pool_free(vkctx, &s->e);
140 ff_vk_shader_free(vkctx, &s->shd);
141
142 ff_vk_uninit(&s->vkctx);
143
144 s->initialized = 0;
145}
146
148{
149 FilterLink *outl = ff_filter_link(outlink);
150 AVFilterContext *avctx = outlink->src;
151 TransposeVulkanContext *s = avctx->priv;
152 FFVulkanContext *vkctx = &s->vkctx;
153 AVFilterLink *inlink = avctx->inputs[0];
154 FilterLink *inl = ff_filter_link(inlink);
155
156 if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
157 (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
158 av_log(avctx, AV_LOG_VERBOSE,
159 "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
160 inlink->w, inlink->h, inlink->w, inlink->h);
162 return outl->hw_frames_ctx ? 0 : AVERROR(ENOMEM);
163 } else {
164 s->passthrough = TRANSPOSE_PT_TYPE_NONE;
165 }
166
167 vkctx->output_width = inlink->h;
168 vkctx->output_height = inlink->w;
169
170 if (inlink->sample_aspect_ratio.num)
171 outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 },
172 inlink->sample_aspect_ratio);
173 else
174 outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
175
176 return ff_vk_filter_config_output(outlink);
177}
178
179#define OFFSET(x) offsetof(TransposeVulkanContext, x)
180#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM | \
181 AV_OPT_FLAG_RUNTIME_PARAM)
182
184 { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, .unit = "dir" },
185 { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
186 { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" },
187 { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" },
188 { "clock_flip", "rotate clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
189
190 { "passthrough", "do not apply transposition if the input matches the specified geometry",
191 OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE}, 0, INT_MAX, FLAGS, .unit = "passthrough" },
192 { "none", "always apply transposition", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
193 { "portrait", "preserve portrait geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
194 { "landscape", "preserve landscape geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" },
195
196 { NULL }
197};
198
199AVFILTER_DEFINE_CLASS(transpose_vulkan);
200
202 {
203 .name = "default",
204 .type = AVMEDIA_TYPE_VIDEO,
205 .filter_frame = &filter_frame,
206 .config_props = &ff_vk_filter_config_input,
207 }
208};
209
211 {
212 .name = "default",
213 .type = AVMEDIA_TYPE_VIDEO,
214 .config_props = &config_props_output,
215 }
216};
217
219 .p.name = "transpose_vulkan",
220 .p.description = NULL_IF_CONFIG_SMALL("Transpose Vulkan Filter"),
221 .p.priv_class = &transpose_vulkan_class,
222 .p.flags = AVFILTER_FLAG_HWDEVICE,
223 .priv_size = sizeof(TransposeVulkanContext),
229 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
230};
const FFFilter ff_vf_transpose_vulkan
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 FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ 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
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:103
#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_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition rational.c:88
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static av_cold void uninit(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
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#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:2070
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:2373
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition vulkan.c:310
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
int ff_vk_shader_add_push_const(FFVulkanShader *shd, int offset, int size, VkShaderStageFlagBits stage)
Add/update push constants for execution.
Definition vulkan.c:1443
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2638
void ff_vk_shader_free(FFVulkanContext *s, FFVulkanShader *shd)
Free a shader.
Definition vulkan.c:2614
int ff_vk_shader_register_exec(FFVulkanContext *s, FFVkExecPool *pool, FFVulkanShader *shd)
Register a shader with an exec pool.
Definition vulkan.c:2407
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:297
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:2267
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
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** inputs
array of pointers to input links
Definition avfilter.h:281
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
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:569
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
int output_height
Definition vulkan.h:341
AVVulkanDeviceQueueFamily * qf
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
@ TRANSPOSE_CLOCK_FLIP
Definition transpose.h:34
@ TRANSPOSE_CCLOCK
Definition transpose.h:33
@ TRANSPOSE_CCLOCK_FLIP
Definition transpose.h:31
@ TRANSPOSE_CLOCK
Definition transpose.h:32
@ TRANSPOSE_PT_TYPE_NONE
Definition transpose.h:25
@ TRANSPOSE_PT_TYPE_PORTRAIT
Definition transpose.h:27
@ TRANSPOSE_PT_TYPE_LANDSCAPE
Definition transpose.h:26
static int config_props_output(AVFilterLink *outlink)
const unsigned int ff_transpose_comp_spv_len
static const AVFilterPad transpose_vulkan_inputs[]
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static const AVFilterPad transpose_vulkan_outputs[]
static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in)
static int config_props_output(AVFilterLink *outlink)
#define OFFSET(x)
const unsigned char ff_transpose_comp_spv_data[]
static const AVOption transpose_vulkan_options[]
static av_cold void transpose_vulkan_uninit(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
int ff_vk_filter_config_input(AVFilterLink *inlink)
int ff_vk_filter_config_output(AVFilterLink *outlink)
int ff_vk_filter_process_simple(FFVulkanContext *vkctx, FFVkExecPool *e, FFVulkanShader *shd, AVFrame *out_f, AVFrame *in_f, VkSampler sampler, uint32_t wgc_z, void *push_src, size_t push_size)
Submit a compute shader with a zero/one input and single out for execution.
int ff_vk_filter_init(AVFilterContext *avctx)
General lavfi IO functions.