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