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 static const enum AVPixelFormat supported_formats[] = {
74 #if CONFIG_VULKAN
76 #endif
77 };
78 
79 #define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
80 
81 static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt);
82 
84  const void *hwconfig,
85  AVHWFramesConstraints *constraints)
86 {
87  const AVCUDAHWConfig *config = hwconfig;
88  enum AVPixelFormat req_fmt = config ? config->hw_format : AV_PIX_FMT_NONE;
89  int i, nb_sw_formats = 0;
90 
92  sizeof(*constraints->valid_sw_formats));
93  if (!constraints->valid_sw_formats)
94  return AVERROR(ENOMEM);
95 
96  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
97  if (req_fmt == AV_PIX_FMT_CUARRAY &&
99  continue;
100  constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i];
101  }
102  constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
103 
104  if (req_fmt == AV_PIX_FMT_CUDA || req_fmt == AV_PIX_FMT_CUARRAY) {
105  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
106  if (!constraints->valid_hw_formats)
107  return AVERROR(ENOMEM);
108 
109  constraints->valid_hw_formats[0] = req_fmt;
110  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
111  } else {
112  constraints->valid_hw_formats = av_malloc_array(2 + HAVE_FFNVCODEC_CUARRAY, sizeof(*constraints->valid_hw_formats));
113  if (!constraints->valid_hw_formats)
114  return AVERROR(ENOMEM);
115 
116  constraints->valid_hw_formats[0] = AV_PIX_FMT_CUDA;
117 #if HAVE_FFNVCODEC_CUARRAY
118  constraints->valid_hw_formats[1] = AV_PIX_FMT_CUARRAY;
119  constraints->valid_hw_formats[2] = AV_PIX_FMT_NONE;
120 #else
121  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
122 #endif
123  }
124 
125  return 0;
126 }
127 
128 static void cuda_buffer_free(void *opaque, uint8_t *data)
129 {
130  AVHWFramesContext *ctx = opaque;
131  AVHWDeviceContext *device_ctx = ctx->device_ctx;
132  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
133  CudaFunctions *cu = hwctx->internal->cuda_dl;
134 
135  CUcontext dummy;
136 
137  CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
138 
139  if (ctx->format == AV_PIX_FMT_CUARRAY) {
141  CHECK_CU(cu->cuArrayDestroy(desc->array));
142  av_free(desc);
143  } else {
144  CHECK_CU(cu->cuMemFree((CUdeviceptr)data));
145  }
146 
147  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
148 }
149 
150 static AVBufferRef *cuda_pool_alloc(void *opaque, size_t size)
151 {
152  AVHWFramesContext *ctx = opaque;
153  CUDAFramesContext *priv = ctx->hwctx;
154  AVHWDeviceContext *device_ctx = ctx->device_ctx;
155  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
156  CudaFunctions *cu = hwctx->internal->cuda_dl;
157 
158  AVBufferRef *ret = NULL;
159  CUcontext dummy = NULL;
160  CUdeviceptr data;
161  int err;
162 
163  err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
164  if (err < 0)
165  return NULL;
166 
167  if (ctx->format == AV_PIX_FMT_CUARRAY) {
169  if (!desc)
170  goto done;
171 
172  if (priv->p.cuarray_num_surfaces > 0) {
173  if (priv->cuarray_num_surfaces_used >= priv->p.cuarray_num_surfaces) {
174  av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
175  av_free(desc);
176  goto done;
177  }
178  desc->index = priv->cuarray_num_surfaces_used++;
179  desc->array = priv->p.cuarray_surfaces[desc->index];
180  } else {
181  err = CHECK_CU(cu->cuArray3DCreate(&desc->array, &priv->p.cuarray_desc));
182  if (err < 0) {
183  av_free(desc);
184  goto done;
185  }
186  }
187 
188  ret = av_buffer_create((uint8_t*)desc, sizeof(*desc), cuda_buffer_free, ctx, 0);
189  if (!ret) {
190  // It is okay (and necessary) to free a pool array here,
191  // since cuarray_num_surfaces_used is already incremented.
192  CHECK_CU(cu->cuArrayDestroy(desc->array));
193  av_free(desc);
194  goto done;
195  }
196 
197  goto done;
198  }
199 
200  err = CHECK_CU(cu->cuMemAlloc(&data, size));
201  if (err < 0)
202  goto done;
203 
204  ret = av_buffer_create((uint8_t*)data, size, cuda_buffer_free, ctx, 0);
205  if (!ret) {
206  CHECK_CU(cu->cuMemFree(data));
207  goto done;
208  }
209 
210  // Common exit: reached on both success (ret holds the buffer) and
211  // failure (ret == NULL); restores the CUDA context and returns ret.
212 done:
213  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
214  return ret;
215 }
216 
218 {
219  AVHWDeviceContext *device_ctx = ctx->device_ctx;
220  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
221  CUDAFramesContext *priv = ctx->hwctx;
222  CudaFunctions *cu = hwctx->internal->cuda_dl;
223 
224  if (priv->p.cuarray_surfaces) {
225  CUcontext dummy;
226  CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
227 
228  // Make sure we don't free surfaces that have been adopted by the pool already
229  for (int i = priv->cuarray_num_surfaces_used; i < priv->p.cuarray_num_surfaces; i++)
230  if (priv->p.cuarray_surfaces[i])
231  CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
232 
233  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
234 
235  av_freep(&priv->p.cuarray_surfaces);
236  priv->p.cuarray_num_surfaces = 0;
237  }
238 }
239 
240 static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt)
241 {
242  switch (fmt) {
243 #if HAVE_FFNVCODEC_CUARRAY
244  case AV_PIX_FMT_NV12: return CU_AD_FORMAT_NV12;
245  case AV_PIX_FMT_P010:
246  case AV_PIX_FMT_P012:
247  case AV_PIX_FMT_P016: return CU_AD_FORMAT_P016;
248  case AV_PIX_FMT_NV16: return CU_AD_FORMAT_NV16;
249  case AV_PIX_FMT_P210:
250  case AV_PIX_FMT_P212:
251  case AV_PIX_FMT_P216: return CU_AD_FORMAT_P216;
252  case AV_PIX_FMT_NV24: return CU_AD_FORMAT_YUV444_8BIT_SEMIPLANAR;
253  case AV_PIX_FMT_P410:
254  case AV_PIX_FMT_P412:
255  case AV_PIX_FMT_P416: return CU_AD_FORMAT_YUV444_16BIT_SEMIPLANAR;
256  case AV_PIX_FMT_YUV420P: return CU_AD_FORMAT_UINT8_PLANAR_420;
257  case AV_PIX_FMT_YUV422P: return CU_AD_FORMAT_UINT8_PLANAR_422;
258  case AV_PIX_FMT_YUV444P: return CU_AD_FORMAT_UINT8_PLANAR_444;
259  case AV_PIX_FMT_YUV420P10: return CU_AD_FORMAT_UINT16_PLANAR_420;
260  case AV_PIX_FMT_YUV422P10: return CU_AD_FORMAT_UINT16_PLANAR_422;
264  case AV_PIX_FMT_YUV444P16: return CU_AD_FORMAT_UINT16_PLANAR_444;
265  case AV_PIX_FMT_0RGB32:
266  case AV_PIX_FMT_0BGR32:
267  case AV_PIX_FMT_RGB32:
268  case AV_PIX_FMT_BGR32: return CU_AD_FORMAT_UNSIGNED_INT8;
269 #endif
270  default: return 0;
271  }
272 }
273 
274 #if HAVE_FFNVCODEC_CUARRAY
275 static unsigned int cuda_array_numchannels_for_pix_fmt(enum AVPixelFormat fmt)
276 {
277  switch (fmt) {
278  case AV_PIX_FMT_0RGB32:
279  case AV_PIX_FMT_0BGR32:
280  case AV_PIX_FMT_RGB32:
281  case AV_PIX_FMT_BGR32: return 4;
282  default: return 3;
283  }
284 }
285 #endif
286 
288 {
289  AVHWDeviceContext *device_ctx = ctx->device_ctx;
290  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
291  CUDAFramesContext *priv = ctx->hwctx;
292  CudaFunctions *cu = hwctx->internal->cuda_dl;
293  int err, i;
294 
295  for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
296  if (ctx->sw_format == supported_formats[i])
297  break;
298  }
300  av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
301  av_get_pix_fmt_name(ctx->sw_format));
302  return AVERROR(ENOSYS);
303  }
304 
305 #if HAVE_FFNVCODEC_CUARRAY
306  if (ctx->format == AV_PIX_FMT_CUARRAY && !cu->cuArrayGetPlane) {
307  av_log(ctx, AV_LOG_ERROR, "cuArrayGetPlane not available, update your driver\n");
308  return AVERROR(ENOSYS);
309  }
310 #else
311  if (ctx->format == AV_PIX_FMT_CUARRAY) {
312  av_log(ctx, AV_LOG_ERROR, "Missing support for cuarray frames. Rebuild with newer ffnvcodec headers.\n");
313  return AVERROR(ENOSYS);
314  }
315 #endif
316 
317  err = CHECK_CU(cu->cuDeviceGetAttribute(&priv->tex_alignment,
318  14 /* CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT */,
319  hwctx->internal->cuda_device));
320  if (err < 0)
321  return err;
322 
323  av_log(ctx, AV_LOG_DEBUG, "CUDA texture alignment: %d\n", priv->tex_alignment);
324 
325  // YUV420P is a special case.
326  // Since nvenc expects the U/V planes to have half the linesize of the Y plane
327  // alignment has to be doubled to ensure the U/V planes still end up aligned.
328  if (ctx->sw_format == AV_PIX_FMT_YUV420P)
329  priv->tex_alignment *= 2;
330 
331  av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height);
332 
333 #if HAVE_FFNVCODEC_CUARRAY
334  if (ctx->format == AV_PIX_FMT_CUARRAY) {
335  if (!priv->p.cuarray_desc.Width)
336  priv->p.cuarray_desc.Width = ctx->width;
337  if (!priv->p.cuarray_desc.Height)
338  priv->p.cuarray_desc.Height = ctx->height;
339  if (!priv->p.cuarray_desc.NumChannels)
340  priv->p.cuarray_desc.NumChannels = cuda_array_numchannels_for_pix_fmt(ctx->sw_format);
341 
342  if (priv->p.cuarray_desc.Depth) {
343  av_log(ctx, AV_LOG_ERROR, "CUarrays with non-zero depth are not supported.\n");
344  return AVERROR(EINVAL);
345  }
346 
347  if (!priv->p.cuarray_desc.Format)
348  priv->p.cuarray_desc.Format = cuda_array_format_for_pix_fmt(ctx->sw_format);
349  if (!priv->p.cuarray_desc.Format) {
350  av_log(ctx, AV_LOG_ERROR, "Invalid CUarray pixel format\n");
351  return AVERROR_BUG;
352  }
353 
354  priv->p.cuarray_desc.Flags |= CUDA_ARRAY3D_SURFACE_LDST | CUDA_ARRAY3D_VIDEO_ENCODE_DECODE;
355  }
356 
357  if (ctx->format == AV_PIX_FMT_CUARRAY && priv->p.cuarray_num_surfaces > 0) {
358  CUcontext dummy;
359 
360  priv->p.cuarray_surfaces = av_calloc(priv->p.cuarray_num_surfaces, sizeof(*priv->p.cuarray_surfaces));
361  if (!priv->p.cuarray_surfaces)
362  return AVERROR(ENOMEM);
363 
364  err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
365  if (err < 0) {
366  av_freep(&priv->p.cuarray_surfaces);
367  return err;
368  }
369 
370  for (i = 0; i < priv->p.cuarray_num_surfaces; i++) {
371  err = CHECK_CU(cu->cuArray3DCreate(&priv->p.cuarray_surfaces[i], &priv->p.cuarray_desc));
372  if (err < 0) {
373  for (i = i - 1; i >= 0; i--)
374  CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
375  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
376 
377  av_freep(&priv->p.cuarray_surfaces);
378  return err;
379  }
380  }
381 
382  err = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
383  if (err < 0)
384  goto fail;
385 
386  av_log(ctx, AV_LOG_DEBUG, "allocated %d CUarray surfaces (%zux%zu)\n",
387  priv->p.cuarray_num_surfaces, priv->p.cuarray_desc.Width, priv->p.cuarray_desc.Height);
388  }
389 #endif
390 
391  if (!ctx->pool) {
392  int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
393  if (size < 0) {
394  err = size;
395  goto fail;
396  }
397 
400  if (!ffhwframesctx(ctx)->pool_internal) {
401  err = AVERROR(ENOMEM);
402  goto fail;
403  }
404  }
405 
406  return 0;
407 
408 fail:
410  return err;
411 }
412 
414 {
415  CUDAFramesContext *priv = ctx->hwctx;
416 #if HAVE_FFNVCODEC_CUARRAY
417  AVHWDeviceContext *device_ctx = ctx->device_ctx;
418  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
419  CudaFunctions *cu = hwctx->internal->cuda_dl;
420 
421  CUcontext dummy;
422 #endif
423  int res;
424 
425  frame->buf[0] = av_buffer_pool_get(ctx->pool);
426  if (!frame->buf[0])
427  return AVERROR(ENOMEM);
428 
429  if (ctx->format == AV_PIX_FMT_CUARRAY) {
430 #if HAVE_FFNVCODEC_CUARRAY
432  if (!desc) {
433  frame->format = ctx->format;
434  frame->width = ctx->width;
435  frame->height = ctx->height;
436  return 0;
437  }
438  frame->data[0] = (uint8_t*)desc->array;
439  frame->data[1] = (uint8_t*)desc->index;
440 
441  res = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
442  if (res < 0)
443  return res;
444 
445  for (int i = 0; i < FF_ARRAY_ELEMS(frame->linesize); i++) {
446  CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
447  CUarray plane_array;
448  CUresult arr_plane_res = cu->cuArrayGetPlane(&plane_array, desc->array, i);
449 
450  if (arr_plane_res == CUDA_ERROR_INVALID_VALUE) {
451  if (i > 0)
452  break;
453  /* Non-planar format (e.g. UNSIGNED_INT8 x4 for packed RGB):
454  * cuArrayGetPlane is unsupported, query the array directly. */
455  res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, desc->array));
456  if (res < 0)
457  goto fail;
458  } else if (arr_plane_res != CUDA_SUCCESS) {
459  res = CHECK_CU(arr_plane_res);
460  goto fail;
461  } else {
462  res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, plane_array));
463  if (res < 0)
464  goto fail;
465  }
466 
467  int elem_size = ff_cuda_cuarray_elem_size(plane_desc.Format);
468  if (elem_size <= 0) {
469  res = AVERROR_BUG;
470  goto fail;
471  }
472 
473  frame->linesize[i] = plane_desc.Width * plane_desc.NumChannels * elem_size;
474 
475  if (arr_plane_res == CUDA_ERROR_INVALID_VALUE)
476  break;
477  }
478 
479  res = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
480  if (res < 0)
481  return res;
482 #else
483  return AVERROR(ENOSYS);
484 #endif
485  } else {
486  res = av_image_fill_arrays(frame->data, frame->linesize, frame->buf[0]->data,
487  ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
488  if (res < 0)
489  return res;
490 
491  // YUV420P is a special case.
492  // Nvenc expects the U/V planes in swapped order from how ffmpeg expects them, also chroma is half-aligned
493  if (ctx->sw_format == AV_PIX_FMT_YUV420P) {
494  frame->linesize[1] = frame->linesize[2] = frame->linesize[0] / 2;
495  frame->data[2] = frame->data[1];
496  frame->data[1] = frame->data[2] + frame->linesize[2] * AV_CEIL_RSHIFT(ctx->height, 1);
497  }
498  }
499 
500  frame->format = ctx->format;
501  frame->width = ctx->width;
502  frame->height = ctx->height;
503 
504  return 0;
505 
506 #if HAVE_FFNVCODEC_CUARRAY
507 fail:
508  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
509  return res;
510 #endif
511 }
512 
514 {
515  if (!frame->hw_frames_ctx)
516  return AV_PIX_FMT_NONE;
517  return ((AVHWFramesContext *)frame->hw_frames_ctx->data)->format;
518 }
519 
522  enum AVPixelFormat **formats)
523 {
524  enum AVPixelFormat *fmts;
525 
526  fmts = av_malloc_array(2, sizeof(*fmts));
527  if (!fmts)
528  return AVERROR(ENOMEM);
529 
530  fmts[0] = ctx->sw_format;
531  fmts[1] = AV_PIX_FMT_NONE;
532 
533  *formats = fmts;
534 
535  return 0;
536 }
537 
539  const AVFrame *src)
540 {
541  CUDAFramesContext *priv = ctx->hwctx;
542  AVHWDeviceContext *device_ctx = ctx->device_ctx;
543  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
544  CudaFunctions *cu = hwctx->internal->cuda_dl;
545 
546  CUcontext dummy;
547  int i, ret;
548 
549  {
550  enum AVPixelFormat src_fmt = cuda_frame_hw_format(src);
551  enum AVPixelFormat dst_fmt = cuda_frame_hw_format(dst);
552  if ((src_fmt != AV_PIX_FMT_NONE &&
553  src_fmt != AV_PIX_FMT_CUDA && src_fmt != AV_PIX_FMT_CUARRAY) ||
554  (dst_fmt != AV_PIX_FMT_NONE &&
555  dst_fmt != AV_PIX_FMT_CUDA && dst_fmt != AV_PIX_FMT_CUARRAY))
556  return AVERROR(ENOSYS);
557  }
558 
559  ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
560  if (ret < 0)
561  return ret;
562 
563  /*
564  * Copy one plane per iteration, bounded by the AVFrame linesizes. src and
565  * dst always share the same sw_format (this path never converts), so they
566  * are either both multi-planar or both single-plane.
567  *
568  * For a CUARRAY side, cuArrayGetPlane() returns the sub-array for plane i
569  * of a multi-planar CUarray (NV12, P0xx, NV24, planar 4:4:4, ...).
570  * cuArrayGetPlane() returns CUDA_ERROR_INVALID_VALUE either when the array
571  * is not multi-planar or when the plane index exceeds its plane count:
572  * - i == 0: the array is packed (e.g. RGB), i.e. a single plane, so the
573  * whole array is used as that plane.
574  * - i > 0: the planes of a multi-planar array always have a non-zero
575  * linesize, so a valid plane is never skipped by the loop bound;
576  * getting INVALID_VALUE here means src/dst disagree on the plane count,
577  * which is an inconsistency and is treated as an error (handled by the
578  * generic cures != CUDA_SUCCESS branch) rather than silently copying a
579  * subset of the planes.
580  */
581  for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->linesize[i]; i++) {
582  int src_is_nonplanar_cuarray = 0;
583  int dst_is_nonplanar_cuarray = 0;
584 
585  CUDA_MEMCPY2D cpy = {
586  .srcPitch = src->linesize[i],
587  .dstPitch = dst->linesize[i],
588  .WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]),
589  .Height = AV_CEIL_RSHIFT(src->height, ((i == 0 || i == 3) ? 0 : priv->shift_height)),
590  };
591 
592  if (src->format == AV_PIX_FMT_CUDA) {
593  cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
594  cpy.srcDevice = (CUdeviceptr)src->data[i];
595  } else if (src->format == AV_PIX_FMT_CUARRAY) {
596 #if HAVE_FFNVCODEC_CUARRAY
597  CUarray array;
598  CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)src->data[0], i);
599  if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
600  /* Not a multi-planar array (packed format): the whole array is
601  * the single plane. */
602  array = (CUarray)src->data[0];
603  src_is_nonplanar_cuarray = 1;
604  } else if (cures != CUDA_SUCCESS) {
605  ret = CHECK_CU(cures);
606  goto exit;
607  }
608 
609  cpy.srcMemoryType = CU_MEMORYTYPE_ARRAY;
610  cpy.srcArray = array;
611 #else
612  ret = AVERROR(ENOSYS);
613  goto exit;
614 #endif
615  } else {
616  cpy.srcMemoryType = CU_MEMORYTYPE_HOST;
617  cpy.srcHost = src->data[i];
618  }
619 
620  if (dst->format == AV_PIX_FMT_CUDA) {
621  cpy.dstMemoryType = CU_MEMORYTYPE_DEVICE;
622  cpy.dstDevice = (CUdeviceptr)dst->data[i];
623  } else if (dst->format == AV_PIX_FMT_CUARRAY) {
624 #if HAVE_FFNVCODEC_CUARRAY
625  CUarray array;
626  CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)dst->data[0], i);
627  if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
628  /* Not a multi-planar array (packed format): the whole array is
629  * the single plane. */
630  array = (CUarray)dst->data[0];
631  dst_is_nonplanar_cuarray = 1;
632  } else if (cures != CUDA_SUCCESS) {
633  ret = CHECK_CU(cures);
634  goto exit;
635  }
636 
637  cpy.dstMemoryType = CU_MEMORYTYPE_ARRAY;
638  cpy.dstArray = array;
639 #else
640  ret = AVERROR(ENOSYS);
641  goto exit;
642 #endif
643  } else {
644  cpy.dstMemoryType = CU_MEMORYTYPE_HOST;
645  cpy.dstHost = dst->data[i];
646  }
647 
648  ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream));
649  if (ret < 0)
650  goto exit;
651 
652  if (src_is_nonplanar_cuarray || dst_is_nonplanar_cuarray)
653  break;
654  }
655 
656  if (!dst->hw_frames_ctx) {
657  ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
658  if (ret < 0)
659  goto exit;
660  }
661 
662 exit:
663  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
664 
665  return ret;
666 }
667 
668 static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
669 {
670  CUDADeviceContext *hwctx = device_ctx->hwctx;
671 
672  if (hwctx->p.internal) {
673  CudaFunctions *cu = hwctx->internal.cuda_dl;
674 
675  if (hwctx->internal.is_allocated && hwctx->p.cuda_ctx) {
677  CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx->internal.cuda_device));
678  else if (!(hwctx->internal.flags & AV_CUDA_USE_CURRENT_CONTEXT))
679  CHECK_CU(cu->cuCtxDestroy(hwctx->p.cuda_ctx));
680 
681  hwctx->p.cuda_ctx = NULL;
682  }
683 
684  cuda_free_functions(&hwctx->internal.cuda_dl);
685  memset(&hwctx->internal, 0, sizeof(hwctx->internal));
686  hwctx->p.internal = NULL;
687  }
688 }
689 
691 {
692  CUDADeviceContext *hwctx = ctx->hwctx;
693  int ret;
694 
695  hwctx->p.internal = &hwctx->internal;
696 
697  if (!hwctx->internal.cuda_dl) {
698  ret = cuda_load_functions(&hwctx->internal.cuda_dl, ctx);
699  if (ret < 0) {
700  av_log(ctx, AV_LOG_ERROR, "Could not dynamically load CUDA\n");
701  goto error;
702  }
703  }
704 
705  return 0;
706 
707 error:
709  return ret;
710 }
711 
712 static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) {
713  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
714  CudaFunctions *cu;
715  CUcontext dummy;
716  int ret, dev_active = 0;
717  unsigned int dev_flags = 0;
718 
719  const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC;
720 
721  cu = hwctx->internal->cuda_dl;
722 
723  hwctx->internal->flags = flags;
724 
726  ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device,
727  &dev_flags, &dev_active));
728  if (ret < 0)
729  return ret;
730 
731  if (dev_active && dev_flags != desired_flags) {
732  av_log(device_ctx, AV_LOG_ERROR, "Primary context already active with incompatible flags.\n");
733  return AVERROR(ENOTSUP);
734  } else if (dev_flags != desired_flags) {
735  ret = CHECK_CU(cu->cuDevicePrimaryCtxSetFlags(hwctx->internal->cuda_device,
736  desired_flags));
737  if (ret < 0)
738  return ret;
739  }
740 
741  ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx,
742  hwctx->internal->cuda_device));
743  if (ret < 0)
744  return ret;
745  } else if (flags & AV_CUDA_USE_CURRENT_CONTEXT) {
746  ret = CHECK_CU(cu->cuCtxGetCurrent(&hwctx->cuda_ctx));
747  if (ret < 0)
748  return ret;
749  av_log(device_ctx, AV_LOG_INFO, "Using current CUDA context.\n");
750  } else {
751  ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags,
752  hwctx->internal->cuda_device));
753  if (ret < 0)
754  return ret;
755 
756  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
757  }
758 
759  hwctx->internal->is_allocated = 1;
760 
761  // Setting stream to NULL will make functions automatically use the default CUstream
762  hwctx->stream = NULL;
763 
764  return 0;
765 }
766 
768  AVDictionary *opts, int *flags)
769 {
770  AVDictionaryEntry *primary_ctx_opt = av_dict_get(opts, "primary_ctx", NULL, 0);
771  AVDictionaryEntry *current_ctx_opt = av_dict_get(opts, "current_ctx", NULL, 0);
772 
773  int use_primary_ctx = 0, use_current_ctx = 0;
774  if (primary_ctx_opt)
775  use_primary_ctx = strtol(primary_ctx_opt->value, NULL, 10);
776 
777  if (current_ctx_opt)
778  use_current_ctx = strtol(current_ctx_opt->value, NULL, 10);
779 
780  if (use_primary_ctx && use_current_ctx) {
781  av_log(device_ctx, AV_LOG_ERROR, "Requested both primary and current CUDA context simultaneously.\n");
782  return AVERROR(EINVAL);
783  }
784 
785  if (primary_ctx_opt && use_primary_ctx) {
786  av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA primary device context\n");
788  } else if (primary_ctx_opt) {
789  av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA primary device context\n");
791  }
792 
793  if (current_ctx_opt && use_current_ctx) {
794  av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA current device context\n");
796  } else if (current_ctx_opt) {
797  av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA current device context\n");
799  }
800 
801  return 0;
802 }
803 
804 static int cuda_device_create(AVHWDeviceContext *device_ctx,
805  const char *device,
806  AVDictionary *opts, int flags)
807 {
808  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
809  CudaFunctions *cu;
810  int ret, device_idx = 0;
811 
812  ret = cuda_flags_from_opts(device_ctx, opts, &flags);
813  if (ret < 0)
814  goto error;
815 
816  if (device)
817  device_idx = strtol(device, NULL, 0);
818 
819  ret = cuda_device_init(device_ctx);
820  if (ret < 0)
821  goto error;
822 
823  cu = hwctx->internal->cuda_dl;
824 
825  ret = CHECK_CU(cu->cuInit(0));
826  if (ret < 0)
827  goto error;
828 
829  ret = CHECK_CU(cu->cuDeviceGet(&hwctx->internal->cuda_device, device_idx));
830  if (ret < 0)
831  goto error;
832 
833  ret = cuda_context_init(device_ctx, flags);
834  if (ret < 0)
835  goto error;
836 
837  return 0;
838 
839 error:
840  cuda_device_uninit(device_ctx);
841  return ret;
842 }
843 
844 static int cuda_device_derive(AVHWDeviceContext *device_ctx,
846  int flags) {
847  AVCUDADeviceContext *hwctx = device_ctx->hwctx;
848  CudaFunctions *cu;
849  const char *src_uuid = NULL;
850 #if CONFIG_VULKAN
851  VkPhysicalDeviceIDProperties vk_idp;
852 #endif
853  int ret, i, device_count;
854 
855  ret = cuda_flags_from_opts(device_ctx, opts, &flags);
856  if (ret < 0)
857  goto error;
858 
859 #if CONFIG_VULKAN
860  vk_idp = (VkPhysicalDeviceIDProperties) {
861  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
862  };
863 #endif
864 
865  switch (src_ctx->type) {
866 #if CONFIG_VULKAN
867 #define TYPE PFN_vkGetPhysicalDeviceProperties2
869  AVVulkanDeviceContext *vkctx = src_ctx->hwctx;
870  TYPE prop_fn = (TYPE)vkctx->get_proc_addr(vkctx->inst, "vkGetPhysicalDeviceProperties2");
871  VkPhysicalDeviceProperties2 vk_dev_props = {
872  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
873  .pNext = &vk_idp,
874  };
875  prop_fn(vkctx->phys_dev, &vk_dev_props);
876  src_uuid = vk_idp.deviceUUID;
877  break;
878  }
879 #undef TYPE
880 #endif
881  default:
882  ret = AVERROR(ENOSYS);
883  goto error;
884  }
885 
886  if (!src_uuid) {
887  av_log(device_ctx, AV_LOG_ERROR,
888  "Failed to get UUID of source device.\n");
889  ret = AVERROR(EINVAL);
890  goto error;
891  }
892 
893  ret = cuda_device_init(device_ctx);
894  if (ret < 0)
895  goto error;
896 
897  cu = hwctx->internal->cuda_dl;
898 
899  ret = CHECK_CU(cu->cuInit(0));
900  if (ret < 0)
901  goto error;
902 
903  ret = CHECK_CU(cu->cuDeviceGetCount(&device_count));
904  if (ret < 0)
905  goto error;
906 
907  hwctx->internal->cuda_device = -1;
908  for (i = 0; i < device_count; i++) {
909  CUdevice dev;
910  CUuuid uuid;
911 
912  ret = CHECK_CU(cu->cuDeviceGet(&dev, i));
913  if (ret < 0)
914  goto error;
915 
916  ret = CHECK_CU(cu->cuDeviceGetUuid(&uuid, dev));
917  if (ret < 0)
918  goto error;
919 
920  if (memcmp(src_uuid, uuid.bytes, sizeof (uuid.bytes)) == 0) {
921  hwctx->internal->cuda_device = dev;
922  break;
923  }
924  }
925 
926  if (hwctx->internal->cuda_device == -1) {
927  av_log(device_ctx, AV_LOG_ERROR, "Could not derive CUDA device.\n");
928  ret = AVERROR(ENODEV);
929  goto error;
930  }
931 
932  ret = cuda_context_init(device_ctx, flags);
933  if (ret < 0)
934  goto error;
935 
936  return 0;
937 
938 error:
939  cuda_device_uninit(device_ctx);
940  return ret;
941 }
942 
945  .name = "CUDA",
946 
947  .device_hwctx_size = sizeof(CUDADeviceContext),
948  .frames_hwctx_size = sizeof(CUDAFramesContext),
949 
950  .device_create = cuda_device_create,
951  .device_derive = cuda_device_derive,
952  .device_init = cuda_device_init,
953  .device_uninit = cuda_device_uninit,
954  .frames_get_constraints = cuda_frames_get_constraints,
955  .frames_init = cuda_frames_init,
956  .frames_uninit = cuda_frames_uninit,
957  .frames_get_buffer = cuda_get_buffer,
958  .transfer_get_formats = cuda_transfer_get_formats,
959  .transfer_data_to = cuda_transfer_data,
960  .transfer_data_from = cuda_transfer_data,
961 
962  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA,
963 #if HAVE_FFNVCODEC_CUARRAY
965 #endif
966  AV_PIX_FMT_NONE },
967 };
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:712
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:844
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:520
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:767
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:79
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
CUDADeviceContext::p
AVCUDADeviceContext p
Definition: hwcontext_cuda.c:43
AV_HWDEVICE_TYPE_CUDA
@ AV_HWDEVICE_TYPE_CUDA
Definition: hwcontext.h:30
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_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
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:690
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:538
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:943
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:513
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:668
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:240
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:128
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:804
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
supported_formats
static enum AVPixelFormat supported_formats[]
Definition: hwcontext_cuda.c:47
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:413
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:150
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:83
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:287
AVDictionaryEntry::value
char * value
Definition: dict.h:92
cuda_frames_uninit
static void cuda_frames_uninit(AVHWFramesContext *ctx)
Definition: hwcontext_cuda.c:217
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
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:3380