2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "vulkan_video.h"
23 const FFVkCodecMap ff_vk_codec_map[AV_CODEC_ID_FIRST_AUDIO] = {
24 [AV_CODEC_ID_H264] = {
27 FF_VK_EXT_VIDEO_DECODE_H264,
28 VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,
30 [AV_CODEC_ID_HEVC] = {
33 FF_VK_EXT_VIDEO_DECODE_H265,
34 VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR
39 FF_VK_EXT_VIDEO_DECODE_AV1,
40 0x01000000 /* TODO fix this */
44 #define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
45 #define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
47 static const struct FFVkFormatMapEntry {
49 enum AVPixelFormat pixfmt;
50 VkImageAspectFlags aspect;
53 { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GRAY8, VK_IMAGE_ASPECT_COLOR_BIT },
54 { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY16, VK_IMAGE_ASPECT_COLOR_BIT },
55 { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT },
58 { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT },
59 { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA, VK_IMAGE_ASPECT_COLOR_BIT },
60 { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGBA, VK_IMAGE_ASPECT_COLOR_BIT },
61 { VK_FORMAT_R8G8B8_UNORM, AV_PIX_FMT_RGB24, VK_IMAGE_ASPECT_COLOR_BIT },
62 { VK_FORMAT_B8G8R8_UNORM, AV_PIX_FMT_BGR24, VK_IMAGE_ASPECT_COLOR_BIT },
63 { VK_FORMAT_R16G16B16_UNORM, AV_PIX_FMT_RGB48, VK_IMAGE_ASPECT_COLOR_BIT },
64 { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_RGBA64, VK_IMAGE_ASPECT_COLOR_BIT },
65 { VK_FORMAT_R5G6B5_UNORM_PACK16, AV_PIX_FMT_RGB565, VK_IMAGE_ASPECT_COLOR_BIT },
66 { VK_FORMAT_B5G6R5_UNORM_PACK16, AV_PIX_FMT_BGR565, VK_IMAGE_ASPECT_COLOR_BIT },
67 { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGR0, VK_IMAGE_ASPECT_COLOR_BIT },
68 { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGB0, VK_IMAGE_ASPECT_COLOR_BIT },
69 { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT },
72 { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GBRAP, VK_IMAGE_ASPECT_COLOR_BIT },
73 { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GBRAP16, VK_IMAGE_ASPECT_COLOR_BIT },
74 { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRPF32, VK_IMAGE_ASPECT_COLOR_BIT },
75 { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT },
77 /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
78 { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, AV_PIX_FMT_NV12, ASPECT_2PLANE },
79 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P010, ASPECT_2PLANE },
80 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, AV_PIX_FMT_P012, ASPECT_2PLANE },
81 { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, AV_PIX_FMT_P016, ASPECT_2PLANE },
83 /* Two-plane 422 YUV at 8, 10 and 16 bits */
84 { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, AV_PIX_FMT_NV16, ASPECT_2PLANE },
85 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P210, ASPECT_2PLANE },
86 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, AV_PIX_FMT_P212, ASPECT_2PLANE },
87 { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, AV_PIX_FMT_P216, ASPECT_2PLANE },
89 /* Two-plane 444 YUV at 8, 10 and 16 bits */
90 { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, AV_PIX_FMT_NV24, ASPECT_2PLANE },
91 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P410, ASPECT_2PLANE },
92 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, AV_PIX_FMT_P412, ASPECT_2PLANE },
93 { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, AV_PIX_FMT_P416, ASPECT_2PLANE },
95 /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
96 { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P, ASPECT_3PLANE },
97 { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE },
98 { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE },
99 { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE },
100 { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P, ASPECT_3PLANE },
101 { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE },
102 { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE },
103 { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE },
104 { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P, ASPECT_3PLANE },
105 { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE },
106 { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE },
107 { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE },
109 /* Single plane 422 at 8, 10 and 12 bits */
110 { VK_FORMAT_G8B8G8R8_422_UNORM, AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT },
111 { VK_FORMAT_B8G8R8G8_422_UNORM, AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT },
112 { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT },
113 { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT },
115 static const int nb_vk_format_map = FF_ARRAY_ELEMS(vk_format_map);
117 enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
119 for (int i = 0; i < nb_vk_format_map; i++)
120 if (vk_format_map[i].vkf == vkf)
121 return vk_format_map[i].pixfmt;
122 return AV_PIX_FMT_NONE;
125 VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf)
127 for (int i = 0; i < nb_vk_format_map; i++)
128 if (vk_format_map[i].vkf == vkf)
129 return vk_format_map[i].aspect;
130 return VK_IMAGE_ASPECT_NONE;
133 VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
135 if (desc->nb_components == 1)
136 return VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR;
137 else if (!desc->log2_chroma_w && !desc->log2_chroma_h)
138 return VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR;
139 else if (!desc->log2_chroma_w && desc->log2_chroma_h == 1)
140 return VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR;
141 else if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1)
142 return VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR;
143 return VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_KHR;
146 VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
149 case 8: return VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR;
150 case 10: return VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR;
151 case 12: return VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR;
154 return VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR;
157 int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level)
160 case STD_VIDEO_H264_LEVEL_IDC_1_0: return 10;
161 case STD_VIDEO_H264_LEVEL_IDC_1_1: return 11;
162 case STD_VIDEO_H264_LEVEL_IDC_1_2: return 12;
163 case STD_VIDEO_H264_LEVEL_IDC_1_3: return 13;
164 case STD_VIDEO_H264_LEVEL_IDC_2_0: return 20;
165 case STD_VIDEO_H264_LEVEL_IDC_2_1: return 21;
166 case STD_VIDEO_H264_LEVEL_IDC_2_2: return 22;
167 case STD_VIDEO_H264_LEVEL_IDC_3_0: return 30;
168 case STD_VIDEO_H264_LEVEL_IDC_3_1: return 31;
169 case STD_VIDEO_H264_LEVEL_IDC_3_2: return 32;
170 case STD_VIDEO_H264_LEVEL_IDC_4_0: return 40;
171 case STD_VIDEO_H264_LEVEL_IDC_4_1: return 41;
172 case STD_VIDEO_H264_LEVEL_IDC_4_2: return 42;
173 case STD_VIDEO_H264_LEVEL_IDC_5_0: return 50;
174 case STD_VIDEO_H264_LEVEL_IDC_5_1: return 51;
175 case STD_VIDEO_H264_LEVEL_IDC_5_2: return 52;
176 case STD_VIDEO_H264_LEVEL_IDC_6_0: return 60;
177 case STD_VIDEO_H264_LEVEL_IDC_6_1: return 61;
179 case STD_VIDEO_H264_LEVEL_IDC_6_2: return 62;
183 int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
186 case STD_VIDEO_H265_LEVEL_IDC_1_0: return 10;
187 case STD_VIDEO_H265_LEVEL_IDC_2_0: return 20;
188 case STD_VIDEO_H265_LEVEL_IDC_2_1: return 21;
189 case STD_VIDEO_H265_LEVEL_IDC_3_0: return 30;
190 case STD_VIDEO_H265_LEVEL_IDC_3_1: return 31;
191 case STD_VIDEO_H265_LEVEL_IDC_4_0: return 40;
192 case STD_VIDEO_H265_LEVEL_IDC_4_1: return 41;
193 case STD_VIDEO_H265_LEVEL_IDC_5_0: return 50;
194 case STD_VIDEO_H265_LEVEL_IDC_5_1: return 51;
195 case STD_VIDEO_H265_LEVEL_IDC_6_0: return 60;
196 case STD_VIDEO_H265_LEVEL_IDC_6_1: return 61;
198 case STD_VIDEO_H265_LEVEL_IDC_6_2: return 62;
202 static void free_data_buf(void *opaque, uint8_t *data)
204 FFVulkanContext *ctx = opaque;
205 FFVkVideoBuffer *buf = (FFVkVideoBuffer *)data;
206 ff_vk_unmap_buffer(ctx, &buf->buf, 0);
207 ff_vk_free_buf(ctx, &buf->buf);
211 static AVBufferRef *alloc_data_buf(void *opaque, size_t size)
214 uint8_t *buf = av_mallocz(size);
218 ref = av_buffer_create(buf, size, free_data_buf, opaque, 0);
224 int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s,
225 AVBufferRef **buf, VkBufferUsageFlags usage,
226 void *create_pNext, size_t size)
230 FFVkVideoBuffer *data;
233 s->buf_pool = av_buffer_pool_init2(sizeof(FFVkVideoBuffer), ctx,
234 alloc_data_buf, NULL);
236 return AVERROR(ENOMEM);
239 *buf = ref = av_buffer_pool_get(s->buf_pool);
241 return AVERROR(ENOMEM);
243 data = (FFVkVideoBuffer *)ref->data;
245 if (data->buf.size >= size)
248 /* No point in requesting anything smaller. */
249 size = FFMAX(size, 1024*1024);
251 /* Align buffer to nearest power of two. Makes fragmentation management
252 * easier, and gives us ample headroom. */
261 ff_vk_free_buf(ctx, &data->buf);
262 memset(data, 0, sizeof(FFVkVideoBuffer));
264 err = ff_vk_create_buf(ctx, &data->buf, size,
265 create_pNext, NULL, usage,
266 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
268 av_buffer_unref(&ref);
273 err = ff_vk_map_buffer(ctx, &data->buf, &data->mem, 0);
275 av_buffer_unref(&ref);
282 av_cold void ff_vk_video_common_uninit(FFVulkanContext *s,
283 FFVkVideoCommon *common)
285 FFVulkanFunctions *vk = &s->vkfn;
287 if (common->session) {
288 vk->DestroyVideoSessionKHR(s->hwctx->act_dev, common->session,
290 common->session = NULL;
293 if (common->nb_mem && common->mem)
294 for (int i = 0; i < common->nb_mem; i++)
295 vk->FreeMemory(s->hwctx->act_dev, common->mem[i], s->hwctx->alloc);
297 av_freep(&common->mem);
299 av_buffer_pool_uninit(&common->buf_pool);
302 av_cold int ff_vk_video_common_init(void *log, FFVulkanContext *s,
303 FFVkVideoCommon *common,
304 VkVideoSessionCreateInfoKHR *session_create)
308 FFVulkanFunctions *vk = &s->vkfn;
309 VkMemoryRequirements2 *mem_req = NULL;
310 VkVideoSessionMemoryRequirementsKHR *mem = NULL;
311 VkBindVideoSessionMemoryInfoKHR *bind_mem = NULL;
314 ret = vk->CreateVideoSessionKHR(s->hwctx->act_dev, session_create,
315 s->hwctx->alloc, &common->session);
316 if (ret != VK_SUCCESS)
317 return AVERROR_EXTERNAL;
319 /* Get memory requirements */
320 ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
324 if (ret != VK_SUCCESS) {
325 err = AVERROR_EXTERNAL;
329 /* Allocate all memory needed to actually allocate memory */
330 common->mem = av_mallocz(sizeof(*common->mem)*common->nb_mem);
332 err = AVERROR(ENOMEM);
335 mem = av_mallocz(sizeof(*mem)*common->nb_mem);
337 err = AVERROR(ENOMEM);
340 mem_req = av_mallocz(sizeof(*mem_req)*common->nb_mem);
342 err = AVERROR(ENOMEM);
345 bind_mem = av_mallocz(sizeof(*bind_mem)*common->nb_mem);
347 err = AVERROR(ENOMEM);
351 /* Set the needed fields to get the memory requirements */
352 for (int i = 0; i < common->nb_mem; i++) {
353 mem_req[i] = (VkMemoryRequirements2) {
354 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
356 mem[i] = (VkVideoSessionMemoryRequirementsKHR) {
357 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_MEMORY_REQUIREMENTS_KHR,
358 .memoryRequirements = mem_req[i].memoryRequirements,
362 /* Finally get the memory requirements */
363 ret = vk->GetVideoSessionMemoryRequirementsKHR(s->hwctx->act_dev,
364 common->session, &common->nb_mem,
366 if (ret != VK_SUCCESS) {
367 err = AVERROR_EXTERNAL;
371 /* Now allocate each requested memory.
372 * For ricing, could pool together memory that ends up in the same index. */
373 for (int i = 0; i < common->nb_mem; i++) {
374 err = ff_vk_alloc_mem(s, &mem[i].memoryRequirements,
375 UINT32_MAX, NULL, NULL, &common->mem[i]);
379 bind_mem[i] = (VkBindVideoSessionMemoryInfoKHR) {
380 .sType = VK_STRUCTURE_TYPE_BIND_VIDEO_SESSION_MEMORY_INFO_KHR,
381 .memory = common->mem[i],
382 .memoryBindIndex = mem[i].memoryBindIndex,
384 .memorySize = mem[i].memoryRequirements.size,
387 av_log(log, AV_LOG_VERBOSE, "Allocating %"SIZE_SPECIFIER" bytes in bind index %i for video session\n",
388 bind_mem[i].memorySize, bind_mem[i].memoryBindIndex);
391 /* Bind the allocated memory */
392 ret = vk->BindVideoSessionMemoryKHR(s->hwctx->act_dev, common->session,
393 common->nb_mem, bind_mem);
394 if (ret != VK_SUCCESS) {
395 err = AVERROR_EXTERNAL;
410 ff_vk_video_common_uninit(s, common);