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