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