FFmpeg
Loading...
Searching...
No Matches
vulkan_decode.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
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.
8 *
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.
13 *
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
17 */
18
20#include "libavutil/refstruct.h"
21#include "vulkan_video.h"
22#include "vulkan_decode.h"
23#include "config_components.h"
24#include "libavutil/avassert.h"
25#include "libavutil/mem.h"
27#include "h264dec.h"
28
29#define DECODER_IS_SDR(codec_id) \
30 (((codec_id) == AV_CODEC_ID_FFV1) || \
31 ((codec_id) == AV_CODEC_ID_DPX) || \
32 ((codec_id) == AV_CODEC_ID_APV) || \
33 ((codec_id) == AV_CODEC_ID_PRORES_RAW) || \
34 ((codec_id) == AV_CODEC_ID_PRORES))
35
36#if CONFIG_H264_VULKAN_HWACCEL
38#endif
39#if CONFIG_HEVC_VULKAN_HWACCEL
41#endif
42#if CONFIG_VP9_VULKAN_HWACCEL
44#endif
45#if CONFIG_AV1_VULKAN_HWACCEL
47#endif
48#if CONFIG_FFV1_VULKAN_HWACCEL
50#endif
51#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
53#endif
54#if CONFIG_PRORES_VULKAN_HWACCEL
56#endif
57#if CONFIG_DPX_VULKAN_HWACCEL
59#endif
60#if CONFIG_APV_VULKAN_HWACCEL
62#endif
63
65#if CONFIG_H264_VULKAN_HWACCEL
67#endif
68#if CONFIG_HEVC_VULKAN_HWACCEL
70#endif
71#if CONFIG_VP9_VULKAN_HWACCEL
73#endif
74#if CONFIG_AV1_VULKAN_HWACCEL
76#endif
77#if CONFIG_FFV1_VULKAN_HWACCEL
79#endif
80#if CONFIG_PRORES_RAW_VULKAN_HWACCEL
82#endif
83#if CONFIG_PRORES_VULKAN_HWACCEL
85#endif
86#if CONFIG_DPX_VULKAN_HWACCEL
88#endif
89#if CONFIG_APV_VULKAN_HWACCEL
91#endif
92};
93
95 VkVideoDecodeH264ProfileInfoKHR h264_profile;
96 VkVideoDecodeH265ProfileInfoKHR h265_profile;
97#if CONFIG_VP9_VULKAN_HWACCEL
98 VkVideoDecodeVP9ProfileInfoKHR vp9_profile;
99#endif
100 VkVideoDecodeAV1ProfileInfoKHR av1_profile;
101
102 VkVideoDecodeUsageInfoKHR usage;
103 VkVideoProfileInfoKHR profile;
104 VkVideoProfileListInfoKHR profile_list;
106
108{
109 for (size_t i = 0; i < FF_ARRAY_ELEMS(dec_descs); i++)
110 if (dec_descs[i]->codec_id == codec_id)
111 return dec_descs[i];
112 av_assert1(!"no codec descriptor");
113 return NULL;
114}
115
116static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
117{
118 const VkVideoProfileListInfoKHR *profile_list;
119
120 VkStructureType profile_struct_type =
121 codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
122 codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
123#if CONFIG_VP9_VULKAN_HWACCEL
124 codec_id == AV_CODEC_ID_VP9 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR :
125#endif
126 codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
127 VK_STRUCTURE_TYPE_MAX_ENUM;
128 if (profile_struct_type == VK_STRUCTURE_TYPE_MAX_ENUM)
129 return NULL;
130
131 profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
132 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
133 if (!profile_list)
134 return NULL;
135
136 for (int i = 0; i < profile_list->profileCount; i++)
137 if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type))
138 return &profile_list->pProfiles[i];
139
140 return NULL;
141}
142
144{
145 FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
146 FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;
147
148 av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
149
151
152 dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
153 dst_ctx->external_fg = src_ctx->external_fg;
154
155 return 0;
156}
157
158int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
159{
162 return 0;
163}
164
166{
168 FFVulkanFunctions *vk = &ctx->s.vkfn;
169
170 vkpic->dpb_frame = NULL;
171 vkpic->dpb_img = NULL;
172 vkpic->out_views = NULL;
173 vkpic->view.ref = VK_NULL_HANDLE;
174 vkpic->view.out = VK_NULL_HANDLE;
175
176 vkpic->invalidate_memory_ranges = vk->InvalidateMappedMemoryRanges;
177}
178
180 FFVulkanDecodePicture *vkpic, int is_current,
181 int alloc_dpb)
182{
183 int err;
185
186 vkpic->slices_size = 0;
187
188 /* If the decoder made a blank frame to make up for a missing ref, or the
189 * frame is the current frame so it's missing one, create a re-representation */
190 if (vkpic->view.ref)
191 return 0;
192
193 init_frame(dec, vkpic);
194
195 /* Refcounted, so executions keep it alive past the picture */
196 vkpic->out_views = ff_vk_imageviews_alloc(&ctx->s, 1);
197 if (!vkpic->out_views)
198 return AVERROR(ENOMEM);
199
200 if (ctx->common.layered_dpb && alloc_dpb) {
201 vkpic->view.ref = ctx->common.layered_view;
202 vkpic->view.aspect_ref = ctx->common.layered_aspect;
203 } else if (alloc_dpb) {
204 vkpic->dpb_img = av_refstruct_pool_get(ctx->common.dpb->img_pool);
205 if (!vkpic->dpb_img)
206 return AVERROR(ENOMEM);
207
208 /* The view is owned by the pool entry */
209 vkpic->view.ref = vkpic->dpb_img->view;
210 vkpic->view.aspect_ref = vkpic->dpb_img->aspect;
211 }
212
213 if (!alloc_dpb || is_current) {
215 AVVulkanFramesContext *hwfc = frames->hwctx;
216
217 err = ff_vk_create_view(&ctx->s,
218 &vkpic->out_views->views[0], &vkpic->view.aspect,
219 ((AVVkFrame *)pic->data[0])->img[0],
220 hwfc->format[0],
221 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
222 (hwfc->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR),
223 0);
224 // the above fixes VUID-VkVideoBeginCodingInfoKHR-slotIndex-07245
225 if (err < 0)
226 return err;
227 vkpic->view.out = vkpic->out_views->views[0];
228
229 if (!alloc_dpb) {
230 vkpic->view.ref = vkpic->view.out;
231 vkpic->view.aspect_ref = vkpic->view.aspect;
232 }
233 }
234
235 return 0;
236}
237
239 const uint8_t *data, size_t size, int add_startcode,
240 uint32_t *nb_slices, const uint32_t **offsets)
241{
244
245 static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
246 const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
247 const int nb = nb_slices ? *nb_slices : 0;
248 uint8_t *slices;
249 uint32_t *slice_off;
250 FFVkBuffer *vkbuf;
251
252 size_t new_size = vp->slices_size + startcode_len + size +
253 ctx->caps.minBitstreamBufferSizeAlignment;
254 new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
255
256 if (offsets) {
257 slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max,
258 (nb + 1)*sizeof(slice_off));
259 if (!slice_off)
260 return AVERROR(ENOMEM);
261
262 *offsets = dec->slice_off = slice_off;
263
264 slice_off[nb] = vp->slices_size;
265 }
266
267 vkbuf = vp->slices_buf;
268 if (!vkbuf || vkbuf->size < new_size) {
269 int err;
270 FFVkBuffer *new_buf;
271
272 /* No point in requesting anything smaller. */
273 size_t buf_size = FFMAX(new_size, 1024*1024);
274
275 /* Align buffer to nearest power of two. Makes fragmentation management
276 * easier, and gives us ample headroom. */
277 buf_size = 2 << av_log2(buf_size);
278
279 /* When the frames context uses DRM modifier tiling,
280 * hwctx->create_pnext contains VkImageDrmFormatModifierListCreateInfoEXT,
281 * which per spec does not extend VkBufferCreateInfo, so we need to find
282 * the VkVideoProfileListInfoKHR structure within it. */
283 void *buf_pnext = ctx->s.hwfc->create_pnext;
284 if (ctx->s.hwfc->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
285 buf_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
286 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
287
288 VkBufferUsageFlags buf_usage = DECODER_IS_SDR(avctx->codec_id) ?
289 (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
290 VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
291 VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR;
292
293 err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_buf,
294 buf_usage, buf_pnext, buf_size,
295 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
296 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
297 if (err < 0)
298 err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_buf,
299 buf_usage, buf_pnext, buf_size,
300 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
301 if (err < 0)
302 return err;
303
304 /* Copy data from the old buffer */
305 if (vkbuf) {
306 memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
308 }
309
310 vp->slices_buf = new_buf;
311 vkbuf = new_buf;
312 }
313 slices = vkbuf->mapped_mem;
314
315 /* Startcode */
316 memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
317
318 /* Slice data */
319 memcpy(slices + vp->slices_size + startcode_len, data, size);
320
321 if (nb_slices)
322 *nb_slices = nb + 1;
323
324 vp->slices_size += startcode_len + size;
325
326 return 0;
327}
328
331 VkVideoSessionParametersKHR *empty_session_params)
332{
333 if (avctx->codec_id == AV_CODEC_ID_VP9)
334 return 0;
335
336 VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
337 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
338 };
339 VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
340 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
341 };
342 StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
343 VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
344 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
345 .pStdSequenceHeader = &av1_empty_seq,
346 };
347 VkVideoSessionParametersCreateInfoKHR session_params_create = {
348 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
349 .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
350 avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
351 avctx->codec_id == AV_CODEC_ID_AV1 ? (void *)&av1_params :
352 NULL,
353 .videoSession = ctx->common.session,
354 };
355
356 VkResult ret;
357 FFVulkanContext *s = &ctx->s;
358 FFVulkanFunctions *vk = &s->vkfn;
359 ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
360 s->hwctx->alloc, empty_session_params);
361 if (ret != VK_SUCCESS) {
362 av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
363 ff_vk_ret2str(ret));
364 return AVERROR_EXTERNAL;
365 }
366
367 return 0;
368}
369
371{
372 int err;
373 FFVulkanContext *s = &ctx->s;
374 FFVulkanFunctions *vk = &s->vkfn;
375
376 VkVideoBeginCodingInfoKHR decode_start = {
377 .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
378 .videoSession = ctx->common.session,
379 };
380
381 if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
383 &decode_start.videoSessionParameters);
384 if (err < 0)
385 return err;
386 }
387
388 VkVideoCodingControlInfoKHR decode_ctrl = {
389 .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
390 .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
391 };
392 VkVideoEndCodingInfoKHR decode_end = {
393 .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
394 };
395
396 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
397 err = ff_vk_exec_start(&ctx->s, exec);
398 if (err < 0)
399 return err;
400
401 vk->CmdBeginVideoCodingKHR(exec->buf, &decode_start);
402 vk->CmdControlVideoCodingKHR(exec->buf, &decode_ctrl);
403 vk->CmdEndVideoCodingKHR(exec->buf, &decode_end);
404
405 err = ff_vk_exec_submit(&ctx->s, exec);
406
407 if (decode_start.videoSessionParameters) {
408 /* Wait to complete to delete the temporary session parameters */
409 if (err >= 0)
410 ff_vk_exec_wait(&ctx->s, exec);
411
412 vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
413 decode_start.videoSessionParameters,
414 s->hwctx->alloc);
415 }
416
417 if (err < 0)
418 av_log(avctx, AV_LOG_ERROR, "Unable to reset decoder: %s",
419 ff_vk_ret2str(err));
420
421 return err;
422}
423
426 AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
427{
428 int err;
429 VkResult ret;
430 VkCommandBuffer cmd_buf;
431 FFVkBuffer *sd_buf;
432
435 FFVulkanFunctions *vk = &ctx->s.vkfn;
436
437 /* Output */
438 AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
439
440 /* Quirks */
441 const int layered_dpb = ctx->common.layered_dpb;
442
443 VkVideoBeginCodingInfoKHR decode_start = {
444 .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
445 .videoSession = ctx->common.session,
446 .videoSessionParameters = dec->session_params ?
447 *dec->session_params : VK_NULL_HANDLE,
448 .referenceSlotCount = vp->decode_info.referenceSlotCount,
449 .pReferenceSlots = vp->decode_info.pReferenceSlots,
450 };
451 VkVideoEndCodingInfoKHR decode_end = {
452 .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
453 };
454
455 VkImageMemoryBarrier2 img_bar[38];
456 int nb_img_bar = 0;
457
458 size_t data_size = FFALIGN(vp->slices_size,
459 ctx->caps.minBitstreamBufferSizeAlignment);
460
461 FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
462
463 /* The current decoding reference has to be bound as an inactive reference */
464 VkVideoReferenceSlotInfoKHR *cur_vk_ref;
465 cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
466 cur_vk_ref[0] = vp->ref_slot;
467 cur_vk_ref[0].slotIndex = -1;
468 decode_start.referenceSlotCount++;
469
470 sd_buf = vp->slices_buf;
471
472 /* Flush if needed */
473 if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
474 VkMappedMemoryRange flush_buf = {
475 .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
476 .memory = sd_buf->mem,
477 .offset = 0,
478 .size = FFALIGN(vp->slices_size,
479 ctx->s.props.properties.limits.nonCoherentAtomSize),
480 };
481
482 ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
483 if (ret != VK_SUCCESS) {
484 av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
485 ff_vk_ret2str(ret));
486 return AVERROR_EXTERNAL;
487 }
488 }
489
490 vp->decode_info.srcBuffer = sd_buf->buf;
491 vp->decode_info.srcBufferOffset = 0;
492 vp->decode_info.srcBufferRange = data_size;
493
494 /* Start command buffer recording */
495 err = ff_vk_exec_start(&ctx->s, exec);
496 if (err < 0)
497 return err;
498 cmd_buf = exec->buf;
499
500 /* Slices; owned by the execution from now on */
502
503 /* Parameters; unset when inline session parameters are used */
504 if (dec->session_params)
506
507 err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
508 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
509 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
510 if (err < 0) {
511 ff_vk_exec_discard(&ctx->s, exec);
512 return err;
513 }
514
515 /* The output view is kept alive by the execution context; freeing the
516 * picture then needs no host wait. */
518
519 /* Output image - change layout, as it comes from a pool */
520 img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
521 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
522 .pNext = NULL,
523 .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
524 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
525 .srcAccessMask = VK_ACCESS_2_NONE,
526 .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
527 .oldLayout = vkf->layout[0],
528 .newLayout = (layered_dpb || vp->dpb_img) ?
529 VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
530 VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
531 .srcQueueFamilyIndex = vkf->queue_family[0],
532 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
533 .image = vkf->img[0],
534 .subresourceRange = (VkImageSubresourceRange) {
535 .aspectMask = vp->view.aspect,
536 .layerCount = 1,
537 .levelCount = 1,
538 },
539 };
540 ff_vk_exec_update_frame(&ctx->s, exec, pic,
541 &img_bar[nb_img_bar], &nb_img_bar);
542
543 /* Current picture's DISTINCT-mode DPB image: transition on first use */
544 if (vp->dpb_img) {
545 FFVkVideoDPBImage *di = vp->dpb_img;
546
547 if (di->layout != VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR) {
548 img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
549 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
550 .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
551 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
552 .srcAccessMask = VK_ACCESS_2_NONE,
553 .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
554 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
555 .oldLayout = di->layout,
556 .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
557 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
558 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
559 .image = di->img,
560 .subresourceRange = (VkImageSubresourceRange) {
561 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
562 .layerCount = 1,
563 .levelCount = 1,
564 },
565 };
566 nb_img_bar++;
567 di->layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
568 }
569 }
570
571 /* COINCIDE-mode references only: DISTINCT-mode references are covered
572 * by the memory barrier, with pool-owned views */
573 if (!dec->dedicated_dpb) {
574 for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
575 AVFrame *ref_frame = rpic[i];
576 FFVulkanDecodePicture *rvp = rvkp[i];
577
578 err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref_frame,
579 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
580 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
581 if (err < 0) {
582 ff_vk_exec_discard(&ctx->s, exec);
583 return err;
584 }
585
586 /* The reference's image views are kept alive by the execution,
587 * so freeing the picture needs no host wait. */
588 if (err == 0 && rvp->out_views)
590
591 {
592 AVVkFrame *rvkf = (AVVkFrame *)ref_frame->data[0];
593
594 img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
595 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
596 .pNext = NULL,
597 .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
598 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
599 .srcAccessMask = VK_ACCESS_2_NONE,
600 .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
601 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
602 .oldLayout = rvkf->layout[0],
603 .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
604 .srcQueueFamilyIndex = rvkf->queue_family[0],
605 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
606 .image = rvkf->img[0],
607 .subresourceRange = (VkImageSubresourceRange) {
608 .aspectMask = rvp->view.aspect_ref,
609 .layerCount = 1,
610 .levelCount = 1,
611 },
612 };
614 &img_bar[nb_img_bar], &nb_img_bar);
615 }
616 }
617 }
618
619 /* Internal DPB images are queue-exclusive: one decode-stage memory
620 * barrier per submission orders all prior work, references included, so
621 * they need no semaphores or dependencies, and image barriers only for
622 * initial layout transitions. */
623 VkMemoryBarrier2 mem_bar = {
624 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER_2,
625 .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
626 .srcAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
627 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
628 .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
629 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
630 };
631
632 /* Change image layouts, and synchronize the internal DPB if in use */
633 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
634 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
635 .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
636 .pMemoryBarriers = &mem_bar,
637 .memoryBarrierCount = ctx->common.dpb ? 1 : 0,
638 .pImageMemoryBarriers = img_bar,
639 .imageMemoryBarrierCount = nb_img_bar,
640 });
641
642 /* Start, use parameters, decode and end decoding */
643 vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
644 vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
645 vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
646
647 /* End recording and submit for execution */
648 return ff_vk_exec_submit(&ctx->s, exec);
649}
650
652{
653 /* Free slices data */
655
656 /* The views are kept alive by every execution referencing them, so no
657 * host wait is needed. */
659
661 /* No wait: pool reuse is ordered by the DPB barrier */
663}
664
665static void free_common(AVRefStructOpaque unused, void *obj)
666{
668 FFVulkanContext *s = &ctx->s;
669
670 /* Wait on and free execution pool */
671 ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
672
673 av_refstruct_pool_uninit(&ctx->buf_pool);
674
676
677 if (ctx->sd_ctx_free)
678 ctx->sd_ctx_free(ctx);
679
681}
682
684{
685 int err;
687 const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
689 AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
690 AVVulkanDeviceContext *hwctx = device->hwctx;
692
693 if (dec->shared_ctx)
694 return 0;
695
696 dec->shared_ctx = av_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
698 if (!dec->shared_ctx)
699 return AVERROR(ENOMEM);
700
701 ctx = dec->shared_ctx;
702
705
706 if (vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
707 if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
708 av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
709 VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
711 return AVERROR(ENOSYS);
712 }
713 }
714
715 err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
716 if (err < 0) {
718 return err;
719 }
720
721 return 0;
722}
723
728 const FFVulkanDecodeDescriptor *vk_desc,
729 VkVideoDecodeH264CapabilitiesKHR *h264_caps,
730 VkVideoDecodeH265CapabilitiesKHR *h265_caps,
731#if CONFIG_VP9_VULKAN_HWACCEL
732 VkVideoDecodeVP9CapabilitiesKHR *vp9_caps,
733#endif
734 VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
735 VkVideoCapabilitiesKHR *caps,
736 VkVideoDecodeCapabilitiesKHR *dec_caps,
737 int cur_profile)
738{
739 VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
740 VkVideoProfileInfoKHR *profile = &prof->profile;
741 VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
742
743 VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
744 VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
745#if CONFIG_VP9_VULKAN_HWACCEL
746 VkVideoDecodeVP9ProfileInfoKHR *vp9_profile = &prof->vp9_profile;
747#endif
748 VkVideoDecodeAV1ProfileInfoKHR *av1_profile = &prof->av1_profile;
749
751 if (!desc)
752 return AVERROR(EINVAL);
753
754 if (avctx->codec_id == AV_CODEC_ID_H264) {
755 dec_caps->pNext = h264_caps;
756 usage->pNext = h264_profile;
757 h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
758
759 /* Vulkan transmits all the constrant_set flags, rather than wanting them
760 * merged in the profile IDC */
761 h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
763
764 h264_profile->pictureLayout =
765 VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR;
766 const H264Context *h = avctx->priv_data;
767 if (h && h->ps.sps && !h->ps.sps->frame_mbs_only_flag)
768 h264_profile->pictureLayout =
769 VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
770 } else if (avctx->codec_id == AV_CODEC_ID_H265) {
771 dec_caps->pNext = h265_caps;
772 usage->pNext = h265_profile;
773 h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
774 h265_profile->stdProfileIdc = cur_profile;
775#if CONFIG_VP9_VULKAN_HWACCEL
776 } else if (avctx->codec_id == AV_CODEC_ID_VP9) {
777 dec_caps->pNext = vp9_caps;
778 usage->pNext = vp9_profile;
779 vp9_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_PROFILE_INFO_KHR;
780 vp9_profile->stdProfile = cur_profile;
781#endif
782 } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
783 dec_caps->pNext = av1_caps;
784 usage->pNext = av1_profile;
785 av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
786 av1_profile->stdProfile = cur_profile;
787 av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
788 }
789
790 usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
791 usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
792
793 profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
794 profile->pNext = usage;
795 profile->videoCodecOperation = vk_desc->decode_op;
796 profile->chromaSubsampling = ff_vk_subsampling_from_av_desc(desc);
797 profile->lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth);
798 profile->chromaBitDepth = profile->lumaBitDepth;
799
800 profile_list->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
801 profile_list->profileCount = 1;
802 profile_list->pProfiles = profile;
803
804 /* Get the capabilities of the decoder for the given profile */
805 caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
806 caps->pNext = dec_caps;
807 dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
808 /* dec_caps->pNext already filled in */
809
810 return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
811 caps);
812}
813
815 enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
817 int *dpb_dedicate)
818{
819 VkResult ret;
820 int max_level, base_profile, cur_profile;
821 const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
823 AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
824 AVVulkanDeviceContext *hwctx = device->hwctx;
825 enum AVPixelFormat source_format;
826 enum AVPixelFormat best_format;
827 VkFormat best_vkfmt;
828
831 FFVulkanFunctions *vk = &ctx->s.vkfn;
832
833 VkVideoCapabilitiesKHR *caps = &ctx->caps;
834 VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
835
836 VkVideoDecodeH264CapabilitiesKHR h264_caps = {
837 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
838 };
839 VkVideoDecodeH265CapabilitiesKHR h265_caps = {
840 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
841 };
842#if CONFIG_VP9_VULKAN_HWACCEL
843 VkVideoDecodeVP9CapabilitiesKHR vp9_caps = {
844 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_VP9_CAPABILITIES_KHR,
845 };
846#endif
847 VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
848 .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
849 };
850
851 VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
852 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
853 .pNext = &prof->profile_list,
854 };
855 VkVideoFormatPropertiesKHR *ret_info;
856 uint32_t nb_out_fmts = 0;
857
858 if (!(vk_desc->decode_extension & ctx->s.extensions)) {
859 av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
860 avcodec_get_name(avctx->codec_id));
861 return AVERROR(ENOSYS);
862 }
863
864 cur_profile = avctx->profile;
867#if CONFIG_VP9_VULKAN_HWACCEL
868 avctx->codec_id == AV_CODEC_ID_VP9 ? STD_VIDEO_VP9_PROFILE_0 :
869#endif
870 avctx->codec_id == AV_CODEC_ID_AV1 ? STD_VIDEO_AV1_PROFILE_MAIN :
871 0;
872
873 ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
874 &h264_caps,
875 &h265_caps,
876#if CONFIG_VP9_VULKAN_HWACCEL
877 &vp9_caps,
878#endif
879 &av1_caps,
880 caps,
881 dec_caps,
882 cur_profile);
883 if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
885 avctx->profile != base_profile) {
886 av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
887 "again with profile %s\n",
889 avcodec_profile_name(avctx->codec_id, cur_profile),
890 avcodec_profile_name(avctx->codec_id, base_profile));
891 cur_profile = base_profile;
892 ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
893 &h264_caps,
894 &h265_caps,
895#if CONFIG_VP9_VULKAN_HWACCEL
896 &vp9_caps,
897#endif
898 &av1_caps,
899 caps,
900 dec_caps,
901 cur_profile);
902 }
903
904 if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
905 av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
906 "%s profile \"%s\" not supported!\n",
908 avcodec_profile_name(avctx->codec_id, cur_profile));
909 return AVERROR(EINVAL);
910 } else if (ret == VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR) {
911 if (avctx->codec_id == AV_CODEC_ID_H264)
912 av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
913 "pictureLayout %#x not supported!\n",
914 (unsigned)prof->h264_profile.pictureLayout);
915 else
916 av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
917 "pictureLayout not supported!\n");
918 return AVERROR(EINVAL);
919 } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
920 av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
921 "format (%s) not supported!\n",
923 return AVERROR(EINVAL);
924 } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
925 ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
926 return AVERROR(EINVAL);
927 } else if (ret != VK_SUCCESS) {
928 return AVERROR_EXTERNAL;
929 }
930
931 max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
932 avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
933#if CONFIG_VP9_VULKAN_HWACCEL
934 avctx->codec_id == AV_CODEC_ID_VP9 ? vp9_caps.maxLevel :
935#endif
936 avctx->codec_id == AV_CODEC_ID_AV1 ? av1_caps.maxLevel :
937 0;
938
939 av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
941 avcodec_profile_name(avctx->codec_id, cur_profile));
942 av_log(avctx, AV_LOG_VERBOSE, " Maximum level: %i (stream %i)\n",
943 max_level, avctx->level);
944 av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n",
945 caps->minCodedExtent.width, caps->maxCodedExtent.width);
946 av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n",
947 caps->minCodedExtent.height, caps->maxCodedExtent.height);
948 av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n",
949 caps->pictureAccessGranularity.width);
950 av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n",
951 caps->pictureAccessGranularity.height);
952 av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n",
953 caps->minBitstreamBufferOffsetAlignment);
954 av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n",
955 caps->minBitstreamBufferSizeAlignment);
956 av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n",
957 caps->maxDpbSlots);
958 av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n",
959 caps->maxActiveReferencePictures);
960 av_log(avctx, AV_LOG_VERBOSE, " Codec header name: '%s' (driver), '%s' (compiled)\n",
961 caps->stdHeaderVersion.extensionName,
962 vk_desc->ext_props.extensionName);
963 av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
964 CODEC_VER(caps->stdHeaderVersion.specVersion),
965 CODEC_VER(vk_desc->ext_props.specVersion));
966 av_log(avctx, AV_LOG_VERBOSE, " Decode modes:%s%s%s\n",
967 dec_caps->flags ? "" :
968 " invalid",
969 dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
970 " reuse_dst_dpb" : "",
971 dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
972 " dedicated_dpb" : "");
973 av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n",
974 caps->flags ? "" :
975 " none",
976 caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
977 " protected" : "",
978 caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
979 " separate_references" : "");
980
981 /* Check if decoding is possible with the given parameters */
982 if (avctx->coded_width < caps->minCodedExtent.width ||
983 avctx->coded_height < caps->minCodedExtent.height ||
984 avctx->coded_width > caps->maxCodedExtent.width ||
985 avctx->coded_height > caps->maxCodedExtent.height)
986 return AVERROR(EINVAL);
987
989 avctx->level > max_level)
990 return AVERROR(EINVAL);
991
992 /* Some basic sanity checking */
993 if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
994 VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) {
995 av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
996 "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
997 "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
998 return AVERROR_EXTERNAL;
999 } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
1000 VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR)) ==
1001 VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR &&
1002 !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
1003 av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
1004 "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
1005 "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
1006 return AVERROR_EXTERNAL;
1007 }
1008
1009 dec->dedicated_dpb = !!(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR);
1010 ctx->common.layered_dpb = !dec->dedicated_dpb ? 0 :
1011 !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
1012
1013 if (dec->dedicated_dpb) {
1014 fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1015 } else {
1016 fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1017 VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
1018 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1019 VK_IMAGE_USAGE_SAMPLED_BIT;
1020
1021 if ((ctx->s.extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE) &&
1022 (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1))
1023 fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1024 }
1025
1026 /* Get the format of the images necessary */
1027 ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
1028 &fmt_info,
1029 &nb_out_fmts, NULL);
1030 if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
1031 (!nb_out_fmts && ret == VK_SUCCESS)) {
1032 return AVERROR(EINVAL);
1033 } else if (ret != VK_SUCCESS) {
1034 av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
1035 ff_vk_ret2str(ret));
1036 return AVERROR_EXTERNAL;
1037 }
1038
1039 ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
1040 if (!ret_info)
1041 return AVERROR(ENOMEM);
1042
1043 for (int i = 0; i < nb_out_fmts; i++)
1044 ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
1045
1046 ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
1047 &fmt_info,
1048 &nb_out_fmts, ret_info);
1049 if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
1050 (!nb_out_fmts && ret == VK_SUCCESS)) {
1051 av_free(ret_info);
1052 return AVERROR(EINVAL);
1053 } else if (ret != VK_SUCCESS) {
1054 av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
1055 ff_vk_ret2str(ret));
1056 av_free(ret_info);
1057 return AVERROR_EXTERNAL;
1058 }
1059
1060 /* Find a format to use */
1061 *pix_fmt = best_format = AV_PIX_FMT_NONE;
1062 *vk_fmt = best_vkfmt = VK_FORMAT_UNDEFINED;
1063 source_format = avctx->sw_pix_fmt;
1064
1065 av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
1066 for (int i = 0; i < nb_out_fmts; i++) {
1068 if (tmp == AV_PIX_FMT_NONE) {
1069 av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
1070 continue;
1071 }
1072
1073 best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
1074 if (tmp == best_format)
1075 best_vkfmt = ret_info[i].format;
1076
1077 av_log(avctx, AV_LOG_DEBUG, " %s%s (Vulkan ID: %i)\n",
1078 av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
1079 ret_info[i].format);
1080 }
1081
1082 av_free(ret_info);
1083
1084 if (best_format == AV_PIX_FMT_NONE) {
1085 av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
1086 return AVERROR(EINVAL);
1087 } else {
1088 av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
1089 av_get_pix_fmt_name(best_format), best_vkfmt);
1090 }
1091
1092 *pix_fmt = best_format;
1093 *vk_fmt = best_vkfmt;
1094
1095 *dpb_dedicate = dec->dedicated_dpb;
1096
1097 return 0;
1098}
1099
1101{
1102 av_free(hwfc->user_opaque);
1103}
1104
1106{
1107 int err, dedicated_dpb;
1108 AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1109 AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
1112
1113 err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
1114 if (err < 0)
1115 return err;
1116
1117 frames_ctx->format = AV_PIX_FMT_VULKAN;
1118 frames_ctx->sw_format = avctx->sw_pix_fmt;
1119 frames_ctx->width = avctx->coded_width;
1120 frames_ctx->height = avctx->coded_height;
1121
1122 if (!DECODER_IS_SDR(avctx->codec_id)) {
1123 prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
1124 if (!prof)
1125 return AVERROR(ENOMEM);
1126
1127 err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
1128 &frames_ctx->sw_format,
1129 &hwfc->format[0],
1130 prof, &dedicated_dpb);
1131 if (err < 0) {
1132 av_free(prof);
1133 return err;
1134 }
1135
1136 const AVPixFmtDescriptor *pdesc = av_pix_fmt_desc_get(frames_ctx->sw_format);
1137 frames_ctx->width = FFALIGN(frames_ctx->width, 1 << pdesc->log2_chroma_w);
1138 frames_ctx->height = FFALIGN(frames_ctx->height, 1 << pdesc->log2_chroma_h);
1139 frames_ctx->user_opaque = prof;
1140 frames_ctx->free = free_profile_data;
1141
1142 hwfc->create_pnext = &prof->profile_list;
1143 } else {
1144 hwfc->format[0] = VK_FORMAT_UNDEFINED;
1145 switch (frames_ctx->sw_format) {
1146 case AV_PIX_FMT_GBRAP16:
1147 /* This should be more efficient for downloading and using */
1148 frames_ctx->sw_format = AV_PIX_FMT_RGBA64;
1149 break;
1150 case AV_PIX_FMT_GBRP10:
1151 /* This saves memory bandwidth when downloading */
1152 frames_ctx->sw_format = AV_PIX_FMT_X2BGR10;
1153 break;
1154 case AV_PIX_FMT_RGB24:
1155 case AV_PIX_FMT_BGR0:
1156 /* mpv has issues with bgr0 mapping, so just remap it */
1157 frames_ctx->sw_format = AV_PIX_FMT_RGB0;
1158 break;
1159 /* DPX endian mismatch remappings */
1160 case AV_PIX_FMT_RGB48LE:
1161 case AV_PIX_FMT_RGB48BE: frames_ctx->sw_format = AV_PIX_FMT_GBRP16; break;
1162 case AV_PIX_FMT_RGBA64BE: frames_ctx->sw_format = AV_PIX_FMT_RGBA64; break;
1163 case AV_PIX_FMT_GRAY16BE: frames_ctx->sw_format = AV_PIX_FMT_GRAY16; break;
1164 /* ProRes needs to clear the input image, which is not possible on YUV formats */
1169 hwfc->format[3] = VK_FORMAT_R16_UNORM;
1175 hwfc->format[0] = VK_FORMAT_R16_UNORM;
1176 hwfc->format[1] = VK_FORMAT_R16_UNORM;
1177 hwfc->format[2] = VK_FORMAT_R16_UNORM;
1178 break;
1179 default:
1180 break;
1181 }
1182 }
1183
1184 if (hwfc->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
1185 hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1186
1187 hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1188 VK_IMAGE_USAGE_STORAGE_BIT |
1189 VK_IMAGE_USAGE_SAMPLED_BIT;
1190
1191 if (prof) {
1193
1194 hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
1195 if (!dec->dedicated_dpb)
1196 hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1197
1198 ctx = dec->shared_ctx;
1199 if ((ctx->s.extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE) &&
1200 (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1))
1201 hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1202 }
1203
1204 return err;
1205}
1206
1207static void vk_decode_free_params(AVRefStructOpaque opaque, void *obj)
1208{
1209 FFVulkanDecodeShared *ctx = opaque.nc;
1210 FFVulkanFunctions *vk = &ctx->s.vkfn;
1211 VkVideoSessionParametersKHR *par = obj;
1212 vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
1213 ctx->s.hwctx->alloc);
1214}
1215
1216int ff_vk_decode_create_params(VkVideoSessionParametersKHR **par_ref, void *logctx, FFVulkanDecodeShared *ctx,
1217 const VkVideoSessionParametersCreateInfoKHR *session_params_create)
1218{
1219 VkVideoSessionParametersKHR *par;
1220 const FFVulkanFunctions *vk = &ctx->s.vkfn;
1221 VkResult ret;
1222
1223 par = av_refstruct_alloc_ext(sizeof(*par), 0, ctx, vk_decode_free_params);
1224 if (!par)
1225 return AVERROR(ENOMEM);
1226
1227 /* Create session parameters */
1228 ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
1229 ctx->s.hwctx->alloc, par);
1230 if (ret != VK_SUCCESS) {
1231 av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1232 ff_vk_ret2str(ret));
1233 *par = VK_NULL_HANDLE;
1234 av_refstruct_unref(&par);
1235 return AVERROR_EXTERNAL;
1236 }
1237 *par_ref = par;
1238
1239 return 0;
1240}
1241
1243{
1245
1246 av_freep(&dec->hevc_headers);
1249 av_freep(&dec->slice_off);
1250 return 0;
1251}
1252
1254{
1255 int err;
1259 int async_depth;
1260 const VkVideoProfileInfoKHR *profile;
1261 const FFVulkanDecodeDescriptor *vk_desc;
1262
1263 VkVideoSessionCreateInfoKHR session_create = {
1264 .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
1265 };
1266
1268 if (err < 0)
1269 return err;
1270
1271 /* Initialize contexts */
1272 ctx = dec->shared_ctx;
1273 s = &ctx->s;
1274
1275 err = ff_vk_init(s, avctx, NULL, avctx->hw_frames_ctx);
1276 if (err < 0)
1277 return err;
1278
1279 vk_desc = get_codecdesc(avctx->codec_id);
1280
1282 if ((vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && !profile) {
1283 av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
1284 return AVERROR(EINVAL);
1285 }
1286
1287 /* Create queue context */
1288 vk_desc = get_codecdesc(avctx->codec_id);
1289 ctx->qf = ff_vk_qf_find(s, vk_desc->queue_flags, vk_desc->decode_op);
1290 if (!ctx->qf) {
1291 av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n",
1292 avcodec_get_name(avctx->codec_id));
1293 return err;
1294 }
1295
1296 session_create.queueFamilyIndex = ctx->qf->idx;
1297 session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
1298 session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
1299 session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
1300 session_create.pictureFormat = s->hwfc->format[0];
1301 session_create.referencePictureFormat = session_create.pictureFormat;
1302 session_create.pStdHeaderVersion = &vk_desc->ext_props;
1303 session_create.pVideoProfile = profile;
1304#ifdef VK_KHR_video_maintenance2
1305 if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)
1306 session_create.flags = VK_VIDEO_SESSION_CREATE_INLINE_SESSION_PARAMETERS_BIT_KHR;
1307#endif
1308
1309 /* Create the decode exec context.
1310 * A small fixed depth is enough to keep the GPU fed, as submissions are
1311 * serialized for hardware decoding; thread-safe hwaccels submit from
1312 * every frame thread concurrently, and need a context per thread. */
1313 async_depth = FF_VK_DEFAULT_EXEC_CONTEXTS;
1315 async_depth = FFMAX(async_depth, avctx->thread_count);
1316
1317 err = ff_vk_exec_pool_init(s, ctx->qf, &ctx->exec_pool,
1318 async_depth, 0, 0, 0, profile);
1319 if (err < 0)
1320 goto fail;
1321
1322 if (!DECODER_IS_SDR(avctx->codec_id)) {
1323 err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
1324 if (err < 0)
1325 goto fail;
1326 }
1327
1328 /* Out-of-place decoding: create the internal, queue-exclusive DPB pool */
1329 if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
1330 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
1331 void *create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
1332 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
1333 /* Reference (DPB) images use the same tiling and pNext chain as output.
1334 * If VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR is 0, the
1335 * driver does not support separate output and DPB with different layouts/tiling. */
1336 void *drm_create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
1337 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
1338 if (drm_create_pnext) {
1339 create_pnext = drm_create_pnext;
1340 tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
1341 av_assert2(ff_vk_find_struct(drm_create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR));
1342 }
1343
1344 err = ff_vk_video_dpb_init(s, &ctx->common, s->hwfc->format[0],
1345 VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR,
1346 tiling, create_pnext,
1347 s->frames->width, s->frames->height,
1348 ctx->common.layered_dpb ?
1349 ctx->caps.maxDpbSlots : 1);
1350 if (err < 0)
1351 goto fail;
1352
1353 if (ctx->common.layered_dpb) {
1354 FFVulkanFunctions *vk = &ctx->s.vkfn;
1355 FFVkExecContext *exec;
1356 VkImageMemoryBarrier2 img_bar;
1357
1358 ctx->common.layered_img = av_refstruct_pool_get(ctx->common.dpb->img_pool);
1359 if (!ctx->common.layered_img) {
1360 err = AVERROR(ENOMEM);
1361 goto fail;
1362 }
1363
1364 ctx->common.layered_view = ctx->common.layered_img->view;
1365 ctx->common.layered_aspect = ctx->common.layered_img->aspect;
1366
1367 /* Created eagerly, so transitioned eagerly; per-picture images
1368 * transition on first use instead */
1369 exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
1370 err = ff_vk_exec_start(&ctx->s, exec);
1371 if (err < 0)
1372 goto fail;
1373
1374 img_bar = (VkImageMemoryBarrier2) {
1375 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
1376 .srcStageMask = VK_PIPELINE_STAGE_2_NONE,
1377 .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
1378 .srcAccessMask = VK_ACCESS_2_NONE,
1379 .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
1380 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
1381 .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
1382 .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
1383 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1384 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1385 .image = ctx->common.layered_img->img,
1386 .subresourceRange = (VkImageSubresourceRange) {
1387 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1388 .layerCount = VK_REMAINING_ARRAY_LAYERS,
1389 .levelCount = 1,
1390 },
1391 };
1392 vk->CmdPipelineBarrier2(exec->buf, &(VkDependencyInfo) {
1393 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
1394 .pImageMemoryBarriers = &img_bar,
1395 .imageMemoryBarrierCount = 1,
1396 });
1397
1398 err = ff_vk_exec_submit(&ctx->s, exec);
1399 if (err < 0)
1400 goto fail;
1401
1402 ctx->common.layered_img->layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
1403 }
1404 }
1405
1406 if (!DECODER_IS_SDR(avctx->codec_id)) {
1407 err = decode_reset(avctx, ctx);
1408 if (err < 0)
1409 return err;
1410 } else {
1411 /* For SDR decoders, this alignment value will be 0. Since this will make
1412 * add_slice() malfunction, set it to a sane default value. */
1413 ctx->caps.minBitstreamBufferSizeAlignment = AV_INPUT_BUFFER_PADDING_SIZE;
1414 }
1415
1416 const VkPhysicalDeviceDriverProperties *driver_props;
1417 driver_props = &dec->shared_ctx->s.driver_props;
1418 if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
1419 driver_props->conformanceVersion.major == 1 &&
1420 driver_props->conformanceVersion.minor == 3 &&
1421 driver_props->conformanceVersion.subminor == 8 &&
1422 driver_props->conformanceVersion.patch < 3)
1423 dec->quirk_av1_offset = 1;
1424
1425 av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization successful\n");
1426
1427 return 0;
1428
1429fail:
1430 ff_vk_decode_uninit(avctx);
1431
1432 return err;
1433}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static const char *const format[]
Definition af_aiir.c:444
static int frames
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define AV_CODEC_ID_H265
Definition codec_id.h:224
#define NULL
Definition coverity.c:32
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, enum AVHWDeviceType dev_type)
Make sure avctx.hw_frames_ctx is set.
Definition decode.c:1069
#define AV_PROFILE_H264_CONSTRAINED
Definition defs.h:107
#define AV_PROFILE_HEVC_MAIN
Definition defs.h:159
#define AV_PROFILE_H264_INTRA
Definition defs.h:108
#define AV_PROFILE_H264_CONSTRAINED_BASELINE
Definition defs.h:111
static enum AVPixelFormat pix_fmt
const char * usage
#define fail
Definition test.h:479
const char * avcodec_profile_name(enum AVCodecID codec_id, int profile)
Return a name for the specified profile, if available.
Definition utils.c:446
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN
Decoding only.
Definition avcodec.h:404
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition utils.c:421
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition codec_id.h:47
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_AV1
Definition codec_id.h:275
@ AV_CODEC_ID_HEVC
Definition codec_id.h:223
@ AV_CODEC_ID_VP9
Definition codec_id.h:217
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
#define AV_HWACCEL_FLAG_IGNORE_LEVEL
Hardware acceleration should be used for decoding even if the codec level used is unknown or higher t...
Definition avcodec.h:1998
#define AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
Hardware acceleration should still be attempted for decoding when the codec profile does not match th...
Definition avcodec.h:2018
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#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
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#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
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition mem.c:495
H.264 / AVC / MPEG-4 part10 codec.
static const int offsets[]
Definition hevc_pel.c:34
static const FFHWAccel * ffhwaccel(const AVHWAccel *codec)
#define HWACCEL_CAP_THREAD_SAFE
@ AV_HWDEVICE_TYPE_VULKAN
Definition hwcontext.h:39
enum VkFormat VkFormat
#define b
Definition input.c:43
#define av_log2
Definition intmath.h:84
static av_cold int decode_end(AVCodecContext *avctx)
Definition 4xm.c:980
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
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
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:645
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition vulkan.c:2815
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition vulkan.c:42
int ff_vk_init(FFVulkanContext *s, void *log_parent, AVBufferRef *device_ref, AVBufferRef *frames_ref)
Initializes the AVClass, in case this context is not used as the main user's context.
Definition vulkan.c:2831
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition vulkan.c:660
FFVkImageViews * ff_vk_imageviews_alloc(FFVulkanContext *s, int nb_views)
Allocate a reference-counted set of image views, zero-initialized for the caller to create.
Definition vulkan.c:1959
void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
Definition vulkan.c:925
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition vulkan.c:622
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:969
void ff_vk_exec_move_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Definition vulkan.c:786
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition vulkan.c:316
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
Definition vulkan.c:779
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition vulkan.c:1426
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
Definition vulkan.c:763
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition vulkan.c:867
const char * desc
Definition libsvtav1.c:83
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
const char data[16]
Definition mxf.c:149
int profile
Definition mxfenc.c:2299
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3380
enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr)
Compute what kind of losses will occur when converting from one specific pixel format to another.
Definition pixdesc.c:3739
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_GBRAP16
Definition pixfmt.h:571
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_RGBA64
Definition pixfmt.h:535
#define AV_PIX_FMT_YUVA422P10
Definition pixfmt.h:597
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
Definition pixfmt.h:104
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition pixfmt.h:75
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition pixfmt.h:265
@ AV_PIX_FMT_RGB48BE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big...
Definition pixfmt.h:109
@ AV_PIX_FMT_RGBA64BE
packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is st...
Definition pixfmt.h:202
@ AV_PIX_FMT_RGB48LE
packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as lit...
Definition pixfmt.h:110
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition pixfmt.h:263
#define AV_PIX_FMT_YUVA422P12
Definition pixfmt.h:599
#define AV_PIX_FMT_X2BGR10
Definition pixfmt.h:620
#define AV_PIX_FMT_GRAY16
Definition pixfmt.h:528
#define AV_PIX_FMT_GBRP16
Definition pixfmt.h:567
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:120
void av_refstruct_replace(void *dstp, const void *src)
Ensure *dstp refers to the same object as src.
Definition refstruct.c:160
void * av_refstruct_pool_get(AVRefStructPool *pool)
Get an object from the pool, reusing an old one from the pool when available.
Definition refstruct.c:297
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
Definition refstruct.h:292
static void * av_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(AVRefStructOpaque opaque, void *obj))
A wrapper around av_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition refstruct.h:94
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
main external API structure.
Definition avcodec.h:443
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
Definition avcodec.h:1502
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:650
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition avcodec.h:1471
const struct AVHWAccel * hwaccel
Hardware accelerator in use.
Definition avcodec.h:1423
int level
Encoding level descriptor.
Definition avcodec.h:1646
int profile
profile
Definition avcodec.h:1636
int export_side_data
Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of metadata exported in frame,...
Definition avcodec.h:1779
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition avcodec.h:1579
int flags
AV_CODEC_FLAG_*.
Definition avcodec.h:500
enum AVCodecID codec_id
Definition avcodec.h:453
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition avcodec.h:619
struct AVCodecInternal * internal
Private context used for internal data.
Definition avcodec.h:478
void * priv_data
Definition avcodec.h:470
void * hwaccel_priv_data
hwaccel-specific private data
Definition internal.h:130
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition frame.h:769
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition frame.h:649
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
void * user_opaque
Arbitrary user data, to be used e.g.
Definition hwcontext.h:166
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition hwcontext.h:153
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
Definition hwcontext.h:161
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
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition pixdesc.h:89
VkImageLayout layout[AV_NUM_DATA_POINTERS]
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
VkPhysicalDevice phys_dev
Physical device.
const char *const * enabled_dev_extensions
Enabled device extensions.
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
void * create_pnext
Extension data for image creation.
VkImageTiling tiling
Controls the tiling of allocated frames.
VkImageUsageFlagBits usage
Defines extra usage of output frames.
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
int caps_internal
Internal hwaccel capabilities.
VkBuffer buf
Definition vulkan.h:95
size_t size
Definition vulkan.h:98
VkMemoryPropertyFlagBits flags
Definition vulkan.h:97
VkDeviceMemory mem
Definition vulkan.h:96
uint8_t * mapped_mem
Definition vulkan.h:103
VkCommandBuffer buf
Definition vulkan.h:142
VkImageView views[AV_NUM_DATA_POINTERS]
Definition vulkan.h:559
VkImageLayout layout
VkImageAspectFlags aspect
VkImageView view
VkPhysicalDeviceDriverProperties driver_props
Definition vulkan.h:302
VkVideoSessionParametersKHR * session_params
FFVulkanDecodeShared * shared_ctx
struct HEVCHeaderSet * hevc_headers
unsigned int slice_off_max
FFVulkanExtensions decode_extension
VkVideoCodecOperationFlagBitsKHR decode_op
VkQueueFlagBits queue_flags
VkExtensionProperties ext_props
struct FFVulkanDecodePicture::@321376256110110067000314232201030232256240036361 view
VkVideoReferenceSlotInfoKHR ref_slot
VkImageAspectFlags aspect_ref
VkVideoDecodeInfoKHR decode_info
FFVkVideoDPBImage * dpb_img
PFN_vkInvalidateMappedMemoryRanges invalidate_memory_ranges
VkImageAspectFlags aspect
FFVkImageViews * out_views
VkVideoDecodeAV1ProfileInfoKHR av1_profile
VkVideoProfileListInfoKHR profile_list
VkVideoDecodeUsageInfoKHR usage
VkVideoDecodeH265ProfileInfoKHR h265_profile
VkVideoDecodeH264ProfileInfoKHR h264_profile
VkVideoProfileInfoKHR profile
FFVulkanContext s
H264Context.
Definition h264dec.h:338
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
int size
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition refstruct.h:58
enum AVCodecID codec_id
#define FF_VK_DEFAULT_EXEC_CONTEXTS
Definition vulkan.h:121
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition vulkan.h:365
const FFVulkanDecodeDescriptor ff_vk_dec_apv_desc
Definition vulkan_apv.c:33
const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc
Definition vulkan_av1.c:26
int ff_vk_decode_frame(AVCodecContext *avctx, AVFrame *pic, FFVulkanDecodePicture *vp, AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
Decode a frame.
int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
Synchronize the contexts between 2 threads.
static const VkVideoProfileInfoKHR * get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
int ff_vk_decode_create_params(VkVideoSessionParametersKHR **par_ref, void *logctx, FFVulkanDecodeShared *ctx, const VkVideoSessionParametersCreateInfoKHR *session_params_create)
Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
static void free_common(AVRefStructOpaque unused, void *obj)
int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
Removes current session parameters to recreate them.
static const FFVulkanDecodeDescriptor * dec_descs[]
int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
Initialize hw_frames_ctx with the parameters needed to decode the stream using the parameters from av...
int ff_vk_decode_add_slice(AVCodecContext *avctx, FFVulkanDecodePicture *vp, const uint8_t *data, size_t size, int add_startcode, uint32_t *nb_slices, const uint32_t **offsets)
Add slice data to frame.
#define DECODER_IS_SDR(codec_id)
static int create_empty_session_parameters(AVCodecContext *avctx, FFVulkanDecodeShared *ctx, VkVideoSessionParametersKHR *empty_session_params)
static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
static int decode_reset(AVCodecContext *avctx, FFVulkanDecodeShared *ctx)
void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
Free a frame and its state.
static const FFVulkanDecodeDescriptor * get_codecdesc(enum AVCodecID codec_id)
static void init_frame(FFVulkanDecodeContext *dec, FFVulkanDecodePicture *vkpic)
static void free_profile_data(AVHWFramesContext *hwfc)
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref, enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt, FFVulkanDecodeProfileData *prof, int *dpb_dedicate)
static void vk_decode_free_params(AVRefStructOpaque opaque, void *obj)
int ff_vk_decode_prepare_frame(FFVulkanDecodeContext *dec, AVFrame *pic, FFVulkanDecodePicture *vkpic, int is_current, int alloc_dpb)
Prepare a frame, creates the image view, and sets up the dpb fields.
static VkResult vulkan_setup_profile(AVCodecContext *avctx, FFVulkanDecodeProfileData *prof, AVVulkanDeviceContext *hwctx, FFVulkanFunctions *vk, const FFVulkanDecodeDescriptor *vk_desc, VkVideoDecodeH264CapabilitiesKHR *h264_caps, VkVideoDecodeH265CapabilitiesKHR *h265_caps, VkVideoDecodeAV1CapabilitiesKHR *av1_caps, VkVideoCapabilitiesKHR *caps, VkVideoDecodeCapabilitiesKHR *dec_caps, int cur_profile)
const FFVulkanDecodeDescriptor ff_vk_dec_dpx_desc
Definition vulkan_dpx.c:34
const FFVulkanDecodeDescriptor ff_vk_dec_ffv1_desc
Definition vulkan_ffv1.c:63
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_VIDEO_MAINTENANCE_2
const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc
Definition vulkan_h264.c:26
const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc
Definition vulkan_hevc.c:26
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
const FFVulkanDecodeDescriptor ff_vk_dec_prores_desc
const FFVulkanDecodeDescriptor ff_vk_dec_prores_raw_desc
VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
Get Vulkan's bit depth from an [8:12] integer.
VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
Get Vulkan's chroma subsampling from a pixfmt descriptor.
int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
int ff_vk_create_view(FFVulkanContext *s, VkImageView *view, VkImageAspectFlags *aspect, VkImage img, VkFormat vkf, VkImageUsageFlags usage, int layered)
Creates image views for video frames.
int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level)
Convert level from Vulkan to AV.
av_cold void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common)
Free video session and required resources.
av_cold int ff_vk_video_dpb_init(FFVulkanContext *s, FFVkVideoCommon *common, VkFormat format, VkImageUsageFlags usage, VkImageTiling tiling, void *create_pnext, int width, int height, int nb_layers)
Initialize the internal DPB image pool.
enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
Get pixfmt from a Vulkan format.
av_cold int ff_vk_video_common_init(AVCodecContext *avctx, FFVulkanContext *s, FFVkVideoCommon *common, VkVideoSessionCreateInfoKHR *session_create)
Initialize video session, allocating and binding necessary memory.
#define CODEC_VER(ver)
const FFVulkanDecodeDescriptor ff_vk_dec_vp9_desc
Definition vulkan_vp9.c:23
static int ref_frame(VVCFrame *dst, const VVCFrame *src)
Definition dec.c:616