mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
nvdec: Add fallback for CUDA/OpenGL interop failure
It happens when local OpenGL context belongs to non-nvidia GPU.
This commit is contained in:
parent
efcabce98e
commit
22eab50907
4 changed files with 72 additions and 3 deletions
|
@ -92,6 +92,9 @@ typedef struct _GstNvCodecCudaVTable
|
||||||
CUresult (CUDAAPI *
|
CUresult (CUDAAPI *
|
||||||
CuGraphicsResourceSetMapFlags) (CUgraphicsResource resource,
|
CuGraphicsResourceSetMapFlags) (CUgraphicsResource resource,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
CUresult (CUDAAPI * CuGLGetDevices) (unsigned int *pCudaDeviceCount,
|
||||||
|
CUdevice * pCudaDevices, unsigned int cudaDeviceCount,
|
||||||
|
CUGLDeviceList deviceList);
|
||||||
} GstNvCodecCudaVTable;
|
} GstNvCodecCudaVTable;
|
||||||
|
|
||||||
static GstNvCodecCudaVTable gst_cuda_vtable = { 0, };
|
static GstNvCodecCudaVTable gst_cuda_vtable = { 0, };
|
||||||
|
@ -150,6 +153,7 @@ gst_cuda_load_library (void)
|
||||||
LOAD_SYMBOL (cuGraphicsGLRegisterImage, CuGraphicsGLRegisterImage);
|
LOAD_SYMBOL (cuGraphicsGLRegisterImage, CuGraphicsGLRegisterImage);
|
||||||
LOAD_SYMBOL (cuGraphicsGLRegisterBuffer, CuGraphicsGLRegisterBuffer);
|
LOAD_SYMBOL (cuGraphicsGLRegisterBuffer, CuGraphicsGLRegisterBuffer);
|
||||||
LOAD_SYMBOL (cuGraphicsResourceSetMapFlags, CuGraphicsResourceSetMapFlags);
|
LOAD_SYMBOL (cuGraphicsResourceSetMapFlags, CuGraphicsResourceSetMapFlags);
|
||||||
|
LOAD_SYMBOL (cuGLGetDevices, CuGLGetDevices);
|
||||||
|
|
||||||
vtable->loaded = TRUE;
|
vtable->loaded = TRUE;
|
||||||
|
|
||||||
|
@ -389,3 +393,13 @@ CuGraphicsResourceSetMapFlags (CUgraphicsResource resource, unsigned int flags)
|
||||||
|
|
||||||
return gst_cuda_vtable.CuGraphicsResourceSetMapFlags (resource, flags);
|
return gst_cuda_vtable.CuGraphicsResourceSetMapFlags (resource, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUresult CUDAAPI
|
||||||
|
CuGLGetDevices (unsigned int *pCudaDeviceCount, CUdevice * pCudaDevices,
|
||||||
|
unsigned int cudaDeviceCount, CUGLDeviceList deviceList)
|
||||||
|
{
|
||||||
|
g_assert (gst_cuda_vtable.CuGLGetDevices != NULL);
|
||||||
|
|
||||||
|
return gst_cuda_vtable.CuGLGetDevices (pCudaDeviceCount, pCudaDevices,
|
||||||
|
cudaDeviceCount, deviceList);
|
||||||
|
}
|
||||||
|
|
|
@ -142,5 +142,11 @@ G_GNUC_INTERNAL
|
||||||
CUresult CUDAAPI CuGraphicsResourceSetMapFlags (CUgraphicsResource resource,
|
CUresult CUDAAPI CuGraphicsResourceSetMapFlags (CUgraphicsResource resource,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL
|
||||||
|
CUresult CUDAAPI CuGLGetDevices (unsigned int * pCudaDeviceCount,
|
||||||
|
CUdevice * pCudaDevices,
|
||||||
|
unsigned int cudaDeviceCount,
|
||||||
|
CUGLDeviceList deviceList);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* __GST_CUDA_LOADER_H__ */
|
#endif /* __GST_CUDA_LOADER_H__ */
|
||||||
|
|
|
@ -479,7 +479,7 @@ gst_nvdec_negotiate (GstVideoDecoder * decoder)
|
||||||
if (nvdec->mem_type == GST_NVDEC_MEM_TYPE_GL &&
|
if (nvdec->mem_type == GST_NVDEC_MEM_TYPE_GL &&
|
||||||
!gst_nvdec_ensure_gl_context (nvdec)) {
|
!gst_nvdec_ensure_gl_context (nvdec)) {
|
||||||
GST_WARNING_OBJECT (nvdec,
|
GST_WARNING_OBJECT (nvdec,
|
||||||
"OpenGL context cannot support PBO memory, fallback to system memory");
|
"OpenGL context is not CUDA-compatible, fallback to system memory");
|
||||||
nvdec->mem_type = GST_NVDEC_MEM_TYPE_SYSTEM;
|
nvdec->mem_type = GST_NVDEC_MEM_TYPE_SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +579,7 @@ parser_display_callback (GstNvDec * nvdec, CUVIDPARSERDISPINFO * dispinfo)
|
||||||
GstVideoCodecFrame *frame = NULL;
|
GstVideoCodecFrame *frame = NULL;
|
||||||
GstBuffer *output_buffer = NULL;
|
GstBuffer *output_buffer = NULL;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gboolean copy_ret;
|
gboolean copy_ret = FALSE;
|
||||||
|
|
||||||
GST_LOG_OBJECT (nvdec, "picture index: %u", dispinfo->picture_index);
|
GST_LOG_OBJECT (nvdec, "picture index: %u", dispinfo->picture_index);
|
||||||
|
|
||||||
|
@ -639,7 +639,19 @@ parser_display_callback (GstNvDec * nvdec, CUVIDPARSERDISPINFO * dispinfo)
|
||||||
#ifdef HAVE_NVCODEC_GST_GL
|
#ifdef HAVE_NVCODEC_GST_GL
|
||||||
if (nvdec->mem_type == GST_NVDEC_MEM_TYPE_GL) {
|
if (nvdec->mem_type == GST_NVDEC_MEM_TYPE_GL) {
|
||||||
copy_ret = gst_nvdec_copy_device_to_gl (nvdec, dispinfo, output_buffer);
|
copy_ret = gst_nvdec_copy_device_to_gl (nvdec, dispinfo, output_buffer);
|
||||||
} else
|
|
||||||
|
/* FIXME: This is the case where OpenGL context of downstream glbufferpool
|
||||||
|
* belongs to non-nvidia (or different device).
|
||||||
|
* There should be enhancement to ensure nvdec has compatible OpenGL context
|
||||||
|
*/
|
||||||
|
if (!copy_ret) {
|
||||||
|
GST_WARNING_OBJECT (nvdec,
|
||||||
|
"Couldn't copy frame to GL memory, fallback to system memory");
|
||||||
|
nvdec->mem_type = GST_NVDEC_MEM_TYPE_SYSTEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!copy_ret)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
copy_ret = gst_nvdec_copy_device_to_system (nvdec, dispinfo, output_buffer);
|
copy_ret = gst_nvdec_copy_device_to_system (nvdec, dispinfo, output_buffer);
|
||||||
|
@ -1203,9 +1215,32 @@ gst_nvdec_finish (GstVideoDecoder * decoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_NVCODEC_GST_GL
|
#ifdef HAVE_NVCODEC_GST_GL
|
||||||
|
static void
|
||||||
|
gst_nvdec_check_cuda_device_from_context (GstGLContext * context,
|
||||||
|
gboolean * ret)
|
||||||
|
{
|
||||||
|
guint device_count = 0;
|
||||||
|
CUdevice device_list[1] = { 0, };
|
||||||
|
CUresult cuda_ret;
|
||||||
|
|
||||||
|
*ret = FALSE;
|
||||||
|
|
||||||
|
cuda_ret = CuGLGetDevices (&device_count,
|
||||||
|
device_list, 1, CU_GL_DEVICE_LIST_ALL);
|
||||||
|
|
||||||
|
if (!gst_cuda_result (cuda_ret) || device_count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*ret = TRUE;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_nvdec_ensure_gl_context (GstNvDec * nvdec)
|
gst_nvdec_ensure_gl_context (GstNvDec * nvdec)
|
||||||
{
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
if (!nvdec->gl_display) {
|
if (!nvdec->gl_display) {
|
||||||
GST_DEBUG_OBJECT (nvdec, "No available OpenGL display");
|
GST_DEBUG_OBJECT (nvdec, "No available OpenGL display");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1241,6 +1276,14 @@ gst_nvdec_ensure_gl_context (GstNvDec * nvdec)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_gl_context_thread_add (nvdec->gl_context,
|
||||||
|
(GstGLContextThreadFunc) gst_nvdec_check_cuda_device_from_context, &ret);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
GST_WARNING_OBJECT (nvdec, "Current OpenGL context is not CUDA-compatible");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,11 @@ typedef struct
|
||||||
gsize Height;
|
gsize Height;
|
||||||
} CUDA_MEMCPY2D;
|
} CUDA_MEMCPY2D;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CU_GL_DEVICE_LIST_ALL = 0x01,
|
||||||
|
} CUGLDeviceList;
|
||||||
|
|
||||||
#define CUDA_VERSION 10000
|
#define CUDA_VERSION 10000
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -112,6 +117,7 @@ typedef struct
|
||||||
#define cuMemcpy2D cuMemcpy2D_v2
|
#define cuMemcpy2D cuMemcpy2D_v2
|
||||||
#define cuMemcpy2DAsync cuMemcpy2DAsync_v2
|
#define cuMemcpy2DAsync cuMemcpy2DAsync_v2
|
||||||
#define cuMemFree cuMemFree_v2
|
#define cuMemFree cuMemFree_v2
|
||||||
|
#define cuGLGetDevices cuGLGetDevices_v2
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue