avutil/hwcontext_cuda: allow using primary CUDA device context
authorOleg Dobkin <olegd@anyvision.co>
Mon, 18 Nov 2019 13:35:49 +0000 (15:35 +0200)
committerTimo Rothenpieler <timo@rothenpieler.org>
Tue, 26 Nov 2019 15:24:40 +0000 (16:24 +0100)
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
configure
libavutil/hwcontext_cuda.c
libavutil/hwcontext_cuda.h
libavutil/hwcontext_cuda_internal.h
libavutil/version.h

index 8f4f288..2519e64 100755 (executable)
--- a/configure
+++ b/configure
@@ -6139,10 +6139,10 @@ fi
 
 if ! disabled ffnvcodec; then
     ffnv_hdr_list="ffnvcodec/nvEncodeAPI.h ffnvcodec/dynlink_cuda.h ffnvcodec/dynlink_cuviddec.h ffnvcodec/dynlink_nvcuvid.h"
-    check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.0" "$ffnv_hdr_list" "" || \
-      check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.8 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \
-      check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.9 ffnvcodec < 8.2" "$ffnv_hdr_list" "" || \
-      check_pkg_config ffnvcodec "ffnvcodec >= 8.0.14.9 ffnvcodec < 8.1" "$ffnv_hdr_list" ""
+    check_pkg_config ffnvcodec "ffnvcodec >= 9.1.23.1" "$ffnv_hdr_list" "" || \
+      check_pkg_config ffnvcodec "ffnvcodec >= 9.0.18.3 ffnvcodec < 9.1" "$ffnv_hdr_list" "" || \
+      check_pkg_config ffnvcodec "ffnvcodec >= 8.2.15.10 ffnvcodec < 8.3" "$ffnv_hdr_list" "" || \
+      check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" ""
 fi
 
 check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)"
index cca39e9..30611b1 100644 (file)
@@ -280,10 +280,16 @@ static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
 
     if (hwctx->internal) {
         CudaFunctions *cu = hwctx->internal->cuda_dl;
+
         if (hwctx->internal->is_allocated && hwctx->cuda_ctx) {
-            CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx));
+            if (hwctx->internal->flags & AV_CUDA_USE_PRIMARY_CONTEXT)
+                CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx->internal->cuda_device));
+            else
+                CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx));
+
             hwctx->cuda_ctx = NULL;
         }
+
         cuda_free_functions(&hwctx->internal->cuda_dl);
     }
 
@@ -322,9 +328,11 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx,
 {
     AVCUDADeviceContext *hwctx = device_ctx->hwctx;
     CudaFunctions *cu;
-    CUdevice cu_device;
     CUcontext dummy;
-    int ret, device_idx = 0;
+    int ret, dev_active = 0, device_idx = 0;
+    unsigned int dev_flags = 0;
+
+    const unsigned int desired_flags = CU_CTX_SCHED_BLOCKING_SYNC;
 
     if (device)
         device_idx = strtol(device, NULL, 0);
@@ -338,21 +346,42 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx,
     if (ret < 0)
         goto error;
 
-    ret = CHECK_CU(cu->cuDeviceGet(&cu_device, device_idx));
+    ret = CHECK_CU(cu->cuDeviceGet(&hwctx->internal->cuda_device, device_idx));
     if (ret < 0)
         goto error;
 
-    ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, cu_device));
-    if (ret < 0)
-        goto error;
+    hwctx->internal->flags = flags;
 
-    // Setting stream to NULL will make functions automatically use the default CUstream
-    hwctx->stream = NULL;
+    if (flags & AV_CUDA_USE_PRIMARY_CONTEXT) {
+        ret = CHECK_CU(cu->cuDevicePrimaryCtxGetState(hwctx->internal->cuda_device, &dev_flags, &dev_active));
+        if (ret < 0)
+            goto error;
 
-    CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+        if (dev_active && dev_flags != desired_flags) {
+            av_log(device_ctx, AV_LOG_ERROR, "Primary context already active with incompatible flags.\n");
+            goto error;
+        } else if (dev_flags != desired_flags) {
+            ret = CHECK_CU(cu->cuDevicePrimaryCtxSetFlags(hwctx->internal->cuda_device, desired_flags));
+            if (ret < 0)
+                goto error;
+        }
+
+        ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx->cuda_ctx, hwctx->internal->cuda_device));
+        if (ret < 0)
+            goto error;
+    } else {
+        ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, desired_flags, hwctx->internal->cuda_device));
+        if (ret < 0)
+            goto error;
+
+        CHECK_CU(cu->cuCtxPopCurrent(&dummy));
+    }
 
     hwctx->internal->is_allocated = 1;
 
+    // Setting stream to NULL will make functions automatically use the default CUstream
+    hwctx->stream = NULL;
+
     return 0;
 
 error:
index 81a0552..cefbe0c 100644 (file)
@@ -49,4 +49,21 @@ typedef struct AVCUDADeviceContext {
  * AVHWFramesContext.hwctx is currently not used
  */
 
+/**
+ * @defgroup hwcontext_cuda Device context creation flags
+ *
+ * Flags for av_hwdevice_ctx_create.
+ *
+ * @{
+ */
+
+/**
+ * Use primary device context instead of creating a new one.
+ */
+#define AV_CUDA_USE_PRIMARY_CONTEXT (1 << 0)
+
+/**
+ * @}
+ */
+
 #endif /* AVUTIL_HWCONTEXT_CUDA_H */
index e1bc6ff..d5633c5 100644 (file)
@@ -31,6 +31,8 @@
 struct AVCUDADeviceContextInternal {
     CudaFunctions *cuda_dl;
     int is_allocated;
+    CUdevice cuda_device;
+    int flags;
 };
 
 #endif /* AVUTIL_HWCONTEXT_CUDA_INTERNAL_H */
index af3abf7..e181633 100644 (file)
@@ -80,7 +80,7 @@
 
 #define LIBAVUTIL_VERSION_MAJOR  56
 #define LIBAVUTIL_VERSION_MINOR  36
-#define LIBAVUTIL_VERSION_MICRO 100
+#define LIBAVUTIL_VERSION_MICRO 101
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
                                                LIBAVUTIL_VERSION_MINOR, \