@@ -39,6 +39,7 @@ typedef struct NVDECDecoder {
AVBufferRef *hw_device_ref;
CUcontext cuda_ctx;
+ int is_ctx_externally_allocated;
CudaFunctions *cudl;
CuvidFunctions *cvdl;
@@ -188,6 +189,7 @@ static int nvdec_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref,
goto fail;
}
decoder->cuda_ctx = device_hwctx->cuda_ctx;
+ decoder->is_ctx_externally_allocated = device_hwctx->is_ctx_externally_allocated;
decoder->cudl = device_hwctx->internal->cuda_dl;
ret = cuvid_load_functions(&decoder->cvdl, logctx);
@@ -370,9 +372,11 @@ static int nvdec_retrieve_data(void *logctx, AVFrame *frame)
unsigned int offset = 0;
int ret = 0;
- err = decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx);
- if (err != CUDA_SUCCESS)
- return AVERROR_UNKNOWN;
+ if (!decoder->is_ctx_externally_allocated) {
+ err = decoder->cudl->cuCtxPushCurrent(decoder->cuda_ctx);
+ if (err != CUDA_SUCCESS)
+ return AVERROR_UNKNOWN;
+ }
err = decoder->cvdl->cuvidMapVideoFrame(decoder->decoder, cf->idx, &devptr,
&pitch, &vpp);
@@ -411,7 +415,9 @@ copy_fail:
decoder->cvdl->cuvidUnmapVideoFrame(decoder->decoder, devptr);
finish:
- decoder->cudl->cuCtxPopCurrent(&dummy);
+ if (!decoder->is_ctx_externally_allocated)
+ decoder->cudl->cuCtxPopCurrent(&dummy);
+
return ret;
}
@@ -575,12 +575,17 @@ int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
AVHWDeviceContext *device_ctx;
int ret = 0;
- device_ref = av_hwdevice_ctx_alloc(type);
- if (!device_ref) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ if (!*pdevice_ref) {
+ device_ref = av_hwdevice_ctx_alloc(type);
+ if (!device_ref) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ device_ctx = (AVHWDeviceContext*)device_ref->data;
+ } else {
+ device_ref = *pdevice_ref;
+ device_ctx = (AVHWDeviceContext*)device_ref->data;
}
- device_ctx = (AVHWDeviceContext*)device_ref->data;
if (!device_ctx->internal->hw_type->device_create) {
ret = AVERROR(ENOSYS);
@@ -73,11 +73,13 @@ static void cuda_buffer_free(void *opaque, uint8_t *data)
CUcontext dummy;
- cu->cuCtxPushCurrent(hwctx->cuda_ctx);
+ if (!hwctx->is_ctx_externally_allocated)
+ cu->cuCtxPushCurrent(hwctx->cuda_ctx);
cu->cuMemFree((CUdeviceptr)data);
- cu->cuCtxPopCurrent(&dummy);
+ if (!hwctx->is_ctx_externally_allocated)
+ cu->cuCtxPopCurrent(&dummy);
}
static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
@@ -91,10 +93,12 @@ static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
CUdeviceptr data;
CUresult err;
- err = cu->cuCtxPushCurrent(hwctx->cuda_ctx);
- if (err != CUDA_SUCCESS) {
- av_log(ctx, AV_LOG_ERROR, "Error setting current CUDA context\n");
- return NULL;
+ if (!hwctx->is_ctx_externally_allocated) {
+ err = cu->cuCtxPushCurrent(hwctx->cuda_ctx);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Error setting current CUDA context\n");
+ return NULL;
+ }
}
err = cu->cuMemAlloc(&data, size);
@@ -108,7 +112,9 @@ static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
}
fail:
- cu->cuCtxPopCurrent(&dummy);
+ if (!hwctx->is_ctx_externally_allocated)
+ cu->cuCtxPopCurrent(&dummy);
+
return ret;
}
@@ -242,9 +248,11 @@ static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
CUresult err;
int i;
- err = cu->cuCtxPushCurrent(device_hwctx->cuda_ctx);
- if (err != CUDA_SUCCESS)
- return AVERROR_UNKNOWN;
+ if (!device_hwctx->is_ctx_externally_allocated) {
+ err = cu->cuCtxPushCurrent(device_hwctx->cuda_ctx);
+ if (err != CUDA_SUCCESS)
+ return AVERROR_UNKNOWN;
+ }
for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
CUDA_MEMCPY2D cpy = {
@@ -265,7 +273,8 @@ static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
}
}
- cu->cuCtxPopCurrent(&dummy);
+ if (!device_hwctx->is_ctx_externally_allocated)
+ cu->cuCtxPopCurrent(&dummy);
return 0;
}
@@ -281,9 +290,11 @@ static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
CUresult err;
int i;
- err = cu->cuCtxPushCurrent(device_hwctx->cuda_ctx);
- if (err != CUDA_SUCCESS)
- return AVERROR_UNKNOWN;
+ if (!device_hwctx->is_ctx_externally_allocated) {
+ err = cu->cuCtxPushCurrent(device_hwctx->cuda_ctx);
+ if (err != CUDA_SUCCESS)
+ return AVERROR_UNKNOWN;
+ }
for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
CUDA_MEMCPY2D cpy = {
@@ -304,7 +315,8 @@ static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
}
}
- cu->cuCtxPopCurrent(&dummy);
+ if (!device_hwctx->is_ctx_externally_allocated)
+ cu->cuCtxPopCurrent(&dummy);
return 0;
}
@@ -314,7 +326,8 @@ static void cuda_device_uninit(AVHWDeviceContext *ctx)
AVCUDADeviceContext *hwctx = ctx->hwctx;
if (hwctx->internal) {
- if (hwctx->internal->is_allocated && hwctx->cuda_ctx) {
+ if (hwctx->internal->is_allocated && hwctx->cuda_ctx
+ && !hwctx->is_ctx_externally_allocated) {
hwctx->internal->cuda_dl->cuCtxDestroy(hwctx->cuda_ctx);
hwctx->cuda_ctx = NULL;
}
@@ -351,42 +364,50 @@ error:
}
static int cuda_device_create(AVHWDeviceContext *ctx, const char *device,
- AVDictionary *opts, int flags)
+ AVDictionary *opts, int flags)
{
AVCUDADeviceContext *hwctx = ctx->hwctx;
CudaFunctions *cu;
CUdevice cu_device;
CUcontext dummy;
CUresult err;
- int device_idx = 0;
-
- if (device)
- device_idx = strtol(device, NULL, 0);
+ if (hwctx->cuda_ctx) {
+ hwctx->is_ctx_externally_allocated = 1;
+ } else {
+ hwctx->is_ctx_externally_allocated = 0;
+ }
if (cuda_device_init(ctx) < 0)
goto error;
- cu = hwctx->internal->cuda_dl;
+ if (!hwctx->is_ctx_externally_allocated) {
+ int device_idx = 0;
- err = cu->cuInit(0);
- if (err != CUDA_SUCCESS) {
- av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
- goto error;
- }
+ if (device)
+ device_idx = strtol(device, NULL, 0);
- err = cu->cuDeviceGet(&cu_device, device_idx);
- if (err != CUDA_SUCCESS) {
- av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", device_idx);
- goto error;
- }
+ cu = hwctx->internal->cuda_dl;
- err = cu->cuCtxCreate(&hwctx->cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, cu_device);
- if (err != CUDA_SUCCESS) {
- av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n");
- goto error;
- }
+ err = cu->cuInit(0);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
+ goto error;
+ }
+
+ err = cu->cuDeviceGet(&cu_device, device_idx);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", device_idx);
+ goto error;
+ }
- cu->cuCtxPopCurrent(&dummy);
+ err = cu->cuCtxCreate(&hwctx->cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, cu_device);
+ if (err != CUDA_SUCCESS) {
+ av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n");
+ goto error;
+ }
+
+ cu->cuCtxPopCurrent(&dummy);
+ }
hwctx->internal->is_allocated = 1;
@@ -42,6 +42,7 @@ typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
typedef struct AVCUDADeviceContext {
CUcontext cuda_ctx;
AVCUDADeviceContextInternal *internal;
+ int is_ctx_externally_allocated;
} AVCUDADeviceContext;
/**