FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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  err = av_buffer_replace(&dst_ctx->session_params, src_ctx->session_params);
100  if (err < 0)
101  return err;
102 
103  dst_ctx->dedicated_dpb = src_ctx->dedicated_dpb;
104  dst_ctx->external_fg = src_ctx->external_fg;
105  dst_ctx->frame_id_alloc_mask = src_ctx->frame_id_alloc_mask;
106 
107  return 0;
108 }
109 
110 int ff_vk_params_invalidate(AVCodecContext *avctx, int t, const uint8_t *b, uint32_t s)
111 {
114  return 0;
115 }
116 
118 {
119  int err;
120  AVFrame *avf = av_frame_alloc();
121  if (!avf)
122  return NULL;
123 
124  err = av_hwframe_get_buffer(ctx->common.dpb_hwfc_ref, avf, 0x0);
125  if (err < 0)
126  av_frame_free(&avf);
127 
128  return avf;
129 }
130 
132 {
134  FFVulkanFunctions *vk = &ctx->s.vkfn;
135 
136  vkpic->dpb_frame = NULL;
137  for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
138  vkpic->view.ref[i] = VK_NULL_HANDLE;
139  vkpic->view.out[i] = VK_NULL_HANDLE;
140  vkpic->view.dst[i] = VK_NULL_HANDLE;
141  }
142 
143  vkpic->destroy_image_view = vk->DestroyImageView;
144  vkpic->wait_semaphores = vk->WaitSemaphores;
145  vkpic->invalidate_memory_ranges = vk->InvalidateMappedMemoryRanges;
146 }
147 
149  FFVulkanDecodePicture *vkpic, int is_current,
150  int alloc_dpb)
151 {
152  int err;
154 
155  vkpic->slices_size = 0;
156 
157  /* If the decoder made a blank frame to make up for a missing ref, or the
158  * frame is the current frame so it's missing one, create a re-representation */
159  if (vkpic->view.ref[0])
160  return 0;
161 
162  init_frame(dec, vkpic);
163 
164  if (ctx->common.layered_dpb && alloc_dpb) {
165  vkpic->view.ref[0] = ctx->common.layered_view;
166  vkpic->view.aspect_ref[0] = ctx->common.layered_aspect;
167  } else if (alloc_dpb) {
168  AVHWFramesContext *dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
169  AVVulkanFramesContext *dpb_hwfc = dpb_frames->hwctx;
170 
171  vkpic->dpb_frame = vk_get_dpb_pool(ctx);
172  if (!vkpic->dpb_frame)
173  return AVERROR(ENOMEM);
174 
175  err = ff_vk_create_view(&ctx->s, &ctx->common,
176  &vkpic->view.ref[0], &vkpic->view.aspect_ref[0],
177  (AVVkFrame *)vkpic->dpb_frame->data[0],
178  dpb_hwfc->format[0], !is_current);
179  if (err < 0)
180  return err;
181 
182  vkpic->view.dst[0] = vkpic->view.ref[0];
183  }
184 
185  if (!alloc_dpb || is_current) {
187  AVVulkanFramesContext *hwfc = frames->hwctx;
188 
189  err = ff_vk_create_view(&ctx->s, &ctx->common,
190  &vkpic->view.out[0], &vkpic->view.aspect[0],
191  (AVVkFrame *)pic->data[0],
192  hwfc->format[0], !is_current);
193  if (err < 0)
194  return err;
195 
196  if (!alloc_dpb) {
197  vkpic->view.ref[0] = vkpic->view.out[0];
198  vkpic->view.aspect_ref[0] = vkpic->view.aspect[0];
199  }
200  }
201 
202  return 0;
203 }
204 
206  FFVulkanDecodePicture *vkpic, int is_current,
207  enum FFVkShaderRepFormat rep_fmt, int alloc_dpb)
208 {
209  int err;
212 
213  vkpic->slices_size = 0;
214 
215  if (vkpic->view.ref[0])
216  return 0;
217 
218  init_frame(dec, vkpic);
219 
220  for (int i = 0; i < av_pix_fmt_count_planes(frames->sw_format); i++) {
221  if (alloc_dpb) {
222  vkpic->dpb_frame = vk_get_dpb_pool(ctx);
223  if (!vkpic->dpb_frame)
224  return AVERROR(ENOMEM);
225 
226  err = ff_vk_create_imageview(&ctx->s,
227  &vkpic->view.ref[i], &vkpic->view.aspect_ref[i],
228  vkpic->dpb_frame, i, rep_fmt);
229  if (err < 0)
230  return err;
231 
232  vkpic->view.dst[i] = vkpic->view.ref[i];
233  }
234 
235  if (!alloc_dpb || is_current) {
236  err = ff_vk_create_imageview(&ctx->s,
237  &vkpic->view.out[i], &vkpic->view.aspect[i],
238  pic, i, rep_fmt);
239  if (err < 0)
240  return err;
241 
242  if (!alloc_dpb) {
243  vkpic->view.ref[i] = vkpic->view.out[i];
244  vkpic->view.aspect_ref[i] = vkpic->view.aspect[i];
245  }
246  }
247  }
248 
249  return 0;
250 }
251 
253  const uint8_t *data, size_t size, int add_startcode,
254  uint32_t *nb_slices, const uint32_t **offsets)
255 {
258 
259  static const uint8_t startcode_prefix[3] = { 0x0, 0x0, 0x1 };
260  const size_t startcode_len = add_startcode ? sizeof(startcode_prefix) : 0;
261  const int nb = nb_slices ? *nb_slices : 0;
262  uint8_t *slices;
263  uint32_t *slice_off;
264  FFVkBuffer *vkbuf;
265 
266  size_t new_size = vp->slices_size + startcode_len + size +
267  ctx->caps.minBitstreamBufferSizeAlignment;
268  new_size = FFALIGN(new_size, ctx->caps.minBitstreamBufferSizeAlignment);
269 
270  if (offsets) {
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 
278  slice_off[nb] = vp->slices_size;
279  }
280 
281  vkbuf = vp->slices_buf ? (FFVkBuffer *)vp->slices_buf->data : NULL;
282  if (!vkbuf || vkbuf->size < new_size) {
283  int err;
284  AVBufferRef *new_ref;
285  FFVkBuffer *new_buf;
286 
287  /* No point in requesting anything smaller. */
288  size_t buf_size = FFMAX(new_size, 1024*1024);
289 
290  /* Align buffer to nearest power of two. Makes fragmentation management
291  * easier, and gives us ample headroom. */
292  buf_size = 2 << av_log2(buf_size);
293 
294  err = ff_vk_get_pooled_buffer(&ctx->s, &ctx->buf_pool, &new_ref,
295  DECODER_IS_SDR(avctx->codec_id) ?
296  (VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
297  VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) :
298  VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
299  ctx->s.hwfc->create_pnext, buf_size,
300  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
301  (DECODER_IS_SDR(avctx->codec_id) ?
302  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT : 0x0));
303  if (err < 0)
304  return err;
305 
306  new_buf = (FFVkBuffer *)new_ref->data;
307 
308  /* Copy data from the old buffer */
309  if (vkbuf) {
310  memcpy(new_buf->mapped_mem, vkbuf->mapped_mem, vp->slices_size);
312  }
313 
314  vp->slices_buf = new_ref;
315  vkbuf = new_buf;
316  }
317  slices = vkbuf->mapped_mem;
318 
319  /* Startcode */
320  memcpy(slices + vp->slices_size, startcode_prefix, startcode_len);
321 
322  /* Slice data */
323  memcpy(slices + vp->slices_size + startcode_len, data, size);
324 
325  if (nb_slices)
326  *nb_slices = nb + 1;
327 
328  vp->slices_size += startcode_len + size;
329 
330  return 0;
331 }
332 
334 {
337 
338  FFVulkanFunctions *vk = &ctx->s.vkfn;
339  VkVideoBeginCodingInfoKHR decode_start = {
340  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
341  .videoSession = ctx->common.session,
342  .videoSessionParameters = ctx->empty_session_params,
343  };
344  VkVideoCodingControlInfoKHR decode_ctrl = {
345  .sType = VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR,
346  .flags = VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR,
347  };
348  VkVideoEndCodingInfoKHR decode_end = {
349  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
350  };
351 
352  VkCommandBuffer cmd_buf;
353  FFVkExecContext *exec;
354 
355  /* Non-video queues do not need to be reset */
356  if (!(get_codecdesc(avctx->codec_id)->decode_op))
357  return;
358 
359  exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
360  ff_vk_exec_start(&ctx->s, exec);
361  cmd_buf = exec->buf;
362 
363  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
364  vk->CmdControlVideoCodingKHR(cmd_buf, &decode_ctrl);
365  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
366  ff_vk_exec_submit(&ctx->s, exec);
367 }
368 
370  AVFrame *pic, FFVulkanDecodePicture *vp,
371  AVFrame *rpic[], FFVulkanDecodePicture *rvkp[])
372 {
373  int err;
374  VkResult ret;
375  VkCommandBuffer cmd_buf;
376  FFVkBuffer *sd_buf;
377 
380  FFVulkanFunctions *vk = &ctx->s.vkfn;
381 
382  /* Output */
383  AVVkFrame *vkf = (AVVkFrame *)pic->buf[0]->data;
384 
385  /* Quirks */
386  const int layered_dpb = ctx->common.layered_dpb;
387 
388  VkVideoBeginCodingInfoKHR decode_start = {
389  .sType = VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR,
390  .videoSession = ctx->common.session,
391  .videoSessionParameters = dec->session_params ?
392  *((VkVideoSessionParametersKHR *)dec->session_params->data) :
393  VK_NULL_HANDLE,
394  .referenceSlotCount = vp->decode_info.referenceSlotCount,
395  .pReferenceSlots = vp->decode_info.pReferenceSlots,
396  };
397  VkVideoEndCodingInfoKHR decode_end = {
398  .sType = VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR,
399  };
400 
401  VkImageMemoryBarrier2 img_bar[37];
402  int nb_img_bar = 0;
403  size_t data_size = FFALIGN(vp->slices_size,
404  ctx->caps.minBitstreamBufferSizeAlignment);
405 
406  FFVkExecContext *exec = ff_vk_exec_get(&ctx->s, &ctx->exec_pool);
407 
408  /* The current decoding reference has to be bound as an inactive reference */
409  VkVideoReferenceSlotInfoKHR *cur_vk_ref;
410  cur_vk_ref = (void *)&decode_start.pReferenceSlots[decode_start.referenceSlotCount];
411  cur_vk_ref[0] = vp->ref_slot;
412  cur_vk_ref[0].slotIndex = -1;
413  decode_start.referenceSlotCount++;
414 
415  sd_buf = (FFVkBuffer *)vp->slices_buf->data;
416 
417  /* Flush if needed */
418  if (!(sd_buf->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
419  VkMappedMemoryRange flush_buf = {
420  .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
421  .memory = sd_buf->mem,
422  .offset = 0,
423  .size = FFALIGN(vp->slices_size,
424  ctx->s.props.properties.limits.nonCoherentAtomSize),
425  };
426 
427  ret = vk->FlushMappedMemoryRanges(ctx->s.hwctx->act_dev, 1, &flush_buf);
428  if (ret != VK_SUCCESS) {
429  av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n",
430  ff_vk_ret2str(ret));
431  return AVERROR_EXTERNAL;
432  }
433  }
434 
435  vp->decode_info.srcBuffer = sd_buf->buf;
436  vp->decode_info.srcBufferOffset = 0;
437  vp->decode_info.srcBufferRange = data_size;
438 
439  /* Start command buffer recording */
440  err = ff_vk_exec_start(&ctx->s, exec);
441  if (err < 0)
442  return err;
443  cmd_buf = exec->buf;
444 
445  /* Slices */
446  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &vp->slices_buf, 1, 0);
447  if (err < 0)
448  return err;
449  vp->slices_buf = NULL; /* Owned by the exec buffer from now on */
450 
451  /* Parameters */
452  err = ff_vk_exec_add_dep_buf(&ctx->s, exec, &dec->session_params, 1, 1);
453  if (err < 0)
454  return err;
455 
456  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, pic,
457  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
458  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
459  if (err < 0)
460  return err;
461 
462  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec, &vp->sem, &vp->sem_value,
463  pic);
464  if (err < 0)
465  return err;
466 
467  /* Output image - change layout, as it comes from a pool */
468  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
469  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
470  .pNext = NULL,
471  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
472  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
473  .srcAccessMask = VK_ACCESS_2_NONE,
474  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
475  .oldLayout = vkf->layout[0],
476  .newLayout = (layered_dpb || vp->dpb_frame) ?
477  VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR :
478  VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, /* Spec, 07252 utter madness */
479  .srcQueueFamilyIndex = vkf->queue_family[0],
480  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
481  .image = vkf->img[0],
482  .subresourceRange = (VkImageSubresourceRange) {
483  .aspectMask = vp->view.aspect[0],
484  .layerCount = 1,
485  .levelCount = 1,
486  },
487  };
488  ff_vk_exec_update_frame(&ctx->s, exec, pic,
489  &img_bar[nb_img_bar], &nb_img_bar);
490 
491  /* Reference for the current image, if existing and not layered */
492  if (vp->dpb_frame) {
493  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, vp->dpb_frame,
494  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
495  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
496  if (err < 0)
497  return err;
498  }
499 
500  if (!layered_dpb) {
501  /* All references (apart from the current) for non-layered refs */
502 
503  for (int i = 0; i < vp->decode_info.referenceSlotCount; i++) {
504  AVFrame *ref_frame = rpic[i];
505  FFVulkanDecodePicture *rvp = rvkp[i];
506  AVFrame *ref = rvp->dpb_frame ? rvp->dpb_frame : ref_frame;
507 
508  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ref,
509  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
510  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
511  if (err < 0)
512  return err;
513 
514  if (err == 0) {
515  err = ff_vk_exec_mirror_sem_value(&ctx->s, exec,
516  &rvp->sem, &rvp->sem_value,
517  ref);
518  if (err < 0)
519  return err;
520  }
521 
522  if (!rvp->dpb_frame) {
523  AVVkFrame *rvkf = (AVVkFrame *)ref->data[0];
524 
525  img_bar[nb_img_bar] = (VkImageMemoryBarrier2) {
526  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2,
527  .pNext = NULL,
528  .srcStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
529  .dstStageMask = VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
530  .srcAccessMask = VK_ACCESS_2_NONE,
531  .dstAccessMask = VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR |
532  VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR,
533  .oldLayout = rvkf->layout[0],
534  .newLayout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR,
535  .srcQueueFamilyIndex = rvkf->queue_family[0],
536  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
537  .image = rvkf->img[0],
538  .subresourceRange = (VkImageSubresourceRange) {
539  .aspectMask = rvp->view.aspect_ref[0],
540  .layerCount = 1,
541  .levelCount = 1,
542  },
543  };
544  ff_vk_exec_update_frame(&ctx->s, exec, ref,
545  &img_bar[nb_img_bar], &nb_img_bar);
546  }
547  }
548  } else if (vp->decode_info.referenceSlotCount ||
549  vp->view.out[0] != vp->view.ref[0]) {
550  /* Single barrier for a single layered ref */
551  err = ff_vk_exec_add_dep_frame(&ctx->s, exec, ctx->common.layered_frame,
552  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR,
553  VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR);
554  if (err < 0)
555  return err;
556  }
557 
558  /* Change image layout */
559  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
560  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
561  .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
562  .pImageMemoryBarriers = img_bar,
563  .imageMemoryBarrierCount = nb_img_bar,
564  });
565 
566  /* Start, use parameters, decode and end decoding */
567  vk->CmdBeginVideoCodingKHR(cmd_buf, &decode_start);
568  vk->CmdDecodeVideoKHR(cmd_buf, &vp->decode_info);
569  vk->CmdEndVideoCodingKHR(cmd_buf, &decode_end);
570 
571  /* End recording and submit for execution */
572  return ff_vk_exec_submit(&ctx->s, exec);
573 }
574 
576 {
577  AVVulkanDeviceContext *hwctx = dev_ctx->hwctx;
578 
579  VkSemaphoreWaitInfo sem_wait = (VkSemaphoreWaitInfo) {
580  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
581  .pSemaphores = &vp->sem,
582  .pValues = &vp->sem_value,
583  .semaphoreCount = 1,
584  };
585 
586  /* We do not have to lock the frame here because we're not interested
587  * in the actual current semaphore value, but only that it's later than
588  * the time we submitted the image for decoding. */
589  if (vp->sem)
590  vp->wait_semaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
591 
592  /* Free slices data */
594 
595  /* Destroy image view (out) */
596  for (int i = 0; i < AV_NUM_DATA_POINTERS; i++) {
597  if (vp->view.out[i] && vp->view.out[i] != vp->view.dst[i])
598  vp->destroy_image_view(hwctx->act_dev, vp->view.out[i], hwctx->alloc);
599 
600  /* Destroy image view (ref, unlayered) */
601  if (vp->view.dst[i])
602  vp->destroy_image_view(hwctx->act_dev, vp->view.dst[i], hwctx->alloc);
603  }
604 
605  av_frame_free(&vp->dpb_frame);
606 }
607 
608 static void free_common(AVRefStructOpaque unused, void *obj)
609 {
610  FFVulkanDecodeShared *ctx = obj;
611  FFVulkanContext *s = &ctx->s;
612  FFVulkanFunctions *vk = &ctx->s.vkfn;
613 
614  /* Wait on and free execution pool */
615  ff_vk_exec_pool_free(&ctx->s, &ctx->exec_pool);
616 
617  /* This also frees all references from this pool */
618  av_frame_free(&ctx->common.layered_frame);
619 
620  /* Destroy parameters */
621  if (ctx->empty_session_params)
622  vk->DestroyVideoSessionParametersKHR(s->hwctx->act_dev,
623  ctx->empty_session_params,
624  s->hwctx->alloc);
625 
626  av_buffer_pool_uninit(&ctx->buf_pool);
627 
628  ff_vk_video_common_uninit(s, &ctx->common);
629 
630  if (ctx->sd_ctx_free)
631  ctx->sd_ctx_free(ctx);
632 
633  ff_vk_uninit(s);
634 }
635 
636 static int vulkan_decode_bootstrap(AVCodecContext *avctx, AVBufferRef *frames_ref)
637 {
638  int err;
640  const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
642  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
643  AVVulkanDeviceContext *hwctx = device->hwctx;
645 
646  if (dec->shared_ctx)
647  return 0;
648 
649  dec->shared_ctx = av_refstruct_alloc_ext(sizeof(*ctx), 0, NULL,
650  free_common);
651  if (!dec->shared_ctx)
652  return AVERROR(ENOMEM);
653 
654  ctx = dec->shared_ctx;
655 
656  ctx->s.extensions = ff_vk_extensions_to_mask(hwctx->enabled_dev_extensions,
658 
659  if (vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
660  if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_DECODE_QUEUE)) {
661  av_log(avctx, AV_LOG_ERROR, "Device does not support the %s extension!\n",
662  VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME);
664  return AVERROR(ENOSYS);
665  }
666  }
667 
668  err = ff_vk_load_functions(device, &ctx->s.vkfn, ctx->s.extensions, 1, 1);
669  if (err < 0) {
671  return err;
672  }
673 
674  return 0;
675 }
676 
677 static VkResult vulkan_setup_profile(AVCodecContext *avctx,
679  AVVulkanDeviceContext *hwctx,
680  FFVulkanFunctions *vk,
681  const FFVulkanDecodeDescriptor *vk_desc,
682  VkVideoDecodeH264CapabilitiesKHR *h264_caps,
683  VkVideoDecodeH265CapabilitiesKHR *h265_caps,
684  VkVideoDecodeAV1CapabilitiesKHR *av1_caps,
685  VkVideoCapabilitiesKHR *caps,
686  VkVideoDecodeCapabilitiesKHR *dec_caps,
687  int cur_profile)
688 {
689  VkVideoDecodeUsageInfoKHR *usage = &prof->usage;
690  VkVideoProfileInfoKHR *profile = &prof->profile;
691  VkVideoProfileListInfoKHR *profile_list = &prof->profile_list;
692 
693  VkVideoDecodeH264ProfileInfoKHR *h264_profile = &prof->h264_profile;
694  VkVideoDecodeH265ProfileInfoKHR *h265_profile = &prof->h265_profile;
695  VkVideoDecodeAV1ProfileInfoKHR *av1_profile = &prof->av1_profile;
696 
698  if (!desc)
699  return AVERROR(EINVAL);
700 
701  if (avctx->codec_id == AV_CODEC_ID_H264) {
702  dec_caps->pNext = h264_caps;
703  usage->pNext = h264_profile;
704  h264_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR;
705 
706  /* Vulkan transmits all the constrant_set flags, rather than wanting them
707  * merged in the profile IDC */
708  h264_profile->stdProfileIdc = cur_profile & ~(AV_PROFILE_H264_CONSTRAINED |
710 
711  h264_profile->pictureLayout = avctx->field_order == AV_FIELD_UNKNOWN ||
713  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR :
714  VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_KHR;
715  } else if (avctx->codec_id == AV_CODEC_ID_H265) {
716  dec_caps->pNext = h265_caps;
717  usage->pNext = h265_profile;
718  h265_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_INFO_KHR;
719  h265_profile->stdProfileIdc = cur_profile;
720  } else if (avctx->codec_id == AV_CODEC_ID_AV1) {
721  dec_caps->pNext = av1_caps;
722  usage->pNext = av1_profile;
723  av1_profile->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_PROFILE_INFO_KHR;
724  av1_profile->stdProfile = cur_profile;
725  av1_profile->filmGrainSupport = !(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN);
726  }
727 
728  usage->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_USAGE_INFO_KHR;
729  usage->videoUsageHints = VK_VIDEO_DECODE_USAGE_DEFAULT_KHR;
730 
731  profile->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR;
732  profile->pNext = usage;
733  profile->videoCodecOperation = vk_desc->decode_op;
734  profile->chromaSubsampling = ff_vk_subsampling_from_av_desc(desc);
735  profile->lumaBitDepth = ff_vk_depth_from_av_depth(desc->comp[0].depth);
736  profile->chromaBitDepth = profile->lumaBitDepth;
737 
738  profile_list->sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
739  profile_list->profileCount = 1;
740  profile_list->pProfiles = profile;
741 
742  /* Get the capabilities of the decoder for the given profile */
743  caps->sType = VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR;
744  caps->pNext = dec_caps;
745  dec_caps->sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR;
746  /* dec_caps->pNext already filled in */
747 
748  return vk->GetPhysicalDeviceVideoCapabilitiesKHR(hwctx->phys_dev, profile,
749  caps);
750 }
751 
752 static int vulkan_decode_get_profile(AVCodecContext *avctx, AVBufferRef *frames_ref,
753  enum AVPixelFormat *pix_fmt, VkFormat *vk_fmt,
755  int *dpb_dedicate)
756 {
757  VkResult ret;
758  int max_level, base_profile, cur_profile;
759  const FFVulkanDecodeDescriptor *vk_desc = get_codecdesc(avctx->codec_id);
761  AVHWDeviceContext *device = (AVHWDeviceContext *)frames->device_ref->data;
762  AVVulkanDeviceContext *hwctx = device->hwctx;
763  enum AVPixelFormat source_format;
764  enum AVPixelFormat best_format;
765  VkFormat best_vkfmt;
766 
769  FFVulkanFunctions *vk = &ctx->s.vkfn;
770 
771  VkVideoCapabilitiesKHR *caps = &ctx->caps;
772  VkVideoDecodeCapabilitiesKHR *dec_caps = &ctx->dec_caps;
773 
774  VkVideoDecodeH264CapabilitiesKHR h264_caps = {
775  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_KHR,
776  };
777  VkVideoDecodeH265CapabilitiesKHR h265_caps = {
778  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_KHR,
779  };
780  VkVideoDecodeAV1CapabilitiesKHR av1_caps = {
781  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_CAPABILITIES_KHR,
782  };
783 
784  VkPhysicalDeviceVideoFormatInfoKHR fmt_info = {
785  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR,
786  .pNext = &prof->profile_list,
787  };
788  VkVideoFormatPropertiesKHR *ret_info;
789  uint32_t nb_out_fmts = 0;
790 
791  if (!(vk_desc->decode_extension & ctx->s.extensions)) {
792  av_log(avctx, AV_LOG_ERROR, "Device does not support decoding %s!\n",
793  avcodec_get_name(avctx->codec_id));
794  return AVERROR(ENOSYS);
795  }
796 
797  cur_profile = avctx->profile;
800  avctx->codec_id == AV_CODEC_ID_AV1 ? STD_VIDEO_AV1_PROFILE_MAIN :
801  0;
802 
803  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
804  &h264_caps,
805  &h265_caps,
806  &av1_caps,
807  caps,
808  dec_caps,
809  cur_profile);
810  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR &&
812  avctx->profile != base_profile) {
813  av_log(avctx, AV_LOG_VERBOSE, "%s profile %s not supported, attempting "
814  "again with profile %s\n",
815  avcodec_get_name(avctx->codec_id),
816  avcodec_profile_name(avctx->codec_id, cur_profile),
817  avcodec_profile_name(avctx->codec_id, base_profile));
818  cur_profile = base_profile;
819  ret = vulkan_setup_profile(avctx, prof, hwctx, vk, vk_desc,
820  &h264_caps,
821  &h265_caps,
822  &av1_caps,
823  caps,
824  dec_caps,
825  cur_profile);
826  }
827 
828  if (ret == VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR) {
829  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
830  "%s profile \"%s\" not supported!\n",
831  avcodec_get_name(avctx->codec_id),
832  avcodec_profile_name(avctx->codec_id, cur_profile));
833  return AVERROR(EINVAL);
834  } else if (ret == VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR) {
835  av_log(avctx, AV_LOG_VERBOSE, "Unable to initialize video session: "
836  "format (%s) not supported!\n",
838  return AVERROR(EINVAL);
839  } else if (ret == VK_ERROR_FEATURE_NOT_PRESENT ||
840  ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
841  return AVERROR(EINVAL);
842  } else if (ret != VK_SUCCESS) {
843  return AVERROR_EXTERNAL;
844  }
845 
846  max_level = avctx->codec_id == AV_CODEC_ID_H264 ? ff_vk_h264_level_to_av(h264_caps.maxLevelIdc) :
847  avctx->codec_id == AV_CODEC_ID_H265 ? ff_vk_h265_level_to_av(h265_caps.maxLevelIdc) :
848  avctx->codec_id == AV_CODEC_ID_AV1 ? av1_caps.maxLevel :
849  0;
850 
851  av_log(avctx, AV_LOG_VERBOSE, "Decoder capabilities for %s profile \"%s\":\n",
852  avcodec_get_name(avctx->codec_id),
853  avcodec_profile_name(avctx->codec_id, cur_profile));
854  av_log(avctx, AV_LOG_VERBOSE, " Maximum level: %i (stream %i)\n",
855  max_level, avctx->level);
856  av_log(avctx, AV_LOG_VERBOSE, " Width: from %i to %i\n",
857  caps->minCodedExtent.width, caps->maxCodedExtent.width);
858  av_log(avctx, AV_LOG_VERBOSE, " Height: from %i to %i\n",
859  caps->minCodedExtent.height, caps->maxCodedExtent.height);
860  av_log(avctx, AV_LOG_VERBOSE, " Width alignment: %i\n",
861  caps->pictureAccessGranularity.width);
862  av_log(avctx, AV_LOG_VERBOSE, " Height alignment: %i\n",
863  caps->pictureAccessGranularity.height);
864  av_log(avctx, AV_LOG_VERBOSE, " Bitstream offset alignment: %"PRIu64"\n",
865  caps->minBitstreamBufferOffsetAlignment);
866  av_log(avctx, AV_LOG_VERBOSE, " Bitstream size alignment: %"PRIu64"\n",
867  caps->minBitstreamBufferSizeAlignment);
868  av_log(avctx, AV_LOG_VERBOSE, " Maximum references: %u\n",
869  caps->maxDpbSlots);
870  av_log(avctx, AV_LOG_VERBOSE, " Maximum active references: %u\n",
871  caps->maxActiveReferencePictures);
872  av_log(avctx, AV_LOG_VERBOSE, " Codec header name: '%s' (driver), '%s' (compiled)\n",
873  caps->stdHeaderVersion.extensionName,
874  vk_desc->ext_props.extensionName);
875  av_log(avctx, AV_LOG_VERBOSE, " Codec header version: %i.%i.%i (driver), %i.%i.%i (compiled)\n",
876  CODEC_VER(caps->stdHeaderVersion.specVersion),
877  CODEC_VER(vk_desc->ext_props.specVersion));
878  av_log(avctx, AV_LOG_VERBOSE, " Decode modes:%s%s%s\n",
879  dec_caps->flags ? "" :
880  " invalid",
881  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR ?
882  " reuse_dst_dpb" : "",
883  dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR ?
884  " dedicated_dpb" : "");
885  av_log(avctx, AV_LOG_VERBOSE, " Capability flags:%s%s%s\n",
886  caps->flags ? "" :
887  " none",
888  caps->flags & VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR ?
889  " protected" : "",
890  caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR ?
891  " separate_references" : "");
892 
893  /* Check if decoding is possible with the given parameters */
894  if (avctx->coded_width < caps->minCodedExtent.width ||
895  avctx->coded_height < caps->minCodedExtent.height ||
896  avctx->coded_width > caps->maxCodedExtent.width ||
897  avctx->coded_height > caps->maxCodedExtent.height)
898  return AVERROR(EINVAL);
899 
901  avctx->level > max_level)
902  return AVERROR(EINVAL);
903 
904  /* Some basic sanity checking */
905  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  av_log(avctx, AV_LOG_ERROR, "Buggy driver signals invalid decoding mode: neither "
908  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR nor "
909  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR are set!\n");
910  return AVERROR_EXTERNAL;
911  } else if ((dec_caps->flags & (VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR |
912  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR) ==
913  VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR) &&
914  !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR)) {
915  av_log(avctx, AV_LOG_ERROR, "Cannot initialize Vulkan decoding session, buggy driver: "
916  "VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR set "
917  "but VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR is unset!\n");
918  return AVERROR_EXTERNAL;
919  }
920 
921  dec->dedicated_dpb = !(dec_caps->flags & VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR);
922  ctx->common.layered_dpb = !dec->dedicated_dpb ? 0 :
923  !(caps->flags & VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR);
924 
925  if (dec->dedicated_dpb) {
926  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
927  } else {
928  fmt_info.imageUsage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
929  VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
930  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
931  VK_IMAGE_USAGE_SAMPLED_BIT;
932 
933  if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
935  fmt_info.imageUsage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
936  }
937 
938  /* Get the format of the images necessary */
939  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
940  &fmt_info,
941  &nb_out_fmts, NULL);
942  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
943  (!nb_out_fmts && ret == VK_SUCCESS)) {
944  return AVERROR(EINVAL);
945  } else if (ret != VK_SUCCESS) {
946  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
947  ff_vk_ret2str(ret));
948  return AVERROR_EXTERNAL;
949  }
950 
951  ret_info = av_mallocz(sizeof(*ret_info)*nb_out_fmts);
952  if (!ret_info)
953  return AVERROR(ENOMEM);
954 
955  for (int i = 0; i < nb_out_fmts; i++)
956  ret_info[i].sType = VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR;
957 
958  ret = vk->GetPhysicalDeviceVideoFormatPropertiesKHR(hwctx->phys_dev,
959  &fmt_info,
960  &nb_out_fmts, ret_info);
961  if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED ||
962  (!nb_out_fmts && ret == VK_SUCCESS)) {
963  av_free(ret_info);
964  return AVERROR(EINVAL);
965  } else if (ret != VK_SUCCESS) {
966  av_log(avctx, AV_LOG_ERROR, "Unable to get Vulkan format properties: %s!\n",
967  ff_vk_ret2str(ret));
968  av_free(ret_info);
969  return AVERROR_EXTERNAL;
970  }
971 
972  /* Find a format to use */
973  *pix_fmt = best_format = AV_PIX_FMT_NONE;
974  *vk_fmt = best_vkfmt = VK_FORMAT_UNDEFINED;
975  source_format = avctx->sw_pix_fmt;
976 
977  av_log(avctx, AV_LOG_DEBUG, "Choosing best pixel format for decoding from %i:\n", nb_out_fmts);
978  for (int i = 0; i < nb_out_fmts; i++) {
980  if (tmp == AV_PIX_FMT_NONE) {
981  av_log(avctx, AV_LOG_WARNING, "Invalid/unknown Vulkan format %i!\n", ret_info[i].format);
982  continue;
983  }
984 
985  best_format = av_find_best_pix_fmt_of_2(tmp, best_format, source_format, 0, NULL);
986  if (tmp == best_format)
987  best_vkfmt = ret_info[i].format;
988 
989  av_log(avctx, AV_LOG_DEBUG, " %s%s (Vulkan ID: %i)\n",
990  av_get_pix_fmt_name(tmp), tmp == best_format ? "*" : "",
991  ret_info[i].format);
992  }
993 
994  av_free(ret_info);
995 
996  if (best_format == AV_PIX_FMT_NONE) {
997  av_log(avctx, AV_LOG_ERROR, "No valid/compatible pixel format found for decoding!\n");
998  return AVERROR(EINVAL);
999  } else {
1000  av_log(avctx, AV_LOG_VERBOSE, "Chosen frame pixfmt: %s (Vulkan ID: %i)\n",
1001  av_get_pix_fmt_name(best_format), best_vkfmt);
1002  }
1003 
1004  *pix_fmt = best_format;
1005  *vk_fmt = best_vkfmt;
1006 
1007  *dpb_dedicate = dec->dedicated_dpb;
1008 
1009  return 0;
1010 }
1011 
1013 {
1014  av_free(hwfc->user_opaque);
1015 }
1016 
1017 int ff_vk_frame_params(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx)
1018 {
1019  VkFormat vkfmt = VK_FORMAT_UNDEFINED;
1020  int err, dedicated_dpb;
1021  AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data;
1022  AVVulkanFramesContext *hwfc = frames_ctx->hwctx;
1025 
1026  err = vulkan_decode_bootstrap(avctx, hw_frames_ctx);
1027  if (err < 0)
1028  return err;
1029 
1030  frames_ctx->sw_format = avctx->sw_pix_fmt;
1031 
1032  if (!DECODER_IS_SDR(avctx->codec_id)) {
1033  prof = av_mallocz(sizeof(FFVulkanDecodeProfileData));
1034  if (!prof)
1035  return AVERROR(ENOMEM);
1036 
1037  err = vulkan_decode_get_profile(avctx, hw_frames_ctx,
1038  &frames_ctx->sw_format, &vkfmt,
1039  prof, &dedicated_dpb);
1040  if (err < 0) {
1041  av_free(prof);
1042  return err;
1043  }
1044 
1045  frames_ctx->user_opaque = prof;
1046  frames_ctx->free = free_profile_data;
1047 
1048  hwfc->create_pnext = &prof->profile_list;
1049  } else {
1050  switch (frames_ctx->sw_format) {
1051  case AV_PIX_FMT_GBRAP16:
1052  /* This should be more efficient for downloading and using */
1053  frames_ctx->sw_format = AV_PIX_FMT_RGBA64;
1054  break;
1055  case AV_PIX_FMT_GBRP10:
1056  /* This saves memory bandwidth when downloading */
1057  frames_ctx->sw_format = AV_PIX_FMT_X2BGR10;
1058  break;
1059  case AV_PIX_FMT_BGR0:
1060  /* mpv has issues with bgr0 mapping, so just remap it */
1061  frames_ctx->sw_format = AV_PIX_FMT_RGB0;
1062  break;
1063  default:
1064  break;
1065  }
1066  }
1067 
1068  frames_ctx->width = avctx->coded_width;
1069  frames_ctx->height = avctx->coded_height;
1070  frames_ctx->format = AV_PIX_FMT_VULKAN;
1071 
1072  hwfc->format[0] = vkfmt;
1073  hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1074  hwfc->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1075  VK_IMAGE_USAGE_STORAGE_BIT |
1076  VK_IMAGE_USAGE_SAMPLED_BIT;
1077 
1078  if (prof) {
1080 
1081  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR;
1082  if (!dec->dedicated_dpb)
1083  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR;
1084 
1085  ctx = dec->shared_ctx;
1086  if (ctx->s.extensions & (FF_VK_EXT_VIDEO_ENCODE_QUEUE |
1088  hwfc->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
1089  }
1090 
1091  return err;
1092 }
1093 
1094 static void vk_decode_free_params(void *opaque, uint8_t *data)
1095 {
1096  FFVulkanDecodeShared *ctx = opaque;
1097  FFVulkanFunctions *vk = &ctx->s.vkfn;
1098  VkVideoSessionParametersKHR *par = (VkVideoSessionParametersKHR *)data;
1099  vk->DestroyVideoSessionParametersKHR(ctx->s.hwctx->act_dev, *par,
1100  ctx->s.hwctx->alloc);
1101  av_free(par);
1102 }
1103 
1105  const VkVideoSessionParametersCreateInfoKHR *session_params_create)
1106 {
1107  VkVideoSessionParametersKHR *par = av_malloc(sizeof(*par));
1108  const FFVulkanFunctions *vk = &ctx->s.vkfn;
1109  VkResult ret;
1110 
1111  if (!par)
1112  return AVERROR(ENOMEM);
1113 
1114  /* Create session parameters */
1115  ret = vk->CreateVideoSessionParametersKHR(ctx->s.hwctx->act_dev, session_params_create,
1116  ctx->s.hwctx->alloc, par);
1117  if (ret != VK_SUCCESS) {
1118  av_log(logctx, AV_LOG_ERROR, "Unable to create Vulkan video session parameters: %s!\n",
1119  ff_vk_ret2str(ret));
1120  av_free(par);
1121  return AVERROR_EXTERNAL;
1122  }
1123  *par_ref = av_buffer_create((uint8_t *)par, sizeof(*par),
1125  if (!*par_ref) {
1126  vk_decode_free_params(ctx, (uint8_t *)par);
1127  return AVERROR(ENOMEM);
1128  }
1129 
1130  return 0;
1131 }
1132 
1134 {
1136 
1137  av_freep(&dec->hevc_headers);
1140  av_freep(&dec->slice_off);
1141  return 0;
1142 }
1143 
1146 {
1147  VkResult ret;
1148  FFVulkanContext *s = &ctx->s;
1149  FFVulkanFunctions *vk = &s->vkfn;
1150 
1151  VkVideoDecodeH264SessionParametersCreateInfoKHR h264_params = {
1152  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_KHR,
1153  };
1154  VkVideoDecodeH265SessionParametersCreateInfoKHR h265_params = {
1155  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_KHR,
1156  };
1157  StdVideoAV1SequenceHeader av1_empty_seq = { 0 };
1158  VkVideoDecodeAV1SessionParametersCreateInfoKHR av1_params = {
1159  .sType = VK_STRUCTURE_TYPE_VIDEO_DECODE_AV1_SESSION_PARAMETERS_CREATE_INFO_KHR,
1160  .pStdSequenceHeader = &av1_empty_seq,
1161  };
1162  VkVideoSessionParametersCreateInfoKHR session_params_create = {
1163  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR,
1164  .pNext = avctx->codec_id == AV_CODEC_ID_H264 ? (void *)&h264_params :
1165  avctx->codec_id == AV_CODEC_ID_HEVC ? (void *)&h265_params :
1166  avctx->codec_id == AV_CODEC_ID_AV1 ? (void *)&av1_params :
1167  NULL,
1168  .videoSession = ctx->common.session,
1169  };
1170 
1171  ret = vk->CreateVideoSessionParametersKHR(s->hwctx->act_dev, &session_params_create,
1172  s->hwctx->alloc, &ctx->empty_session_params);
1173  if (ret != VK_SUCCESS) {
1174  av_log(avctx, AV_LOG_ERROR, "Unable to create empty Vulkan video session parameters: %s!\n",
1175  ff_vk_ret2str(ret));
1176  return AVERROR_EXTERNAL;
1177  }
1178 
1179  return 0;
1180 }
1181 
1183 {
1184  int err;
1187  FFVulkanContext *s;
1188  int async_depth;
1189  const VkVideoProfileInfoKHR *profile;
1190  const FFVulkanDecodeDescriptor *vk_desc;
1191  const VkPhysicalDeviceDriverProperties *driver_props;
1192 
1193  VkVideoSessionCreateInfoKHR session_create = {
1194  .sType = VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR,
1195  };
1196 
1198  if (err < 0)
1199  return err;
1200 
1201  /* Initialize contexts */
1202  ctx = dec->shared_ctx;
1203  s = &ctx->s;
1204 
1205  err = ff_vk_init(s, avctx, NULL, avctx->hw_frames_ctx);
1206  if (err < 0)
1207  return err;
1208 
1209  vk_desc = get_codecdesc(avctx->codec_id);
1210 
1212  if ((vk_desc->queue_flags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) && !profile) {
1213  av_log(avctx, AV_LOG_ERROR, "Video profile missing from frames context!");
1214  return AVERROR(EINVAL);
1215  }
1216 
1217  /* Create queue context */
1218  vk_desc = get_codecdesc(avctx->codec_id);
1219  ctx->qf = ff_vk_qf_find(s, vk_desc->queue_flags, vk_desc->decode_op);
1220  if (!ctx->qf) {
1221  av_log(avctx, AV_LOG_ERROR, "Decoding of %s is not supported by this device\n",
1222  avcodec_get_name(avctx->codec_id));
1223  return err;
1224  }
1225 
1226  session_create.queueFamilyIndex = ctx->qf->idx;
1227  session_create.maxCodedExtent = ctx->caps.maxCodedExtent;
1228  session_create.maxDpbSlots = ctx->caps.maxDpbSlots;
1229  session_create.maxActiveReferencePictures = ctx->caps.maxActiveReferencePictures;
1230  session_create.pictureFormat = s->hwfc->format[0];
1231  session_create.referencePictureFormat = session_create.pictureFormat;
1232  session_create.pStdHeaderVersion = &vk_desc->ext_props;
1233  session_create.pVideoProfile = profile;
1234 #ifdef VK_KHR_video_maintenance2
1235  if (ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)
1236  session_create.flags = VK_VIDEO_SESSION_CREATE_INLINE_SESSION_PARAMETERS_BIT_KHR;
1237 #endif
1238 
1239  /* Create decode exec context for this specific main thread.
1240  * 2 async contexts per thread was experimentally determined to be optimal
1241  * for a majority of streams. */
1242  async_depth = 2*ctx->qf->num;
1243  /* We don't need more than 2 per thread context */
1244  async_depth = FFMIN(async_depth, 2*avctx->thread_count);
1245  /* Make sure there are enough async contexts for each thread */
1246  async_depth = FFMAX(async_depth, avctx->thread_count);
1247 
1248  err = ff_vk_exec_pool_init(s, ctx->qf, &ctx->exec_pool,
1249  async_depth, 0, 0, 0, profile);
1250  if (err < 0)
1251  goto fail;
1252 
1253  if (!DECODER_IS_SDR(avctx->codec_id)) {
1254  err = ff_vk_video_common_init(avctx, s, &ctx->common, &session_create);
1255  if (err < 0)
1256  goto fail;
1257  }
1258 
1259  /* If doing an out-of-place decoding, create a DPB pool */
1260  if (dec->dedicated_dpb || avctx->codec_id == AV_CODEC_ID_AV1) {
1262  AVVulkanFramesContext *dpb_hwfc;
1263 
1264  ctx->common.dpb_hwfc_ref = av_hwframe_ctx_alloc(s->frames->device_ref);
1265  if (!ctx->common.dpb_hwfc_ref) {
1266  err = AVERROR(ENOMEM);
1267  goto fail;
1268  }
1269 
1270  dpb_frames = (AVHWFramesContext *)ctx->common.dpb_hwfc_ref->data;
1271  dpb_frames->format = s->frames->format;
1272  dpb_frames->sw_format = s->frames->sw_format;
1273  dpb_frames->width = avctx->coded_width;
1274  dpb_frames->height = avctx->coded_height;
1275 
1276  dpb_hwfc = dpb_frames->hwctx;
1277  dpb_hwfc->create_pnext = (void *)ff_vk_find_struct(ctx->s.hwfc->create_pnext,
1278  VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
1279  dpb_hwfc->format[0] = s->hwfc->format[0];
1280  dpb_hwfc->tiling = VK_IMAGE_TILING_OPTIMAL;
1281  dpb_hwfc->usage = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR |
1282  VK_IMAGE_USAGE_SAMPLED_BIT; /* Shuts validator up. */
1283 
1284  if (ctx->common.layered_dpb)
1285  dpb_hwfc->nb_layers = ctx->caps.maxDpbSlots;
1286 
1287  err = av_hwframe_ctx_init(ctx->common.dpb_hwfc_ref);
1288  if (err < 0)
1289  goto fail;
1290 
1291  if (ctx->common.layered_dpb) {
1292  ctx->common.layered_frame = vk_get_dpb_pool(ctx);
1293  if (!ctx->common.layered_frame) {
1294  err = AVERROR(ENOMEM);
1295  goto fail;
1296  }
1297 
1298  err = ff_vk_create_view(&ctx->s, &ctx->common,
1299  &ctx->common.layered_view,
1300  &ctx->common.layered_aspect,
1301  (AVVkFrame *)ctx->common.layered_frame->data[0],
1302  s->hwfc->format[0], 1);
1303  if (err < 0)
1304  goto fail;
1305  }
1306  }
1307 
1308  if (!DECODER_IS_SDR(avctx->codec_id)) {
1309  if (!(ctx->s.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_2)) {
1310  err = create_empty_session_parameters(avctx, ctx);
1311  if (err < 0)
1312  return err;
1313  }
1314  } else {
1315  /* For SDR decoders, this alignment value will be 0. Since this will make
1316  * add_slice() malfunction, set it to a sane default value. */
1317  ctx->caps.minBitstreamBufferSizeAlignment = AV_INPUT_BUFFER_PADDING_SIZE;
1318  }
1319 
1320  driver_props = &dec->shared_ctx->s.driver_props;
1321  if (driver_props->driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
1322  driver_props->conformanceVersion.major == 1 &&
1323  driver_props->conformanceVersion.minor == 3 &&
1324  driver_props->conformanceVersion.subminor == 8 &&
1325  driver_props->conformanceVersion.patch < 3)
1326  dec->quirk_av1_offset = 1;
1327 
1328  ff_vk_decode_flush(avctx);
1329 
1330  av_log(avctx, AV_LOG_VERBOSE, "Vulkan decoder initialization sucessful\n");
1331 
1332  return 0;
1333 
1334 fail:
1335  ff_vk_decode_uninit(avctx);
1336 
1337  return err;
1338 }
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:216
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:205
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:210
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:318
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:56
AV_PROFILE_HEVC_MAIN
#define AV_PROFILE_HEVC_MAIN
Definition: defs.h:159
FFVulkanDecodePicture::invalidate_memory_ranges
PFN_vkInvalidateMappedMemoryRanges invalidate_memory_ranges
Definition: vulkan_decode.h:117
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:821
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:63
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:333
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
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:259
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:682
AVVulkanFramesContext::create_pnext
void * create_pnext
Extension data for image creation.
Definition: hwcontext_vulkan.h:238
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:330
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:1144
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:250
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:226
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:2935
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:509
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2924
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: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:741
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:148
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:1986
FFVkShaderRepFormat
FFVkShaderRepFormat
Returns the format to use for images in shaders.
Definition: vulkan.h:402
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:431
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:302
FFVulkanDecodeDescriptor::decode_op
VkVideoCodecOperationFlagBitsKHR decode_op
Definition: vulkan_decode.h:33
fail
#define fail()
Definition: checkasm.h:196
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:1561
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
FFVulkanDecodePicture::view
struct FFVulkanDecodePicture::@315 view
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:208
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:488
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:607
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:369
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:752
init_frame
static void init_frame(FFVulkanDecodeContext *dec, FFVulkanDecodePicture *vkpic)
Definition: vulkan_decode.c:131
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:51
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:210
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:209
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:324
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:1104
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:840
offsets
static const int offsets[]
Definition: hevc_pel.c:34
FFVulkanContext::driver_props
VkPhysicalDeviceDriverProperties driver_props
Definition: vulkan.h:282
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1416
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:112
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:231
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:581
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:251
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:1043
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition: avcodec.h:441
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
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
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:575
tmp
static uint8_t tmp[20]
Definition: aes_ctr.c:47
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:294
FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
Definition: vulkan_functions.h:63
AVCodecContext::internal
struct AVCodecInternal * internal
Private context used for internal data.
Definition: avcodec.h:466
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:2006
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:1133
AVVulkanFramesContext::format
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
Definition: hwcontext_vulkan.h:268
FFVkBuffer::size
size_t size
Definition: vulkan.h:91
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:227
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:100
FFVulkanContext
Definition: vulkan.h:274
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:1017
AVCodecContext::level
int level
Encoding level descriptor.
Definition: avcodec.h:1628
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:1839
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:608
FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
Definition: vulkan_functions.h:55
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:87
AVVkFrame
Definition: hwcontext_vulkan.h:297
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:613
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:361
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
FFVkExecContext
Definition: vulkan.h:111
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:1094
FFVulkanDecodeProfileData
Definition: vulkan_decode.h:38
FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
Definition: vulkan_functions.h:58
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:521
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:1484
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:57
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
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
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:1453
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:333
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:252
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:238
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:122
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:707
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:431
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:39
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:1618
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:1774
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:110
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:217
vulkan_video.h
AVCodecContext::coded_width
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:607
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:273
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:327
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:980
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:677
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FFVkBuffer
Definition: vulkan.h:87
vk_get_dpb_pool
static AVFrame * vk_get_dpb_pool(FFVulkanDecodeShared *ctx)
Definition: vulkan_decode.c:117
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:866
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:636
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:1182
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:638
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:502
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
FFVulkanFunctions
Definition: vulkan_functions.h:268
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:1216
src
#define src
Definition: vp8dsp.c:248
free_profile_data
static void free_profile_data(AVHWFramesContext *hwfc)
Definition: vulkan_decode.c:1012
AV_CODEC_EXPORT_DATA_FILM_GRAIN
#define AV_CODEC_EXPORT_DATA_FILM_GRAIN
Decoding only.
Definition: avcodec.h:400
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