[FFmpeg-devel] [PATCH] Allow using primary CUDA device context
Oleg Dobkin
olegd at anyvision.co
Mon Nov 18 12:56:54 EET 2019
On Mon, 2019-11-18 at 12:51 +0200, Oleg Dobkin wrote:
> I've changed enum into a flag and moved it into
> AVCUDADeviceContextInternal.
>
>
> Can't one just call cuCtxGetDevice on the context to get the device?
>
> Not sure the cuCtxGetDevice can be used for the primary context;
> also,
> according to documentation it returns device id not handle. Anyway,
> is
> it that bad to store an additional handle?
>
>
> Also needs configure updated for the higher ffnvcodec version
>
> I'm looking at the configure and can't figure out how ffnvcodec
> version
> is enforced. The script seems to accept several ranges of ffnvcodec
> versions. I could just increment the top-level check, but I'm not
> sure
> this is the correct way.
>
> On Sun, 2019-11-17 at 23:31 +0100, Timo Rothenpieler wrote:
>
> On 17.11.2019 15:58, Oleg Dobkin wrote:
>
> Add AVCUDADeviceContextFlags to control the creation of CUDA device
> context for the hardware CUDA decoder.
>
> The current values are 0 (default behavior) - new context will be
> created for each decoder, and 1 - primary CUDA context will be used.
>
> There are several reasons for using primary device context instead of
> creating a new one:
>
> - This is the recommended way to handle device contexts (see
>
>
https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__CTX.html#group__CUDA__CTX_1g65dc0012348bc84810e2103a40d8e2cf
>
> )
>
> - Memory allocations, kernels and other state are associated with
> the
> current device context. Currently, the context is not accessible from
> FFmpeg API, so, technically, the memory created by the hardware
> decoder
> (the video frame) can't be safely read.
>
> Signed-off-by: Oleg Dobkin <olegd at anyvision.co>
> ---
> libavutil/hwcontext_cuda.c | 20 +++++++++++++++-----
> libavutil/hwcontext_cuda.h | 7 +++++++
> 2 files changed, 22 insertions(+), 5 deletions(-)
>
> diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c
> index cca39e9fc7..608ea57569 100644
> --- a/libavutil/hwcontext_cuda.c
> +++ b/libavutil/hwcontext_cuda.c
> @@ -281,8 +281,12 @@ 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->flags == DCF_CREATE_CONTEXT)
>
> Should actually be checking for the flag, not equality.
>
>
> + CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx));
> + else
> + CHECK_CU(cu->cuDevicePrimaryCtxRelease(hwctx-
>
> cuda_device));
> hwctx->cuda_ctx = NULL;
> + hwctx->cuda_device = NULL;
> }
> cuda_free_functions(&hwctx->internal->cuda_dl);
> }
> @@ -322,7 +326,6 @@ 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;
>
> @@ -338,18 +341,25 @@ 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->cuda_device,
> device_idx));
> if (ret < 0)
> goto error;
>
> - ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx,
> CU_CTX_SCHED_BLOCKING_SYNC, cu_device));
> + hwctx->flags = flags;
> +
> + if (flags == DCF_CREATE_CONTEXT)
> + ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx,
> CU_CTX_SCHED_BLOCKING_SYNC, hwctx->cuda_device));
> + else
> + ret = CHECK_CU(cu->cuDevicePrimaryCtxRetain(&hwctx-
>
> cuda_ctx, hwctx->cuda_device));
> +
> if (ret < 0)
> goto error;
>
> // Setting stream to NULL will make functions automatically use
> the default CUstream
> hwctx->stream = NULL;
>
> - CHECK_CU(cu->cuCtxPopCurrent(&dummy));
> + if (flags == DCF_CREATE_CONTEXT)
> + CHECK_CU(cu->cuCtxPopCurrent(&dummy));
>
> hwctx->internal->is_allocated = 1;
>
> diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
> index 81a0552cab..bab5eefe54 100644
> --- a/libavutil/hwcontext_cuda.h
> +++ b/libavutil/hwcontext_cuda.h
> @@ -34,6 +34,11 @@
> * AVBufferRefs whose data pointer is a CUdeviceptr.
> */
>
> +enum AVCUDADeviceContextFlags {
> + DCF_CREATE_CONTEXT = 0,
> + DCF_USE_PRIMARY_CONTEXT = 1
> +};
>
> I'd only define a flag for the new behavior. If it's not set, keep
> old
> behavior.
>
>
> typedef struct AVCUDADeviceContextInternal
> AVCUDADeviceContextInternal;
>
> /**
> @@ -43,6 +48,8 @@ typedef struct AVCUDADeviceContext {
> CUcontext cuda_ctx;
> CUstream stream;
> AVCUDADeviceContextInternal *internal;
> + CUdevice cuda_device;
>
> Can't one just call cuCtxGetDevice on the context to get the device?
>
>
> + enum AVCUDADeviceContextFlags flags;
>
> The device_create/av_hwdevice_ctx_create function already has a (at
> the
> moment unused) flags parameter. So there should be no need to add
> this here.
> If need be, the information should be stored in
> AVCUDADeviceContextInternal instead.
>
>
> } AVCUDADeviceContext;
>
>
> Also needs configure updated for the higher ffnvcodec version that's
> required after this patch, and probably deserved a lavu micro bump.
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
>
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-cuDevicePrimaryCtxRetain-and-cuDevicePrimaryCtxR.patch
Type: text/x-patch
Size: 2903 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20191118/361c04c7/attachment.bin>
More information about the ffmpeg-devel
mailing list