FFmpeg
hwcontext_cuda.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 "buffer.h"
20 #include "common.h"
21 #include "hwcontext.h"
22 #include "hwcontext_internal.h"
24 #if CONFIG_VULKAN
25 #include "hwcontext_vulkan.h"
26 #endif
27 #include "cuda_check.h"
28 #include "mem.h"
29 #include "pixdesc.h"
30 #include "pixfmt.h"
31 #include "imgutils.h"
32 
33 typedef struct CUDAFramesContext {
35 
38 
41 
42 typedef struct CUDADeviceContext {
46 
47 
48 
49 #define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
50 
51 static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt);
52 
54  const void *hwconfig,
55  AVHWFramesConstraints *constraints)
56 {
57  const AVCUDAHWConfig *config = hwconfig;
58  enum AVPixelFormat req_fmt = config ? config->hw_format : AV_PIX_FMT_NONE;
59  int n = 0;
60 
61  if (req_fmt == AV_PIX_FMT_CUDA || req_fmt == AV_PIX_FMT_CUARRAY) {
62  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
63  if (!constraints->valid_hw_formats)
64  return AVERROR(ENOMEM);
65 
66  constraints->valid_hw_formats[0] = req_fmt;
67  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
68  } else {
69  constraints->valid_hw_formats = av_malloc_array(2 + HAVE_FFNVCODEC_CUARRAY, sizeof(*constraints->valid_hw_formats));
70  if (!constraints->valid_hw_formats)
71  return AVERROR(ENOMEM);
72 
73  constraints->valid_hw_formats[0] = AV_PIX_FMT_CUDA;
74 #if HAVE_FFNVCODEC_CUARRAY
75  constraints->valid_hw_formats[1] = AV_PIX_FMT_CUARRAY;
76  constraints->valid_hw_formats[2] = AV_PIX_FMT_NONE;
77 #else
78  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
79 #endif
80  }
81 
83  sizeof(*constraints->valid_sw_formats));
84  if (!constraints->valid_sw_formats)
85  return AVERROR(ENOMEM);
86 
87  n = 0;
88  for (int i = 0; i < AV_PIX_FMT_NB; i++) {
89  if (req_fmt == AV_PIX_FMT_CUARRAY) {
91  constraints->valid_sw_formats[n++] = i;
92  } else {
94  /* Palette formats carry their palette in a separate zero-linesize
95  * data[1] plane that the transfer path does not handle, so exclude
96  * them along with the hwaccel formats. */
98  constraints->valid_sw_formats[n++] = i;
99  }
100  }
101 #if CONFIG_VULKAN
102  if (req_fmt != AV_PIX_FMT_CUARRAY)
103  constraints->valid_sw_formats[n++] = AV_PIX_FMT_VULKAN;
104 #endif
105  constraints->valid_sw_formats[n] = AV_PIX_FMT_NONE;
106 
107  return 0;
108 }
109 
110 static void cuda_buffer_free(void *opaque, uint8_t *data)
111 {
112  AVHWFramesContext *ctx = opaque;
113  AVHWDeviceContext *device_ctx = ctx->device_ctx;
114  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
115  CudaFunctions *cu = hwctx->internal->cuda_dl;
116 
117  CUcontext dummy;
118 
119  CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
120 
121  if (ctx->format == AV_PIX_FMT_CUARRAY) {
123  CHECK_CU(cu->cuArrayDestroy(desc->array));
124  av_free(desc);
125  } else {
126  CHECK_CU(cu->cuMemFree((CUdeviceptr)data));
127  }
128 
129  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
130 }
131 
132 static AVBufferRef *cuda_pool_alloc(void *opaque, size_t size)
133 {
134  AVHWFramesContext *ctx = opaque;
135  CUDAFramesContext *priv = ctx->hwctx;
136  AVHWDeviceContext *device_ctx = ctx->device_ctx;
137  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
138  CudaFunctions *cu = hwctx->internal->cuda_dl;
139 
140  AVBufferRef *ret = NULL;
141  CUcontext dummy = NULL;
142  CUdeviceptr data;
143  int err;
144 
145  err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
146  if (err < 0)
147  return NULL;
148 
149  if (ctx->format == AV_PIX_FMT_CUARRAY) {
151  if (!desc)
152  goto done;
153 
154  if (priv->p.cuarray_num_surfaces > 0) {
155  if (priv->cuarray_num_surfaces_used >= priv->p.cuarray_num_surfaces) {
156  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
157  av_free(desc);
158  goto done;
159  }
160  desc->index = priv->cuarray_num_surfaces_used++;
161  desc->array = priv->p.cuarray_surfaces[desc->index];
162  } else {
163  err = CHECK_CU(cu->cuArray3DCreate(&desc->array, &priv->p.cuarray_desc));
164  if (err < 0) {
165  av_free(desc);
166  goto done;
167  }
168  }
169 
170  ret = av_buffer_create((uint8_t*)desc, sizeof(*desc), cuda_buffer_free, ctx, 0);
171  if (!ret) {
172  // It is okay (and necessary) to free a pool array here,
173  // since cuarray_num_surfaces_used is already incremented.
174  CHECK_CU(cu->cuArrayDestroy(desc->array));
175  av_free(desc);
176  goto done;
177  }
178 
179  goto done;
180  }
181 
182  err = CHECK_CU(cu->cuMemAlloc(&data, size));
183  if (err < 0)
184  goto done;
185 
186  ret = av_buffer_create((uint8_t*)data, size, cuda_buffer_free, ctx, 0);
187  if (!ret) {
188  CHECK_CU(cu->cuMemFree(data));
189  goto done;
190  }
191 
192  // Common exit: reached on both success (ret holds the buffer) and
193  // failure (ret == NULL); restores the CUDA context and returns ret.
194 done:
195  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
196  return ret;
197 }
198 
200 {
201  AVHWDeviceContext *device_ctx = ctx->device_ctx;
202  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
203  CUDAFramesContext *priv = ctx->hwctx;
204  CudaFunctions *cu = hwctx->internal->cuda_dl;
205 
206  if (priv->p.cuarray_surfaces) {
207  CUcontext dummy;
208  CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
209 
210  // Make sure we don't free surfaces that have been adopted by the pool already
211  for (int i = priv->cuarray_num_surfaces_used; i < priv->p.cuarray_num_surfaces; i++)
212  if (priv->p.cuarray_surfaces[i])
213  CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
214 
215  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
216 
217  av_freep(&priv->p.cuarray_surfaces);
218  priv->p.cuarray_num_surfaces = 0;
219  }
220 }
221 
222 static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt)
223 {
224  switch (fmt) {
225 #if HAVE_FFNVCODEC_CUARRAY
226  case AV_PIX_FMT_NV12: return CU_AD_FORMAT_NV12;
227  case AV_PIX_FMT_P010:
228  case AV_PIX_FMT_P012:
229  case AV_PIX_FMT_P016: return CU_AD_FORMAT_P016;
230  case AV_PIX_FMT_NV16: return CU_AD_FORMAT_NV16;
231  case AV_PIX_FMT_P210:
232  case AV_PIX_FMT_P212:
233  case AV_PIX_FMT_P216: return CU_AD_FORMAT_P216;
234  case AV_PIX_FMT_NV24: return CU_AD_FORMAT_YUV444_8BIT_SEMIPLANAR;
235  case AV_PIX_FMT_P410:
236  case AV_PIX_FMT_P412:
237  case AV_PIX_FMT_P416: return CU_AD_FORMAT_YUV444_16BIT_SEMIPLANAR;
238  case AV_PIX_FMT_YUV420P: return CU_AD_FORMAT_UINT8_PLANAR_420;
239  case AV_PIX_FMT_YUV422P: return CU_AD_FORMAT_UINT8_PLANAR_422;
240  case AV_PIX_FMT_YUV444P: return CU_AD_FORMAT_UINT8_PLANAR_444;
241  case AV_PIX_FMT_YUV420P10: return CU_AD_FORMAT_UINT16_PLANAR_420;
242  case AV_PIX_FMT_YUV422P10: return CU_AD_FORMAT_UINT16_PLANAR_422;
246  case AV_PIX_FMT_YUV444P16: return CU_AD_FORMAT_UINT16_PLANAR_444;
247  case AV_PIX_FMT_0RGB32:
248  case AV_PIX_FMT_0BGR32:
249  case AV_PIX_FMT_RGB32:
250  case AV_PIX_FMT_BGR32: return CU_AD_FORMAT_UNSIGNED_INT8;
251 #endif
252  default: return 0;
253  }
254 }
255 
256 #if HAVE_FFNVCODEC_CUARRAY
257 static unsigned int cuda_array_numchannels_for_pix_fmt(enum AVPixelFormat fmt)
258 {
259  switch (fmt) {
260  case AV_PIX_FMT_0RGB32:
261  case AV_PIX_FMT_0BGR32:
262  case AV_PIX_FMT_RGB32:
263  case AV_PIX_FMT_BGR32: return 4;
264  default: return 3;
265  }
266 }
267 #endif
268 
270 {
271  AVHWDeviceContext *device_ctx = ctx->device_ctx;
272  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
273  CUDAFramesContext *priv = ctx->hwctx;
274  CudaFunctions *cu = hwctx->internal->cuda_dl;
275  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ctx->sw_format);
276  int err;
277 
278  if (!desc) {
279  av_log(ctx, AV_LOG_ERROR, "Invalid pixel format\n");
280  return AVERROR(EINVAL);
281  }
282 
283  /* Palette formats keep their palette in a separate zero-linesize plane
284  * that the transfer path does not copy, so they are not supported. */
285  if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
286  av_log(ctx, AV_LOG_ERROR, "Palette formats are not supported\n");
287  return AVERROR(ENOSYS);
288  }
289 
290 #if HAVE_FFNVCODEC_CUARRAY
291  if (ctx->format == AV_PIX_FMT_CUARRAY && !cu->cuArrayGetPlane) {
292  av_log(ctx, AV_LOG_ERROR, "cuArrayGetPlane not available, update your driver\n");
293  return AVERROR(ENOSYS);
294  }
295 #else
296  if (ctx->format == AV_PIX_FMT_CUARRAY) {
297  av_log(ctx, AV_LOG_ERROR, "Missing support for cuarray frames. Rebuild with newer ffnvcodec headers.\n");
298  return AVERROR(ENOSYS);
299  }
300 #endif
301 
302  err = CHECK_CU(cu->cuDeviceGetAttribute(&priv->tex_alignment,
303  14 /* CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT */,
304  hwctx->internal->cuda_device));
305  if (err < 0)
306  return err;
307 
308  av_log(ctx, AV_LOG_DEBUG, "CUDA texture alignment: %d\n", priv->tex_alignment);
309 
310  // YUV420P is a special case.
311  // Since nvenc expects the U/V planes to have half the linesize of the Y plane
312  // alignment has to be doubled to ensure the U/V planes still end up aligned.
313  if (ctx->sw_format == AV_PIX_FMT_YUV420P)
314  priv->tex_alignment *= 2;
315 
316  av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height);
317 
318 #if HAVE_FFNVCODEC_CUARRAY
319  if (ctx->format == AV_PIX_FMT_CUARRAY) {
320  if (!priv->p.cuarray_desc.Width)
321  priv->p.cuarray_desc.Width = ctx->width;
322  if (!priv->p.cuarray_desc.Height)
323  priv->p.cuarray_desc.Height = ctx->height;
324  if (!priv->p.cuarray_desc.NumChannels)
325  priv->p.cuarray_desc.NumChannels = cuda_array_numchannels_for_pix_fmt(ctx->sw_format);
326 
327  if (priv->p.cuarray_desc.Depth) {
328  av_log(ctx, AV_LOG_ERROR, "CUarrays with non-zero depth are not supported.\n");
329  return AVERROR(EINVAL);
330  }
331 
332  if (!priv->p.cuarray_desc.Format)
333  priv->p.cuarray_desc.Format = cuda_array_format_for_pix_fmt(ctx->sw_format);
334  if (!priv->p.cuarray_desc.Format) {
335  av_log(ctx, AV_LOG_ERROR, "Invalid CUarray pixel format\n");
336  return AVERROR_BUG;
337  }
338 
339  priv->p.cuarray_desc.Flags |= CUDA_ARRAY3D_SURFACE_LDST | CUDA_ARRAY3D_VIDEO_ENCODE_DECODE;
340  }
341 
342  if (ctx->format == AV_PIX_FMT_CUARRAY && priv->p.cuarray_num_surfaces > 0) {
343  CUcontext dummy;
344 
345  priv->p.cuarray_surfaces = av_calloc(priv->p.cuarray_num_surfaces, sizeof(*priv->p.cuarray_surfaces));
346  if (!priv->p.cuarray_surfaces)
347  return AVERROR(ENOMEM);
348 
349  err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
350  if (err < 0) {
351  av_freep(&priv->p.cuarray_surfaces);
352  return err;
353  }
354 
355  for (int i = 0; i < priv->p.cuarray_num_surfaces; i++) {
356  err = CHECK_CU(cu->cuArray3DCreate(&priv->p.cuarray_surfaces[i], &priv->p.cuarray_desc));
357  if (err < 0) {
358  for (i = i - 1; i >= 0; i--)
359  CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
360  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
361 
362  av_freep(&priv->p.cuarray_surfaces);
363  return err;
364  }
365  }
366 
367  err = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
368  if (err < 0)
369  goto fail;
370 
371  av_log(ctx, AV_LOG_DEBUG, "allocated %d CUarray surfaces (%zux%zu)\n",
372  priv->p.cuarray_num_surfaces, priv->p.cuarray_desc.Width, priv->p.cuarray_desc.Height);
373  }
374 #endif
375 
376  if (!ctx->pool) {
377  int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
378  if (size < 0) {
379  err = size;
380  goto fail;
381  }
382 
385  if (!ffhwframesctx(ctx)->pool_internal) {
386  err = AVERROR(ENOMEM);
387  goto fail;
388  }
389  }
390 
391  return 0;
392 
393 fail:
395  return err;
396 }
397 
399 {
400  CUDAFramesContext *priv = ctx->hwctx;
401 #if HAVE_FFNVCODEC_CUARRAY
402  AVHWDeviceContext *device_ctx = ctx->device_ctx;
403  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
404  CudaFunctions *cu = hwctx->internal->cuda_dl;
405 
406  CUcontext dummy;
407 #endif
408  int res;
409 
410  frame->buf[0] = av_buffer_pool_get(ctx->pool);
411  if (!frame->buf[0])
412  return AVERROR(ENOMEM);
413 
414  if (ctx->format == AV_PIX_FMT_CUARRAY) {
415 #if HAVE_FFNVCODEC_CUARRAY
417  if (!desc) {
418  frame->format = ctx->format;
419  frame->width = ctx->width;
420  frame->height = ctx->height;
421  return 0;
422  }
423  frame->data[0] = (uint8_t*)desc->array;
424  frame->data[1] = (uint8_t*)desc->index;
425 
426  res = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
427  if (res < 0)
428  return res;
429 
430  for (int i = 0; i < FF_ARRAY_ELEMS(frame->linesize); i++) {
431  CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
432  CUarray plane_array;
433  CUresult arr_plane_res = cu->cuArrayGetPlane(&plane_array, desc->array, i);
434 
435  if (arr_plane_res == CUDA_ERROR_INVALID_VALUE) {
436  if (i > 0)
437  break;
438  /* Non-planar format (e.g. UNSIGNED_INT8 x4 for packed RGB):
439  * cuArrayGetPlane is unsupported, query the array directly. */
440  res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, desc->array));
441  if (res < 0)
442  goto fail;
443  } else if (arr_plane_res != CUDA_SUCCESS) {
444  res = CHECK_CU(arr_plane_res);
445  goto fail;
446  } else {
447  res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, plane_array));
448  if (res < 0)
449  goto fail;
450  }
451 
452  int elem_size = ff_cuda_cuarray_elem_size(plane_desc.Format);
453  if (elem_size <= 0) {
454  res = AVERROR_BUG;
455  goto fail;
456  }
457 
458  frame->linesize[i] = plane_desc.Width * plane_desc.NumChannels * elem_size;
459 
460  if (arr_plane_res == CUDA_ERROR_INVALID_VALUE)
461  break;
462  }
463 
464  res = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
465  if (res < 0)
466  return res;
467 #else
468  return AVERROR(ENOSYS);
469 #endif
470  } else {
471  res = av_image_fill_arrays(frame->data, frame->linesize, frame->buf[0]->data,
472  ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
473  if (res < 0)
474  return res;
475 
476  // YUV420P is a special case.
477  // Nvenc expects the U/V planes in swapped order from how ffmpeg expects them, also chroma is half-aligned
478  if (ctx->sw_format == AV_PIX_FMT_YUV420P) {
479  frame->linesize[1] = frame->linesize[2] = frame->linesize[0] / 2;
480  frame->data[2] = frame->data[1];
481  frame->data[1] = frame->data[2] + frame->linesize[2] * AV_CEIL_RSHIFT(ctx->height, 1);
482  }
483  }
484 
485  frame->format = ctx->format;
486  frame->width = ctx->width;
487  frame->height = ctx->height;
488 
489  return 0;
490 
491 #if HAVE_FFNVCODEC_CUARRAY
492 fail:
493  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
494  return res;
495 #endif
496 }
497 
499 {
500  if (!frame->hw_frames_ctx)
501  return AV_PIX_FMT_NONE;
502  return ((AVHWFramesContext *)frame->hw_frames_ctx->data)->format;
503 }
504 
507  enum AVPixelFormat **formats)
508 {
509  enum AVPixelFormat *fmts;
510 
511  fmts = av_malloc_array(2, sizeof(*fmts));
512  if (!fmts)
513  return AVERROR(ENOMEM);
514 
515  fmts[0] = ctx->sw_format;
516  fmts[1] = AV_PIX_FMT_NONE;
517 
518  *formats = fmts;
519 
520  return 0;
521 }
522 
524  const AVFrame *src)
525 {
526  CUDAFramesContext *priv = ctx->hwctx;
527  AVHWDeviceContext *device_ctx = ctx->device_ctx;
528  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
529  CudaFunctions *cu = hwctx->internal->cuda_dl;
530 
531  CUcontext dummy;
532  int i, ret, copy_queued = 0;
533 
534  {
535  enum AVPixelFormat src_fmt = cuda_frame_hw_format(src);
536  enum AVPixelFormat dst_fmt = cuda_frame_hw_format(dst);
537  if ((src_fmt != AV_PIX_FMT_NONE &&
538  src_fmt != AV_PIX_FMT_CUDA && src_fmt != AV_PIX_FMT_CUARRAY) ||
539  (dst_fmt != AV_PIX_FMT_NONE &&
540  dst_fmt != AV_PIX_FMT_CUDA && dst_fmt != AV_PIX_FMT_CUARRAY))
541  return AVERROR(ENOSYS);
542  }
543 
544  ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
545  if (ret < 0)
546  return ret;
547 
548  /*
549  * Copy one plane per iteration, bounded by the AVFrame linesizes. src and
550  * dst always share the same sw_format (this path never converts), so they
551  * are either both multi-planar or both single-plane.
552  *
553  * For a CUARRAY side, cuArrayGetPlane() returns the sub-array for plane i
554  * of a multi-planar CUarray (NV12, P0xx, NV24, planar 4:4:4, ...).
555  * cuArrayGetPlane() returns CUDA_ERROR_INVALID_VALUE either when the array
556  * is not multi-planar or when the plane index exceeds its plane count:
557  * - i == 0: the array is packed (e.g. RGB), i.e. a single plane, so the
558  * whole array is used as that plane.
559  * - i > 0: the planes of a multi-planar array always have a non-zero
560  * linesize, so a valid plane is never skipped by the loop bound;
561  * getting INVALID_VALUE here means src/dst disagree on the plane count,
562  * which is an inconsistency and is treated as an error (handled by the
563  * generic cures != CUDA_SUCCESS branch) rather than silently copying a
564  * subset of the planes.
565  */
566  for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->linesize[i]; i++) {
567  int src_is_nonplanar_cuarray = 0;
568  int dst_is_nonplanar_cuarray = 0;
569 
570  CUDA_MEMCPY2D cpy = {
571  .srcPitch = src->linesize[i],
572  .dstPitch = dst->linesize[i],
573  .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]),
574  .Height = AV_CEIL_RSHIFT(src->height, ((i == 0 || i == 3) ? 0 : priv->shift_height)),
575  };
576 
577  if (src->format == AV_PIX_FMT_CUDA) {
578  cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
579  cpy.srcDevice = (CUdeviceptr)src->data[i];
580  } else if (src->format == AV_PIX_FMT_CUARRAY) {
581 #if HAVE_FFNVCODEC_CUARRAY
582  CUarray array;
583  CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)src->data[0], i);
584  if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
585  /* Not a multi-planar array (packed format): the whole array is
586  * the single plane. */
587  array = (CUarray)src->data[0];
588  src_is_nonplanar_cuarray = 1;
589  } else if (cures != CUDA_SUCCESS) {
590  ret = CHECK_CU(cures);
591  goto fail;
592  }
593 
594  cpy.srcMemoryType = CU_MEMORYTYPE_ARRAY;
595  cpy.srcArray = array;
596 #else
597  ret = AVERROR(ENOSYS);
598  goto exit;
599 #endif
600  } else {
601  cpy.srcMemoryType = CU_MEMORYTYPE_HOST;
602  cpy.srcHost = src->data[i];
603  }
604 
605  if (dst->format == AV_PIX_FMT_CUDA) {
606  cpy.dstMemoryType = CU_MEMORYTYPE_DEVICE;
607  cpy.dstDevice = (CUdeviceptr)dst->data[i];
608  } else if (dst->format == AV_PIX_FMT_CUARRAY) {
609 #if HAVE_FFNVCODEC_CUARRAY
610  CUarray array;
611  CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)dst->data[0], i);
612  if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
613  /* Not a multi-planar array (packed format): the whole array is
614  * the single plane. */
615  array = (CUarray)dst->data[0];
616  dst_is_nonplanar_cuarray = 1;
617  } else if (cures != CUDA_SUCCESS) {
618  ret = CHECK_CU(cures);
619  goto fail;
620  }
621 
622  cpy.dstMemoryType = CU_MEMORYTYPE_ARRAY;
623  cpy.dstArray = array;
624 #else
625  ret = AVERROR(ENOSYS);
626  goto exit;
627 #endif
628  } else {
629  cpy.dstMemoryType = CU_MEMORYTYPE_HOST;
630  cpy.dstHost = dst->data[i];
631  }
632 
633  ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream));
634  if (ret < 0)
635  goto fail;
636  copy_queued = 1;
637 
638  if (src_is_nonplanar_cuarray || dst_is_nonplanar_cuarray)
639  break;
640  }
641 
642  if (!dst->hw_frames_ctx) {
643  ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
644  if (ret < 0)
645  goto exit;
646  }
647 
648 fail:
649  if (ret < 0 && copy_queued)
650  CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
651 exit:
652  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
653 
654  return ret;
655 }
656 
657 static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
658 {
659  CUDADeviceContext *hwctx = device_ctx->hwctx;
660 
661  if (hwctx->p.internal) {
662  CudaFunctions *cu = hwctx->internal.cuda_dl;
663 
664  if (hwctx->internal.is_allocated && hwctx->p.cuda_ctx) {
666  CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx->internal.cuda_device));
667  else if (!(hwctx->internal.flags & AV_CUDA_USE_CURRENT_CONTEXT))
668  CHECK_CU(cu->cuCtxDestroy(hwctx->p.cuda_ctx));
669 
670  hwctx->p.cuda_ctx = NULL;
671  }
672 
673  cuda_free_functions(&hwctx->internal.cuda_dl);
674  memset(&hwctx->internal, 0, sizeof(hwctx->internal));
675  hwctx->p.internal = NULL;
676  }
677 }
678 
680 {
681  CUDADeviceContext *hwctx = ctx->hwctx;
682  int ret;
683 
684  hwctx->p.internal = &hwctx->internal;
685 
686  if (!hwctx->internal.cuda_dl) {
687  ret = cuda_load_functions(&hwctx->internal.cuda_dl, ctx);
688  if (ret < 0) {
689  av_log(ctx, AV_LOG_ERROR, "Could not dynamically load CUDA\n");
690  goto error;
691  }
692  }
693 
694  return 0;
695 
696 error:
698  return ret;
699 }
700 
701 static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) {
702  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
703  CudaFunctions *cu;
704  CUcontext dummy;
705  int ret, dev_active = 0;
706  unsigned int dev_flags = 0;
707 
708  const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC;
709 
710  cu = hwctx->internal->cuda_dl;
711 
712  hwctx->internal->flags = flags;
713 
715  ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device,
716  &dev_flags, &dev_active));
717  if (ret < 0)
718  return ret;
719 
720  if (dev_active && dev_flags != desired_flags) {
721  av_log(device_ctx, AV_LOG_ERROR, "Primary context already active with incompatible flags.\n");
722  return AVERROR(ENOTSUP);
723  } else if (dev_flags != desired_flags) {
724  ret = CHECK_CU(cu->cuDevicePrimaryCtxSetFlags(hwctx->internal->cuda_device,
725  desired_flags));
726  if (ret < 0)
727  return ret;
728  }
729 
730  ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx,
731  hwctx->internal->cuda_device));
732  if (ret < 0)
733  return ret;
734  } else if (flags & AV_CUDA_USE_CURRENT_CONTEXT) {
735  ret = CHECK_CU(cu->cuCtxGetCurrent(&hwctx->cuda_ctx));
736  if (ret < 0)
737  return ret;
738  av_log(device_ctx, AV_LOG_INFO, "Using current CUDA context.\n");
739  } else {
740  ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags,
741  hwctx->internal->cuda_device));
742  if (ret < 0)
743  return ret;
744 
745  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
746  }
747 
748  hwctx->internal->is_allocated = 1;
749 
750  // Setting stream to NULL will make functions automatically use the default CUstream
751  hwctx->stream = NULL;
752 
753  return 0;
754 }
755 
757  AVDictionary *opts, int *flags)
758 {
759  AVDictionaryEntry *primary_ctx_opt = av_dict_get(opts, "primary_ctx", NULL, 0);
760  AVDictionaryEntry *current_ctx_opt = av_dict_get(opts, "current_ctx", NULL, 0);
761 
762  int use_primary_ctx = 0, use_current_ctx = 0;
763  if (primary_ctx_opt)
764  use_primary_ctx = strtol(primary_ctx_opt->value, NULL, 10);
765 
766  if (current_ctx_opt)
767  use_current_ctx = strtol(current_ctx_opt->value, NULL, 10);
768 
769  if (use_primary_ctx && use_current_ctx) {
770  av_log(device_ctx, AV_LOG_ERROR, "Requested both primary and current CUDA context simultaneously.\n");
771  return AVERROR(EINVAL);
772  }
773 
774  if (primary_ctx_opt && use_primary_ctx) {
775  av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA primary device context\n");
777  } else if (primary_ctx_opt) {
778  av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA primary device context\n");
780  }
781 
782  if (current_ctx_opt && use_current_ctx) {
783  av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA current device context\n");
785  } else if (current_ctx_opt) {
786  av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA current device context\n");
788  }
789 
790  return 0;
791 }
792 
793 static int cuda_device_create(AVHWDeviceContext *device_ctx,
794  const char *device,
795  AVDictionary *opts, int flags)
796 {
797  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
798  CudaFunctions *cu;
799  int ret, device_idx = 0;
800 
801  ret = cuda_flags_from_opts(device_ctx, opts, &flags);
802  if (ret < 0)
803  goto error;
804 
805  if (device)
806  device_idx = strtol(device, NULL, 0);
807 
808  ret = cuda_device_init(device_ctx);
809  if (ret < 0)
810  goto error;
811 
812  cu = hwctx->internal->cuda_dl;
813 
814  ret = CHECK_CU(cu->cuInit(0));
815  if (ret < 0)
816  goto error;
817 
818  ret = CHECK_CU(cu->cuDeviceGet(&hwctx->internal->cuda_device, device_idx));
819  if (ret < 0)
820  goto error;
821 
822  ret = cuda_context_init(device_ctx, flags);
823  if (ret < 0)
824  goto error;
825 
826  return 0;
827 
828 error:
829  cuda_device_uninit(device_ctx);
830  return ret;
831 }
832 
833 static int cuda_device_derive(AVHWDeviceContext *device_ctx,
835  int flags) {
836  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
837  CudaFunctions *cu;
838  const char *src_uuid = NULL;
839 #if CONFIG_VULKAN
840  VkPhysicalDeviceIDProperties vk_idp;
841 #endif
842  int ret, i, device_count;
843 
844  ret = cuda_flags_from_opts(device_ctx, opts, &flags);
845  if (ret < 0)
846  goto error;
847 
848 #if CONFIG_VULKAN
849  vk_idp = (VkPhysicalDeviceIDProperties) {
850  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
851  };
852 #endif
853 
854  switch (src_ctx->type) {
855 #if CONFIG_VULKAN
856 #define TYPE PFN_vkGetPhysicalDeviceProperties2
858  AVVulkanDeviceContext *vkctx = src_ctx->hwctx;
859  TYPE prop_fn = (TYPE)vkctx->get_proc_addr(vkctx->inst, "vkGetPhysicalDeviceProperties2");
860  VkPhysicalDeviceProperties2 vk_dev_props = {
861  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
862  .pNext = &vk_idp,
863  };
864  prop_fn(vkctx->phys_dev, &vk_dev_props);
865  src_uuid = vk_idp.deviceUUID;
866  break;
867  }
868 #undef TYPE
869 #endif
870  default:
871  ret = AVERROR(ENOSYS);
872  goto error;
873  }
874 
875  if (!src_uuid) {
876  av_log(device_ctx, AV_LOG_ERROR,
877  "Failed to get UUID of source device.\n");
878  ret = AVERROR(EINVAL);
879  goto error;
880  }
881 
882  ret = cuda_device_init(device_ctx);
883  if (ret < 0)
884  goto error;
885 
886  cu = hwctx->internal->cuda_dl;
887 
888  ret = CHECK_CU(cu->cuInit(0));
889  if (ret < 0)
890  goto error;
891 
892  ret = CHECK_CU(cu->cuDeviceGetCount(&device_count));
893  if (ret < 0)
894  goto error;
895 
896  hwctx->internal->cuda_device = -1;
897  for (i = 0; i < device_count; i++) {
898  CUdevice dev;
899  CUuuid uuid;
900 
901  ret = CHECK_CU(cu->cuDeviceGet(&dev, i));
902  if (ret < 0)
903  goto error;
904 
905  ret = CHECK_CU(cu->cuDeviceGetUuid(&uuid, dev));
906  if (ret < 0)
907  goto error;
908 
909  if (memcmp(src_uuid, uuid.bytes, sizeof (uuid.bytes)) == 0) {
910  hwctx->internal->cuda_device = dev;
911  break;
912  }
913  }
914 
915  if (hwctx->internal->cuda_device == -1) {
916  av_log(device_ctx, AV_LOG_ERROR, "Could not derive CUDA device.\n");
917  ret = AVERROR(ENODEV);
918  goto error;
919  }
920 
921  ret = cuda_context_init(device_ctx, flags);
922  if (ret < 0)
923  goto error;
924 
925  return 0;
926 
927 error:
928  cuda_device_uninit(device_ctx);
929  return ret;
930 }
931 
934  .name = "CUDA",
935 
936  .device_hwctx_size = sizeof(CUDADeviceContext),
937  .frames_hwctx_size = sizeof(CUDAFramesContext),
938 
939  .device_create = cuda_device_create,
940  .device_derive = cuda_device_derive,
941  .device_init = cuda_device_init,
942  .device_uninit = cuda_device_uninit,
943  .frames_get_constraints = cuda_frames_get_constraints,
944  .frames_init = cuda_frames_init,
945  .frames_uninit = cuda_frames_uninit,
946  .frames_get_buffer = cuda_get_buffer,
947  .transfer_get_formats = cuda_transfer_get_formats,
948  .transfer_data_to = cuda_transfer_data,
949  .transfer_data_from = cuda_transfer_data,
950 
951  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA,
952 #if HAVE_FFNVCODEC_CUARRAY
954 #endif
955  AV_PIX_FMT_NONE },
956 };
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
formats
formats
Definition: signature.h:47
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
FFHWFramesContext::pool_internal
AVBufferPool * pool_internal
Definition: hwcontext_internal.h:101
AVVulkanDeviceContext::phys_dev
VkPhysicalDevice phys_dev
Physical device.
Definition: hwcontext_vulkan.h:79
ff_cuda_cuarray_elem_size
static int ff_cuda_cuarray_elem_size(CUarray_format fmt)
Return the element size in bytes for a CUarray_format, or 0 for unknown.
Definition: hwcontext_cuda_internal.h:44
AV_PIX_FMT_CUDA
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition: pixfmt.h:260
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
AVCUDADeviceContextInternal
Definition: hwcontext_cuda_internal.h:31
cuda_context_init
static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags)
Definition: hwcontext_cuda.c:701
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
cuda_device_derive
static int cuda_device_derive(AVHWDeviceContext *device_ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
Definition: hwcontext_cuda.c:833
hwcontext_cuda_internal.h
cuda_transfer_get_formats
static int cuda_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_cuda.c:505
AV_PIX_FMT_BGR32
#define AV_PIX_FMT_BGR32
Definition: pixfmt.h:519
cuda_flags_from_opts
static int cuda_flags_from_opts(AVHWDeviceContext *device_ctx, AVDictionary *opts, int *flags)
Definition: hwcontext_cuda.c:756
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3460
CUDAFramesContext
Definition: hwcontext_cuda.c:33
AV_PIX_FMT_YUV444P10MSB
#define AV_PIX_FMT_YUV444P10MSB
Definition: pixfmt.h:560
CHECK_CU
#define CHECK_CU(x)
Definition: hwcontext_cuda.c:49
AVCUDADeviceContextInternal::is_allocated
int is_allocated
Definition: hwcontext_cuda_internal.h:33
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
pixdesc.h
CUDADeviceContext::internal
AVCUDADeviceContextInternal internal
Definition: hwcontext_cuda.c:44
AVVulkanDeviceContext::get_proc_addr
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
Definition: hwcontext_vulkan.h:69
data
const char data[16]
Definition: mxf.c:149
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:545
AVVulkanDeviceContext::inst
VkInstance inst
Vulkan instance.
Definition: hwcontext_vulkan.h:74
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVDictionary
Definition: dict.c:32
AVHWFramesConstraints::valid_hw_formats
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:449
tf_sess_config.config
config
Definition: tf_sess_config.py:33
dummy
static int dummy
Definition: ffplay.c:3751
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
AV_PIX_FMT_P212
#define AV_PIX_FMT_P212
Definition: pixfmt.h:624
AV_PIX_FMT_YUV444P12MSB
#define AV_PIX_FMT_YUV444P12MSB
Definition: pixfmt.h:561
AV_HWDEVICE_TYPE_VULKAN
@ AV_HWDEVICE_TYPE_VULKAN
Definition: hwcontext.h:39
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:444
AV_PIX_FMT_NB
@ AV_PIX_FMT_NB
number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of...
Definition: pixfmt.h:508
CUDADeviceContext::p
AVCUDADeviceContext p
Definition: hwcontext_cuda.c:43
AV_HWDEVICE_TYPE_CUDA
@ AV_HWDEVICE_TYPE_CUDA
Definition: hwcontext.h:30
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
AVCUDADeviceContextInternal::cuda_device
CUdevice cuda_device
Definition: hwcontext_cuda_internal.h:34
av_pix_fmt_get_chroma_sub_sample
int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, int *h_shift, int *v_shift)
Utility function to access log2_chroma_w log2_chroma_h from the pixel format AVPixFmtDescriptor.
Definition: pixdesc.c:3488
AVCUDADeviceContext::cuda_ctx
CUcontext cuda_ctx
Definition: hwcontext_cuda.h:45
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:548
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
ffhwframesctx
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
Definition: hwcontext_internal.h:115
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
AVCUDAFramesContext::cuarray_surfaces
CUarray * cuarray_surfaces
If cuarray_num_surfaces is >0, this contains the array of pre-allocated surfaces.
Definition: hwcontext_cuda.h:105
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
AVHWFramesConstraints::valid_sw_formats
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:456
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:60
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:390
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:504
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:558
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
AV_PIX_FMT_0BGR32
#define AV_PIX_FMT_0BGR32
Definition: pixfmt.h:522
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
AVCUDAFramesContext::cuarray_num_surfaces
int cuarray_num_surfaces
If >0, pre-allocate a fixed pool of surfaces.
Definition: hwcontext_cuda.h:98
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
cuda_device_init
static int cuda_device_init(AVHWDeviceContext *ctx)
Definition: hwcontext_cuda.c:679
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
if
if(ret)
Definition: filter_design.txt:179
fail
#define fail
Definition: test.h:478
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
opts
static AVDictionary * opts
Definition: movenc.c:51
TYPE
#define TYPE
Definition: ffv1dec.c:96
AV_CUDA_USE_CURRENT_CONTEXT
#define AV_CUDA_USE_CURRENT_CONTEXT
Use current device context instead of creating a new one.
Definition: hwcontext_cuda.h:140
NULL
#define NULL
Definition: coverity.c:32
AVCUDADeviceContextInternal::flags
int flags
Definition: hwcontext_cuda_internal.h:35
CUDAFramesContext::p
AVCUDAFramesContext p
Definition: hwcontext_cuda.c:34
AV_PIX_FMT_P410
#define AV_PIX_FMT_P410
Definition: pixfmt.h:623
hwcontext_vulkan.h
CUDAFramesContext::shift_width
int shift_width
Definition: hwcontext_cuda.c:36
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:546
cuda_transfer_data
static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_cuda.c:523
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
AVCUDADeviceContext::stream
CUstream stream
Definition: hwcontext_cuda.h:46
AVCUDADeviceContext::internal
AVCUDADeviceContextInternal * internal
Definition: hwcontext_cuda.h:47
CUDAFramesContext::tex_alignment
int tex_alignment
Definition: hwcontext_cuda.c:37
av_image_fill_arrays
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], const uint8_t *src, enum AVPixelFormat pix_fmt, int width, int height, int align)
Setup the data pointers and linesizes based on the specified image parameters and the provided array.
Definition: imgutils.c:446
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:609
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
CUDAFramesContext::shift_height
int shift_height
Definition: hwcontext_cuda.c:36
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
size
int size
Definition: twinvq_data.h:10344
ff_hwcontext_type_cuda
const HWContextType ff_hwcontext_type_cuda
Definition: hwcontext_cuda.c:932
AV_PIX_FMT_NV16
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:198
buffer.h
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:517
av_image_get_buffer_size
int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align)
Return the size in bytes of the amount of data required to store an image with the given parameters.
Definition: imgutils.c:466
AV_PIX_FMT_P216
#define AV_PIX_FMT_P216
Definition: pixfmt.h:626
AV_PIX_FMT_P210
#define AV_PIX_FMT_P210
Definition: pixfmt.h:622
cuda_frame_hw_format
static enum AVPixelFormat cuda_frame_hw_format(const AVFrame *frame)
Definition: hwcontext_cuda.c:498
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
AVCUDADeviceContextInternal::cuda_dl
CudaFunctions * cuda_dl
Definition: hwcontext_cuda_internal.h:32
AVCUDAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_cuda.h:79
AVCUDAArrayFrameDescriptor
CUDA frame descriptor for pool allocation of AV_PIX_FMT_CUARRAY frames.
Definition: hwcontext_cuda.h:60
AV_PIX_FMT_CUARRAY
@ AV_PIX_FMT_CUARRAY
hardware decoding through openharmony
Definition: pixfmt.h:506
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
AV_PIX_FMT_NV24
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:371
common.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
cuda_device_uninit
static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
Definition: hwcontext_cuda.c:657
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
AV_PIX_FMT_P016
#define AV_PIX_FMT_P016
Definition: pixfmt.h:610
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:406
cuda_array_format_for_pix_fmt
static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt)
Definition: hwcontext_cuda.c:222
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
AVCUDADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_cuda.h:44
array
static int array[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:116
ret
ret
Definition: filter_design.txt:187
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:75
pixfmt.h
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
AV_PIX_FMT_0RGB32
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:521
cuda_check.h
cuda_buffer_free
static void cuda_buffer_free(void *opaque, uint8_t *data)
Definition: hwcontext_cuda.c:110
AV_CUDA_USE_PRIMARY_CONTEXT
#define AV_CUDA_USE_PRIMARY_CONTEXT
Use primary device context instead of creating a new one.
Definition: hwcontext_cuda.h:135
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
cuda_device_create
static int cuda_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_cuda.c:793
CUDAFramesContext::cuarray_num_surfaces_used
int cuarray_num_surfaces_used
Definition: hwcontext_cuda.c:39
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
cuda_get_buffer
static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_cuda.c:398
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:608
desc
const char * desc
Definition: libsvtav1.c:83
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
cuda_pool_alloc
static AVBufferRef * cuda_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_cuda.c:132
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
hwcontext_internal.h
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVDictionaryEntry
Definition: dict.h:90
AV_PIX_FMT_P416
#define AV_PIX_FMT_P416
Definition: pixfmt.h:627
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AVCUDAHWConfig
CUDA hardware pipeline configuration details.
Definition: hwcontext_cuda.h:116
imgutils.h
hwcontext.h
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
CUDADeviceContext
Definition: hwcontext_cuda.c:42
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
HWContextType
Definition: hwcontext_internal.h:29
cuda_frames_get_constraints
static int cuda_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_cuda.c:53
AV_PIX_FMT_P412
#define AV_PIX_FMT_P412
Definition: pixfmt.h:625
cuda_frames_init
static int cuda_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_cuda.c:269
AVDictionaryEntry::value
char * value
Definition: dict.h:92
cuda_frames_uninit
static void cuda_frames_uninit(AVHWFramesContext *ctx)
Definition: hwcontext_cuda.c:199
AV_PIX_FMT_FLAG_PAL
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition: pixdesc.h:120
AVCUDAFramesContext::cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR CUarrays will be initialized with.
Definition: hwcontext_cuda.h:89
src
#define src
Definition: vp8dsp.c:248