FFmpeg
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 
19 #include "libavutil/refstruct.h"
20 #include "vulkan_video.h"
21 #include "vulkan_decode.h"
22 #include "config_components.h"
23 #include "libavutil/avassert.h"
24 #include "libavutil/mem.h"
26 
27 #if CONFIG_H264_VULKAN_HWACCEL
29 #endif
30 #if CONFIG_HEVC_VULKAN_HWACCEL
32 #endif
33 #if CONFIG_AV1_VULKAN_HWACCEL
35 #endif
36 
38 #if CONFIG_H264_VULKAN_HWACCEL
40 #endif
41 #if CONFIG_HEVC_VULKAN_HWACCEL
43 #endif
44 #if CONFIG_AV1_VULKAN_HWACCEL
46 #endif
47 };
48 
50 {
51  for (size_t i = 0; i < FF_ARRAY_ELEMS(dec_descs); i++)
52  if (dec_descs[i]->codec_id == codec_id)
53  return dec_descs[i];
54  av_assert1(!"no codec descriptor");
55  return NULL;
56 }
57 
58 static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
59 {
60  const VkVideoProfileListInfoKHR *profile_list;
61 
62  VkStructureType profile_struct_type =
63  codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
64  codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
65  codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
66  0;
67 
68  profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
69  VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
70  if (!profile_list)
71  return NULL;
72 
73  for (int i = 0; i < profile_list->profileCount; i++)
74  if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type))
75  return &profile_list->pProfiles[i];
76 
77  return NULL;
78 }
79 
81 {
82  int err;
83  FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
84  FFVulkanDecodeContext *dst_ctx = dst->internal->hwaccel_priv_data;
85 
86  if (!dst_ctx->exec_pool.cmd_bufs) {
88 
89  const VkVideoProfileInfoKHR *profile = get_video_profile(ctx, dst->codec_id);
90  if (!profile) {
91  av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!\n");
92  return AVERROR(EINVAL);
93  }
94 
95  err = ff_vk_exec_pool_init(&ctx->s, &ctx->qf,
96  &dst_ctx->exec_pool,
97  src_ctx->exec_pool.pool_size,
98  src_ctx->exec_pool.nb_queries,
99  VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
100  profile);
101  if (err < 0)
102  return err;
103  }
104 
105  av_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
106 
107  if (src_ctx->session_params) {
108  err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params);
109  if (err < 0)
110  return err;
111  }
112 
113  dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
114  dst_ctx->external_fg = src_ctx->external_fg;
115  dst_ctx->frame_id_alloc_mask = src_ctx->frame_id_alloc_mask;
116 
117  return 0;
118 }
119 
120 int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
121 {
124  return 0;
125 }
126 
128 {
129  int err;
130  AVFrame *avf = av_frame_alloc();
131  if (!avf)
132  return NULL;
133 
134  err = av_hwframe_get_buffer(ctx->common.dpb_hwfc_ref, avf, 0x0);
135  if (err < 0)
136  av_frame_free(&avf);
137 
138  return avf;
139 }
140 
142  FFVulkanDecodePicture *vkpic, int is_current,
143  int alloc_dpb)
144 {
145  int err;
147  FFVulkanFunctions *vk = &ctx->s.vkfn;
148 
149  vkpic->slices_size = 0;
150 
151  /* If the decoder made a blank frame to make up for a missing ref, or the
152  * frame is the current frame so it's missing one, create a re-representation */
153  if (vkpic->img_view_ref)
154  return 0;
155 
156  vkpic->dpb_frame = NULL;
157  vkpic->img_view_ref = VK_NULL_HANDLE;
158  vkpic->img_view_out = VK_NULL_HANDLE;
159  vkpic->img_view_dest = VK_NULL_HANDLE;
160 
161  vkpic->destroy_image_view = vk->DestroyImageView;
162  vkpic->wait_semaphores = vk->WaitSemaphores;
163 
164  if (ctx->common.layered_dpb && alloc_dpb) {
165  vkpic->img_view_ref = ctx->common.layered_view;
166  vkpic->img_aspect_ref = ctx->common.layered_aspect;
167  } else if (alloc_dpb) {
168  AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
169  AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx;
170 
171  vkpic->dpb_frame = vk_get_dpb_pool(ctx);
172  if (!vkpic->dpb_frame)
173  return AVERROR(ENOMEM);
174 
175  err = ff_vk_create_view(&ctx->s, &ctx->common,
176  &vkpic->img_view_ref, &vkpic->img_aspect_ref,
177  (AVVkFrame *)vkpic->dpb_frame->data[0],
178  dpb_hwfc->format[0], !is_current);
179  if (err < 0)
180  return err;
181 
182  vkpic->img_view_dest = vkpic->img_view_ref;
183  }
184 
185  if (!alloc_dpb || is_current) {
187  AVVulkanFramesContext *hwfc = frames->hwctx;
188 
189  err = ff_vk_create_view(&ctx->s, &ctx->common,
190  &vkpic->img_view_out, &vkpic->img_aspect,
191  (AVVkFrame *)pic->data[0],
192  hwfc->format[0], !is_current);
193  if (err < 0)
194  return err;
195 
196  if (!alloc_dpb) {
197  vkpic->img_view_ref = vkpic->img_view_out;
198  vkpic->img_aspect_ref = vkpic->img_aspect;
199  }
200  }
201 
202  return 0;
203 }
204 
206  const uint8_t *data, size_t size, int add_startcode,
207  uint32_t *nb_slices, const uint32_t **offsets)
208 {
211 
212  static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
213  const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
214  const int nb = *nb_slices;
215  uint8_t *slices;
216  uint32_t *slice_off;
217  FFVkBuffer *vkbuf;
218 
219  size_t new_size = vp->slices_size + startcode_len + size +
220  ctx->caps.minBitstreamBufferSizeAlignment;
221  new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
222 
223  slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max,
224  (nb + 1)*sizeof(slice_off));
225  if (!slice_off)
226  return AVERROR(ENOMEM);
227 
228  *offsets = dec->slice_off = slice_off;
229  slice_off[nb] = vp->slices_size;
230 
231  vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
232  if (!vkbuf || vkbuf->size < new_size) {
233  int err;
234  AVBufferRef *new_ref;
235  FFVkBuffer *new_buf;
236 
237  /* No point in requesting anything smaller. */
238  size_t buf_size = FFMAX(new_size, 1024*1024);
239 
240  /* Align buffer to nearest power of two. Makes fragmentation management
241  * easier, and gives us ample headroom. */
242  buf_size = 2 << av_log2(buf_size);
243 
244  err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
245  VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
246  ctx->s.hwfc->create_pnext, buf_size,
247  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
248  if (err < 0)
249  return err;
250 
251  new_buf = (FFVkBuffer *)new_ref->data;
252 
253  /* Copy data from the old buffer */
254  if (vkbuf) {
255  memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
257  }
258 
259  vp->slices_buf = new_ref;
260  vkbuf = new_buf;
261  }
262  slices = vkbuf->mapped_mem;
263 
264  /* Startcode */
265  memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
266 
267  /* Slice data */
268  memcpy(slices + vp->slices_size + startcode_len, data, size);
269 
270  *nb_slices = nb + 1;
271  vp->slices_size += startcode_len + size;
272 
273  return 0;
274 }
275 
277 {
280 
281  FFVulkanFunctions *vk = &ctx->s.vkfn;
282  VkVideoBeginCodingInfoKHR decode_start = {
283  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
284  .videoSession = ctx->common.session,
285  .videoSessionParameters = ctx->empty_session_params,
286  };
287  VkVideoCodingControlInfoKHR decode_ctrl = {
288  .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
289  .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
290  };
291  VkVideoEndCodingInfoKHR decode_end = {
292  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
293  };
294 
295  VkCommandBuffer cmd_buf;
296  FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);
297  int had_submission = exec->had_submission;
298  ff_vk_exec_start(&ctx->s, exec);
299  cmd_buf = exec->buf;
300 
301  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
302  vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
303  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
304  ff_vk_exec_submit(&ctx->s, exec);
305 
306  /* If this is the very first time this context is used, then remove the
307  * had_submission flag to indicate that no query result is available,
308  * as no decode command was issued. */
309  exec->had_submission = had_submission;
310 }
311 
313  AVFrame *pic, FFVulkanDecodePicture *vp,
314  AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
315 {
316  int err;
317  VkResult ret;
318  VkCommandBuffer cmd_buf;
319  FFVkBuffer *sd_buf;
320 
323  FFVulkanFunctions *vk = &ctx->s.vkfn;
324 
325  /* Output */
326  AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
327 
328  /* Quirks */
329  const int layered_dpb = ctx->common.layered_dpb;
330 
331  VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)dec->session_params->data;
332  VkVideoBeginCodingInfoKHR decode_start = {
333  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
334  .videoSession = ctx->common.session,
335  .videoSessionParameters = *par,
336  .referenceSlotCount = vp->decode_info.referenceSlotCount,
337  .pReferenceSlots = vp->decode_info.pReferenceSlots,
338  };
339  VkVideoEndCodingInfoKHR decode_end = {
340  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
341  };
342 
343  VkImageMemoryBarrier2 img_bar[37];
344  int nb_img_bar = 0;
345  size_t data_size = FFALIGN(vp->slices_size,
346  ctx->caps.minBitstreamBufferSizeAlignment);
347 
348  FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &dec->exec_pool);
349 
350  /* The current decoding reference has to be bound as an inactive reference */
351  VkVideoReferenceSlotInfoKHR *cur_vk_ref;
352  cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
353  cur_vk_ref[0] = vp->ref_slot;
354  cur_vk_ref[0].slotIndex = -1;
355  decode_start.referenceSlotCount++;
356 
357  if (dec->exec_pool.nb_queries && exec->had_submission) {
358  uint32_t *result;
359  ret = ff_vk_exec_get_query(&ctx->s, exec, (void **)&result,
360  VK_QUERY_RESULT_WAIT_BIT);
361  if (ret != VK_NOT_READY && ret != VK_SUCCESS) {
362  av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
363  ff_vk_ret2str(ret));
364  return AVERROR_EXTERNAL;
365  }
366 
367  av_log(avctx,
368  result[0] != VK_QUERY_RESULT_STATUS_COMPLETE_KHR ?
370  "Result of previous frame decoding: %u\n", result[0]);
371  }
372 
373  sd_buf = (FFVkBuffer *)vp->slices_buf->data;
374 
375  /* Flush if needed */
376  if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
377  VkMappedMemoryRange flush_buf = {
378  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
379  .memory = sd_buf->mem,
380  .offset = 0,
381  .size = FFALIGN(vp->slices_size,
382  ctx->s.props.properties.limits.nonCoherentAtomSize),
383  };
384 
385  ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
386  if (ret != VK_SUCCESS) {
387  av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
388  ff_vk_ret2str(ret));
389  return AVERROR_EXTERNAL;
390  }
391  }
392 
393  vp->decode_info.srcBuffer = sd_buf->buf;
394  vp->decode_info.srcBufferOffset = 0;
395  vp->decode_info.srcBufferRange = data_size;
396 
397  /* Start command buffer recording */
398  err = ff_vk_exec_start(&ctx->s, exec);
399  if (err < 0)
400  return err;
401  cmd_buf = exec->buf;
402 
403  /* Slices */
404  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
405  if (err < 0)
406  return err;
407  vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
408 
409  /* Parameters */
410  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
411  if (err < 0)
412  return err;
413 
414  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
415  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
416  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
417  if (err < 0)
418  return err;
419 
420  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
421  pic);
422  if (err < 0)
423  return err;
424 
425  /* Output image - change layout, as it comes from a pool */
426  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
427  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
428  .pNext = NULL,
429  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
430  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
431  .srcAccessMask = VK_ACCESS_2_NONE,
432  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
433  .oldLayout = vkf->layout[0],
434  .newLayout = (layered_dpb || vp->dpb_frame) ?
435  VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
436  VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
437  .srcQueueFamilyIndex = vkf->queue_family[0],
438  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
439  .image = vkf->img[0],
440  .subresourceRange = (VkImageSubresourceRange) {
441  .aspectMask = vp->img_aspect,
442  .layerCount = 1,
443  .levelCount = 1,
444  },
445  };
446  ff_vk_exec_update_frame(&ctx->s, exec, pic,
447  &img_bar[nb_img_bar], &nb_img_bar);
448 
449  /* Reference for the current image, if existing and not layered */
450  if (vp->dpb_frame) {
451  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
452  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
453  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
454  if (err < 0)
455  return err;
456  }
457 
458  if (!layered_dpb) {
459  /* All references (apart from the current) for non-layered refs */
460 
461  for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
462  AVFrame *ref_frame = rpic[i];
463  FFVulkanDecodePicture *rvp = rvkp[i];
464  AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame;
465 
466  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref,
467  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
468  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
469  if (err < 0)
470  return err;
471 
472  if (err == 0) {
473  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec,
474  &rvp->sem, &rvp->sem_value,
475  ref);
476  if (err < 0)
477  return err;
478  }
479 
480  if (!rvp->dpb_frame) {
481  AVVkFrame *rvkf = (AVVkFrame *)ref->data[0];
482 
483  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
484  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
485  .pNext = NULL,
486  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
487  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
488  .srcAccessMask = VK_ACCESS_2_NONE,
489  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
490  VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
491  .oldLayout = rvkf->layout[0],
492  .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
493  .srcQueueFamilyIndex = rvkf->queue_family[0],
494  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
495  .image = rvkf->img[0],
496  .subresourceRange = (VkImageSubresourceRange) {
497  .aspectMask = rvp->img_aspect_ref,
498  .layerCount = 1,
499  .levelCount = 1,
500  },
501  };
502  ff_vk_exec_update_frame(&ctx->s, exec, ref,
503  &img_bar[nb_img_bar], &nb_img_bar);
504  }
505  }
506  } else if (vp->decode_info.referenceSlotCount ||
507  vp->img_view_out != vp->img_view_ref) {
508  /* Single barrier for a single layered ref */
509  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
510  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
511  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
512  if (err < 0)
513  return err;
514  }
515 
516  /* Change image layout */
517  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
518  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
519  .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
520  .pImageMemoryBarriers = img_bar,
521  .imageMemoryBarrierCount = nb_img_bar,
522  });
523 
524  /* Start, use parameters, decode and end decoding */
525  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
526 
527  /* Start status query */
528  if (dec->exec_pool.nb_queries)
529  vk->CmdBeginQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0, 0);
530 
531  vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
532 
533  /* End status query */
534  if (dec->exec_pool.nb_queries)
535  vk->CmdEndQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0);
536 
537  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
538 
539  /* End recording and submit for execution */
540  return ff_vk_exec_submit(&ctx->s, exec);
541 }
542 
544 {
545  AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
546 
547  VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) {
548  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
549  .pSemaphores = &vp->sem,
550  .pValues = &vp->sem_value,
551  .semaphoreCount = 1,
552  };
553 
554  /* We do not have to lock the frame here because we're not interested
555  * in the actual current semaphore value, but only that it's later than
556  * the time we submitted the image for decoding. */
557  if (vp->sem)
558  vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
559 
560  /* Free slices data */
562 
563  /* Destroy image view (out) */
564  if (vp->img_view_out && vp->img_view_out != vp->img_view_dest)
565  vp->destroy_image_view(hwctx->act_dev, vp->img_view_out, hwctx->alloc);
566 
567  /* Destroy image view (ref, unlayered) */
568  if (vp->img_view_dest)
569  vp->destroy_image_view(hwctx->act_dev, vp->img_view_dest, hwctx->alloc);
570 
571  av_frame_free(&vp->dpb_frame);
572 }
573 
574 static void free_common(AVRefStructOpaque unused, void *obj)
575 {
576  FFVulkanDecodeShared *ctx = obj;
577  FFVulkanContext *s = &ctx->s;
578  FFVulkanFunctions *vk = &ctx->s.vkfn;
579 
580  /* This also frees all references from this pool */
581  av_frame_free(&ctx->common.layered_frame);
582 
583  /* Destroy parameters */
584  if (ctx->empty_session_params)
585  vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
586  ctx->empty_session_params,
587  s->hwctx->alloc);
588 
589  av_buffer_pool_uninit(&ctx->buf_pool);
590 
591  ff_vk_video_common_uninit(s, &ctx->common);
592 
593  ff_vk_uninit(s);
594 }
595 
596 static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
597 {
598  int err;
601  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
602  AVVulkanDeviceContext *hwctx = device->hwctx;
604 
605  if (dec->shared_ctx)
606  return 0;
607 
608  dec->shared_ctx = av_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
609  free_common);
610  if (!dec->shared_ctx)
611  return AVERROR(ENOMEM);
612 
613  ctx = dec->shared_ctx;
614 
615  ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
617 
618  if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
619  av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
620  VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
622  return AVERROR(ENOSYS);
623  }
624 
625  err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
626  if (err < 0) {
628  return err;
629  }
630 
631  return 0;
632 }
633 
634 static VkResult vulkan_setup_profile(AVCodecContext *avctx,
636  AVVulkanDeviceContext *hwctx,
637  FFVulkanFunctions *vk,
638  const FFVulkanDecodeDescriptor *vk_desc,
639  VkVideoDecodeH264CapabilitiesKHR *h264_caps,
640  VkVideoDecodeH265CapabilitiesKHR *h265_caps,
641  VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
642  VkVideoCapabilitiesKHR *caps,
643  VkVideoDecodeCapabilitiesKHR *dec_caps,
644  int cur_profile)
645 {
646  VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
647  VkVideoProfileInfoKHR *profile = &prof->profile;
648  VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
649 
650  VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
651  VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
652  VkVideoDecodeAV1ProfileInfoKHR *av1_profile = &prof->av1_profile;
653 
655  if (!desc)
656  return AVERROR(EINVAL);
657 
658  if (avctx->codec_id == AV_CODEC_ID_H264) {
659  dec_caps->pNext = h264_caps;
660  usage->pNext = h264_profile;
661  h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
662 
663  /* Vulkan transmits all the constrant_set flags, rather than wanting them
664  * merged in the profile IDC */
665  h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
667 
668  h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN ||
670  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR :
671  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
672  } else if (avctx->codec_id == AV_CODEC_ID_H265) {
673  dec_caps->pNext = h265_caps;
674  usage->pNext = h265_profile;
675  h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
676  h265_profile->stdProfileIdc = cur_profile;
677  } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
678  dec_caps->pNext = av1_caps;
679  usage->pNext = av1_profile;
680  av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
681  av1_profile->stdProfile = cur_profile;
682  av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
683  }
684 
685  usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
686  usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
687 
688  profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
689  profile->pNext = usage;
690  profile->videoCodecOperation = vk_desc->decode_op;
691  profile->chromaSubsampling = ff_vk_subsampling_from_av_desc(desc);
692  profile->lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth);
693  profile->chromaBitDepth = profile->lumaBitDepth;
694 
695  profile_list->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
696  profile_list->profileCount = 1;
697  profile_list->pProfiles = profile;
698 
699  /* Get the capabilities of the decoder for the given profile */
700  caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
701  caps->pNext = dec_caps;
702  dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
703  /* dec_caps->pNext already filled in */
704 
705  return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
706  caps);
707 }
708 
709 static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref,
710  enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
712  int *dpb_dedicate)
713 {
714  VkResult ret;
715  int max_level, base_profile, cur_profile;
716  const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
718  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
719  AVVulkanDeviceContext *hwctx = device->hwctx;
720  enum AVPixelFormat source_format;
721  enum AVPixelFormat best_format;
722  VkFormat best_vkfmt;
723 
726  FFVulkanFunctions *vk = &ctx->s.vkfn;
727 
728  VkVideoCapabilitiesKHR *caps = &ctx->caps;
729  VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
730 
731  VkVideoDecodeH264CapabilitiesKHR h264_caps = {
732  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
733  };
734  VkVideoDecodeH265CapabilitiesKHR h265_caps = {
735  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
736  };
737  VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
738  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
739  };
740 
741  VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
742  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
743  .pNext = &prof->profile_list,
744  };
745  VkVideoFormatPropertiesKHR *ret_info;
746  uint32_t nb_out_fmts = 0;
747 
748  if (!(vk_desc->decode_extension & ctx->s.extensions)) {
749  av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
750  avcodec_get_name(avctx->codec_id));
751  return AVERROR(ENOSYS);
752  }
753 
754  cur_profile = avctx->profile;
757  avctx->codec_id == AV_CODEC_ID_AV1 ? STD_VIDEO_AV1_PROFILE_MAIN :
758  0;
759 
760  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
761  &h264_caps,
762  &h265_caps,
763  &av1_caps,
764  caps,
765  dec_caps,
766  cur_profile);
767  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
769  avctx->profile != base_profile) {
770  av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
771  "again with profile %s\n",
772  avcodec_get_name(avctx->codec_id),
773  avcodec_profile_name(avctx->codec_id, cur_profile),
774  avcodec_profile_name(avctx->codec_id, base_profile));
775  cur_profile = base_profile;
776  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
777  &h264_caps,
778  &h265_caps,
779  &av1_caps,
780  caps,
781  dec_caps,
782  cur_profile);
783  }
784 
785  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
786  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
787  "%s profile \"%s\" not supported!\n",
788  avcodec_get_name(avctx->codec_id),
789  avcodec_profile_name(avctx->codec_id, cur_profile));
790  return AVERROR(EINVAL);
791  } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
792  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
793  "format (%s) not supported!\n",
795  return AVERROR(EINVAL);
796  } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
797  ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
798  return AVERROR(EINVAL);
799  } else if (ret != VK_SUCCESS) {
800  return AVERROR_EXTERNAL;
801  }
802 
803  max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
804  avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
805  avctx->codec_id == AV_CODEC_ID_AV1 ? av1_caps.maxLevel :
806  0;
807 
808  av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
809  avcodec_get_name(avctx->codec_id),
810  avcodec_profile_name(avctx->codec_id, cur_profile));
811  av_log(avctx, AV_LOG_VERBOSE, " Maximum level: %i (stream %i)\n",
812  max_level, avctx->level);
813  av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n",
814  caps->minCodedExtent.width, caps->maxCodedExtent.width);
815  av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n",
816  caps->minCodedExtent.height, caps->maxCodedExtent.height);
817  av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n",
818  caps->pictureAccessGranularity.width);
819  av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n",
820  caps->pictureAccessGranularity.height);
821  av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n",
822  caps->minBitstreamBufferOffsetAlignment);
823  av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n",
824  caps->minBitstreamBufferSizeAlignment);
825  av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n",
826  caps->maxDpbSlots);
827  av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n",
828  caps->maxActiveReferencePictures);
829  av_log(avctx, AV_LOG_VERBOSE, " Codec header name: '%s' (driver), '%s' (compiled)\n",
830  caps->stdHeaderVersion.extensionName,
831  vk_desc->ext_props.extensionName);
832  av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
833  CODEC_VER(caps->stdHeaderVersion.specVersion),
834  CODEC_VER(vk_desc->ext_props.specVersion));
835  av_log(avctx, AV_LOG_VERBOSE, " Decode modes:%s%s%s\n",
836  dec_caps->flags ? "" :
837  " invalid",
838  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
839  " reuse_dst_dpb" : "",
840  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
841  " dedicated_dpb" : "");
842  av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n",
843  caps->flags ? "" :
844  " none",
845  caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
846  " protected" : "",
847  caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
848  " separate_references" : "");
849 
850  /* Check if decoding is possible with the given parameters */
851  if (avctx->coded_width < caps->minCodedExtent.width ||
852  avctx->coded_height < caps->minCodedExtent.height ||
853  avctx->coded_width > caps->maxCodedExtent.width ||
854  avctx->coded_height > caps->maxCodedExtent.height)
855  return AVERROR(EINVAL);
856 
858  avctx->level > max_level)
859  return AVERROR(EINVAL);
860 
861  /* Some basic sanity checking */
862  if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
863  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) {
864  av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
865  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
866  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
867  return AVERROR_EXTERNAL;
868  } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
869  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) ==
870  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) &&
871  !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
872  av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
873  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
874  "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
875  return AVERROR_EXTERNAL;
876  }
877 
878  dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR);
879  ctx->common.layered_dpb = !dec->dedicated_dpb ? 0 :
880  !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
881 
882  if (dec->dedicated_dpb) {
883  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
884  } else {
885  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
886  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
887  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
888  VK_IMAGE_USAGE_SAMPLED_BIT;
889 
890  if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
892  fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
893  }
894 
895  /* Get the format of the images necessary */
896  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
897  &fmt_info,
898  &nb_out_fmts, NULL);
899  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
900  (!nb_out_fmts && ret == VK_SUCCESS)) {
901  return AVERROR(EINVAL);
902  } else if (ret != VK_SUCCESS) {
903  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
904  ff_vk_ret2str(ret));
905  return AVERROR_EXTERNAL;
906  }
907 
908  ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
909  if (!ret_info)
910  return AVERROR(ENOMEM);
911 
912  for (int i = 0; i < nb_out_fmts; i++)
913  ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
914 
915  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
916  &fmt_info,
917  &nb_out_fmts, ret_info);
918  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
919  (!nb_out_fmts && ret == VK_SUCCESS)) {
920  av_free(ret_info);
921  return AVERROR(EINVAL);
922  } else if (ret != VK_SUCCESS) {
923  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
924  ff_vk_ret2str(ret));
925  av_free(ret_info);
926  return AVERROR_EXTERNAL;
927  }
928 
929  /* Find a format to use */
930  *pix_fmt = best_format = AV_PIX_FMT_NONE;
931  *vk_fmt = best_vkfmt = VK_FORMAT_UNDEFINED;
932  source_format = avctx->sw_pix_fmt;
933 
934  av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
935  for (int i = 0; i < nb_out_fmts; i++) {
937  if (tmp == AV_PIX_FMT_NONE) {
938  av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
939  continue;
940  }
941 
942  best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
943  if (tmp == best_format)
944  best_vkfmt = ret_info[i].format;
945 
946  av_log(avctx, AV_LOG_DEBUG, " %s%s (Vulkan ID: %i)\n",
947  av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
948  ret_info[i].format);
949  }
950 
951  av_free(ret_info);
952 
953  if (best_format == AV_PIX_FMT_NONE) {
954  av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
955  return AVERROR(EINVAL);
956  } else {
957  av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
958  av_get_pix_fmt_name(best_format), best_vkfmt);
959  }
960 
961  *pix_fmt = best_format;
962  *vk_fmt = best_vkfmt;
963 
964  *dpb_dedicate = dec->dedicated_dpb;
965 
966  return 0;
967 }
968 
970 {
971  av_free(hwfc->user_opaque);
972 }
973 
974 int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
975 {
976  VkFormat vkfmt;
977  int err, dedicated_dpb;
978  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
979  AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
983 
984  frames_ctx->sw_format = AV_PIX_FMT_NONE;
985 
986  err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
987  if (err < 0)
988  return err;
989 
990  prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
991  if (!prof)
992  return AVERROR(ENOMEM);
993 
994  err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
995  &frames_ctx->sw_format, &vkfmt,
996  prof, &dedicated_dpb);
997  if (err < 0) {
998  av_free(prof);
999  return err;
1000  }
1001 
1002  frames_ctx->user_opaque = prof;
1003  frames_ctx->free = free_profile_data;
1004 
1005  frames_ctx->width = avctx->coded_width;
1006  frames_ctx->height = avctx->coded_height;
1007  frames_ctx->format = AV_PIX_FMT_VULKAN;
1008 
1009  hwfc->format[0] = vkfmt;
1010  hwfc->create_pnext = &prof->profile_list;
1011  hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1012  hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1013  VK_IMAGE_USAGE_SAMPLED_BIT |
1014  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
1015 
1016  if (!dec->dedicated_dpb)
1017  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1018 
1019  ctx = dec->shared_ctx;
1020  if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
1022  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1023 
1024  return err;
1025 }
1026 
1027 static void vk_decode_free_params(void *opaque, uint8_t *data)
1028 {
1029  FFVulkanDecodeShared *ctx = opaque;
1030  FFVulkanFunctions *vk = &ctx->s.vkfn;
1031  VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data;
1032  vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
1033  ctx->s.hwctx->alloc);
1034  av_free(par);
1035 }
1036 
1038  const VkVideoSessionParametersCreateInfoKHR *session_params_create)
1039 {
1040  VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
1041  const FFVulkanFunctions *vk = &ctx->s.vkfn;
1042  VkResult ret;
1043 
1044  if (!par)
1045  return AVERROR(ENOMEM);
1046 
1047  /* Create session parameters */
1048  ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
1049  ctx->s.hwctx->alloc, par);
1050  if (ret != VK_SUCCESS) {
1051  av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1052  ff_vk_ret2str(ret));
1053  av_free(par);
1054  return AVERROR_EXTERNAL;
1055  }
1056  *par_ref = av_buffer_create((uint8_t *)par, sizeof(*par),
1058  if (!*par_ref) {
1059  vk_decode_free_params(ctx, (uint8_t *)par);
1060  return AVERROR(ENOMEM);
1061  }
1062 
1063  return 0;
1064 }
1065 
1067 {
1070 
1071  /* Wait on and free execution pool */
1072  ff_vk_exec_pool_free(&ctx->s, &dec->exec_pool);
1073 
1074  av_freep(&dec->hevc_headers);
1077  av_freep(&dec->slice_off);
1078  return 0;
1079 }
1080 
1082 {
1083  int err, nb_q = 0;
1084  VkResult ret;
1087  FFVulkanContext *s;
1088  FFVulkanFunctions *vk;
1089  const VkVideoProfileInfoKHR *profile;
1090  const FFVulkanDecodeDescriptor *vk_desc;
1091  const VkPhysicalDeviceDriverProperties *driver_props;
1092 
1093  VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
1094  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
1095  };
1096  VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
1097  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
1098  };
1099  StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
1100  VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
1101  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
1102  .pStdSequenceHeader = &av1_empty_seq,
1103  };
1104  VkVideoSessionParametersCreateInfoKHR session_params_create = {
1105  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
1106  .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
1107  avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
1108  avctx->codec_id == AV_CODEC_ID_AV1 ? (void *)&av1_params :
1109  NULL,
1110  };
1111  VkVideoSessionCreateInfoKHR session_create = {
1112  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
1113  };
1114 
1116  if (err < 0)
1117  return err;
1118 
1119  /* Initialize contexts */
1120  ctx = dec->shared_ctx;
1121  s = &ctx->s;
1122  vk = &ctx->s.vkfn;
1123 
1124  err = ff_vk_init(s, avctx, NULL, avctx->hw_frames_ctx);
1125  if (err < 0)
1126  return err;
1127 
1129  if (!profile) {
1130  av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
1131  return AVERROR(EINVAL);
1132  }
1133 
1134  /* Create queue context */
1135  vk_desc = get_codecdesc(avctx->codec_id);
1136  err = ff_vk_video_qf_init(s, &ctx->qf,
1137  VK_QUEUE_VIDEO_DECODE_BIT_KHR,
1138  vk_desc->decode_op);
1139  if (err < 0) {
1140  av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n",
1141  avcodec_get_name(avctx->codec_id));
1142  return err;
1143  }
1144 
1145  /* Enable queries if supported */
1146  if (s->query_props[ctx->qf.queue_family].queryResultStatusSupport)
1147  nb_q = 1;
1148 
1149  session_create.flags = 0x0;
1150  session_create.queueFamilyIndex = ctx->qf.queue_family;
1151  session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
1152  session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
1153  session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
1154  session_create.pictureFormat = s->hwfc->format[0];
1155  session_create.referencePictureFormat = session_create.pictureFormat;
1156  session_create.pStdHeaderVersion = &vk_desc->ext_props;
1157  session_create.pVideoProfile = profile;
1158 
1159  /* Create decode exec context for this specific main thread.
1160  * 2 async contexts per thread was experimentally determined to be optimal
1161  * for a majority of streams. */
1162  err = ff_vk_exec_pool_init(s, &ctx->qf, &dec->exec_pool,
1163  FFMAX(2*ctx->qf.nb_queues, avctx->thread_count),
1164  nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
1165  profile);
1166  if (err < 0)
1167  goto fail;
1168 
1169  err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
1170  if (err < 0)
1171  goto fail;
1172 
1173  /* If doing an out-of-place decoding, create a DPB pool */
1174  if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
1176  AVVulkanFramesContext *dpb_hwfc;
1177 
1178  ctx->common.dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref);
1179  if (!ctx->common.dpb_hwfc_ref) {
1180  err = AVERROR(ENOMEM);
1181  goto fail;
1182  }
1183 
1184  dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
1185  dpb_frames->format = s->frames->format;
1186  dpb_frames->sw_format = s->frames->sw_format;
1187  dpb_frames->width = avctx->coded_width;
1188  dpb_frames->height = avctx->coded_height;
1189 
1190  dpb_hwfc = dpb_frames->hwctx;
1191  dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
1192  VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
1193  dpb_hwfc->format[0] = s->hwfc->format[0];
1194  dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1195  dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1196  VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */
1197 
1198  if (ctx->common.layered_dpb)
1199  dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots;
1200 
1201  err = av_hwframe_ctx_init(ctx->common.dpb_hwfc_ref);
1202  if (err < 0)
1203  goto fail;
1204 
1205  if (ctx->common.layered_dpb) {
1206  ctx->common.layered_frame = vk_get_dpb_pool(ctx);
1207  if (!ctx->common.layered_frame) {
1208  err = AVERROR(ENOMEM);
1209  goto fail;
1210  }
1211 
1212  err = ff_vk_create_view(&ctx->s, &ctx->common,
1213  &ctx->common.layered_view,
1214  &ctx->common.layered_aspect,
1215  (AVVkFrame *)ctx->common.layered_frame->data[0],
1216  s->hwfc->format[0], 1);
1217  if (err < 0)
1218  goto fail;
1219  }
1220  }
1221 
1222  session_params_create.videoSession = ctx->common.session;
1223  ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
1224  s->hwctx->alloc, &ctx->empty_session_params);
1225  if (ret != VK_SUCCESS) {
1226  av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
1227  ff_vk_ret2str(ret));
1228  return AVERROR_EXTERNAL;
1229  }
1230 
1231  driver_props = &dec->shared_ctx->s.driver_props;
1232  if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
1233  driver_props->conformanceVersion.major == 1 &&
1234  driver_props->conformanceVersion.minor == 3 &&
1235  driver_props->conformanceVersion.subminor == 8 &&
1236  driver_props->conformanceVersion.patch < 3)
1237  dec->quirk_av1_offset = 1;
1238 
1239  ff_vk_decode_flush(avctx);
1240 
1241  av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization sucessful\n");
1242 
1243  return 0;
1244 
1245 fail:
1246  ff_vk_decode_uninit(avctx);
1247 
1248  return err;
1249 }
vulkan_loader.h
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
AVVulkanDeviceContext::phys_dev
VkPhysicalDevice phys_dev
Physical device.
Definition: hwcontext_vulkan.h:79
FFVulkanDecodePicture::slices_size
size_t slices_size
Definition: vulkan_decode.h:105
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
FFVulkanDecodeShared::s
FFVulkanContext s
Definition: vulkan_decode.h:47
FFVulkanDecodeProfileData::profile
VkVideoProfileInfoKHR profile
Definition: vulkan_decode.h:42
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
AV_PROFILE_H264_INTRA
#define AV_PROFILE_H264_INTRA
Definition: defs.h:108
FFVulkanDecodeProfileData::h265_profile
VkVideoDecodeH265ProfileInfoKHR h265_profile
Definition: vulkan_decode.h:39
ff_vk_video_qf_init
int ff_vk_video_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits family, VkVideoCodecOperationFlagBitsKHR caps)
Chooses a QF and loads it into a context.
Definition: vulkan_video.c:271
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3170
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
FFVulkanDecodeContext::shared_ctx
FFVulkanDecodeShared * shared_ctx
Definition: vulkan_decode.h:60
AV_FIELD_PROGRESSIVE
@ AV_FIELD_PROGRESSIVE
Definition: defs.h:202
AVRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:197
FFVulkanDecodeContext::exec_pool
FFVkExecPool exec_pool
Definition: vulkan_decode.h:62
dpb_frames
int dpb_frames
Definition: h264_levels.c:163
ff_vk_exec_get_query
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, VkQueryResultFlagBits flags)
Performs nb_queries queries and returns their results and statuses.
Definition: vulkan.c:465
AV_PROFILE_HEVC_MAIN
#define AV_PROFILE_HEVC_MAIN
Definition: defs.h:159
ff_vk_exec_update_frame
void ff_vk_exec_update_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkImageMemoryBarrier2 *bar, uint32_t *nb_img_bar)
Definition: vulkan.c:788
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:322
ff_vk_depth_from_av_depth
VkVideoComponentBitDepthFlagBitsKHR ff_vk_depth_from_av_depth(int depth)
Get Vulkan's bit depth from an [8:12] integer.
Definition: vulkan_video.c:128
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
ff_vk_dec_av1_desc
const FFVulkanDecodeDescriptor ff_vk_dec_av1_desc
Definition: vulkan_av1.c:26
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
AVHWFramesContext::free
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
Definition: hwcontext.h:158
AVCodecContext::field_order
enum AVFieldOrder field_order
Field order.
Definition: avcodec.h:722
AVVulkanFramesContext::create_pnext
void * create_pnext
Extension data for image creation.
Definition: hwcontext_vulkan.h:243
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:326
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:149
ff_vk_create_view
int ff_vk_create_view(FFVulkanContext *s, FFVkVideoCommon *common, VkImageView *view, VkImageAspectFlags *aspect, AVVkFrame *src, VkFormat vkf, int is_dpb)
Creates image views for video frames.
Definition: vulkan_video.c:285
FFVulkanDecodeContext::frame_id_alloc_mask
uint32_t frame_id_alloc_mask
Definition: vulkan_decode.h:66
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
ff_vk_init
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:2636
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:493
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2625
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
avcodec_profile_name
const char * avcodec_profile_name(enum AVCodecID codec_id, int profile)
Return a name for the specified profile, if available.
Definition: utils.c:442
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:257
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:217
FFVulkanDecodeProfileData::av1_profile
VkVideoDecodeAV1ProfileInfoKHR av1_profile
Definition: vulkan_decode.h:40
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:602
FFVulkanDecodeContext
Definition: vulkan_decode.h:59
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
ff_vk_exec_add_dep_frame
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition: vulkan.c:718
ff_vk_decode_prepare_frame
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.
Definition: vulkan_decode.c:141
AV_HWACCEL_FLAG_IGNORE_LEVEL
#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:2165
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:88
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
AV_HWDEVICE_TYPE_VULKAN
@ AV_HWDEVICE_TYPE_VULKAN
Definition: hwcontext.h:39
FFVulkanDecodeContext::session_params
AVBufferRef * session_params
Definition: vulkan_decode.h:61
ff_vk_subsampling_from_av_desc
VkVideoChromaSubsamplingFlagBitsKHR ff_vk_subsampling_from_av_desc(const AVPixFmtDescriptor *desc)
Get Vulkan's chroma subsampling from a pixfmt descriptor.
Definition: vulkan_video.c:115
AVVulkanDeviceContext::alloc
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
Definition: hwcontext_vulkan.h:63
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:307
FFVulkanDecodeDescriptor::decode_op
VkVideoCodecOperationFlagBitsKHR decode_op
Definition: vulkan_decode.h:32
fail
#define fail()
Definition: checkasm.h:193
FFVulkanDecodePicture::sem_value
uint64_t sem_value
Definition: vulkan_decode.h:90
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1601
frames
if it could not because there are no more frames
Definition: filter_design.txt:266
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:213
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:508
ff_vk_ret2str
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition: vulkan.c:35
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:647
ff_vk_decode_frame
int ff_vk_decode_frame(AVCodecContext *avctx, AVFrame *pic, FFVulkanDecodePicture *vp, AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
Decode a frame.
Definition: vulkan_decode.c:312
FFVulkanDecodeShared
Definition: vulkan_decode.h:46
vulkan_decode_get_profile
static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref, enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt, FFVulkanDecodeProfileData *prof, int *dpb_dedicate)
Definition: vulkan_decode.c:709
refstruct.h
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
FFVulkanDecodeContext::slice_off
uint32_t * slice_off
Definition: vulkan_decode.h:76
avassert.h
FFVulkanDecodePicture::img_view_out
VkImageView img_view_out
Definition: vulkan_decode.h:84
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FFVulkanDecodeProfileData::h264_profile
VkVideoDecodeH264ProfileInfoKHR h264_profile
Definition: vulkan_decode.h:38
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
AVHWFramesContext::height
int height
Definition: hwcontext.h:217
AV_FIELD_UNKNOWN
@ AV_FIELD_UNKNOWN
Definition: defs.h:201
FFVulkanDecodeProfileData::profile_list
VkVideoProfileListInfoKHR profile_list
Definition: vulkan_decode.h:43
av_fast_realloc
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:497
FFVulkanDecodePicture::wait_semaphores
PFN_vkWaitSemaphores wait_semaphores
Definition: vulkan_decode.h:108
s
#define s(width, name)
Definition: cbs_vp9.c:198
FFVulkanDecodePicture
Definition: vulkan_decode.h:80
ff_vk_video_common_init
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.
Definition: vulkan_video.c:359
ff_vk_decode_create_params
int ff_vk_decode_create_params(AVBufferRef **par_ref, void *logctx, FFVulkanDecodeShared *ctx, const VkVideoSessionParametersCreateInfoKHR *session_params_create)
Create VkVideoSessionParametersKHR wrapped in an AVBufferRef.
Definition: vulkan_decode.c:1037
ff_vk_exec_mirror_sem_value
int ff_vk_exec_mirror_sem_value(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *dst, uint64_t *dst_val, AVFrame *f)
Definition: vulkan.c:807
offsets
static const int offsets[]
Definition: hevc_pel.c:34
FFVulkanContext::driver_props
VkPhysicalDeviceDriverProperties driver_props
Definition: vulkan.h:279
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1451
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
ff_vk_load_functions
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
Definition: vulkan_loader.h:105
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
av_refstruct_alloc_ext
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
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_vk_exec_add_dep_buf
int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e, AVBufferRef **deps, int nb_deps, int ref)
Execution dependency management.
Definition: vulkan.c:573
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:410
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:242
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:128
ff_decode_get_hw_frames_ctx
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, enum AVHWDeviceType dev_type)
Make sure avctx.hw_frames_ctx is set.
Definition: decode.c:1117
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:461
if
if(ret)
Definition: filter_design.txt:179
get_video_profile
static const VkVideoProfileInfoKHR * get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
Definition: vulkan_decode.c:58
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
FFVulkanDecodePicture::img_view_ref
VkImageView img_view_ref
Definition: vulkan_decode.h:83
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:210
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AV_CODEC_ID_AV1
@ AV_CODEC_ID_AV1
Definition: codec_id.h:284
AVVulkanDeviceContext::nb_enabled_dev_extensions
int nb_enabled_dev_extensions
Definition: hwcontext_vulkan.h:113
ff_vk_decode_free_frame
void ff_vk_decode_free_frame(AVHWDeviceContext *dev_ctx, FFVulkanDecodePicture *vp)
Free a frame and its state.
Definition: vulkan_decode.c:543
ff_vk_video_common_uninit
av_cold void ff_vk_video_common_uninit(FFVulkanContext *s, FFVkVideoCommon *common)
Free video session and required resources.
Definition: vulkan_video.c:329
FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
Definition: vulkan_functions.h:61
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:486
FFVulkanDecodeProfileData::usage
VkVideoDecodeUsageInfoKHR usage
Definition: vulkan_decode.h:41
FFVulkanDecodeDescriptor::decode_extension
FFVulkanExtensions decode_extension
Definition: vulkan_decode.h:31
AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH
#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:2185
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
ff_vk_decode_uninit
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
Definition: vulkan_decode.c:1066
AVVulkanFramesContext::format
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
Definition: hwcontext_vulkan.h:273
FFVkExecContext::had_submission
int had_submission
Definition: vulkan.h:111
FFVkBuffer::size
size_t size
Definition: vulkan.h:91
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:232
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:263
ff_vk_exec_pool_init
int ff_vk_exec_pool_init(FFVulkanContext *s, FFVkQueueFamilyCtx *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:306
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:99
FFVulkanContext
Definition: vulkan.h:271
ff_vk_frame_params
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...
Definition: vulkan_decode.c:974
AVCodecContext::level
int level
Encoding level descriptor.
Definition: avcodec.h:1802
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
usage
const char * usage
Definition: floatimg_cmp.c:60
free_common
static void free_common(AVRefStructOpaque unused, void *obj)
Definition: vulkan_decode.c:574
FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
Definition: vulkan_functions.h:54
ff_vk_h265_level_to_av
int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
Definition: vulkan_video.c:191
sem_wait
#define sem_wait(psem)
Definition: semaphore.h:27
AVCodecInternal::hwaccel_priv_data
void * hwaccel_priv_data
hwaccel-specific private data
Definition: internal.h:130
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
AVVkFrame
Definition: hwcontext_vulkan.h:302
size
int size
Definition: twinvq_data.h:10344
ref_frame
static int ref_frame(VVCFrame *dst, const VVCFrame *src)
Definition: dec.c:593
FFVulkanDecodePicture::img_aspect_ref
VkImageAspectFlags img_aspect_ref
Definition: vulkan_decode.h:87
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:90
ff_vk_dec_h264_desc
const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc
Definition: vulkan_h264.c:24
FFVulkanDecodeContext::slice_off_max
unsigned int slice_off_max
Definition: vulkan_decode.h:77
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:366
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
FFVkExecContext
Definition: vulkan.h:107
vk_decode_free_params
static void vk_decode_free_params(void *opaque, uint8_t *data)
Definition: vulkan_decode.c:1027
FFVulkanDecodeProfileData
Definition: vulkan_decode.h:37
FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
Definition: vulkan_functions.h:56
av_refstruct_unref
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
avcodec_get_name
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:409
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:507
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FFVulkanDecodeDescriptor::ext_props
VkExtensionProperties ext_props
Definition: vulkan_decode.h:34
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
ff_vk_h264_level_to_av
int ff_vk_h264_level_to_av(StdVideoH264LevelIdc level)
Convert level from Vulkan to AV.
Definition: vulkan_video.c:139
AVCodecContext::hwaccel_flags
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
Definition: avcodec.h:1524
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:228
FFVulkanDecodePicture::ref_slot
VkVideoReferenceSlotInfoKHR ref_slot
Definition: vulkan_decode.h:94
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:89
FFVulkanDecodePicture::sem
VkSemaphore sem
Definition: vulkan_decode.h:89
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
FFVulkanDecodeContext::external_fg
int external_fg
Definition: vulkan_decode.h:65
av_buffer_replace
int av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
Ensure dst refers to the same data as src.
Definition: buffer.c:233
profile
int profile
Definition: mxfenc.c:2233
AVCodecContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition: avcodec.h:1493
CODEC_VER
#define CODEC_VER(ver)
Definition: vulkan_video.h:30
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
ff_vk_decode_flush
void ff_vk_decode_flush(AVCodecContext *avctx)
Flush decoder.
Definition: vulkan_decode.c:276
ret
ret
Definition: filter_design.txt:187
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:150
AVHWFramesContext::user_opaque
void * user_opaque
Arbitrary user data, to be used e.g.
Definition: hwcontext.h:163
ff_vk_decode_add_slice
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.
Definition: vulkan_decode.c:205
AV_PROFILE_H264_CONSTRAINED
#define AV_PROFILE_H264_CONSTRAINED
Definition: defs.h:107
dec_descs
static const FFVulkanDecodeDescriptor * dec_descs[]
Definition: vulkan_decode.c:37
FFVulkanDecodeContext::hevc_headers
struct HEVCHeaderSet * hevc_headers
Definition: vulkan_decode.h:73
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:119
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:740
ff_vk_dec_hevc_desc
const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc
Definition: vulkan_hevc.c:26
get_codecdesc
static const FFVulkanDecodeDescriptor * get_codecdesc(enum AVCodecID codec_id)
Definition: vulkan_decode.c:49
AVCodecContext
main external API structure.
Definition: avcodec.h:451
FFVulkanDecodeContext::dedicated_dpb
int dedicated_dpb
Definition: vulkan_decode.h:64
av_find_best_pix_fmt_of_2
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:3449
av_refstruct_replace
void av_refstruct_replace(void *dstp, const void *src)
Ensure *dstp refers to the same object as src.
Definition: refstruct.c:160
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1658
FFVulkanDecodeDescriptor
Definition: vulkan_decode.h:29
AV_CODEC_ID_H265
#define AV_CODEC_ID_H265
Definition: codec_id.h:229
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
AVCodecContext::export_side_data
int export_side_data
Bit set of AV_CODEC_EXPORT_DATA_* flags, which affects the kind of metadata exported in frame,...
Definition: avcodec.h:1953
ff_vk_params_invalidate
int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
Removes current session parameters to recreate them.
Definition: vulkan_decode.c:120
FFVulkanDecodePicture::dpb_frame
AVFrame * dpb_frame
Definition: vulkan_decode.h:81
AV_PROFILE_H264_CONSTRAINED_BASELINE
#define AV_PROFILE_H264_CONSTRAINED_BASELINE
Definition: defs.h:111
ff_vk_update_thread_context
int ff_vk_update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
Synchronize the contexts between 2 threads.
Definition: vulkan_decode.c:80
AVVulkanFramesContext::tiling
VkImageTiling tiling
Controls the tiling of allocated frames.
Definition: hwcontext_vulkan.h:222
vulkan_video.h
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:647
desc
const char * desc
Definition: libsvtav1.c:79
AVVulkanDeviceContext::enabled_dev_extensions
const char *const * enabled_dev_extensions
Enabled device extensions.
Definition: hwcontext_vulkan.h:112
AVVulkanFramesContext::nb_layers
int nb_layers
Number of layers each image will have.
Definition: hwcontext_vulkan.h:278
FFVulkanDecodePicture::slices_buf
AVBufferRef * slices_buf
Definition: vulkan_decode.h:104
mem.h
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:332
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FFVkExecPool::cmd_bufs
VkCommandBuffer * cmd_bufs
Definition: vulkan.h:254
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
vulkan_decode.h
FFVulkanDecodePicture::img_view_dest
VkImageView img_view_dest
Definition: vulkan_decode.h:85
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: 4xm.c:976
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
vulkan_setup_profile
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)
Definition: vulkan_decode.c:634
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFVkBuffer
Definition: vulkan.h:87
vk_get_dpb_pool
static AVFrame * vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
Definition: vulkan_decode.c:127
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:833
FFVulkanDecodePicture::destroy_image_view
PFN_vkDestroyImageView destroy_image_view
Definition: vulkan_decode.h:109
ff_vk_extensions_to_mask
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
Definition: vulkan_loader.h:36
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
vulkan_decode_bootstrap
static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
Definition: vulkan_decode.c:596
ff_vk_pix_fmt_from_vkfmt
enum AVPixelFormat ff_vk_pix_fmt_from_vkfmt(VkFormat vkf)
Get pixfmt from a Vulkan format.
Definition: vulkan_video.c:99
ff_vk_decode_init
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
Definition: vulkan_decode.c:1081
FFVulkanDecodePicture::decode_info
VkVideoDecodeInfoKHR decode_info
Definition: vulkan_decode.h:101
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:678
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:491
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
FFVulkanFunctions
Definition: vulkan_functions.h:264
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:255
FFVulkanDecodeContext::quirk_av1_offset
int quirk_av1_offset
Definition: vulkan_decode.h:70
ff_vk_get_pooled_buffer
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, AVBufferRef **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition: vulkan.c:1200
src
#define src
Definition: vp8dsp.c:248
free_profile_data
static void free_profile_data(AVHWFramesContext *hwfc)
Definition: vulkan_decode.c:969
AV_CODEC_EXPORT_DATA_FILM_GRAIN
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN
Decoding only.
Definition: avcodec.h:420
av_get_pix_fmt_name
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:3090
FFVulkanDecodePicture::img_aspect
VkImageAspectFlags img_aspect
Definition: vulkan_decode.h:86