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 "refstruct.h"
20 #include "vulkan_video.h"
21 #include "vulkan_decode.h"
22 #include "config_components.h"
23 #include "libavutil/avassert.h"
25 
26 #if CONFIG_H264_VULKAN_HWACCEL
28 #endif
29 #if CONFIG_HEVC_VULKAN_HWACCEL
31 #endif
32 #if CONFIG_AV1_VULKAN_HWACCEL
34 #endif
35 
37 #if CONFIG_H264_VULKAN_HWACCEL
39 #endif
40 #if CONFIG_HEVC_VULKAN_HWACCEL
42 #endif
43 #if CONFIG_AV1_VULKAN_HWACCEL
45 #endif
46 };
47 
49 {
50  for (size_t i = 0; i < FF_ARRAY_ELEMS(dec_descs); i++)
51  if (dec_descs[i]->codec_id == codec_id)
52  return dec_descs[i];
53  av_assert1(!"no codec descriptor");
54  return NULL;
55 }
56 
57 static const VkVideoProfileInfoKHR *get_video_profile(FFVulkanDecodeShared *ctx, enum AVCodecID codec_id)
58 {
59  const VkVideoProfileListInfoKHR *profile_list;
60 
61  VkStructureType profile_struct_type =
62  codec_id == AV_CODEC_ID_H264 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR :
63  codec_id == AV_CODEC_ID_HEVC ? VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR :
64  codec_id == AV_CODEC_ID_AV1 ? VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR :
65  0;
66 
67  profile_list = ff_vk_find_struct(ctx->s.hwfc->create_pnext,
68  VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
69  if (!profile_list)
70  return NULL;
71 
72  for (int i = 0; i < profile_list->profileCount; i++)
73  if (ff_vk_find_struct(profile_list->pProfiles[i].pNext, profile_struct_type))
74  return &profile_list->pProfiles[i];
75 
76  return NULL;
77 }
78 
80 {
81  int err;
82  FFVulkanDecodeContext *src_ctx = src->internal->hwaccel_priv_data;
84 
85  if (!dst_ctx->exec_pool.cmd_bufs) {
87 
88  const VkVideoProfileInfoKHR *profile = get_video_profile(ctx, dst->codec_id);
89  if (!profile) {
90  av_log(dst, AV_LOG_ERROR, "Video profile missing from frames context!");
91  return AVERROR(EINVAL);
92  }
93 
94  err = ff_vk_exec_pool_init(&ctx->s, &ctx->qf,
95  &dst_ctx->exec_pool,
96  src_ctx->exec_pool.pool_size,
97  src_ctx->exec_pool.nb_queries,
98  VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
99  profile);
100  if (err < 0)
101  return err;
102  }
103 
104  ff_refstruct_replace(&dst_ctx->shared_ctx, src_ctx->shared_ctx);
105 
106  if (src_ctx->session_params) {
107  err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params);
108  if (err < 0)
109  return err;
110  }
111 
112  dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
113  dst_ctx->layered_dpb = src_ctx->layered_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 
127 static int vk_decode_create_view(FFVulkanDecodeContext *dec, VkImageView *dst_view,
128  VkImageAspectFlags *aspect, AVVkFrame *src,
129  VkFormat vkf, int is_current)
130 {
131  VkResult ret;
133  FFVulkanFunctions *vk = &ctx->s.vkfn;
134  VkImageAspectFlags aspect_mask = ff_vk_aspect_bits_from_vkfmt(vkf);
135 
136  VkSamplerYcbcrConversionInfo yuv_sampler_info = {
137  .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
138  .conversion = ctx->yuv_sampler,
139  };
140  VkImageViewCreateInfo img_view_create_info = {
141  .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
142  .pNext = &yuv_sampler_info,
143  .viewType = dec->layered_dpb && !is_current ?
144  VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
145  .format = vkf,
146  .image = src->img[0],
147  .components = (VkComponentMapping) {
148  .r = VK_COMPONENT_SWIZZLE_IDENTITY,
149  .g = VK_COMPONENT_SWIZZLE_IDENTITY,
150  .b = VK_COMPONENT_SWIZZLE_IDENTITY,
151  .a = VK_COMPONENT_SWIZZLE_IDENTITY,
152  },
153  .subresourceRange = (VkImageSubresourceRange) {
154  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
155  .baseArrayLayer = 0,
156  .layerCount = dec->layered_dpb && !is_current ?
157  VK_REMAINING_ARRAY_LAYERS : 1,
158  .levelCount = 1,
159  },
160  };
161 
162  ret = vk->CreateImageView(ctx->s.hwctx->act_dev, &img_view_create_info,
163  ctx->s.hwctx->alloc, dst_view);
164  if (ret != VK_SUCCESS)
165  return AVERROR_EXTERNAL;
166 
167  *aspect = aspect_mask;
168 
169  return 0;
170 }
171 
173 {
174  int err;
175  AVFrame *avf = av_frame_alloc();
176  if (!avf)
177  return NULL;
178 
179  err = av_hwframe_get_buffer(ctx->dpb_hwfc_ref, avf, 0x0);
180  if (err < 0)
181  av_frame_free(&avf);
182 
183  return avf;
184 }
185 
187  FFVulkanDecodePicture *vkpic, int is_current,
188  int alloc_dpb)
189 {
190  int err;
192  FFVulkanFunctions *vk = &ctx->s.vkfn;
193 
194  vkpic->slices_size = 0;
195 
196  /* If the decoder made a blank frame to make up for a missing ref, or the
197  * frame is the current frame so it's missing one, create a re-representation */
198  if (vkpic->img_view_ref)
199  return 0;
200 
201  vkpic->dpb_frame = NULL;
202  vkpic->img_view_ref = VK_NULL_HANDLE;
203  vkpic->img_view_out = VK_NULL_HANDLE;
204  vkpic->img_view_dest = VK_NULL_HANDLE;
205 
206  vkpic->destroy_image_view = vk->DestroyImageView;
207  vkpic->wait_semaphores = vk->WaitSemaphores;
208 
209  if (dec->layered_dpb && alloc_dpb) {
210  vkpic->img_view_ref = ctx->layered_view;
211  vkpic->img_aspect_ref = ctx->layered_aspect;
212  } else if (alloc_dpb) {
213  AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->dpb_hwfc_ref->data;
214  AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx;
215 
216  vkpic->dpb_frame = vk_get_dpb_pool(ctx);
217  if (!vkpic->dpb_frame)
218  return AVERROR(ENOMEM);
219 
220  err = vk_decode_create_view(dec, &vkpic->img_view_ref,
221  &vkpic->img_aspect_ref,
222  (AVVkFrame *)vkpic->dpb_frame->data[0],
223  dpb_hwfc->format[0], is_current);
224  if (err < 0)
225  return err;
226 
227  vkpic->img_view_dest = vkpic->img_view_ref;
228  }
229 
230  if (!alloc_dpb || is_current) {
232  AVVulkanFramesContext *hwfc = frames->hwctx;
233 
234  err = vk_decode_create_view(dec, &vkpic->img_view_out,
235  &vkpic->img_aspect,
236  (AVVkFrame *)pic->data[0],
237  hwfc->format[0], is_current);
238  if (err < 0)
239  return err;
240 
241  if (!alloc_dpb) {
242  vkpic->img_view_ref = vkpic->img_view_out;
243  vkpic->img_aspect_ref = vkpic->img_aspect;
244  }
245  }
246 
247  return 0;
248 }
249 
251  const uint8_t *data, size_t size, int add_startcode,
252  uint32_t *nb_slices, const uint32_t **offsets)
253 {
256 
257  static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
258  const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
259  const int nb = *nb_slices;
260  uint8_t *slices;
261  uint32_t *slice_off;
262  FFVkVideoBuffer *vkbuf;
263 
264  size_t new_size = vp->slices_size + startcode_len + size +
265  ctx->caps.minBitstreamBufferSizeAlignment;
266  new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
267 
268  slice_off = av_fast_realloc(dec->slice_off, &dec->slice_off_max,
269  (nb + 1)*sizeof(slice_off));
270  if (!slice_off)
271  return AVERROR(ENOMEM);
272 
273  *offsets = dec->slice_off = slice_off;
274  slice_off[nb] = vp->slices_size;
275 
276  vkbuf = vp->slices_buf ? (FFVkVideoBuffer *)vp->slices_buf->data : NULL;
277  if (!vkbuf || vkbuf->buf.size < new_size) {
278  int err;
279  AVBufferRef *new_ref;
280  FFVkVideoBuffer *new_buf;
281  err = ff_vk_video_get_buffer(&ctx->s, &ctx->common, &new_ref,
282  VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
283  ctx->s.hwfc->create_pnext, new_size);
284  if (err < 0)
285  return err;
286 
287  new_buf = (FFVkVideoBuffer *)new_ref->data;
288 
289  /* Copy data from the old buffer */
290  if (vkbuf) {
291  memcpy(new_buf->mem, vkbuf->mem, vp->slices_size);
293  }
294 
295  vp->slices_buf = new_ref;
296  vkbuf = new_buf;
297  }
298  slices = vkbuf->mem;
299 
300  /* Startcode */
301  memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
302 
303  /* Slice data */
304  memcpy(slices + vp->slices_size + startcode_len, data, size);
305 
306  *nb_slices = nb + 1;
307  vp->slices_size += startcode_len + size;
308 
309  return 0;
310 }
311 
313 {
316 
317  FFVulkanFunctions *vk = &ctx->s.vkfn;
318  VkVideoBeginCodingInfoKHR decode_start = {
319  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
320  .videoSession = ctx->common.session,
321  .videoSessionParameters = ctx->empty_session_params,
322  };
323  VkVideoCodingControlInfoKHR decode_ctrl = {
324  .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
325  .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
326  };
327  VkVideoEndCodingInfoKHR decode_end = {
328  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
329  };
330 
331  VkCommandBuffer cmd_buf;
333  ff_vk_exec_start(&ctx->s, exec);
334  cmd_buf = exec->buf;
335 
336  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
337  vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
338  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
339  ff_vk_exec_submit(&ctx->s, exec);
340 }
341 
343  AVFrame *pic, FFVulkanDecodePicture *vp,
344  AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
345 {
346  int err;
347  VkResult ret;
348  VkCommandBuffer cmd_buf;
349  FFVkVideoBuffer *sd_buf;
350 
353  FFVulkanFunctions *vk = &ctx->s.vkfn;
354 
355  /* Output */
356  AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
357 
358  /* Quirks */
359  const int layered_dpb = dec->layered_dpb;
360 
361  VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)dec->session_params->data;
362  VkVideoBeginCodingInfoKHR decode_start = {
363  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
364  .videoSession = ctx->common.session,
365  .videoSessionParameters = *par,
366  .referenceSlotCount = vp->decode_info.referenceSlotCount,
367  .pReferenceSlots = vp->decode_info.pReferenceSlots,
368  };
369  VkVideoEndCodingInfoKHR decode_end = {
370  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
371  };
372 
373  VkImageMemoryBarrier2 img_bar[37];
374  int nb_img_bar = 0;
375  size_t data_size = FFALIGN(vp->slices_size,
376  ctx->caps.minBitstreamBufferSizeAlignment);
377 
379 
380  /* The current decoding reference has to be bound as an inactive reference */
381  VkVideoReferenceSlotInfoKHR *cur_vk_ref;
382  cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
383  cur_vk_ref[0] = vp->ref_slot;
384  cur_vk_ref[0].slotIndex = -1;
385  decode_start.referenceSlotCount++;
386 
387  if (dec->exec_pool.nb_queries) {
388  int64_t prev_sub_res = 0;
389  ff_vk_exec_wait(&ctx->s, exec);
390  ret = ff_vk_exec_get_query(&ctx->s, exec, NULL, &prev_sub_res);
391  if (ret != VK_NOT_READY && ret != VK_SUCCESS) {
392  av_log(avctx, AV_LOG_ERROR, "Unable to perform query: %s!\n",
393  ff_vk_ret2str(ret));
394  return AVERROR_EXTERNAL;
395  }
396 
397  if (ret == VK_SUCCESS)
398  av_log(avctx, prev_sub_res < 0 ? AV_LOG_ERROR : AV_LOG_DEBUG,
399  "Result of previous frame decoding: %"PRId64"\n", prev_sub_res);
400  }
401 
402  sd_buf = (FFVkVideoBuffer *)vp->slices_buf->data;
403 
404  /* Flush if needed */
405  if (!(sd_buf->buf.flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
406  VkMappedMemoryRange flush_buf = {
407  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
408  .memory = sd_buf->buf.mem,
409  .offset = 0,
410  .size = FFALIGN(vp->slices_size,
411  ctx->s.props.properties.limits.nonCoherentAtomSize),
412  };
413 
414  ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
415  if (ret != VK_SUCCESS) {
416  av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
417  ff_vk_ret2str(ret));
418  return AVERROR_EXTERNAL;
419  }
420  }
421 
422  vp->decode_info.srcBuffer = sd_buf->buf.buf;
423  vp->decode_info.srcBufferOffset = 0;
424  vp->decode_info.srcBufferRange = data_size;
425 
426  /* Start command buffer recording */
427  err = ff_vk_exec_start(&ctx->s, exec);
428  if (err < 0)
429  return err;
430  cmd_buf = exec->buf;
431 
432  /* Slices */
433  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
434  if (err < 0)
435  return err;
436  vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
437 
438  /* Parameters */
439  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
440  if (err < 0)
441  return err;
442 
443  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
444  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
445  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
446  if (err < 0)
447  return err;
448 
449  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
450  pic);
451  if (err < 0)
452  return err;
453 
454  /* Output image - change layout, as it comes from a pool */
455  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
456  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
457  .pNext = NULL,
458  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
459  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
460  .srcAccessMask = VK_ACCESS_2_NONE,
461  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
462  .oldLayout = vkf->layout[0],
463  .newLayout = (dec->layered_dpb || vp->dpb_frame) ?
464  VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
465  VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
466  .srcQueueFamilyIndex = vkf->queue_family[0],
467  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
468  .image = vkf->img[0],
469  .subresourceRange = (VkImageSubresourceRange) {
470  .aspectMask = vp->img_aspect,
471  .layerCount = 1,
472  .levelCount = 1,
473  },
474  };
475  ff_vk_exec_update_frame(&ctx->s, exec, pic,
476  &img_bar[nb_img_bar], &nb_img_bar);
477 
478  /* Reference for the current image, if existing and not layered */
479  if (vp->dpb_frame) {
480  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
481  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
482  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
483  if (err < 0)
484  return err;
485  }
486 
487  if (!layered_dpb) {
488  /* All references (apart from the current) for non-layered refs */
489 
490  for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
491  AVFrame *ref_frame = rpic[i];
492  FFVulkanDecodePicture *rvp = rvkp[i];
493  AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame;
494 
495  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref,
496  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
497  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
498  if (err < 0)
499  return err;
500 
501  if (err == 0) {
502  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec,
503  &rvp->sem, &rvp->sem_value,
504  ref);
505  if (err < 0)
506  return err;
507  }
508 
509  if (!rvp->dpb_frame) {
510  AVVkFrame *rvkf = (AVVkFrame *)ref->data[0];
511 
512  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
513  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
514  .pNext = NULL,
515  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
516  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
517  .srcAccessMask = VK_ACCESS_2_NONE,
518  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
519  VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
520  .oldLayout = rvkf->layout[0],
521  .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
522  .srcQueueFamilyIndex = rvkf->queue_family[0],
523  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
524  .image = rvkf->img[0],
525  .subresourceRange = (VkImageSubresourceRange) {
526  .aspectMask = rvp->img_aspect_ref,
527  .layerCount = 1,
528  .levelCount = 1,
529  },
530  };
531  ff_vk_exec_update_frame(&ctx->s, exec, ref,
532  &img_bar[nb_img_bar], &nb_img_bar);
533  }
534  }
535  } else if (vp->decode_info.referenceSlotCount ||
536  vp->img_view_out != vp->img_view_ref) {
537  /* Single barrier for a single layered ref */
538  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->layered_frame,
539  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
540  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
541  if (err < 0)
542  return err;
543  }
544 
545  /* Change image layout */
546  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
547  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
548  .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
549  .pImageMemoryBarriers = img_bar,
550  .imageMemoryBarrierCount = nb_img_bar,
551  });
552 
553  /* Start, use parameters, decode and end decoding */
554  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
555 
556  /* Start status query */
557  if (dec->exec_pool.nb_queries)
558  vk->CmdBeginQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0, 0);
559 
560  vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
561 
562  /* End status query */
563  if (dec->exec_pool.nb_queries)
564  vk->CmdEndQuery(cmd_buf, dec->exec_pool.query_pool, exec->query_idx + 0);
565 
566  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
567 
568  /* End recording and submit for execution */
569  return ff_vk_exec_submit(&ctx->s, exec);
570 }
571 
573 {
574  AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
575 
576  VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) {
577  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
578  .pSemaphores = &vp->sem,
579  .pValues = &vp->sem_value,
580  .semaphoreCount = 1,
581  };
582 
583  /* We do not have to lock the frame here because we're not interested
584  * in the actual current semaphore value, but only that it's later than
585  * the time we submitted the image for decoding. */
586  if (vp->sem)
587  vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
588 
589  /* Free slices data */
591 
592  /* Destroy image view (out) */
593  if (vp->img_view_out && vp->img_view_out != vp->img_view_dest)
594  vp->destroy_image_view(hwctx->act_dev, vp->img_view_out, hwctx->alloc);
595 
596  /* Destroy image view (ref, unlayered) */
597  if (vp->img_view_dest)
598  vp->destroy_image_view(hwctx->act_dev, vp->img_view_dest, hwctx->alloc);
599 
600  av_frame_free(&vp->dpb_frame);
601 }
602 
603 static void free_common(FFRefStructOpaque unused, void *obj)
604 {
605  FFVulkanDecodeShared *ctx = obj;
606  FFVulkanContext *s = &ctx->s;
607  FFVulkanFunctions *vk = &ctx->s.vkfn;
608 
609  /* Destroy layered view */
610  if (ctx->layered_view)
611  vk->DestroyImageView(s->hwctx->act_dev, ctx->layered_view, s->hwctx->alloc);
612 
613  /* This also frees all references from this pool */
614  av_frame_free(&ctx->layered_frame);
615  av_buffer_unref(&ctx->dpb_hwfc_ref);
616 
617  /* Destroy parameters */
618  if (ctx->empty_session_params)
619  vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
620  ctx->empty_session_params,
621  s->hwctx->alloc);
622 
623  ff_vk_video_common_uninit(s, &ctx->common);
624 
625  if (ctx->yuv_sampler)
626  vk->DestroySamplerYcbcrConversion(s->hwctx->act_dev, ctx->yuv_sampler,
627  s->hwctx->alloc);
628 
629  ff_vk_uninit(s);
630 }
631 
632 static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
633 {
634  int err;
637  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
638  AVVulkanDeviceContext *hwctx = device->hwctx;
640 
641  if (dec->shared_ctx)
642  return 0;
643 
644  dec->shared_ctx = ff_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
645  free_common);
646  if (!dec->shared_ctx)
647  return AVERROR(ENOMEM);
648 
649  ctx = dec->shared_ctx;
650 
651  ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
653 
654  if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
655  av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
656  VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
658  return AVERROR(ENOSYS);
659  }
660 
661  err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
662  if (err < 0) {
664  return err;
665  }
666 
667  return 0;
668 }
669 
670 static VkResult vulkan_setup_profile(AVCodecContext *avctx,
672  AVVulkanDeviceContext *hwctx,
673  FFVulkanFunctions *vk,
674  const FFVulkanDecodeDescriptor *vk_desc,
675  VkVideoDecodeH264CapabilitiesKHR *h264_caps,
676  VkVideoDecodeH265CapabilitiesKHR *h265_caps,
677  VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
678  VkVideoCapabilitiesKHR *caps,
679  VkVideoDecodeCapabilitiesKHR *dec_caps,
680  int cur_profile)
681 {
682  VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
683  VkVideoProfileInfoKHR *profile = &prof->profile;
684  VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
685 
686  VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
687  VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
688  VkVideoDecodeAV1ProfileInfoKHR *av1_profile = &prof->av1_profile;
689 
691  if (!desc)
692  return AVERROR(EINVAL);
693 
694  if (avctx->codec_id == AV_CODEC_ID_H264) {
695  dec_caps->pNext = h264_caps;
696  usage->pNext = h264_profile;
697  h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
698 
699  /* Vulkan transmits all the constrant_set flags, rather than wanting them
700  * merged in the profile IDC */
701  h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
703 
704  h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN ||
706  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR :
707  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
708  } else if (avctx->codec_id == AV_CODEC_ID_H265) {
709  dec_caps->pNext = h265_caps;
710  usage->pNext = h265_profile;
711  h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
712  h265_profile->stdProfileIdc = cur_profile;
713  } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
714  dec_caps->pNext = av1_caps;
715  usage->pNext = av1_profile;
716  av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
717  av1_profile->stdProfile = cur_profile;
718  av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
719  }
720 
721  usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
722  usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
723 
724  profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
725  profile->pNext = usage;
726  profile->videoCodecOperation = vk_desc->decode_op;
727  profile->chromaSubsampling = ff_vk_subsampling_from_av_desc(desc);
728  profile->lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth);
729  profile->chromaBitDepth = profile->lumaBitDepth;
730 
731  profile_list->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
732  profile_list->profileCount = 1;
733  profile_list->pProfiles = profile;
734 
735  /* Get the capabilities of the decoder for the given profile */
736  caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
737  caps->pNext = dec_caps;
738  dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
739  /* dec_caps->pNext already filled in */
740 
741  return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
742  caps);
743 }
744 
745 static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref,
746  enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
748  int *dpb_dedicate)
749 {
750  VkResult ret;
751  int max_level, base_profile, cur_profile;
752  const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
754  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
755  AVVulkanDeviceContext *hwctx = device->hwctx;
756  enum AVPixelFormat source_format;
757  enum AVPixelFormat best_format;
758  VkFormat best_vkfmt;
759 
762  FFVulkanFunctions *vk = &ctx->s.vkfn;
763 
764  VkVideoCapabilitiesKHR *caps = &ctx->caps;
765  VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
766 
767  VkVideoDecodeH264CapabilitiesKHR h264_caps = {
768  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
769  };
770  VkVideoDecodeH265CapabilitiesKHR h265_caps = {
771  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
772  };
773  VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
774  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
775  };
776 
777  VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
778  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
779  .pNext = &prof->profile_list,
780  };
781  VkVideoFormatPropertiesKHR *ret_info;
782  uint32_t nb_out_fmts = 0;
783 
784  if (!(vk_desc->decode_extension & ctx->s.extensions)) {
785  av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
786  avcodec_get_name(avctx->codec_id));
787  return AVERROR(ENOSYS);
788  }
789 
790  cur_profile = avctx->profile;
793  avctx->codec_id == AV_CODEC_ID_AV1 ? STD_VIDEO_AV1_PROFILE_MAIN :
794  0;
795 
796  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
797  &h264_caps,
798  &h265_caps,
799  &av1_caps,
800  caps,
801  dec_caps,
802  cur_profile);
803  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
805  avctx->profile != base_profile) {
806  av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
807  "again with profile %s\n",
808  avcodec_get_name(avctx->codec_id),
809  avcodec_profile_name(avctx->codec_id, cur_profile),
810  avcodec_profile_name(avctx->codec_id, base_profile));
811  cur_profile = base_profile;
812  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
813  &h264_caps,
814  &h265_caps,
815  &av1_caps,
816  caps,
817  dec_caps,
818  cur_profile);
819  }
820 
821  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
822  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
823  "%s profile \"%s\" not supported!\n",
824  avcodec_get_name(avctx->codec_id),
825  avcodec_profile_name(avctx->codec_id, cur_profile));
826  return AVERROR(EINVAL);
827  } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
828  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
829  "format (%s) not supported!\n",
831  return AVERROR(EINVAL);
832  } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
833  ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
834  return AVERROR(EINVAL);
835  } else if (ret != VK_SUCCESS) {
836  return AVERROR_EXTERNAL;
837  }
838 
839  max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
840  avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
841  avctx->codec_id == AV_CODEC_ID_AV1 ? av1_caps.maxLevel :
842  0;
843 
844  av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
845  avcodec_get_name(avctx->codec_id),
846  avcodec_profile_name(avctx->codec_id, cur_profile));
847  av_log(avctx, AV_LOG_VERBOSE, " Maximum level: %i (stream %i)\n",
848  max_level, avctx->level);
849  av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n",
850  caps->minCodedExtent.width, caps->maxCodedExtent.width);
851  av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n",
852  caps->minCodedExtent.height, caps->maxCodedExtent.height);
853  av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n",
854  caps->pictureAccessGranularity.width);
855  av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n",
856  caps->pictureAccessGranularity.height);
857  av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n",
858  caps->minBitstreamBufferOffsetAlignment);
859  av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n",
860  caps->minBitstreamBufferSizeAlignment);
861  av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n",
862  caps->maxDpbSlots);
863  av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n",
864  caps->maxActiveReferencePictures);
865  av_log(avctx, AV_LOG_VERBOSE, " Codec header name: '%s' (driver), '%s' (compiled)\n",
866  caps->stdHeaderVersion.extensionName,
867  vk_desc->ext_props.extensionName);
868  av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
869  CODEC_VER(caps->stdHeaderVersion.specVersion),
870  CODEC_VER(vk_desc->ext_props.specVersion));
871  av_log(avctx, AV_LOG_VERBOSE, " Decode modes:%s%s%s\n",
872  dec_caps->flags ? "" :
873  " invalid",
874  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
875  " reuse_dst_dpb" : "",
876  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
877  " dedicated_dpb" : "");
878  av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n",
879  caps->flags ? "" :
880  " none",
881  caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
882  " protected" : "",
883  caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
884  " separate_references" : "");
885 
886  /* Check if decoding is possible with the given parameters */
887  if (avctx->coded_width < caps->minCodedExtent.width ||
888  avctx->coded_height < caps->minCodedExtent.height ||
889  avctx->coded_width > caps->maxCodedExtent.width ||
890  avctx->coded_height > caps->maxCodedExtent.height)
891  return AVERROR(EINVAL);
892 
894  avctx->level > max_level)
895  return AVERROR(EINVAL);
896 
897  /* Some basic sanity checking */
898  if (!(dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
899  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR))) {
900  av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
901  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
902  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
903  return AVERROR_EXTERNAL;
904  } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
905  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) ==
906  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) &&
907  !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
908  av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
909  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
910  "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
911  return AVERROR_EXTERNAL;
912  }
913 
914  /* TODO: make dedicated_dpb tunable */
915  dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR);
916  dec->layered_dpb = !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
917 
918  if (dec->dedicated_dpb) {
919  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
920  } else {
921  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
922  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
923  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
924  VK_IMAGE_USAGE_SAMPLED_BIT;
925  }
926 
927  /* Get the format of the images necessary */
928  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
929  &fmt_info,
930  &nb_out_fmts, NULL);
931  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
932  (!nb_out_fmts && ret == VK_SUCCESS)) {
933  return AVERROR(EINVAL);
934  } else if (ret != VK_SUCCESS) {
935  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
936  ff_vk_ret2str(ret));
937  return AVERROR_EXTERNAL;
938  }
939 
940  ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
941  if (!ret_info)
942  return AVERROR(ENOMEM);
943 
944  for (int i = 0; i < nb_out_fmts; i++)
945  ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
946 
947  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
948  &fmt_info,
949  &nb_out_fmts, ret_info);
950  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
951  (!nb_out_fmts && ret == VK_SUCCESS)) {
952  av_free(ret_info);
953  return AVERROR(EINVAL);
954  } else if (ret != VK_SUCCESS) {
955  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
956  ff_vk_ret2str(ret));
957  av_free(ret_info);
958  return AVERROR_EXTERNAL;
959  }
960 
961  /* Find a format to use */
962  *pix_fmt = best_format = AV_PIX_FMT_NONE;
963  *vk_fmt = best_vkfmt = VK_FORMAT_UNDEFINED;
964  source_format = avctx->sw_pix_fmt;
965 
966  av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
967  for (int i = 0; i < nb_out_fmts; i++) {
969  if (tmp == AV_PIX_FMT_NONE) {
970  av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
971  continue;
972  }
973 
974  best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
975  if (tmp == best_format)
976  best_vkfmt = ret_info[i].format;
977 
978  av_log(avctx, AV_LOG_DEBUG, " %s%s (Vulkan ID: %i)\n",
979  av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
980  ret_info[i].format);
981  }
982 
983  av_free(ret_info);
984 
985  if (best_format == AV_PIX_FMT_NONE) {
986  av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
987  return AVERROR(EINVAL);
988  } else {
989  av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
990  av_get_pix_fmt_name(best_format), best_vkfmt);
991  }
992 
993  *pix_fmt = best_format;
994  *vk_fmt = best_vkfmt;
995 
996  *dpb_dedicate = dec->dedicated_dpb;
997 
998  return 0;
999 }
1000 
1002 {
1003  av_free(hwfc->user_opaque);
1004 }
1005 
1006 int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
1007 {
1008  VkFormat vkfmt;
1009  int err, dedicated_dpb;
1010  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1011  AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
1014 
1015  frames_ctx->sw_format = AV_PIX_FMT_NONE;
1016 
1017  err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
1018  if (err < 0)
1019  return err;
1020 
1021  prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
1022  if (!prof)
1023  return AVERROR(ENOMEM);
1024 
1025  err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
1026  &frames_ctx->sw_format, &vkfmt,
1027  prof, &dedicated_dpb);
1028  if (err < 0) {
1029  av_free(prof);
1030  return err;
1031  }
1032 
1033  frames_ctx->user_opaque = prof;
1034  frames_ctx->free = free_profile_data;
1035 
1036  frames_ctx->width = avctx->coded_width;
1037  frames_ctx->height = avctx->coded_height;
1038  frames_ctx->format = AV_PIX_FMT_VULKAN;
1039 
1040  hwfc->format[0] = vkfmt;
1041  hwfc->create_pnext = &prof->profile_list;
1042  hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1043  hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1044  VK_IMAGE_USAGE_SAMPLED_BIT |
1045  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
1046 
1047  if (!dec->dedicated_dpb)
1048  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1049 
1050  return err;
1051 }
1052 
1053 static void vk_decode_free_params(void *opaque, uint8_t *data)
1054 {
1055  FFVulkanDecodeShared *ctx = opaque;
1056  FFVulkanFunctions *vk = &ctx->s.vkfn;
1057  VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data;
1058  vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
1059  ctx->s.hwctx->alloc);
1060  av_free(par);
1061 }
1062 
1064  const VkVideoSessionParametersCreateInfoKHR *session_params_create)
1065 {
1066  VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
1067  const FFVulkanFunctions *vk = &ctx->s.vkfn;
1068  VkResult ret;
1069 
1070  if (!par)
1071  return AVERROR(ENOMEM);
1072 
1073  /* Create session parameters */
1074  ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
1075  ctx->s.hwctx->alloc, par);
1076  if (ret != VK_SUCCESS) {
1077  av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1078  ff_vk_ret2str(ret));
1079  av_free(par);
1080  return AVERROR_EXTERNAL;
1081  }
1082  *par_ref = av_buffer_create((uint8_t *)par, sizeof(*par),
1084  if (!*par_ref) {
1085  vk_decode_free_params(ctx, (uint8_t *)par);
1086  return AVERROR(ENOMEM);
1087  }
1088 
1089  return 0;
1090 }
1091 
1093 {
1096 
1097  /* Wait on and free execution pool */
1098  ff_vk_exec_pool_free(&ctx->s, &dec->exec_pool);
1099 
1100  av_freep(&dec->hevc_headers);
1103  av_freep(&dec->slice_off);
1104  return 0;
1105 }
1106 
1108 {
1109  int err, qf, cxpos = 0, cypos = 0, nb_q = 0;
1110  VkResult ret;
1113  FFVulkanContext *s;
1114  FFVulkanFunctions *vk;
1115  const VkVideoProfileInfoKHR *profile;
1116  const FFVulkanDecodeDescriptor *vk_desc;
1117  const VkPhysicalDeviceDriverProperties *driver_props;
1118 
1119  VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
1120  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
1121  };
1122  VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
1123  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
1124  };
1125  StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
1126  VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
1127  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
1128  .pStdSequenceHeader = &av1_empty_seq,
1129  };
1130  VkVideoSessionParametersCreateInfoKHR session_params_create = {
1131  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
1132  .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
1133  avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
1134  avctx->codec_id == AV_CODEC_ID_AV1 ? (void *)&av1_params :
1135  NULL,
1136  };
1137  VkVideoSessionCreateInfoKHR session_create = {
1138  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
1139  };
1140  VkSamplerYcbcrConversionCreateInfo yuv_sampler_info = {
1141  .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
1142  .components = ff_comp_identity_map,
1143  .ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
1144  .ycbcrRange = avctx->color_range == AVCOL_RANGE_MPEG, /* Ignored */
1145  };
1146 
1148  if (err < 0)
1149  return err;
1150 
1151  /* Initialize contexts */
1152  ctx = dec->shared_ctx;
1153  s = &ctx->s;
1154  vk = &ctx->s.vkfn;
1155 
1156  s->frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
1157  s->frames = (AVHWFramesContext *)s->frames_ref->data;
1158  s->hwfc = s->frames->hwctx;
1159 
1160  s->device = (AVHWDeviceContext *)s->frames->device_ref->data;
1161  s->hwctx = s->device->hwctx;
1162 
1164  if (!profile) {
1165  av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
1166  return AVERROR(EINVAL);
1167  }
1168 
1169  err = ff_vk_load_props(s);
1170  if (err < 0)
1171  goto fail;
1172 
1173  /* Create queue context */
1174  qf = ff_vk_qf_init(s, &ctx->qf, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
1175 
1176  vk_desc = get_codecdesc(avctx->codec_id);
1177  /* Check for support */
1178  if (!(s->video_props[qf].videoCodecOperations & vk_desc->decode_op)) {
1179  av_log(avctx, AV_LOG_ERROR, "Decoding %s not supported on the given "
1180  "queue family %i!\n", avcodec_get_name(avctx->codec_id), qf);
1181  return AVERROR(EINVAL);
1182  }
1183 
1184  /* Enable queries if supported */
1185  if (s->query_props[qf].queryResultStatusSupport)
1186  nb_q = 1;
1187 
1188  session_create.flags = 0x0;
1189  session_create.queueFamilyIndex = s->hwctx->queue_family_decode_index;
1190  session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
1191  session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
1192  session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
1193  session_create.pictureFormat = s->hwfc->format[0];
1194  session_create.referencePictureFormat = session_create.pictureFormat;
1195  session_create.pStdHeaderVersion = &vk_desc->ext_props;
1196  session_create.pVideoProfile = profile;
1197 
1198  /* Create decode exec context for this specific main thread.
1199  * 2 async contexts per thread was experimentally determined to be optimal
1200  * for a majority of streams. */
1201  err = ff_vk_exec_pool_init(s, &ctx->qf, &dec->exec_pool, 2,
1202  nb_q, VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR, 0,
1203  profile);
1204  if (err < 0)
1205  goto fail;
1206 
1207  err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
1208  if (err < 0)
1209  goto fail;
1210 
1211  /* Get sampler */
1213  yuv_sampler_info.xChromaOffset = cxpos >> 7;
1214  yuv_sampler_info.yChromaOffset = cypos >> 7;
1215  yuv_sampler_info.format = s->hwfc->format[0];
1216  ret = vk->CreateSamplerYcbcrConversion(s->hwctx->act_dev, &yuv_sampler_info,
1217  s->hwctx->alloc, &ctx->yuv_sampler);
1218  if (ret != VK_SUCCESS) {
1219  err = AVERROR_EXTERNAL;
1220  goto fail;
1221  }
1222 
1223  /* If doing an out-of-place decoding, create a DPB pool */
1224  if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
1226  AVVulkanFramesContext *dpb_hwfc;
1227 
1228  ctx->dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref);
1229  if (!ctx->dpb_hwfc_ref) {
1230  err = AVERROR(ENOMEM);
1231  goto fail;
1232  }
1233 
1234  dpb_frames = (AVHWFramesContext *)ctx->dpb_hwfc_ref->data;
1235  dpb_frames->format = s->frames->format;
1236  dpb_frames->sw_format = s->frames->sw_format;
1237  dpb_frames->width = avctx->coded_width;
1238  dpb_frames->height = avctx->coded_height;
1239 
1240  dpb_hwfc = dpb_frames->hwctx;
1241  dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
1242  VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
1243  dpb_hwfc->format[0] = s->hwfc->format[0];
1244  dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1245  dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1246  VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */
1247 
1248  if (dec->layered_dpb)
1249  dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots;
1250 
1251  err = av_hwframe_ctx_init(ctx->dpb_hwfc_ref);
1252  if (err < 0)
1253  goto fail;
1254 
1255  if (dec->layered_dpb) {
1256  ctx->layered_frame = vk_get_dpb_pool(ctx);
1257  if (!ctx->layered_frame) {
1258  err = AVERROR(ENOMEM);
1259  goto fail;
1260  }
1261 
1262  err = vk_decode_create_view(dec, &ctx->layered_view, &ctx->layered_aspect,
1263  (AVVkFrame *)ctx->layered_frame->data[0],
1264  s->hwfc->format[0], 0);
1265  if (err < 0)
1266  goto fail;
1267  }
1268  }
1269 
1270  session_params_create.videoSession = ctx->common.session;
1271  ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
1272  s->hwctx->alloc, &ctx->empty_session_params);
1273  if (ret != VK_SUCCESS) {
1274  av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
1275  ff_vk_ret2str(ret));
1276  return AVERROR_EXTERNAL;
1277  }
1278 
1279  driver_props = &dec->shared_ctx->s.driver_props;
1280  if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
1281  driver_props->conformanceVersion.major == 1 &&
1282  driver_props->conformanceVersion.minor == 3 &&
1283  driver_props->conformanceVersion.subminor == 8 &&
1284  driver_props->conformanceVersion.patch < 3)
1285  dec->quirk_av1_offset = 1;
1286 
1287  ff_vk_decode_flush(avctx);
1288 
1289  av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization sucessful\n");
1290 
1291  return 0;
1292 
1293 fail:
1294  ff_vk_decode_uninit(avctx);
1295 
1296  return err;
1297 }
vulkan_loader.h
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
ff_vk_load_props
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition: vulkan.c:85
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVVulkanDeviceContext::phys_dev
VkPhysicalDevice phys_dev
Physical device.
Definition: hwcontext_vulkan.h:65
FFVulkanDecodePicture::slices_size
size_t slices_size
Definition: vulkan_decode.h:112
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:496
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:107
FFVulkanDecodeProfileData::h265_profile
VkVideoDecodeH265ProfileInfoKHR h265_profile
Definition: vulkan_decode.h:39
ff_comp_identity_map
const VkComponentMapping ff_comp_identity_map
Definition: vulkan.c:25
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2962
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
FFVulkanDecodeContext::shared_ctx
FFVulkanDecodeShared * shared_ctx
Definition: vulkan_decode.h:66
AV_FIELD_PROGRESSIVE
@ AV_FIELD_PROGRESSIVE
Definition: defs.h:200
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:68
dpb_frames
int dpb_frames
Definition: h264_levels.c:163
ff_vk_qf_init
int ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, VkQueueFlagBits dev_family)
Chooses a QF and loads it into a context.
Definition: vulkan.c:224
ff_refstruct_alloc_ext
static void * ff_refstruct_alloc_ext(size_t size, unsigned flags, void *opaque, void(*free_cb)(FFRefStructOpaque opaque, void *obj))
A wrapper around ff_refstruct_alloc_ext_c() for the common case of a non-const qualified opaque.
Definition: refstruct.h:94
FFVkVideoBuffer
Definition: vulkan_video.h:66
AV_PROFILE_HEVC_MAIN
#define AV_PROFILE_HEVC_MAIN
Definition: defs.h:158
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:678
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:130
FFVkVideoBuffer::buf
FFVkBuffer buf
Definition: vulkan_video.h:67
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:322
ff_vk_video_common_init
av_cold int ff_vk_video_common_init(void *log, FFVulkanContext *s, FFVkVideoCommon *common, VkVideoSessionCreateInfoKHR *session_create)
Initialize video session, allocating and binding necessary memory.
Definition: vulkan_video.c:279
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:123
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:344
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:708
AVVulkanFramesContext::create_pnext
void * create_pnext
Extension data for image creation.
Definition: hwcontext_vulkan.h:206
b
#define b
Definition: input.c:41
data
const char data[16]
Definition: mxf.c:148
FFVulkanDecodeContext::frame_id_alloc_mask
uint32_t frame_id_alloc_mask
Definition: vulkan_decode.h:73
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:1872
FFRefStructOpaque
RefStruct is an API for creating reference-counted objects with minimal overhead.
Definition: refstruct.h:58
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
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:439
FFVkExecPool::query_pool
VkQueryPool query_pool
Definition: vulkan.h:218
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:557
FFVulkanDecodeContext
Definition: vulkan_decode.h:65
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:598
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:186
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:2138
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:365
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:96
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:67
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:110
AVVulkanDeviceContext::alloc
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
Definition: hwcontext_vulkan.h:48
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:270
FFVulkanDecodeDescriptor::decode_op
VkVideoCodecOperationFlagBitsKHR decode_op
Definition: vulkan_decode.h:32
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:279
FF_VK_EXT_VIDEO_DECODE_QUEUE
@ FF_VK_EXT_VIDEO_DECODE_QUEUE
Definition: vulkan_functions.h:43
fail
#define fail()
Definition: checkasm.h:179
FFVulkanDecodePicture::sem_value
uint64_t sem_value
Definition: vulkan_decode.h:97
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:176
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:502
ff_vk_ret2str
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition: vulkan.c:33
AVCodecContext::coded_height
int coded_height
Definition: avcodec.h:633
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:342
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:745
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:118
FFVulkanDecodeContext::slice_off
uint32_t * slice_off
Definition: vulkan_decode.h:83
avassert.h
FFVulkanDecodePicture::img_view_out
VkImageView img_view_out
Definition: vulkan_decode.h:91
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
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:199
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:495
FFVulkanDecodePicture::wait_semaphores
PFN_vkWaitSemaphores wait_semaphores
Definition: vulkan_decode.h:115
s
#define s(width, name)
Definition: cbs_vp9.c:198
FFVulkanDecodePicture
Definition: vulkan_decode.h:87
av_chroma_location_enum_to_pos
int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation pos)
Converts AVChromaLocation to swscale x/y chroma position.
Definition: pixdesc.c:3380
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:1063
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:697
offsets
static const int offsets[]
Definition: hevc_pel.c:34
FFVulkanContext::driver_props
VkPhysicalDeviceDriverProperties driver_props
Definition: vulkan.h:234
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1406
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:91
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:503
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
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:574
codec_id
enum AVCodecID codec_id
Definition: vaapi_decode.c:386
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:255
AV_CODEC_ID_H264
@ AV_CODEC_ID_H264
Definition: codec_id.h:79
FFVkExecContext::query_idx
int query_idx
Definition: vulkan.h:170
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:1063
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:455
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:57
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:44
FFVulkanDecodePicture::img_view_ref
VkImageView img_view_ref
Definition: vulkan_decode.h:90
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
AVCodecContext::color_range
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: avcodec.h:695
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:280
AVVulkanDeviceContext::nb_enabled_dev_extensions
int nb_enabled_dev_extensions
Definition: hwcontext_vulkan.h:99
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:572
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:259
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:480
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:2158
ff_vk_decode_uninit
int ff_vk_decode_uninit(AVCodecContext *avctx)
Free decoder.
Definition: vulkan_decode.c:1092
FFVkVideoBuffer::mem
uint8_t * mem
Definition: vulkan_video.h:68
AVVulkanFramesContext::format
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
Definition: hwcontext_vulkan.h:236
FFVkBuffer::size
size_t size
Definition: vulkan.h:99
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:195
FFVkExecPool::nb_queries
int nb_queries
Definition: vulkan.h:224
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:295
FFVulkanContext
Definition: vulkan.h:228
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:1006
AVCodecContext::level
int level
Encoding level descriptor.
Definition: avcodec.h:1783
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
ff_vk_h265_level_to_av
int ff_vk_h265_level_to_av(StdVideoH265LevelIdc level)
Definition: vulkan_video.c:160
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:121
AVVkFrame
Definition: hwcontext_vulkan.h:265
size
int size
Definition: twinvq_data.h:10344
FFVulkanDecodePicture::img_aspect_ref
VkImageAspectFlags img_aspect_ref
Definition: vulkan_decode.h:94
free_common
static void free_common(FFRefStructOpaque unused, void *obj)
Definition: vulkan_decode.c:603
FFVkBuffer::flags
VkMemoryPropertyFlagBits flags
Definition: vulkan.h:98
ff_vk_dec_h264_desc
const FFVulkanDecodeDescriptor ff_vk_dec_h264_desc
Definition: vulkan_h264.c:24
ref_frame
static int ref_frame(VVCFrame *dst, const VVCFrame *src)
Definition: vvcdec.c:552
FFVulkanDecodeContext::slice_off_max
unsigned int slice_off_max
Definition: vulkan_decode.h:84
AVVkFrame::queue_family
uint32_t queue_family[AV_NUM_DATA_POINTERS]
Queue family of the images.
Definition: hwcontext_vulkan.h:329
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
FFVkExecContext
Definition: vulkan.h:152
vk_decode_free_params
static void vk_decode_free_params(void *opaque, uint8_t *data)
Definition: vulkan_decode.c:1053
FFVulkanDecodeProfileData
Definition: vulkan_decode.h:37
avcodec_get_name
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:406
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:512
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
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:134
AVCodecContext::hwaccel_flags
int hwaccel_flags
Bit set of AV_HWACCEL_FLAG_* flags, which affect hardware accelerated decoding (if active).
Definition: avcodec.h:1506
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:226
FFVulkanDecodePicture::ref_slot
VkVideoReferenceSlotInfoKHR ref_slot
Definition: vulkan_decode.h:101
FFVkBuffer::mem
VkDeviceMemory mem
Definition: vulkan.h:97
FFVulkanDecodePicture::sem
VkSemaphore sem
Definition: vulkan_decode.h:96
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:254
FFVulkanDecodeContext::external_fg
int external_fg
Definition: vulkan_decode.h:72
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
AVCodecContext::chroma_sample_location
enum AVChromaLocation chroma_sample_location
This defines the location of chroma samples.
Definition: avcodec.h:702
profile
int profile
Definition: mxfenc.c:2226
ff_vk_exec_get_query
VkResult ff_vk_exec_get_query(FFVulkanContext *s, FFVkExecContext *e, void **data, int64_t *status)
Performs nb_queries queries and returns their results and statuses.
Definition: vulkan.c:446
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:666
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:1475
CODEC_VER
#define CODEC_VER(ver)
Definition: vulkan_video.h:29
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:312
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:250
ff_refstruct_replace
void ff_refstruct_replace(void *dstp, const void *src)
Ensure *dstp refers to the same object as src.
Definition: refstruct.c:160
AV_PROFILE_H264_CONSTRAINED
#define AV_PROFILE_H264_CONSTRAINED
Definition: defs.h:106
dec_descs
static const FFVulkanDecodeDescriptor * dec_descs[]
Definition: vulkan_decode.c:36
FFVulkanDecodeContext::hevc_headers
struct HEVCHeaderSet * hevc_headers
Definition: vulkan_decode.h:80
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:164
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:695
ff_vk_dec_hevc_desc
const FFVulkanDecodeDescriptor ff_vk_dec_hevc_desc
Definition: vulkan_hevc.c:25
get_codecdesc
static const FFVulkanDecodeDescriptor * get_codecdesc(enum AVCodecID codec_id)
Definition: vulkan_decode.c:48
AVCodecContext
main external API structure.
Definition: avcodec.h:445
FFVulkanDecodeContext::dedicated_dpb
int dedicated_dpb
Definition: vulkan_decode.h:70
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:3241
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1639
FFVulkanDecodeDescriptor
Definition: vulkan_decode.h:29
AV_CODEC_ID_H265
#define AV_CODEC_ID_H265
Definition: codec_id.h:227
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
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:1926
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
ff_vk_video_get_buffer
int ff_vk_video_get_buffer(FFVulkanContext *ctx, FFVkVideoCommon *s, AVBufferRef **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size)
Get a mapped FFVkPooledBuffer with a specific guaranteed minimum size from a pool.
Definition: vulkan_video.c:201
FFVulkanDecodePicture::dpb_frame
AVFrame * dpb_frame
Definition: vulkan_decode.h:88
AV_PROFILE_H264_CONSTRAINED_BASELINE
#define AV_PROFILE_H264_CONSTRAINED_BASELINE
Definition: defs.h:110
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:79
AVVulkanFramesContext::tiling
VkImageTiling tiling
Controls the tiling of allocated frames.
Definition: hwcontext_vulkan.h:185
vulkan_video.h
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:633
desc
const char * desc
Definition: libsvtav1.c:75
AVVulkanDeviceContext::enabled_dev_extensions
const char *const * enabled_dev_extensions
Enabled device extensions.
Definition: hwcontext_vulkan.h:98
AVVulkanFramesContext::nb_layers
int nb_layers
Number of layers each image will have.
Definition: hwcontext_vulkan.h:241
FFVulkanDecodePicture::slices_buf
AVBufferRef * slices_buf
Definition: vulkan_decode.h:111
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:295
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
FFVkExecPool::cmd_bufs
VkCommandBuffer * cmd_bufs
Definition: vulkan.h:215
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:70
vulkan_decode.h
FFVulkanDecodePicture::img_view_dest
VkImageView img_view_dest
Definition: vulkan_decode.h:92
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
decode_end
static av_cold int decode_end(AVCodecContext *avctx)
Definition: 4xm.c:975
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:670
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
FFVulkanDecodeContext::layered_dpb
int layered_dpb
Definition: vulkan_decode.h:71
vk_get_dpb_pool
static AVFrame * vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
Definition: vulkan_decode.c:172
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:723
FFVulkanDecodePicture::destroy_image_view
PFN_vkDestroyImageView destroy_image_view
Definition: vulkan_decode.h:116
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:632
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:94
ff_vk_decode_init
int ff_vk_decode_init(AVCodecContext *avctx)
Initialize decoder.
Definition: vulkan_decode.c:1107
ff_vk_aspect_bits_from_vkfmt
VkImageAspectFlags ff_vk_aspect_bits_from_vkfmt(VkFormat vkf)
Get aspect bits which include all planes from a VkFormat.
Definition: vulkan_video.c:102
FFVulkanDecodePicture::decode_info
VkVideoDecodeInfoKHR decode_info
Definition: vulkan_decode.h:108
AVCodecContext::sw_pix_fmt
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:664
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
FFVulkanFunctions
Definition: vulkan_functions.h:226
ff_refstruct_unref
void ff_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition: refstruct.c:120
FFVkExecPool::pool_size
int pool_size
Definition: vulkan.h:216
FFVulkanDecodeContext::quirk_av1_offset
int quirk_av1_offset
Definition: vulkan_decode.h:77
free_profile_data
static void free_profile_data(AVHWFramesContext *hwfc)
Definition: vulkan_decode.c:1001
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:2882
FFVulkanDecodePicture::img_aspect
VkImageAspectFlags img_aspect
Definition: vulkan_decode.h:93
vk_decode_create_view
static int vk_decode_create_view(FFVulkanDecodeContext *dec, VkImageView *dst_view, VkImageAspectFlags *aspect, AVVkFrame *src, VkFormat vkf, int is_current)
Definition: vulkan_decode.c:127