FFmpeg
Loading...
Searching...
No Matches
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
41
46
47
48
49#define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
50
51static 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
110static 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
132static 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
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) {
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
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.
194done:
195 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
196 return ret;
197}
198
199#if HAVE_CUDAFUNCTIONS_CUMEMHOSTALLOC
200static void cuda_transfer_buffer_free(void *opaque, uint8_t *data)
201{
202 AVHWDeviceContext *device_ctx = opaque;
203 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
204 CudaFunctions *cu = hwctx->internal->cuda_dl;
205 CUcontext dummy;
206
207 CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
208 CHECK_CU(cu->cuMemFreeHost(data));
209 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
210}
211
212/* The device transfers directly to and from page-locked memory, other memory
213 * goes through a buffer of the driver. */
214static AVBufferRef *cuda_transfer_buffer_alloc(void *device_ref, size_t size)
215{
216 AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)((AVBufferRef *)device_ref)->data;
217 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
218 CudaFunctions *cu = hwctx->internal->cuda_dl;
220 CUcontext dummy;
221 void *host;
222
223 if (CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx)) < 0)
224 return av_buffer_alloc(size);
225
226 if (CHECK_CU(cu->cuMemHostAlloc(&host, size, 0)) >= 0) {
227 ret = av_buffer_create(host, size, cuda_transfer_buffer_free, device_ctx, 0);
228 if (!ret)
229 CHECK_CU(cu->cuMemFreeHost(host));
230 }
231
232 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
233 return ret ? ret : av_buffer_alloc(size);
234}
235#endif
236
238{
239 AVHWDeviceContext *device_ctx = ctx->device_ctx;
240 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
241 CUDAFramesContext *priv = ctx->hwctx;
242 CudaFunctions *cu = hwctx->internal->cuda_dl;
243
244 if (priv->p.cuarray_surfaces) {
245 CUcontext dummy;
246 CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
247
248 // Make sure we don't free surfaces that have been adopted by the pool already
249 for (int i = priv->cuarray_num_surfaces_used; i < priv->p.cuarray_num_surfaces; i++)
250 if (priv->p.cuarray_surfaces[i])
251 CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
252
253 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
254
256 priv->p.cuarray_num_surfaces = 0;
257 }
258}
259
260static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt)
261{
262 switch (fmt) {
263#if HAVE_FFNVCODEC_CUARRAY
264 case AV_PIX_FMT_NV12: return CU_AD_FORMAT_NV12;
265 case AV_PIX_FMT_P010:
266 case AV_PIX_FMT_P012:
267 case AV_PIX_FMT_P016: return CU_AD_FORMAT_P016;
268 case AV_PIX_FMT_NV16: return CU_AD_FORMAT_NV16;
269 case AV_PIX_FMT_P210:
270 case AV_PIX_FMT_P212:
271 case AV_PIX_FMT_P216: return CU_AD_FORMAT_P216;
272 case AV_PIX_FMT_NV24: return CU_AD_FORMAT_YUV444_8BIT_SEMIPLANAR;
273 case AV_PIX_FMT_P410:
274 case AV_PIX_FMT_P412:
275 case AV_PIX_FMT_P416: return CU_AD_FORMAT_YUV444_16BIT_SEMIPLANAR;
276 case AV_PIX_FMT_YUV420P: return CU_AD_FORMAT_UINT8_PLANAR_420;
277 case AV_PIX_FMT_YUV422P: return CU_AD_FORMAT_UINT8_PLANAR_422;
278 case AV_PIX_FMT_YUV444P: return CU_AD_FORMAT_UINT8_PLANAR_444;
279 case AV_PIX_FMT_YUV420P10: return CU_AD_FORMAT_UINT16_PLANAR_420;
280 case AV_PIX_FMT_YUV422P10: return CU_AD_FORMAT_UINT16_PLANAR_422;
284 case AV_PIX_FMT_YUV444P16: return CU_AD_FORMAT_UINT16_PLANAR_444;
287 case AV_PIX_FMT_RGB32:
288 case AV_PIX_FMT_BGR32: return CU_AD_FORMAT_UNSIGNED_INT8;
289#endif
290 default: return 0;
291 }
292}
293
294#if HAVE_FFNVCODEC_CUARRAY
295static unsigned int cuda_array_numchannels_for_pix_fmt(enum AVPixelFormat fmt)
296{
297 switch (fmt) {
300 case AV_PIX_FMT_RGB32:
301 case AV_PIX_FMT_BGR32: return 4;
302 default: return 3;
303 }
304}
305#endif
306
308{
309 AVHWDeviceContext *device_ctx = ctx->device_ctx;
310 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
311 CUDAFramesContext *priv = ctx->hwctx;
312 CudaFunctions *cu = hwctx->internal->cuda_dl;
313 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ctx->sw_format);
314 int err;
315
316 if (!desc) {
317 av_log(ctx, AV_LOG_ERROR, "Invalid pixel format\n");
318 return AVERROR(EINVAL);
319 }
320
321 /* Palette formats keep their palette in a separate zero-linesize plane
322 * that the transfer path does not copy, so they are not supported. */
323 if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
324 av_log(ctx, AV_LOG_ERROR, "Palette formats are not supported\n");
325 return AVERROR(ENOSYS);
326 }
327
328#if HAVE_FFNVCODEC_CUARRAY
329 if (ctx->format == AV_PIX_FMT_CUARRAY && !cu->cuArrayGetPlane) {
330 av_log(ctx, AV_LOG_ERROR, "cuArrayGetPlane not available, update your driver\n");
331 return AVERROR(ENOSYS);
332 }
333#else
334 if (ctx->format == AV_PIX_FMT_CUARRAY) {
335 av_log(ctx, AV_LOG_ERROR, "Missing support for cuarray frames. Rebuild with newer ffnvcodec headers.\n");
336 return AVERROR(ENOSYS);
337 }
338#endif
339
340 err = CHECK_CU(cu->cuDeviceGetAttribute(&priv->tex_alignment,
341 14 /* CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT */,
342 hwctx->internal->cuda_device));
343 if (err < 0)
344 return err;
345
346 av_log(ctx, AV_LOG_DEBUG, "CUDA texture alignment: %d\n", priv->tex_alignment);
347
348 // YUV420P is a special case.
349 // Since nvenc expects the U/V planes to have half the linesize of the Y plane
350 // alignment has to be doubled to ensure the U/V planes still end up aligned.
351 if (ctx->sw_format == AV_PIX_FMT_YUV420P)
352 priv->tex_alignment *= 2;
353
355
356#if HAVE_FFNVCODEC_CUARRAY
357 if (ctx->format == AV_PIX_FMT_CUARRAY) {
358 if (!priv->p.cuarray_desc.Width)
359 priv->p.cuarray_desc.Width = ctx->width;
360 if (!priv->p.cuarray_desc.Height)
361 priv->p.cuarray_desc.Height = ctx->height;
362 if (!priv->p.cuarray_desc.NumChannels)
363 priv->p.cuarray_desc.NumChannels = cuda_array_numchannels_for_pix_fmt(ctx->sw_format);
364
365 if (priv->p.cuarray_desc.Depth) {
366 av_log(ctx, AV_LOG_ERROR, "CUarrays with non-zero depth are not supported.\n");
367 return AVERROR(EINVAL);
368 }
369
370 if (!priv->p.cuarray_desc.Format)
371 priv->p.cuarray_desc.Format = cuda_array_format_for_pix_fmt(ctx->sw_format);
372 if (!priv->p.cuarray_desc.Format) {
373 av_log(ctx, AV_LOG_ERROR, "Invalid CUarray pixel format\n");
374 return AVERROR_BUG;
375 }
376
377 priv->p.cuarray_desc.Flags |= CUDA_ARRAY3D_SURFACE_LDST | CUDA_ARRAY3D_VIDEO_ENCODE_DECODE;
378 }
379
380 if (ctx->format == AV_PIX_FMT_CUARRAY && priv->p.cuarray_num_surfaces > 0) {
381 CUcontext dummy;
382
383 priv->p.cuarray_surfaces = av_calloc(priv->p.cuarray_num_surfaces, sizeof(*priv->p.cuarray_surfaces));
384 if (!priv->p.cuarray_surfaces)
385 return AVERROR(ENOMEM);
386
387 err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
388 if (err < 0) {
390 return err;
391 }
392
393 for (int i = 0; i < priv->p.cuarray_num_surfaces; i++) {
394 err = CHECK_CU(cu->cuArray3DCreate(&priv->p.cuarray_surfaces[i], &priv->p.cuarray_desc));
395 if (err < 0) {
396 for (i = i - 1; i >= 0; i--)
397 CHECK_CU(cu->cuArrayDestroy(priv->p.cuarray_surfaces[i]));
398 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
399
401 return err;
402 }
403 }
404
405 err = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
406 if (err < 0)
407 goto fail;
408
409 av_log(ctx, AV_LOG_DEBUG, "allocated %d CUarray surfaces (%zux%zu)\n",
410 priv->p.cuarray_num_surfaces, priv->p.cuarray_desc.Width, priv->p.cuarray_desc.Height);
411 }
412#endif
413
414 if (!ctx->pool) {
415 int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
416 if (size < 0) {
417 err = size;
418 goto fail;
419 }
420
423 if (!ffhwframesctx(ctx)->pool_internal) {
424 err = AVERROR(ENOMEM);
425 goto fail;
426 }
427 }
428
429 return 0;
430
431fail:
433 return err;
434}
435
437{
438 CUDAFramesContext *priv = ctx->hwctx;
439#if HAVE_FFNVCODEC_CUARRAY
440 AVHWDeviceContext *device_ctx = ctx->device_ctx;
441 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
442 CudaFunctions *cu = hwctx->internal->cuda_dl;
443
444 CUcontext dummy;
445#endif
446 int res;
447
448 frame->buf[0] = av_buffer_pool_get(ctx->pool);
449 if (!frame->buf[0])
450 return AVERROR(ENOMEM);
451
452 if (ctx->format == AV_PIX_FMT_CUARRAY) {
453#if HAVE_FFNVCODEC_CUARRAY
455 if (!desc) {
456 frame->format = ctx->format;
457 frame->width = ctx->width;
458 frame->height = ctx->height;
459 return 0;
460 }
461 frame->data[0] = (uint8_t*)desc->array;
462 frame->data[1] = (uint8_t*)desc->index;
463
464 res = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
465 if (res < 0)
466 return res;
467
468 for (int i = 0; i < FF_ARRAY_ELEMS(frame->linesize); i++) {
469 CUDA_ARRAY3D_DESCRIPTOR plane_desc = { 0 };
470 CUarray plane_array;
471 CUresult arr_plane_res = cu->cuArrayGetPlane(&plane_array, desc->array, i);
472
473 if (arr_plane_res == CUDA_ERROR_INVALID_VALUE) {
474 if (i > 0)
475 break;
476 /* Non-planar format (e.g. UNSIGNED_INT8 x4 for packed RGB):
477 * cuArrayGetPlane is unsupported, query the array directly. */
478 res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, desc->array));
479 if (res < 0)
480 goto fail;
481 } else if (arr_plane_res != CUDA_SUCCESS) {
482 res = CHECK_CU(arr_plane_res);
483 goto fail;
484 } else {
485 res = CHECK_CU(cu->cuArray3DGetDescriptor(&plane_desc, plane_array));
486 if (res < 0)
487 goto fail;
488 }
489
490 int elem_size = ff_cuda_cuarray_elem_size(plane_desc.Format);
491 if (elem_size <= 0) {
492 res = AVERROR_BUG;
493 goto fail;
494 }
495
496 frame->linesize[i] = plane_desc.Width * plane_desc.NumChannels * elem_size;
497
498 if (arr_plane_res == CUDA_ERROR_INVALID_VALUE)
499 break;
500 }
501
502 res = CHECK_CU(cu->cuCtxPopCurrent(&dummy));
503 if (res < 0)
504 return res;
505#else
506 return AVERROR(ENOSYS);
507#endif
508 } else {
509 res = av_image_fill_arrays(frame->data, frame->linesize, frame->buf[0]->data,
510 ctx->sw_format, ctx->width, ctx->height, priv->tex_alignment);
511 if (res < 0)
512 return res;
513
514 // YUV420P is a special case.
515 // Nvenc expects the U/V planes in swapped order from how ffmpeg expects them, also chroma is half-aligned
516 if (ctx->sw_format == AV_PIX_FMT_YUV420P) {
517 frame->linesize[1] = frame->linesize[2] = frame->linesize[0] / 2;
518 frame->data[2] = frame->data[1];
519 frame->data[1] = frame->data[2] + frame->linesize[2] * AV_CEIL_RSHIFT(ctx->height, 1);
520 }
521 }
522
523 frame->format = ctx->format;
524 frame->width = ctx->width;
525 frame->height = ctx->height;
526
527 return 0;
528
529#if HAVE_FFNVCODEC_CUARRAY
530fail:
531 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
532 return res;
533#endif
534}
535
537{
538 if (!frame->hw_frames_ctx)
539 return AV_PIX_FMT_NONE;
540 return ((AVHWFramesContext *)frame->hw_frames_ctx->data)->format;
541}
542
545 enum AVPixelFormat **formats)
546{
547 enum AVPixelFormat *fmts;
548
549 fmts = av_malloc_array(2, sizeof(*fmts));
550 if (!fmts)
551 return AVERROR(ENOMEM);
552
553 fmts[0] = ctx->sw_format;
554 fmts[1] = AV_PIX_FMT_NONE;
555
556 *formats = fmts;
557
558 return 0;
559}
560
562 const AVFrame *src)
563{
564 CUDAFramesContext *priv = ctx->hwctx;
565 AVHWDeviceContext *device_ctx = ctx->device_ctx;
566 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
567 CudaFunctions *cu = hwctx->internal->cuda_dl;
568
569 const AVFrame *sw_frame = src->hw_frames_ctx ? dst : src;
570 AVFrame *top_down = NULL, *bottom_up_dst = NULL;
571 CUcontext dummy;
572 int i, ret, copy_queued = 0, bottom_up = 0;
573
574 {
575 enum AVPixelFormat src_fmt = cuda_frame_hw_format(src);
576 enum AVPixelFormat dst_fmt = cuda_frame_hw_format(dst);
577 if ((src_fmt != AV_PIX_FMT_NONE &&
578 src_fmt != AV_PIX_FMT_CUDA && src_fmt != AV_PIX_FMT_CUARRAY) ||
579 (dst_fmt != AV_PIX_FMT_NONE &&
580 dst_fmt != AV_PIX_FMT_CUDA && dst_fmt != AV_PIX_FMT_CUARRAY))
581 return AVERROR(ENOSYS);
582 }
583
584 for (i = 0; i < FF_ARRAY_ELEMS(sw_frame->linesize); i++)
585 bottom_up |= sw_frame->linesize[i] < 0;
586
587 /* The device copies rows upwards through memory, so a bottom-up frame is
588 * transferred through a top-down copy of it. */
589 if (bottom_up) {
590 top_down = av_frame_alloc();
591 if (!top_down)
592 return AVERROR(ENOMEM);
593 top_down->format = ctx->sw_format;
594 top_down->width = ctx->width;
595 top_down->height = ctx->height;
596 ret = av_hwframe_get_transfer_buffer((src->hw_frames_ctx ? src : dst)->hw_frames_ctx,
597 top_down);
598 if (ret < 0)
599 goto free_top_down;
600 top_down->width = src->width;
601 top_down->height = src->height;
602 if (sw_frame == src) {
603 av_image_copy2(top_down->data, top_down->linesize, src->data, src->linesize,
604 ctx->sw_format, src->width, src->height);
605 src = top_down;
606 } else {
607 bottom_up_dst = dst;
608 dst = top_down;
609 }
610 }
611
612 ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
613 if (ret < 0)
614 goto free_top_down;
615
616 /*
617 * Copy one plane per iteration, bounded by the AVFrame linesizes. src and
618 * dst always share the same sw_format (this path never converts), so they
619 * are either both multi-planar or both single-plane.
620 *
621 * For a CUARRAY side, cuArrayGetPlane() returns the sub-array for plane i
622 * of a multi-planar CUarray (NV12, P0xx, NV24, planar 4:4:4, ...).
623 * cuArrayGetPlane() returns CUDA_ERROR_INVALID_VALUE either when the array
624 * is not multi-planar or when the plane index exceeds its plane count:
625 * - i == 0: the array is packed (e.g. RGB), i.e. a single plane, so the
626 * whole array is used as that plane.
627 * - i > 0: the planes of a multi-planar array always have a non-zero
628 * linesize, so a valid plane is never skipped by the loop bound;
629 * getting INVALID_VALUE here means src/dst disagree on the plane count,
630 * which is an inconsistency and is treated as an error (handled by the
631 * generic cures != CUDA_SUCCESS branch) rather than silently copying a
632 * subset of the planes.
633 */
634 for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->linesize[i]; i++) {
635 int src_is_nonplanar_cuarray = 0;
636 int dst_is_nonplanar_cuarray = 0;
637
638 int bytewidth = av_image_get_linesize(ctx->sw_format, src->width, i);
639 if (bytewidth < 0) {
640 ret = bytewidth;
641 goto fail;
642 }
643
644 CUDA_MEMCPY2D cpy = {
645 .srcPitch = src->linesize[i],
646 .dstPitch = dst->linesize[i],
647 .WidthInBytes = bytewidth,
648 .Height = AV_CEIL_RSHIFT(src->height, ((i == 0 || i == 3) ? 0 : priv->shift_height)),
649 };
650
651 if (src->format == AV_PIX_FMT_CUDA) {
652 cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
653 cpy.srcDevice = (CUdeviceptr)src->data[i];
654 } else if (src->format == AV_PIX_FMT_CUARRAY) {
655#if HAVE_FFNVCODEC_CUARRAY
656 CUarray array;
657 CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)src->data[0], i);
658 if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
659 /* Not a multi-planar array (packed format): the whole array is
660 * the single plane. */
661 array = (CUarray)src->data[0];
662 src_is_nonplanar_cuarray = 1;
663 } else if (cures != CUDA_SUCCESS) {
664 ret = CHECK_CU(cures);
665 goto fail;
666 }
667
668 cpy.srcMemoryType = CU_MEMORYTYPE_ARRAY;
669 cpy.srcArray = array;
670#else
671 ret = AVERROR(ENOSYS);
672 goto exit;
673#endif
674 } else {
675 cpy.srcMemoryType = CU_MEMORYTYPE_HOST;
676 cpy.srcHost = src->data[i];
677 }
678
679 if (dst->format == AV_PIX_FMT_CUDA) {
680 cpy.dstMemoryType = CU_MEMORYTYPE_DEVICE;
681 cpy.dstDevice = (CUdeviceptr)dst->data[i];
682 } else if (dst->format == AV_PIX_FMT_CUARRAY) {
683#if HAVE_FFNVCODEC_CUARRAY
684 CUarray array;
685 CUresult cures = cu->cuArrayGetPlane(&array, (CUarray)dst->data[0], i);
686 if (cures == CUDA_ERROR_INVALID_VALUE && i == 0) {
687 /* Not a multi-planar array (packed format): the whole array is
688 * the single plane. */
689 array = (CUarray)dst->data[0];
690 dst_is_nonplanar_cuarray = 1;
691 } else if (cures != CUDA_SUCCESS) {
692 ret = CHECK_CU(cures);
693 goto fail;
694 }
695
696 cpy.dstMemoryType = CU_MEMORYTYPE_ARRAY;
697 cpy.dstArray = array;
698#else
699 ret = AVERROR(ENOSYS);
700 goto exit;
701#endif
702 } else {
703 cpy.dstMemoryType = CU_MEMORYTYPE_HOST;
704 cpy.dstHost = dst->data[i];
705 }
706
707 ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream));
708 if (ret < 0)
709 goto fail;
710 copy_queued = 1;
711
712 if (src_is_nonplanar_cuarray || dst_is_nonplanar_cuarray)
713 break;
714 }
715
716 /* The caller may reuse host memory once the transfer returns. */
717 if (!src->hw_frames_ctx || !dst->hw_frames_ctx) {
718 ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
719 if (ret < 0)
720 goto exit;
721 }
722
723fail:
724 if (ret < 0 && copy_queued)
725 CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
726exit:
727 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
728
729 if (bottom_up_dst && ret >= 0)
730 av_image_copy2(bottom_up_dst->data, bottom_up_dst->linesize,
731 top_down->data, top_down->linesize,
732 ctx->sw_format, src->width, src->height);
733free_top_down:
734 av_frame_free(&top_down);
735
736 return ret;
737}
738
739static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
740{
741 CUDADeviceContext *hwctx = device_ctx->hwctx;
742
743 if (hwctx->p.internal) {
744 CudaFunctions *cu = hwctx->internal.cuda_dl;
745
746 if (hwctx->internal.is_allocated && hwctx->p.cuda_ctx) {
748 CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx->internal.cuda_device));
749 else if (!(hwctx->internal.flags & AV_CUDA_USE_CURRENT_CONTEXT))
750 CHECK_CU(cu->cuCtxDestroy(hwctx->p.cuda_ctx));
751
752 hwctx->p.cuda_ctx = NULL;
753 }
754
755 cuda_free_functions(&hwctx->internal.cuda_dl);
756 memset(&hwctx->internal, 0, sizeof(hwctx->internal));
757 hwctx->p.internal = NULL;
758 }
759}
760
762{
763 CUDADeviceContext *hwctx = ctx->hwctx;
764 int ret;
765
766 hwctx->p.internal = &hwctx->internal;
767
768 if (!hwctx->internal.cuda_dl) {
769 ret = cuda_load_functions(&hwctx->internal.cuda_dl, ctx);
770 if (ret < 0) {
771 av_log(ctx, AV_LOG_ERROR, "Could not dynamically load CUDA\n");
772 goto error;
773 }
774 }
775
776 return 0;
777
778error:
780 return ret;
781}
782
783static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) {
784 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
785 CudaFunctions *cu;
786 CUcontext dummy;
787 int ret, dev_active = 0;
788 unsigned int dev_flags = 0;
789
790 const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC;
791
792 cu = hwctx->internal->cuda_dl;
793
794 hwctx->internal->flags = flags;
795
797 ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device,
798 &dev_flags, &dev_active));
799 if (ret < 0)
800 return ret;
801
802 if (dev_active && dev_flags != desired_flags) {
803 av_log(device_ctx, AV_LOG_ERROR, "Primary context already active with incompatible flags.\n");
804 return AVERROR(ENOTSUP);
805 } else if (dev_flags != desired_flags) {
806 ret = CHECK_CU(cu->cuDevicePrimaryCtxSetFlags(hwctx->internal->cuda_device,
807 desired_flags));
808 if (ret < 0)
809 return ret;
810 }
811
812 ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx,
813 hwctx->internal->cuda_device));
814 if (ret < 0)
815 return ret;
816 } else if (flags & AV_CUDA_USE_CURRENT_CONTEXT) {
817 ret = CHECK_CU(cu->cuCtxGetCurrent(&hwctx->cuda_ctx));
818 if (ret < 0)
819 return ret;
820 av_log(device_ctx, AV_LOG_INFO, "Using current CUDA context.\n");
821 } else {
822 ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags,
823 hwctx->internal->cuda_device));
824 if (ret < 0)
825 return ret;
826
827 CHECK_CU(cu->cuCtxPopCurrent(&dummy));
828 }
829
830 hwctx->internal->is_allocated = 1;
831
832 // Setting stream to NULL will make functions automatically use the default CUstream
833 hwctx->stream = NULL;
834
835 return 0;
836}
837
839 AVDictionary *opts, int *flags)
840{
841 AVDictionaryEntry *primary_ctx_opt = av_dict_get(opts, "primary_ctx", NULL, 0);
842 AVDictionaryEntry *current_ctx_opt = av_dict_get(opts, "current_ctx", NULL, 0);
843
844 int use_primary_ctx = 0, use_current_ctx = 0;
845 if (primary_ctx_opt)
846 use_primary_ctx = strtol(primary_ctx_opt->value, NULL, 10);
847
848 if (current_ctx_opt)
849 use_current_ctx = strtol(current_ctx_opt->value, NULL, 10);
850
851 if (use_primary_ctx && use_current_ctx) {
852 av_log(device_ctx, AV_LOG_ERROR, "Requested both primary and current CUDA context simultaneously.\n");
853 return AVERROR(EINVAL);
854 }
855
856 if (primary_ctx_opt && use_primary_ctx) {
857 av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA primary device context\n");
859 } else if (primary_ctx_opt) {
860 av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA primary device context\n");
862 }
863
864 if (current_ctx_opt && use_current_ctx) {
865 av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA current device context\n");
867 } else if (current_ctx_opt) {
868 av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA current device context\n");
870 }
871
872 return 0;
873}
874
876 const char *device,
877 AVDictionary *opts, int flags)
878{
879 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
880 CudaFunctions *cu;
881 int ret, device_idx = 0;
882
883 ret = cuda_flags_from_opts(device_ctx, opts, &flags);
884 if (ret < 0)
885 goto error;
886
887 if (device)
888 device_idx = strtol(device, NULL, 0);
889
890 ret = cuda_device_init(device_ctx);
891 if (ret < 0)
892 goto error;
893
894 cu = hwctx->internal->cuda_dl;
895
896 ret = CHECK_CU(cu->cuInit(0));
897 if (ret < 0)
898 goto error;
899
900 ret = CHECK_CU(cu->cuDeviceGet(&hwctx->internal->cuda_device, device_idx));
901 if (ret < 0)
902 goto error;
903
904 ret = cuda_context_init(device_ctx, flags);
905 if (ret < 0)
906 goto error;
907
908 return 0;
909
910error:
911 cuda_device_uninit(device_ctx);
912 return ret;
913}
914
917 int flags) {
918 AVCUDADeviceContext *hwctx = device_ctx->hwctx;
919 CudaFunctions *cu;
920 const char *src_uuid = NULL;
921#if CONFIG_VULKAN
922 VkPhysicalDeviceIDProperties vk_idp;
923#endif
924 int ret, i, device_count;
925
926 ret = cuda_flags_from_opts(device_ctx, opts, &flags);
927 if (ret < 0)
928 goto error;
929
930#if CONFIG_VULKAN
931 vk_idp = (VkPhysicalDeviceIDProperties) {
932 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
933 };
934#endif
935
936 switch (src_ctx->type) {
937#if CONFIG_VULKAN
938#define TYPE PFN_vkGetPhysicalDeviceProperties2
940 AVVulkanDeviceContext *vkctx = src_ctx->hwctx;
941 TYPE prop_fn = (TYPE)vkctx->get_proc_addr(vkctx->inst, "vkGetPhysicalDeviceProperties2");
942 VkPhysicalDeviceProperties2 vk_dev_props = {
943 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
944 .pNext = &vk_idp,
945 };
946 prop_fn(vkctx->phys_dev, &vk_dev_props);
947 src_uuid = vk_idp.deviceUUID;
948 break;
949 }
950#undef TYPE
951#endif
952 default:
953 ret = AVERROR(ENOSYS);
954 goto error;
955 }
956
957 if (!src_uuid) {
958 av_log(device_ctx, AV_LOG_ERROR,
959 "Failed to get UUID of source device.\n");
960 ret = AVERROR(EINVAL);
961 goto error;
962 }
963
964 ret = cuda_device_init(device_ctx);
965 if (ret < 0)
966 goto error;
967
968 cu = hwctx->internal->cuda_dl;
969
970 ret = CHECK_CU(cu->cuInit(0));
971 if (ret < 0)
972 goto error;
973
974 ret = CHECK_CU(cu->cuDeviceGetCount(&device_count));
975 if (ret < 0)
976 goto error;
977
978 hwctx->internal->cuda_device = -1;
979 for (i = 0; i < device_count; i++) {
980 CUdevice dev;
981 CUuuid uuid;
982
983 ret = CHECK_CU(cu->cuDeviceGet(&dev, i));
984 if (ret < 0)
985 goto error;
986
987 ret = CHECK_CU(cu->cuDeviceGetUuid(&uuid, dev));
988 if (ret < 0)
989 goto error;
990
991 if (memcmp(src_uuid, uuid.bytes, sizeof (uuid.bytes)) == 0) {
992 hwctx->internal->cuda_device = dev;
993 break;
994 }
995 }
996
997 if (hwctx->internal->cuda_device == -1) {
998 av_log(device_ctx, AV_LOG_ERROR, "Could not derive CUDA device.\n");
999 ret = AVERROR(ENODEV);
1000 goto error;
1001 }
1002
1003 ret = cuda_context_init(device_ctx, flags);
1004 if (ret < 0)
1005 goto error;
1006
1007 return 0;
1008
1009error:
1010 cuda_device_uninit(device_ctx);
1011 return ret;
1012}
1013
1015 .type = AV_HWDEVICE_TYPE_CUDA,
1016 .name = "CUDA",
1017
1018 .device_hwctx_size = sizeof(CUDADeviceContext),
1019 .frames_hwctx_size = sizeof(CUDAFramesContext),
1020
1021 .device_create = cuda_device_create,
1022 .device_derive = cuda_device_derive,
1023 .device_init = cuda_device_init,
1024 .device_uninit = cuda_device_uninit,
1025 .frames_get_constraints = cuda_frames_get_constraints,
1026 .frames_init = cuda_frames_init,
1027 .frames_uninit = cuda_frames_uninit,
1028 .frames_get_buffer = cuda_get_buffer,
1029 .transfer_get_formats = cuda_transfer_get_formats,
1030#if HAVE_CUDAFUNCTIONS_CUMEMHOSTALLOC
1031 .transfer_buffer_alloc = cuda_transfer_buffer_alloc,
1032#endif
1033 .transfer_data_to = cuda_transfer_data,
1034 .transfer_data_from = cuda_transfer_data,
1035
1036 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA,
1037#if HAVE_FFNVCODEC_CUARRAY
1039#endif
1041};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static AVFormatContext * ctx
static AVDictionary * opts
refcounted data buffer API
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
static AVFrame * frame
int ret
Definition ffplay.c:391
SDL_atomic_t done
Definition ffplay.c:392
static int dummy
Definition ffplay.c:4417
#define TYPE
Definition ffv1dec.c:90
#define fail
Definition test.h:479
#define AV_CUDA_USE_CURRENT_CONTEXT
Use current device context instead of creating a new one.
#define AV_CUDA_USE_PRIMARY_CONTEXT
Use primary device context instead of creating a new one.
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition buffer.c:78
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:56
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition buffer.c:396
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:260
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:61
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:65
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:53
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
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
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
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane.
Definition imgutils.c:76
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition imgutils.h:184
int av_hwframe_get_transfer_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame)
Allocate the buffers of a software frame that data is transferred to or from frames of the given AVHW...
Definition hwcontext.c:442
AVHWFrameTransferDirection
Definition hwcontext.h:421
@ AV_HWDEVICE_TYPE_VULKAN
Definition hwcontext.h:39
@ AV_HWDEVICE_TYPE_CUDA
Definition hwcontext.h:30
static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
static CUarray_format cuda_array_format_for_pix_fmt(enum AVPixelFormat fmt)
static int cuda_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static int cuda_flags_from_opts(AVHWDeviceContext *device_ctx, AVDictionary *opts, int *flags)
static enum AVPixelFormat cuda_frame_hw_format(const AVFrame *frame)
static AVBufferRef * cuda_pool_alloc(void *opaque, size_t size)
static int cuda_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
static void cuda_buffer_free(void *opaque, uint8_t *data)
static int cuda_device_init(AVHWDeviceContext *ctx)
static int cuda_frames_init(AVHWFramesContext *ctx)
static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags)
static void cuda_frames_uninit(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_cuda
#define CHECK_CU(x)
static int cuda_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags)
static int cuda_device_derive(AVHWDeviceContext *device_ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
static int cuda_transfer_data(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
FFmpeg internal API for CUDA.
static int ff_cuda_cuarray_elem_size(CUarray_format fmt)
Return the element size in bytes for a CUarray_format, or 0 for unknown.
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
misc image utilities
const char * desc
Definition libsvtav1.c:83
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
char * host
Definition mscl.c:249
const char data[16]
Definition mxf.c:149
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:3512
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3484
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition pixdesc.h:128
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition pixdesc.h:120
pixel format definitions
#define AV_PIX_FMT_0RGB32
Definition pixfmt.h:524
#define AV_PIX_FMT_P212
Definition pixfmt.h:629
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:548
#define AV_PIX_FMT_P412
Definition pixfmt.h:630
#define AV_PIX_FMT_P210
Definition pixfmt.h:627
#define AV_PIX_FMT_P012
Definition pixfmt.h:614
#define AV_PIX_FMT_P216
Definition pixfmt.h:631
#define AV_PIX_FMT_P010
Definition pixfmt.h:613
#define AV_PIX_FMT_P016
Definition pixfmt.h:615
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:549
#define AV_PIX_FMT_YUV444P12MSB
Definition pixfmt.h:564
#define AV_PIX_FMT_BGR32
Definition pixfmt.h:522
#define AV_PIX_FMT_P410
Definition pixfmt.h:628
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ 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
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition pixfmt.h:379
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ 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:511
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition pixfmt.h:260
@ 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
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:198
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_CUARRAY
hardware decoding through openharmony
Definition pixfmt.h:506
#define AV_PIX_FMT_P416
Definition pixfmt.h:632
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:561
#define AV_PIX_FMT_YUV444P10MSB
Definition pixfmt.h:563
#define AV_PIX_FMT_0BGR32
Definition pixfmt.h:525
#define AV_PIX_FMT_RGB32
Definition pixfmt.h:520
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:551
formats
Definition signature.h:47
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
CUDA frame descriptor for pool allocation of AV_PIX_FMT_CUARRAY frames.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
This struct is allocated as AVHWFramesContext.hwctx.
CUarray * cuarray_surfaces
If cuarray_num_surfaces is >0, this contains the array of pre-allocated surfaces.
CUDA_ARRAY3D_DESCRIPTOR cuarray_desc
CUDA_ARRAY3D_DESCRIPTOR CUarrays will be initialized with.
int cuarray_num_surfaces
If >0, pre-allocate a fixed pool of surfaces.
CUDA hardware pipeline configuration details.
char * value
Definition dict.h:92
This structure describes decoded (raw) audio or video data.
Definition frame.h:479
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:500
int width
Definition frame.h:551
int height
Definition frame.h:551
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:524
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:566
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition hwcontext.h:88
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition hwcontext.h:75
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition hwcontext.h:459
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:464
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:471
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
VkPhysicalDevice phys_dev
Physical device.
VkInstance inst
Vulkan instance.
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
AVCUDADeviceContextInternal internal
AVCUDADeviceContext p
AVCUDAFramesContext p
AVBufferPool * pool_internal
#define av_free(p)
#define av_malloc_array(a, b)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static void error(const char *err)
#define src
Definition vp8dsp.c:248
static int array[MAX_W *MAX_W]
int size