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
24 #if CONFIG_VULKAN
26 #endif
32
37
42
55 #if CONFIG_VULKAN
57 #endif
58 };
59
60 #define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
61
63 const void *hwconfig,
65 {
67
72
76
80
83
84 return 0;
85 }
86
88 {
93
95
97
99
101 }
102
104 {
109
113 int err;
114
116 if (err < 0)
118
120 if (err < 0)
122
127 }
128
132 }
133
135 {
141
144 break;
145 }
150 }
151
153 14 /* CU_DEVICE_ATTRIBUTE_TEXTURE_ALIGNMENT */,
155 if (err < 0)
156 return err;
157
159
160 // YUV420P is a special case.
161 // Since nvenc expects the U/V planes to have half the linesize of the Y plane
162 // alignment has to be doubled to ensure the U/V planes still end up aligned.
165
167
172
177 }
178
179 return 0;
180 }
181
183 {
185 int res;
186
190
193 if (res < 0)
194 return res;
195
196 // YUV420P is a special case.
197 // Nvenc expects the U/V planes in swapped order from how ffmpeg expects them, also chroma is half-aligned
202 }
203
207
208 return 0;
209 }
210
214 {
216
218 if (!fmts)
220
221 fmts[0] =
ctx->sw_format;
223
225
226 return 0;
227 }
228
231 {
236
239
243
247
249 CUDA_MEMCPY2D cpy = {
250 .srcPitch =
src->linesize[
i],
254 };
255
256 if (
src->hw_frames_ctx) {
257 cpy.srcMemoryType = CU_MEMORYTYPE_DEVICE;
258 cpy.srcDevice = (CUdeviceptr)
src->data[
i];
259 } else {
260 cpy.srcMemoryType = CU_MEMORYTYPE_HOST;
261 cpy.srcHost =
src->data[
i];
262 }
263
265 cpy.dstMemoryType = CU_MEMORYTYPE_DEVICE;
266 cpy.dstDevice = (CUdeviceptr)dst->
data[
i];
267 } else {
268 cpy.dstMemoryType = CU_MEMORYTYPE_HOST;
269 cpy.dstHost = dst->
data[
i];
270 }
271
274 goto exit;
275 }
276
280 goto exit;
281 }
282
283 exit:
285
286 return 0;
287 }
288
290 {
292
295
301
303 }
304
308 }
309 }
310
312 {
315
317
323 }
324 }
325
326 return 0;
327
331 }
332
335 CudaFunctions *cu;
337 int ret, dev_active = 0;
338 unsigned int dev_flags = 0;
339
340 const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC;
341
343
345
348 &dev_flags, &dev_active));
351
352 if (dev_active && dev_flags != desired_flags) {
353 av_log(device_ctx,
AV_LOG_ERROR,
"Primary context already active with incompatible flags.\n");
355 } else if (dev_flags != desired_flags) {
357 desired_flags));
360 }
361
371 } else {
376
378 }
379
381
382 // Setting stream to NULL will make functions automatically use the default CUstream
384
385 return 0;
386 }
387
390 {
393
394 int use_primary_ctx = 0, use_current_ctx = 0;
395 if (primary_ctx_opt)
396 use_primary_ctx = strtol(primary_ctx_opt->
value,
NULL, 10);
397
398 if (current_ctx_opt)
399 use_current_ctx = strtol(current_ctx_opt->
value,
NULL, 10);
400
401 if (use_primary_ctx && use_current_ctx) {
402 av_log(device_ctx,
AV_LOG_ERROR,
"Requested both primary and current CUDA context simultaneously.\n");
404 }
405
406 if (primary_ctx_opt && use_primary_ctx) {
409 } else if (primary_ctx_opt) {
412 }
413
414 if (current_ctx_opt && use_current_ctx) {
417 } else if (current_ctx_opt) {
420 }
421
422 return 0;
423 }
424
426 const char *device,
428 {
430 CudaFunctions *cu;
431 int ret, device_idx = 0;
432
436
437 if (device)
438 device_idx = strtol(device,
NULL, 0);
439
443
445
449
453
457
458 return 0;
459
463 }
464
469 CudaFunctions *cu;
470 const char *src_uuid =
NULL;
471 #if CONFIG_VULKAN
472 VkPhysicalDeviceIDProperties vk_idp;
473 #endif
474 int ret,
i, device_count;
475
479
480 #if CONFIG_VULKAN
481 vk_idp = (VkPhysicalDeviceIDProperties) {
482 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES,
483 };
484 #endif
485
486 switch (src_ctx->
type) {
487 #if CONFIG_VULKAN
488 #define TYPE PFN_vkGetPhysicalDeviceProperties2
492 VkPhysicalDeviceProperties2 vk_dev_props = {
493 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
494 .pNext = &vk_idp,
495 };
496 prop_fn(vkctx->
phys_dev, &vk_dev_props);
497 src_uuid = vk_idp.deviceUUID;
498 break;
499 }
500 #undef TYPE
501 #endif
502 default:
505 }
506
507 if (!src_uuid) {
509 "Failed to get UUID of source device.\n");
512 }
513
517
519
523
524 ret =
CHECK_CU(cu->cuDeviceGetCount(&device_count));
527
529 for (
i = 0;
i < device_count;
i++) {
530 CUdevice dev;
531 CUuuid uuid;
532
536
540
541 if (memcmp(src_uuid, uuid.bytes, sizeof (uuid.bytes)) == 0) {
543 break;
544 }
545 }
546
550 }
551
555
556 return 0;
557
561 }
562
565 .name = "CUDA",
566
569
580
582 };