nvdec,nvenc: Port to dynamic library loading

... and put them into new nvcodec plugin.

* nvcodec plugin
Now each nvenc and nvdec element is moved to be a part of nvcodec plugin
for better interoperability.
Additionally, cuda runtime API header dependencies
(i.e., cuda_runtime_api.h and cuda_gl_interop.h) are removed.
Note that cuda runtime APIs have prefix "cuda". Since 1.16 release with
Windows support, only "cuda.h" and "cudaGL.h" dependent symbols have
been used except for some defined types. However, those types could be
replaced with other types which were defined by "cuda.h".

* dynamic library loading
CUDA library will be opened with g_module_open() instead of build-time linking.
On Windows, nvcuda.dll is installed to system path by CUDA Toolkit
installer, and on *nix, user should ensure that libcuda.so.1 can be
loadable (i.e., via LD_LIBRARY_PATH or default dlopen path)
Therefore, NVIDIA_VIDEO_CODEC_SDK_PATH env build time dependency for Windows
is removed.
This commit is contained in:
Seungha Yang 2019-05-17 22:27:50 +09:00
parent 5c3879ace6
commit c18fda03d9
32 changed files with 1057 additions and 509 deletions

View file

@ -881,103 +881,60 @@ AG_GST_CHECK_FEATURE(CUDA, [NVIDIA CUDA API],, [
HAVE_CUDA="yes"
if test "x$CUDA_PREFIX" != "x"; then
dnl only override if not already set
if test "x$CUDA_CFLAGS" = "x" -a "x$CUDA_LIBS" = "x"; then
if test "x$CUDA_CFLAGS" = "x"; then
dnl this is an educated guess, user can always override these
CUDA_CFLAGS="-I$CUDA_PREFIX/include"
CUDA_LIBS="-L$CUDA_PREFIX/lib -L$CUDA_PREFIX/lib64 -L$CUDA_PREFIX/lib/stubs -L$CUDA_PREFIX/lib64/stubs -lcuda -lcudart"
fi
else
PKG_CHECK_MODULES([CUDA], [cuda-10.1 cudart-10.1],, [
PKG_CHECK_MODULES([CUDA], [cuda-10.0 cudart-10.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.2 cudart-9.2],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.1 cudart-9.1],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.0 cudart-9.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-8.0 cudart-8.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-7.5 cudart-7.5],, [
PKG_CHECK_MODULES([CUDA], [cuda-7.0 cudart-7.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-6.5 cudart-6.5],, [
PKG_CHECK_MODULES([CUDA], [cuda-10.1],, [
PKG_CHECK_MODULES([CUDA], [cuda-10.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.2],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.1],, [
PKG_CHECK_MODULES([CUDA], [cuda-9.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-8.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-7.5],, [
PKG_CHECK_MODULES([CUDA], [cuda-7.0],, [
PKG_CHECK_MODULES([CUDA], [cuda-6.5],, [
AC_MSG_WARN([Could not find cuda headers/libraries])])])])])])])])])])
fi
HAVE_CUDA_H=no
HAVE_CUDART_H=no
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CUDA_CFLAGS $save_CPPFLAGS "
AC_CHECK_HEADER([cuda.h], [HAVE_CUDA_H=yes],
AC_MSG_WARN([Could not find cuda.h]))
AC_CHECK_HEADER([cuda_runtime_api.h], [HAVE_CUDART_H=yes],
AC_MSG_WARN([Could not find cuda_runtime_api.h]))
CPPFLAGS=$save_CPPFLAGS
dnl libcuda and libcudart libraries
save_LIBS="$LIBS"
LIBS="$CUDA_LIBS $save_LIBS"
HAVE_CUDART_LIB="no"
AC_CHECK_LIB(cudart,cudaGetErrorString,[HAVE_CUDART_LIB="yes"], [
AC_MSG_WARN([Could not find cudart library])])
HAVE_CUDA_LIB="no"
AC_CHECK_LIB(cuda,cuInit,[HAVE_CUDA_LIB="yes"], [
AC_MSG_WARN([Could not find cuda library])])
LIBS="$save_LIBS"
])
dnl *** NVDEC ***
translit(dnm, m, l) AM_CONDITIONAL(USE_NVDEC, true)
AG_GST_CHECK_FEATURE(NVDEC, [nvdec], nvdec, [
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CUDA_CFLAGS $save_CPPFLAGS"
CPPFLAGS=$save_CPPFLAGS
HAVE_NVCUVID=no
save_LIBS="$LIBS"
LIBS="$CUDA_LIBS $save_LIBS"
AC_CHECK_LIB(nvcuvid, cuvidCtxLock, [HAVE_NVCUVID=yes],
AC_MSG_WARN([Could not find library nvcuvid]))
LIBS="$save_LIBS"
if test "x$HAVE_NVCUVID" = "xyes"; then
HAVE_NVDEC=yes
else
HAVE_NVDEC=no
fi
])
dnl *** NVENC ***
translit(dnm, m, l) AM_CONDITIONAL(USE_NVENC, true)
AG_GST_CHECK_FEATURE(NVENC, [NVIDIA Encode API], nvenc, [
dnl libnvnidia-encode library
HAVE_NVENCODE_LIB=no
AC_ARG_VAR(NVENCODE_LIBS, [linker flags for nvidia-encode])
saved_LIBS="$LIBS"
LIBS="$NVENCODE_LIBS $saved_LIBS"
AC_CHECK_LIB(nvidia-encode, NvEncodeAPICreateInstance, [HAVE_NVENCODE_LIB="yes"],
AC_MSG_WARN([Could not find library nvidia-encode]))
NVENCODE_LIBS="$NVENCODE_LIBS -lnvidia-encode"
AC_SUBST(NVENCODE_LIBS)
LIBS="$saved_LIBS"
dnl *** USE_NVCODEC ***
translit(dnm, m, l) AM_CONDITIONAL(USE_NVCODEC, true)
AG_GST_CHECK_FEATURE(NVCODEC, [NVIDIA Codec plugin], nvcodec, [
USE_NVENC_GST_GL=no
if test "x$HAVE_CUDA_H" = "xyes" \
-a "x$HAVE_CUDART_H" = "xyes" \
-a "x$HAVE_CUDA_LIB" = "xyes" \
-a "x$HAVE_CUDART_LIB" = "xyes" \
-a "x$HAVE_NVENCODE_LIB" = "xyes"; then
HAVE_NVENC="yes"
if test "x$HAVE_CUDA_H" = "xyes"; then
HAVE_NVCODEC="yes"
if test "x$GST_GL_HAVE_API_GL" = "x1"; then
dnl cuda-gl interop header
dnl cudaGL header
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$save_CPPFLAGS $CUDA_CFLAGS"
AC_CHECK_HEADER([cuda_gl_interop.h], [
USE_NVENC_GST_GL="yes"
AC_DEFINE(HAVE_NVENC_GST_GL, [1] , [NVENC GStreamer OpenGL support available])
AC_CHECK_HEADER([cudaGL.h], [
USE_NVCODEC_GST_GL="yes"
AC_DEFINE(HAVE_NVCODEC_GST_GL, [1] , [NVCODEC GStreamer OpenGL support available])
], [], [
/* missing headers in old cudaGL.h */
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include <cuda.h>
])
CPPFLAGS="$save_CPPFLAGS"
fi
else
HAVE_NVENC="no"
HAVE_NVCODEC="no"
fi
])
AM_CONDITIONAL(USE_NVENC_GST_GL, test "x$USE_NVENC_GST_GL" = "xyes")
AM_CONDITIONAL(USE_NVCODEC_GST_GL, test "x$USE_NVCODEC_GST_GL" = "xyes")
dnl check for tinyalsa
translit(dnm, m, l) AM_CONDITIONAL(USE_TINYALSA, true)
@ -2494,8 +2451,7 @@ sys/fbdev/Makefile
sys/ipcpipeline/Makefile
sys/kms/Makefile
sys/msdk/Makefile
sys/nvdec/Makefile
sys/nvenc/Makefile
sys/nvcodec/Makefile
sys/opensles/Makefile
sys/shm/Makefile
sys/tinyalsa/Makefile

View file

@ -119,8 +119,7 @@ option('mplex', type : 'feature', value : 'auto', description : 'mplex audio/vid
option('msdk', type : 'feature', value : 'auto', description : 'Intel Media SDK video encoder/decoder plugin')
option('musepack', type : 'feature', value : 'auto', description : 'libmpcdec Musepack decoder plugin')
option('neon', type : 'feature', value : 'auto', description : 'NEON HTTP source plugin')
option('nvdec', type : 'feature', value : 'auto', description : 'NVIDIA GPU decoder plugin')
option('nvenc', type : 'feature', value : 'auto', description : 'NVIDIA GPU encoder plugin')
option('nvcodec', type : 'feature', value : 'auto', description : 'NVIDIA GPU codec plugin')
option('ofa', type : 'feature', value : 'auto', description : 'Open Fingerprint Architecture library plugin')
option('openal', type : 'feature', value : 'auto', description : 'OpenAL plugin')
option('openexr', type : 'feature', value : 'auto', description : 'OpenEXR plugin')

View file

@ -94,16 +94,10 @@ else
UVCH264_DIR=
endif
if USE_NVDEC
NVDEC_DIR=nvdec
if USE_NVCODEC
NVCODEC_DIR=nvcodec
else
NVDEC_DIR=
endif
if USE_NVENC
NVENC_DIR=nvenc
else
NVENC_DIR=
NVCODEC_DIR=
endif
if USE_TINYALSA
@ -118,10 +112,10 @@ else
MSDK_DIR=
endif
SUBDIRS = $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(IPCPIPELINE_DIR) $(KMS_DIR) $(OPENSLES_DIR) $(SHM_DIR) $(UVCH264_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR) $(NVDEC_DIR) $(NVENC_DIR) $(TINYALSA_DIR) $(MSDK_DIR)
SUBDIRS = $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(IPCPIPELINE_DIR) $(KMS_DIR) $(OPENSLES_DIR) $(SHM_DIR) $(UVCH264_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR) $(NVCODEC_DIR) $(TINYALSA_DIR) $(MSDK_DIR)
DIST_SUBDIRS = androidmedia applemedia bluez d3dvideosink decklink directsound dvb fbdev ipcpipeline kms dshowdecwrapper dshowsrcwrapper dshowvideosink \
opensles shm uvch264 wasapi winks winscreencap \
nvdec nvenc tinyalsa msdk
nvcodec tinyalsa msdk
include $(top_srcdir)/common/parallel-subdirs.mak

View file

@ -13,6 +13,7 @@ subdir('fbdev')
subdir('ipcpipeline')
subdir('kms')
subdir('msdk')
subdir('nvcodec')
subdir('opensles')
subdir('shm')
subdir('tinyalsa')
@ -21,98 +22,3 @@ subdir('wasapi')
subdir('winks')
subdir('winscreencap')
# CUDA dependency
cuda_dep = dependency('', required : false)
cudart_dep = dependency('', required : false)
cuda_libdir = ''
cuda_incdir = ''
cuda_versions = [
'10.1',
'10.0',
'9.2',
'9.1',
'9.0',
'8.0',
'7.5',
'7.0',
'6.5',
]
cuda_ver = ''
# FIXME: use break syntax when we use meson >= '0.49'
foreach v : cuda_versions
if cuda_ver == ''
cuda_dep = dependency('cuda-' + v, required: false)
cudart_dep = dependency('cudart-' + v, required: false)
if cuda_dep.found() and cudart_dep.found()
cuda_ver = v
endif
endif
endforeach
if cuda_dep.found()
cuda_header_found = cc.has_header('cuda.h', dependencies: cuda_dep)
cuda_lib_found = cc.has_function('cuInit', dependencies: cuda_dep)
if not cuda_header_found or not cuda_lib_found
message ('Missing required header and/or function in cuda dependency')
cuda_dep = dependency('', required : false)
endif
endif
if cudart_dep.found()
cudart_header_found = cc.has_header('cuda_runtime_api.h', dependencies: cudart_dep)
cudart_lib_found = cc.has_function('cudaGetErrorString', dependencies: cudart_dep)
if not cudart_header_found or not cudart_lib_found
message ('Missing required header and/or function in cudart dependency')
cudart_dep = dependency('', required : false)
endif
endif
if not cuda_dep.found() or not cudart_dep.found()
cuda_root = run_command(python3, '-c', 'import os; print(os.environ.get("CUDA_PATH"))').stdout().strip()
if cuda_root != '' and cuda_root != 'None'
if host_machine.system() == 'windows'
arc = ''
if build_machine.cpu_family() == 'x86_64'
arc = 'x64'
else
arc = 'Win32'
endif
cuda_libdir = join_paths (cuda_root, 'lib', arc)
else
cuda_libdir = [join_paths (cuda_root, 'lib'), join_paths (cuda_root, 'lib', 'stubs'),
join_paths (cuda_root, 'lib64'), join_paths (cuda_root, 'lib64', 'stubs')]
endif
cuda_incdir = join_paths (cuda_root, 'include')
cuda_lib = cc.find_library('cuda', dirs: cuda_libdir, required: false)
cudart_lib = cc.find_library('cudart', dirs: cuda_libdir, required: false)
if cuda_lib.found()
cuda_header_found = cc.has_header('cuda.h', args: '-I' + cuda_incdir)
cuda_lib_found = cc.has_function('cuInit', dependencies: cuda_lib)
if cuda_header_found and cuda_lib_found
cuda_dep = declare_dependency(include_directories: include_directories(cuda_incdir),
dependencies: cuda_lib)
endif
endif
if cudart_lib.found()
cudart_header_found = cc.has_header('cuda_runtime_api.h', args: '-I' + cuda_incdir)
cudart_lib_found = cc.has_function('cudaGetErrorString', dependencies: cudart_lib)
if cudart_header_found and cudart_lib_found
cudart_dep = declare_dependency(dependencies: cudart_lib)
endif
endif
endif
endif
if cuda_dep.found() and cudart_dep.found()
subdir('nvdec')
subdir('nvenc')
elif get_option('nvdec').enabled()
error('The nvdec plugin was enabled explicitly, but required CUDA dependencies were not found.')
elif get_option('nvenc').enabled()
error('The nvenc plugin was enabled explicitly, but required CUDA dependencies were not found.')
endif

46
sys/nvcodec/Makefile.am Normal file
View file

@ -0,0 +1,46 @@
plugin_LTLIBRARIES = libgstnvcodec.la
libgstnvcodec_la_SOURCES = \
plugin.c \
gstnvenc.c \
gstnvbaseenc.c \
gstnvh264enc.c \
gstnvh265enc.c \
gstcudaloader.c
if USE_NVCODEC_GST_GL
libgstnvcodec_la_SOURCES += \
gstnvdec.c \
gstcuvidloader.c
endif
noinst_HEADERS = \
gstnvdec.h \
gstnvenc.h \
gstcuvidloader.h \
gstnvbaseenc.h \
gstnvh264enc.h \
gstnvh265enc.h \
nvEncodeAPI.h \
cuviddec.h \
nvcuvid.h \
gstcuvidloader.h
libgstnvcodec_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_PBUTILS_CFLAGS) \
$(GST_VIDEO_CFLAGS) \
$(GST_CFLAGS) \
$(CUDA_CFLAGS)
libgstnvcodec_la_LIBADD = \
$(GST_PBUTILS_LIBS) \
$(GST_VIDEO_LIBS) \
$(GST_LIBS) \
$(GMODULE_NO_EXPORT_LIBS)
if USE_NVCODEC_GST_GL
libgstnvcodec_la_CFLAGS += $(GST_GL_CFLAGS)
libgstnvcodec_la_LIBADD += $(GST_GL_LIBS)
endif
libgstnvcodec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

331
sys/nvcodec/gstcudaloader.c Normal file
View file

@ -0,0 +1,331 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstcudaloader.h"
#include <gmodule.h>
#ifndef G_OS_WIN32
#define CUDA_LIBNAME "libcuda.so.1"
#else
#define CUDA_LIBNAME "nvcuda.dll"
#endif
#define LOAD_SYMBOL(name,func) G_STMT_START { \
if (!g_module_symbol (module, G_STRINGIFY (name), (gpointer *) &vtable->func)) { \
GST_ERROR ("Failed to load '%s' from %s, %s", G_STRINGIFY (name), filename, g_module_error()); \
goto error; \
} \
} G_STMT_END;
typedef struct _GstNvCodecCudaVTable
{
gboolean loaded;
CUresult (*CuInit) (unsigned int Flags);
CUresult (*CuGetErrorName) (CUresult error, const char **pStr);
CUresult (*CuGetErrorString) (CUresult error, const char **pStr);
CUresult (*CuCtxCreate) (CUcontext * pctx, unsigned int flags,
CUdevice dev);
CUresult (*CuCtxDestroy) (CUcontext ctx);
CUresult (*CuCtxPopCurrent) (CUcontext * pctx);
CUresult (*CuCtxPushCurrent) (CUcontext ctx);
CUresult (*CuGraphicsMapResources) (unsigned int count,
CUgraphicsResource * resources, CUstream hStream);
CUresult (*CuGraphicsUnmapResources) (unsigned int count,
CUgraphicsResource * resources, CUstream hStream);
CUresult (*CuGraphicsSubResourceGetMappedArray) (CUarray * pArray,
CUgraphicsResource resource, unsigned int arrayIndex,
unsigned int mipLevel);
CUresult (*CuGraphicsResourceGetMappedPointer) (CUdeviceptr * pDevPtr,
size_t * pSize, CUgraphicsResource resource);
CUresult (*CuGraphicsUnregisterResource) (CUgraphicsResource resource);
CUresult (*CuMemAlloc) (CUdeviceptr * dptr, unsigned int bytesize);
CUresult (*CuMemAllocPitch) (CUdeviceptr * dptr, size_t * pPitch,
size_t WidthInBytes, size_t Height, unsigned int ElementSizeBytes);
CUresult (*CuMemcpy2D) (const CUDA_MEMCPY2D * pCopy);
CUresult (*CuMemFree) (CUdeviceptr dptr);
CUresult (*CuDeviceGet) (CUdevice * device, int ordinal);
CUresult (*CuDeviceGetCount) (int *count);
CUresult (*CuDeviceGetName) (char *name, int len, CUdevice dev);
CUresult (*CuDeviceGetAttribute) (int *pi, CUdevice_attribute attrib,
CUdevice dev);
CUresult (*CuGraphicsGLRegisterImage) (CUgraphicsResource * pCudaResource,
unsigned int image, unsigned int target, unsigned int Flags);
CUresult (*CuGraphicsGLRegisterBuffer) (CUgraphicsResource * pCudaResource,
unsigned int buffer, unsigned int Flags);
} GstNvCodecCudaVTable;
static GstNvCodecCudaVTable gst_cuda_vtable = { 0, };
gboolean
gst_cuda_load_library (void)
{
GModule *module;
const gchar *filename = CUDA_LIBNAME;
GstNvCodecCudaVTable *vtable;
if (gst_cuda_vtable.loaded)
return TRUE;
module = g_module_open (filename, G_MODULE_BIND_LAZY);
if (module == NULL) {
GST_ERROR ("Could not open library %s, %s", filename, g_module_error ());
return FALSE;
}
vtable = &gst_cuda_vtable;
/* cuda.h */
LOAD_SYMBOL (cuInit, CuInit);
LOAD_SYMBOL (cuGetErrorName, CuGetErrorName);
LOAD_SYMBOL (cuGetErrorString, CuGetErrorString);
LOAD_SYMBOL (cuCtxCreate, CuCtxCreate);
LOAD_SYMBOL (cuCtxDestroy, CuCtxDestroy);
LOAD_SYMBOL (cuCtxPopCurrent, CuCtxPopCurrent);
LOAD_SYMBOL (cuCtxPushCurrent, CuCtxPushCurrent);
LOAD_SYMBOL (cuGraphicsMapResources, CuGraphicsMapResources);
LOAD_SYMBOL (cuGraphicsUnmapResources, CuGraphicsUnmapResources);
LOAD_SYMBOL (cuGraphicsSubResourceGetMappedArray,
CuGraphicsSubResourceGetMappedArray);
LOAD_SYMBOL (cuGraphicsResourceGetMappedPointer,
CuGraphicsResourceGetMappedPointer);
LOAD_SYMBOL (cuGraphicsUnregisterResource, CuGraphicsUnregisterResource);
LOAD_SYMBOL (cuMemAlloc, CuMemAlloc);
LOAD_SYMBOL (cuMemAllocPitch, CuMemAllocPitch);
LOAD_SYMBOL (cuMemcpy2D, CuMemcpy2D);
LOAD_SYMBOL (cuMemFree, CuMemFree);
LOAD_SYMBOL (cuDeviceGet, CuDeviceGet);
LOAD_SYMBOL (cuDeviceGetCount, CuDeviceGetCount);
LOAD_SYMBOL (cuDeviceGetName, CuDeviceGetName);
LOAD_SYMBOL (cuDeviceGetAttribute, CuDeviceGetAttribute);
/* cudaGL.h */
LOAD_SYMBOL (cuGraphicsGLRegisterImage, CuGraphicsGLRegisterImage);
LOAD_SYMBOL (cuGraphicsGLRegisterBuffer, CuGraphicsGLRegisterBuffer);
vtable->loaded = TRUE;
return TRUE;
error:
g_module_close (module);
return FALSE;
}
CUresult
CuInit (unsigned int Flags)
{
g_assert (gst_cuda_vtable.CuInit != NULL);
return gst_cuda_vtable.CuInit (Flags);
}
CUresult
CuGetErrorName (CUresult error, const char **pStr)
{
g_assert (gst_cuda_vtable.CuGetErrorName != NULL);
return gst_cuda_vtable.CuGetErrorName (error, pStr);
}
CUresult
CuGetErrorString (CUresult error, const char **pStr)
{
g_assert (gst_cuda_vtable.CuGetErrorString != NULL);
return gst_cuda_vtable.CuGetErrorString (error, pStr);
}
CUresult
CuCtxCreate (CUcontext * pctx, unsigned int flags, CUdevice dev)
{
g_assert (gst_cuda_vtable.CuCtxCreate != NULL);
return gst_cuda_vtable.CuCtxCreate (pctx, flags, dev);
}
CUresult
CuCtxDestroy (CUcontext ctx)
{
g_assert (gst_cuda_vtable.CuCtxDestroy != NULL);
return gst_cuda_vtable.CuCtxDestroy (ctx);
}
CUresult
CuCtxPopCurrent (CUcontext * pctx)
{
g_assert (gst_cuda_vtable.CuCtxPopCurrent != NULL);
return gst_cuda_vtable.CuCtxPopCurrent (pctx);
}
CUresult
CuCtxPushCurrent (CUcontext ctx)
{
g_assert (gst_cuda_vtable.CuCtxPushCurrent != NULL);
return gst_cuda_vtable.CuCtxPushCurrent (ctx);
}
CUresult
CuGraphicsMapResources (unsigned int count, CUgraphicsResource * resources,
CUstream hStream)
{
g_assert (gst_cuda_vtable.CuGraphicsMapResources != NULL);
return gst_cuda_vtable.CuGraphicsMapResources (count, resources, hStream);
}
CUresult
CuGraphicsUnmapResources (unsigned int count, CUgraphicsResource * resources,
CUstream hStream)
{
g_assert (gst_cuda_vtable.CuGraphicsUnmapResources != NULL);
return gst_cuda_vtable.CuGraphicsUnmapResources (count, resources, hStream);
}
CUresult
CuGraphicsSubResourceGetMappedArray (CUarray * pArray,
CUgraphicsResource resource, unsigned int arrayIndex, unsigned int mipLevel)
{
g_assert (gst_cuda_vtable.CuGraphicsSubResourceGetMappedArray != NULL);
return gst_cuda_vtable.CuGraphicsSubResourceGetMappedArray (pArray, resource,
arrayIndex, mipLevel);
}
CUresult
CuGraphicsResourceGetMappedPointer (CUdeviceptr * pDevPtr, size_t * pSize,
CUgraphicsResource resource)
{
g_assert (gst_cuda_vtable.CuGraphicsResourceGetMappedPointer != NULL);
return gst_cuda_vtable.CuGraphicsResourceGetMappedPointer (pDevPtr, pSize,
resource);
}
CUresult
CuGraphicsUnregisterResource (CUgraphicsResource resource)
{
g_assert (gst_cuda_vtable.CuGraphicsUnregisterResource != NULL);
return gst_cuda_vtable.CuGraphicsUnregisterResource (resource);
}
CUresult
CuMemAlloc (CUdeviceptr * dptr, unsigned int bytesize)
{
g_assert (gst_cuda_vtable.CuMemAlloc != NULL);
return gst_cuda_vtable.CuMemAlloc (dptr, bytesize);
}
CUresult
CuMemAllocPitch (CUdeviceptr * dptr, size_t * pPitch, size_t WidthInBytes,
size_t Height, unsigned int ElementSizeBytes)
{
g_assert (gst_cuda_vtable.CuMemAllocPitch != NULL);
return gst_cuda_vtable.CuMemAllocPitch (dptr, pPitch, WidthInBytes, Height,
ElementSizeBytes);
}
CUresult
CuMemcpy2D (const CUDA_MEMCPY2D * pCopy)
{
g_assert (gst_cuda_vtable.CuMemcpy2D != NULL);
return gst_cuda_vtable.CuMemcpy2D (pCopy);
}
CUresult
CuMemFree (CUdeviceptr dptr)
{
g_assert (gst_cuda_vtable.CuMemFree != NULL);
return gst_cuda_vtable.CuMemFree (dptr);
}
CUresult
CuDeviceGet (CUdevice * device, int ordinal)
{
g_assert (gst_cuda_vtable.CuDeviceGet != NULL);
return gst_cuda_vtable.CuDeviceGet (device, ordinal);
}
CUresult
CuDeviceGetCount (int *count)
{
g_assert (gst_cuda_vtable.CuDeviceGetCount != NULL);
return gst_cuda_vtable.CuDeviceGetCount (count);
}
CUresult
CuDeviceGetName (char *name, int len, CUdevice dev)
{
g_assert (gst_cuda_vtable.CuDeviceGetName != NULL);
return gst_cuda_vtable.CuDeviceGetName (name, len, dev);
}
CUresult
CuDeviceGetAttribute (int *pi, CUdevice_attribute attrib, CUdevice dev)
{
g_assert (gst_cuda_vtable.CuDeviceGetAttribute != NULL);
return gst_cuda_vtable.CuDeviceGetAttribute (pi, attrib, dev);
}
/* cudaGL.h */
CUresult
CuGraphicsGLRegisterImage (CUgraphicsResource * pCudaResource,
unsigned int image, unsigned int target, unsigned int Flags)
{
g_assert (gst_cuda_vtable.CuGraphicsGLRegisterImage != NULL);
return gst_cuda_vtable.CuGraphicsGLRegisterImage (pCudaResource, image,
target, Flags);
}
CUresult
CuGraphicsGLRegisterBuffer (CUgraphicsResource * pCudaResource,
unsigned int buffer, unsigned int Flags)
{
g_assert (gst_cuda_vtable.CuGraphicsGLRegisterBuffer != NULL);
return gst_cuda_vtable.CuGraphicsGLRegisterBuffer (pCudaResource, buffer,
Flags);
}

128
sys/nvcodec/gstcudaloader.h Normal file
View file

@ -0,0 +1,128 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_CUDA_LOADER_H__
#define __GST_CUDA_LOADER_H__
#include <gst/gst.h>
#include <cuda.h>
G_BEGIN_DECLS
G_GNUC_INTERNAL
gboolean gst_cuda_load_library (void);
/* cuda.h */
G_GNUC_INTERNAL
CUresult CuInit (unsigned int Flags);
G_GNUC_INTERNAL
CUresult CuGetErrorName (CUresult error,
const char **pStr);
G_GNUC_INTERNAL
CUresult CuGetErrorString (CUresult error,
const char **pStr);
G_GNUC_INTERNAL
CUresult CuCtxCreate (CUcontext * pctx,
unsigned int flags,
CUdevice dev);
G_GNUC_INTERNAL
CUresult CuCtxDestroy (CUcontext ctx);
G_GNUC_INTERNAL
CUresult CuCtxPopCurrent (CUcontext * pctx);
G_GNUC_INTERNAL
CUresult CuCtxPushCurrent (CUcontext ctx);
G_GNUC_INTERNAL
CUresult CuGraphicsMapResources (unsigned int count,
CUgraphicsResource * resources,
CUstream hStream);
G_GNUC_INTERNAL
CUresult CuGraphicsUnmapResources (unsigned int count,
CUgraphicsResource * resources,
CUstream hStream);
G_GNUC_INTERNAL
CUresult CuGraphicsSubResourceGetMappedArray (CUarray * pArray,
CUgraphicsResource resource,
unsigned int arrayIndex,
unsigned int mipLevel);
G_GNUC_INTERNAL
CUresult CuGraphicsResourceGetMappedPointer (CUdeviceptr * pDevPtr,
size_t * pSize,
CUgraphicsResource resource);
G_GNUC_INTERNAL
CUresult CuGraphicsUnregisterResource (CUgraphicsResource resource);
G_GNUC_INTERNAL
CUresult CuMemAlloc (CUdeviceptr * dptr,
unsigned int bytesize);
G_GNUC_INTERNAL
CUresult CuMemAllocPitch (CUdeviceptr * dptr,
size_t * pPitch,
size_t WidthInBytes,
size_t Height,
unsigned int ElementSizeBytes);
G_GNUC_INTERNAL
CUresult CuMemcpy2D (const CUDA_MEMCPY2D * pCopy);
G_GNUC_INTERNAL
CUresult CuMemFree (CUdeviceptr dptr);
G_GNUC_INTERNAL
CUresult CuDeviceGet (CUdevice * device,
int ordinal);
G_GNUC_INTERNAL
CUresult CuDeviceGetCount (int *count);
G_GNUC_INTERNAL
CUresult CuDeviceGetName (char *name,
int len,
CUdevice dev);
G_GNUC_INTERNAL
CUresult CuDeviceGetAttribute (int *pi,
CUdevice_attribute attrib,
CUdevice dev);
/* cudaGL.h */
G_GNUC_INTERNAL
CUresult CuGraphicsGLRegisterImage (CUgraphicsResource * pCudaResource,
unsigned int image,
unsigned int target,
unsigned int Flags);
G_GNUC_INTERNAL
CUresult CuGraphicsGLRegisterBuffer (CUgraphicsResource * pCudaResource,
unsigned int buffer,
unsigned int Flags);
G_END_DECLS
#endif /* __GST_CUDA_LOADER_H__ */

View file

@ -0,0 +1,203 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstcuvidloader.h"
#include <gmodule.h>
#ifdef G_OS_WIN32
#define NVCUVID_LIBNAME "nvcuvid.dll"
#else
#define NVCUVID_LIBNAME "libnvcuvid.so.1"
#endif
#define LOAD_SYMBOL(name,func) G_STMT_START { \
if (!g_module_symbol (module, G_STRINGIFY (name), (gpointer *) &vtable->func)) { \
GST_ERROR ("Failed to load '%s' from %s, %s", G_STRINGIFY (name), filename, g_module_error()); \
goto error; \
} \
} G_STMT_END;
typedef struct _GstnvdecCuvidVTable
{
gboolean loaded;
CUresult (*CuvidCtxLockCreate) (CUvideoctxlock * pLock, CUcontext ctx);
CUresult (*CuvidCtxLockDestroy) (CUvideoctxlock lck);
CUresult (*CuvidCtxLock) (CUvideoctxlock lck, unsigned int reserved_flags);
CUresult (*CuvidCtxUnlock) (CUvideoctxlock lck,
unsigned int reserved_flags);
CUresult (*CuvidCreateDecoder) (CUvideodecoder * phDecoder,
CUVIDDECODECREATEINFO * pdci);
CUresult (*CuvidDestroyDecoder) (CUvideodecoder hDecoder);
CUresult (*CuvidDecodePicture) (CUvideodecoder hDecoder,
CUVIDPICPARAMS * pPicParams);
CUresult (*CuvidCreateVideoParser) (CUvideoparser * pObj,
CUVIDPARSERPARAMS * pParams);
CUresult (*CuvidParseVideoData) (CUvideoparser obj,
CUVIDSOURCEDATAPACKET * pPacket);
CUresult (*CuvidDestroyVideoParser) (CUvideoparser obj);
CUresult (*CuvidMapVideoFrame) (CUvideodecoder hDecoder, int nPicIdx,
guintptr * pDevPtr, unsigned int *pPitch, CUVIDPROCPARAMS * pVPP);
CUresult (*CuvidUnmapVideoFrame) (CUvideodecoder hDecoder, guintptr DevPtr);
} GstnvdecCuvidVTable;
static GstnvdecCuvidVTable gst_cuvid_vtable = { 0, };
gboolean
gst_cuvid_load_library (void)
{
GModule *module;
const gchar *filename = NVCUVID_LIBNAME;
GstnvdecCuvidVTable *vtable;
if (gst_cuvid_vtable.loaded)
return TRUE;
module = g_module_open (filename, G_MODULE_BIND_LAZY);
if (module == NULL) {
GST_ERROR ("Could not open library %s, %s", filename, g_module_error ());
return FALSE;
}
vtable = &gst_cuvid_vtable;
LOAD_SYMBOL (cuvidCtxLockCreate, CuvidCtxLockCreate);
LOAD_SYMBOL (cuvidCtxLockDestroy, CuvidCtxLockDestroy);
LOAD_SYMBOL (cuvidCtxLock, CuvidCtxLock);
LOAD_SYMBOL (cuvidCtxUnlock, CuvidCtxUnlock);
LOAD_SYMBOL (cuvidCreateDecoder, CuvidCreateDecoder);
LOAD_SYMBOL (cuvidDestroyDecoder, CuvidDestroyDecoder);
LOAD_SYMBOL (cuvidDecodePicture, CuvidDecodePicture);
LOAD_SYMBOL (cuvidCreateVideoParser, CuvidCreateVideoParser);
LOAD_SYMBOL (cuvidParseVideoData, CuvidParseVideoData);
LOAD_SYMBOL (cuvidDestroyVideoParser, CuvidDestroyVideoParser);
LOAD_SYMBOL (cuvidMapVideoFrame, CuvidMapVideoFrame);
LOAD_SYMBOL (cuvidUnmapVideoFrame, CuvidUnmapVideoFrame);
vtable->loaded = TRUE;
return TRUE;
error:
g_module_close (module);
return FALSE;
}
CUresult
CuvidCtxLockCreate (CUvideoctxlock * pLock, CUcontext ctx)
{
g_assert (gst_cuvid_vtable.CuvidCtxLockCreate != NULL);
return gst_cuvid_vtable.CuvidCtxLockCreate (pLock, ctx);
}
CUresult
CuvidCtxLockDestroy (CUvideoctxlock lck)
{
g_assert (gst_cuvid_vtable.CuvidCtxLockDestroy != NULL);
return gst_cuvid_vtable.CuvidCtxLockDestroy (lck);
}
CUresult
CuvidCtxLock (CUvideoctxlock lck, unsigned int reserved_flags)
{
g_assert (gst_cuvid_vtable.CuvidCtxLock != NULL);
return gst_cuvid_vtable.CuvidCtxLock (lck, reserved_flags);
}
CUresult
CuvidCtxUnlock (CUvideoctxlock lck, unsigned int reserved_flags)
{
g_assert (gst_cuvid_vtable.CuvidCtxLockDestroy != NULL);
return gst_cuvid_vtable.CuvidCtxUnlock (lck, reserved_flags);
}
CUresult
CuvidCreateDecoder (CUvideodecoder * phDecoder, CUVIDDECODECREATEINFO * pdci)
{
g_assert (gst_cuvid_vtable.CuvidCreateDecoder != NULL);
return gst_cuvid_vtable.CuvidCreateDecoder (phDecoder, pdci);
}
CUresult
CuvidDestroyDecoder (CUvideodecoder hDecoder)
{
g_assert (gst_cuvid_vtable.CuvidDestroyDecoder != NULL);
return gst_cuvid_vtable.CuvidDestroyDecoder (hDecoder);
}
CUresult
CuvidDecodePicture (CUvideodecoder hDecoder, CUVIDPICPARAMS * pPicParams)
{
g_assert (gst_cuvid_vtable.CuvidDecodePicture != NULL);
return gst_cuvid_vtable.CuvidDecodePicture (hDecoder, pPicParams);
}
CUresult
CuvidCreateVideoParser (CUvideoparser * pObj, CUVIDPARSERPARAMS * pParams)
{
g_assert (gst_cuvid_vtable.CuvidCreateVideoParser != NULL);
return gst_cuvid_vtable.CuvidCreateVideoParser (pObj, pParams);
}
CUresult
CuvidParseVideoData (CUvideoparser obj, CUVIDSOURCEDATAPACKET * pPacket)
{
g_assert (gst_cuvid_vtable.CuvidParseVideoData != NULL);
return gst_cuvid_vtable.CuvidParseVideoData (obj, pPacket);
}
CUresult
CuvidDestroyVideoParser (CUvideoparser obj)
{
g_assert (gst_cuvid_vtable.CuvidDestroyVideoParser != NULL);
return gst_cuvid_vtable.CuvidDestroyVideoParser (obj);
}
CUresult
CuvidMapVideoFrame (CUvideodecoder hDecoder, int nPicIdx,
guintptr * pDevPtr, unsigned int *pPitch, CUVIDPROCPARAMS * pVPP)
{
g_assert (gst_cuvid_vtable.CuvidMapVideoFrame != NULL);
return gst_cuvid_vtable.CuvidMapVideoFrame (hDecoder, nPicIdx, pDevPtr,
pPitch, pVPP);
}
CUresult
CuvidUnmapVideoFrame (CUvideodecoder hDecoder, guintptr DevPtr)
{
g_assert (gst_cuvid_vtable.CuvidUnmapVideoFrame != NULL);
return gst_cuvid_vtable.CuvidUnmapVideoFrame (hDecoder, DevPtr);
}

View file

@ -0,0 +1,80 @@
/* GStreamer
* Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_CUVID_LOADER_H__
#define __GST_CUVID_LOADER_H__
#include <gst/gst.h>
#include "nvcuvid.h"
G_BEGIN_DECLS
/* cuvid.h */
G_GNUC_INTERNAL
gboolean gst_cuvid_load_library (void);
G_GNUC_INTERNAL
CUresult CuvidCtxLockCreate (CUvideoctxlock * pLock, CUcontext ctx);
G_GNUC_INTERNAL
CUresult CuvidCtxLockDestroy (CUvideoctxlock lck);
G_GNUC_INTERNAL
CUresult CuvidCtxLock (CUvideoctxlock lck,
unsigned int reserved_flags);
G_GNUC_INTERNAL
CUresult CuvidCtxUnlock (CUvideoctxlock lck,
unsigned int reserved_flags);
G_GNUC_INTERNAL
CUresult CuvidCreateDecoder (CUvideodecoder * phDecoder,
CUVIDDECODECREATEINFO * pdci);
G_GNUC_INTERNAL
CUresult CuvidDestroyDecoder (CUvideodecoder hDecoder);
G_GNUC_INTERNAL
CUresult CuvidDecodePicture (CUvideodecoder hDecoder,
CUVIDPICPARAMS * pPicParams);
G_GNUC_INTERNAL
CUresult CuvidCreateVideoParser (CUvideoparser * pObj,
CUVIDPARSERPARAMS * pParams);
G_GNUC_INTERNAL
CUresult CuvidParseVideoData (CUvideoparser obj,
CUVIDSOURCEDATAPACKET * pPacket);
G_GNUC_INTERNAL
CUresult CuvidDestroyVideoParser (CUvideoparser obj);
G_GNUC_INTERNAL
CUresult CuvidMapVideoFrame (CUvideodecoder hDecoder,
int nPicIdx,
guintptr * pDevPtr,
unsigned int *pPitch,
CUVIDPROCPARAMS * pVPP);
G_GNUC_INTERNAL
CUresult CuvidUnmapVideoFrame (CUvideodecoder hDecoder,
guintptr DevPtr);
G_END_DECLS
#endif /* __GST_CUVID_LOADER_H__ */

View file

@ -29,12 +29,15 @@
#define GST_CAT_DEFAULT gst_nvenc_debug
#if HAVE_NVENC_GST_GL
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>
#include <cudaGL.h>
#if HAVE_NVCODEC_GST_GL
#include <gst/gl/gl.h>
/* missing headers in old cudaGL.h */
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#include <cudaGL.h>
#endif
/* TODO:
@ -168,7 +171,7 @@ enum
* some period of time. */
G_LOCK_DEFINE_STATIC (initialization_lock);
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
struct gl_input_resource
{
GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES];
@ -439,7 +442,7 @@ gst_nv_base_enc_open (GstVideoEncoder * enc)
static void
gst_nv_base_enc_set_context (GstElement * element, GstContext * context)
{
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (element);
gst_gl_handle_set_context (element, context,
@ -456,12 +459,12 @@ gst_nv_base_enc_set_context (GstElement * element, GstContext * context)
static gboolean
gst_nv_base_enc_sink_query (GstVideoEncoder * enc, GstQuery * query)
{
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (enc);
#endif
switch (GST_QUERY_TYPE (query)) {
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
case GST_QUERY_CONTEXT:{
gboolean ret;
@ -494,7 +497,7 @@ gst_nv_base_enc_start (GstVideoEncoder * enc)
nvenc->last_flow = GST_FLOW_OK;
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
{
gst_gl_ensure_element_data (GST_ELEMENT (nvenc),
(GstGLDisplay **) & nvenc->display,
@ -834,7 +837,7 @@ gst_nv_base_enc_bitstream_thread (gpointer user_data)
void *in_buf = state->in_bufs[i];
g_assert (in_buf != NULL);
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
if (nvenc->gl_input) {
struct gl_input_resource *in_gl_resource = in_buf;
@ -972,11 +975,11 @@ gst_nv_base_enc_free_buffers (GstNvBaseEnc * nvenc)
for (i = 0; i < nvenc->n_bufs; ++i) {
NV_ENC_OUTPUT_PTR out_buf = nvenc->output_bufs[i];
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
if (nvenc->gl_input) {
struct gl_input_resource *in_gl_resource = nvenc->input_bufs[i];
cuCtxPushCurrent (nvenc->cuda_ctx);
CuCtxPushCurrent (nvenc->cuda_ctx);
if (in_gl_resource->mapped) {
GST_LOG_OBJECT (nvenc, "Unmap resource %p", in_gl_resource);
@ -998,14 +1001,14 @@ gst_nv_base_enc_free_buffers (GstNvBaseEnc * nvenc)
GST_ERROR_OBJECT (nvenc, "Failed to unregister resource %p, ret %d",
in_gl_resource, nv_ret);
nv_ret = cuMemFree ((CUdeviceptr) in_gl_resource->cuda_pointer);
nv_ret = CuMemFree ((CUdeviceptr) in_gl_resource->cuda_pointer);
if (nv_ret != NV_ENC_SUCCESS) {
GST_ERROR_OBJECT (nvenc, "Failed to free CUDA device memory, ret %d",
nv_ret);
}
g_free (in_gl_resource);
cuCtxPopCurrent (NULL);
CuCtxPopCurrent (NULL);
} else
#endif
{
@ -1282,7 +1285,7 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
/* now allocate some buffers only on first configuration */
if (!old_state) {
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
GstCapsFeatures *features;
#endif
guint num_macroblocks, i;
@ -1298,7 +1301,7 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
/* input buffers */
nvenc->input_bufs = g_new0 (gpointer, nvenc->n_bufs);
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
features = gst_caps_get_features (state->caps, 0);
if (gst_caps_features_contains (features,
GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) {
@ -1309,7 +1312,7 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
pixel_depth += GST_VIDEO_INFO_COMP_DEPTH (info, i);
}
cuCtxPushCurrent (nvenc->cuda_ctx);
CuCtxPushCurrent (nvenc->cuda_ctx);
for (i = 0; i < nvenc->n_bufs; ++i) {
struct gl_input_resource *in_gl_resource =
g_new0 (struct gl_input_resource, 1);
@ -1322,13 +1325,13 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
/* scratch buffer for non-contigious planer into a contigious buffer */
cu_ret =
cuMemAllocPitch ((CUdeviceptr *) & in_gl_resource->cuda_pointer,
CuMemAllocPitch ((CUdeviceptr *) & in_gl_resource->cuda_pointer,
&in_gl_resource->cuda_stride, input_width,
_get_frame_data_height (info), 16);
if (cu_ret != CUDA_SUCCESS) {
const gchar *err;
cuGetErrorString (cu_ret, &err);
CuGetErrorString (cu_ret, &err);
GST_ERROR_OBJECT (nvenc, "failed to alocate cuda scratch buffer "
"ret %d error :%s", cu_ret, err);
g_assert_not_reached ();
@ -1356,7 +1359,7 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
g_async_queue_push (nvenc->in_bufs_pool, nvenc->input_bufs[i]);
}
cuCtxPopCurrent (NULL);
CuCtxPopCurrent (NULL);
} else
#endif
{
@ -1493,7 +1496,7 @@ _plane_get_n_components (GstVideoInfo * info, guint plane)
}
}
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
struct map_gl_input
{
GstNvBaseEnc *nvenc;
@ -1505,12 +1508,12 @@ struct map_gl_input
static void
_map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data)
{
cudaError_t cuda_ret;
CUresult cuda_ret;
guint8 *data_pointer;
guint i;
CUDA_MEMCPY2D param;
cuCtxPushCurrent (data->nvenc->cuda_ctx);
CuCtxPushCurrent (data->nvenc->cuda_ctx);
data_pointer = data->in_gl_resource->cuda_pointer;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (data->info); i++) {
guint plane_n_components;
@ -1536,27 +1539,27 @@ _map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data)
gl_mem->mem.tex_id);
cuda_ret =
cuGraphicsGLRegisterBuffer (&data->in_gl_resource->cuda_texture,
gl_buf_obj->id, cudaGraphicsRegisterFlagsReadOnly);
if (cuda_ret != cudaSuccess) {
CuGraphicsGLRegisterBuffer (&data->in_gl_resource->cuda_texture,
gl_buf_obj->id, CU_GRAPHICS_REGISTER_FLAGS_READ_ONLY);
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to register GL texture %u to cuda "
"ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
}
cuda_ret =
cuGraphicsMapResources (1, &data->in_gl_resource->cuda_texture, 0);
if (cuda_ret != cudaSuccess) {
CuGraphicsMapResources (1, &data->in_gl_resource->cuda_texture, 0);
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to map GL texture %u into cuda "
"ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
}
cuda_ret =
cuGraphicsResourceGetMappedPointer (&data->in_gl_resource->
CuGraphicsResourceGetMappedPointer (&data->in_gl_resource->
cuda_plane_pointers[i], &data->in_gl_resource->cuda_num_bytes,
data->in_gl_resource->cuda_texture);
if (cuda_ret != cudaSuccess) {
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to get mapped pointer of map GL "
"texture %u in cuda ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
@ -1580,24 +1583,24 @@ _map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data)
param.WidthInBytes = _get_plane_width (data->info, i) * plane_n_components;
param.Height = _get_plane_height (data->info, i);
cuda_ret = cuMemcpy2D (&param);
if (cuda_ret != cudaSuccess) {
cuda_ret = CuMemcpy2D (&param);
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to copy GL texture %u into cuda "
"ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
}
cuda_ret =
cuGraphicsUnmapResources (1, &data->in_gl_resource->cuda_texture, 0);
if (cuda_ret != cudaSuccess) {
CuGraphicsUnmapResources (1, &data->in_gl_resource->cuda_texture, 0);
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to unmap GL texture %u from cuda "
"ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
}
cuda_ret =
cuGraphicsUnregisterResource (data->in_gl_resource->cuda_texture);
if (cuda_ret != cudaSuccess) {
CuGraphicsUnregisterResource (data->in_gl_resource->cuda_texture);
if (cuda_ret != CUDA_SUCCESS) {
GST_ERROR_OBJECT (data->nvenc, "failed to unregister GL texture %u from "
"cuda ret :%d", gl_mem->mem.tex_id, cuda_ret);
g_assert_not_reached ();
@ -1608,7 +1611,7 @@ _map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data)
data->in_gl_resource->cuda_stride *
_get_plane_height (&data->nvenc->input_info, i);
}
cuCtxPopCurrent (NULL);
CuCtxPopCurrent (NULL);
}
#endif
@ -1712,7 +1715,7 @@ gst_nv_base_enc_handle_frame (GstVideoEncoder * enc, GstVideoCodecFrame * frame)
if (!gst_nv_base_enc_set_format (enc, nvenc->input_state))
return GST_FLOW_ERROR;
}
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
if (nvenc->gl_input)
in_map_flags |= GST_MAP_GL;
#endif
@ -1737,7 +1740,7 @@ gst_nv_base_enc_handle_frame (GstVideoEncoder * enc, GstVideoCodecFrame * frame)
state = g_new0 (struct frame_state, 1);
state->n_buffers = 1;
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
if (nvenc->gl_input) {
struct gl_input_resource *in_gl_resource = input_buffer;
struct map_gl_input data;

View file

@ -53,8 +53,8 @@ cuda_OK (CUresult result)
const gchar *error_name, *error_text;
if (result != CUDA_SUCCESS) {
cuGetErrorName (result, &error_name);
cuGetErrorString (result, &error_text);
CuGetErrorName (result, &error_name);
CuGetErrorString (result, &error_text);
GST_WARNING ("CUDA call failed: %s, %s", error_name, error_text);
return FALSE;
}
@ -71,7 +71,7 @@ gst_nvdec_cuda_context_finalize (GObject * object)
if (self->lock) {
GST_DEBUG ("destroying CUDA context lock");
if (cuda_OK (cuvidCtxLockDestroy (self->lock)))
if (cuda_OK (CuvidCtxLockDestroy (self->lock)))
self->lock = NULL;
else
GST_ERROR ("failed to destroy CUDA context lock");
@ -79,7 +79,7 @@ gst_nvdec_cuda_context_finalize (GObject * object)
if (self->context) {
GST_DEBUG ("destroying CUDA context");
if (cuda_OK (cuCtxDestroy (self->context)))
if (cuda_OK (CuCtxDestroy (self->context)))
self->context = NULL;
else
GST_ERROR ("failed to destroy CUDA context");
@ -97,16 +97,16 @@ gst_nvdec_cuda_context_class_init (GstNvDecCudaContextClass * klass)
static void
gst_nvdec_cuda_context_init (GstNvDecCudaContext * self)
{
if (!cuda_OK (cuInit (0)))
if (!cuda_OK (CuInit (0)))
GST_ERROR ("failed to init CUDA");
if (!cuda_OK (cuCtxCreate (&self->context, CU_CTX_SCHED_AUTO, 0)))
if (!cuda_OK (CuCtxCreate (&self->context, CU_CTX_SCHED_AUTO, 0)))
GST_ERROR ("failed to create CUDA context");
if (!cuda_OK (cuCtxPopCurrent (NULL)))
if (!cuda_OK (CuCtxPopCurrent (NULL)))
GST_ERROR ("failed to pop current CUDA context");
if (!cuda_OK (cuvidCtxLockCreate (&self->lock, self->context)))
if (!cuda_OK (CuvidCtxLockCreate (&self->lock, self->context)))
GST_ERROR ("failed to create CUDA context lock");
}
@ -126,13 +126,13 @@ register_cuda_resource (GstGLContext * context, gpointer * args)
GstMapInfo map_info = GST_MAP_INFO_INIT;
guint texture_id;
if (!cuda_OK (cuvidCtxLock (cgr_info->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxLock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to lock CUDA context");
if (gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL)) {
texture_id = *(guint *) map_info.data;
if (!cuda_OK (cuGraphicsGLRegisterImage (&cgr_info->resource, texture_id,
if (!cuda_OK (CuGraphicsGLRegisterImage (&cgr_info->resource, texture_id,
GL_TEXTURE_2D, CU_GRAPHICS_REGISTER_FLAGS_WRITE_DISCARD)))
GST_WARNING ("failed to register texture with CUDA");
@ -140,7 +140,7 @@ register_cuda_resource (GstGLContext * context, gpointer * args)
} else
GST_WARNING ("failed to map memory");
if (!cuda_OK (cuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to unlock CUDA context");
}
@ -148,14 +148,14 @@ static void
unregister_cuda_resource (GstGLContext * context,
GstNvDecCudaGraphicsResourceInfo * cgr_info)
{
if (!cuda_OK (cuvidCtxLock (cgr_info->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxLock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to lock CUDA context");
if (!cuda_OK (cuGraphicsUnregisterResource ((const CUgraphicsResource)
if (!cuda_OK (CuGraphicsUnregisterResource ((const CUgraphicsResource)
cgr_info->resource)))
GST_WARNING ("failed to unregister resource");
if (!cuda_OK (cuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxUnlock (cgr_info->cuda_context->lock, 0)))
GST_WARNING ("failed to unlock CUDA context");
}
@ -285,14 +285,14 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
GST_DEBUG_OBJECT (nvdec, "width: %u, height: %u", width, height);
if (!nvdec->decoder || (nvdec->width != width || nvdec->height != height)) {
if (!cuda_OK (cuvidCtxLock (nvdec->cuda_context->lock, 0))) {
if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) {
GST_ERROR_OBJECT (nvdec, "failed to lock CUDA context");
return FALSE;
}
if (nvdec->decoder) {
GST_DEBUG_OBJECT (nvdec, "destroying decoder");
if (!cuda_OK (cuvidDestroyDecoder (nvdec->decoder))) {
if (!cuda_OK (CuvidDestroyDecoder (nvdec->decoder))) {
GST_ERROR_OBJECT (nvdec, "failed to destroy decoder");
ret = FALSE;
} else
@ -322,12 +322,12 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
create_info.target_rect.bottom = height;
if (nvdec->decoder
|| !cuda_OK (cuvidCreateDecoder (&nvdec->decoder, &create_info))) {
|| !cuda_OK (CuvidCreateDecoder (&nvdec->decoder, &create_info))) {
GST_ERROR_OBJECT (nvdec, "failed to create decoder");
ret = FALSE;
}
if (!cuda_OK (cuvidCtxUnlock (nvdec->cuda_context->lock, 0))) {
if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) {
GST_ERROR_OBJECT (nvdec, "failed to unlock CUDA context");
ret = FALSE;
}
@ -348,13 +348,13 @@ parser_decode_callback (GstNvDec * nvdec, CUVIDPICPARAMS * params)
GST_LOG_OBJECT (nvdec, "picture index: %u", params->CurrPicIdx);
if (!cuda_OK (cuvidCtxLock (nvdec->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0)))
GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context");
if (!cuda_OK (cuvidDecodePicture (nvdec->decoder, params)))
if (!cuda_OK (CuvidDecodePicture (nvdec->decoder, params)))
GST_WARNING_OBJECT (nvdec, "failed to decode picture");
if (!cuda_OK (cuvidCtxUnlock (nvdec->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0)))
GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context");
item = g_slice_new (GstNvDecQueueItem);
@ -404,28 +404,28 @@ maybe_destroy_decoder_and_parser (GstNvDec * nvdec)
{
gboolean ret = TRUE;
if (!cuda_OK (cuvidCtxLock (nvdec->cuda_context->lock, 0))) {
if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) {
GST_ERROR_OBJECT (nvdec, "failed to lock CUDA context");
return FALSE;
}
if (nvdec->decoder) {
GST_DEBUG_OBJECT (nvdec, "destroying decoder");
ret = cuda_OK (cuvidDestroyDecoder (nvdec->decoder));
ret = cuda_OK (CuvidDestroyDecoder (nvdec->decoder));
if (ret)
nvdec->decoder = NULL;
else
GST_ERROR_OBJECT (nvdec, "failed to destroy decoder");
}
if (!cuda_OK (cuvidCtxUnlock (nvdec->cuda_context->lock, 0))) {
if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0))) {
GST_ERROR_OBJECT (nvdec, "failed to unlock CUDA context");
return FALSE;
}
if (nvdec->parser) {
GST_DEBUG_OBJECT (nvdec, "destroying parser");
if (!cuda_OK (cuvidDestroyVideoParser (nvdec->parser))) {
if (!cuda_OK (CuvidDestroyVideoParser (nvdec->parser))) {
GST_ERROR_OBJECT (nvdec, "failed to destroy parser");
return FALSE;
}
@ -556,7 +556,7 @@ gst_nvdec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state)
(PFNVIDDISPLAYCALLBACK) parser_display_callback;
GST_DEBUG_OBJECT (nvdec, "creating parser");
if (!cuda_OK (cuvidCreateVideoParser (&nvdec->parser, &parser_params))) {
if (!cuda_OK (CuvidCreateVideoParser (&nvdec->parser, &parser_params))) {
GST_ERROR_OBJECT (nvdec, "failed to create parser");
return FALSE;
}
@ -572,7 +572,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
CUgraphicsResource *resources = (CUgraphicsResource *) args[2];
guint num_resources = GPOINTER_TO_UINT (args[3]);
CUVIDPROCPARAMS proc_params = { 0, };
CUdeviceptr dptr;
guintptr dptr;
CUarray array;
guint pitch, i;
CUDA_MEMCPY2D mcpy2d = { 0, };
@ -583,18 +583,18 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
proc_params.top_field_first = dispinfo->top_field_first;
proc_params.unpaired_field = dispinfo->repeat_first_field == -1;
if (!cuda_OK (cuvidCtxLock (nvdec->cuda_context->lock, 0))) {
if (!cuda_OK (CuvidCtxLock (nvdec->cuda_context->lock, 0))) {
GST_WARNING_OBJECT (nvdec, "failed to lock CUDA context");
return;
}
if (!cuda_OK (cuvidMapVideoFrame (nvdec->decoder, dispinfo->picture_index,
if (!cuda_OK (CuvidMapVideoFrame (nvdec->decoder, dispinfo->picture_index,
&dptr, &pitch, &proc_params))) {
GST_WARNING_OBJECT (nvdec, "failed to map CUDA video frame");
goto unlock_cuda_context;
}
if (!cuda_OK (cuGraphicsMapResources (num_resources, resources, NULL))) {
if (!cuda_OK (CuGraphicsMapResources (num_resources, resources, NULL))) {
GST_WARNING_OBJECT (nvdec, "failed to map CUDA resources");
goto unmap_video_frame;
}
@ -606,7 +606,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
mcpy2d.WidthInBytes = nvdec->width;
for (i = 0; i < num_resources; i++) {
if (!cuda_OK (cuGraphicsSubResourceGetMappedArray (&array, resources[i], 0,
if (!cuda_OK (CuGraphicsSubResourceGetMappedArray (&array, resources[i], 0,
0))) {
GST_WARNING_OBJECT (nvdec, "failed to map CUDA array");
break;
@ -616,19 +616,19 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
mcpy2d.dstArray = array;
mcpy2d.Height = nvdec->height / (i + 1);
if (!cuda_OK (cuMemcpy2D (&mcpy2d)))
if (!cuda_OK (CuMemcpy2D (&mcpy2d)))
GST_WARNING_OBJECT (nvdec, "memcpy to mapped array failed");
}
if (!cuda_OK (cuGraphicsUnmapResources (num_resources, resources, NULL)))
if (!cuda_OK (CuGraphicsUnmapResources (num_resources, resources, NULL)))
GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA resources");
unmap_video_frame:
if (!cuda_OK (cuvidUnmapVideoFrame (nvdec->decoder, dptr)))
if (!cuda_OK (CuvidUnmapVideoFrame (nvdec->decoder, dptr)))
GST_WARNING_OBJECT (nvdec, "failed to unmap CUDA video frame");
unlock_cuda_context:
if (!cuda_OK (cuvidCtxUnlock (nvdec->cuda_context->lock, 0)))
if (!cuda_OK (CuvidCtxUnlock (nvdec->cuda_context->lock, 0)))
GST_WARNING_OBJECT (nvdec, "failed to unlock CUDA context");
}
@ -963,7 +963,7 @@ gst_nvdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
if (GST_BUFFER_IS_DISCONT (frame->input_buffer))
packet.flags |= CUVID_PKT_DISCONTINUITY;
if (!cuda_OK (cuvidParseVideoData (nvdec->parser, &packet)))
if (!cuda_OK (CuvidParseVideoData (nvdec->parser, &packet)))
GST_WARNING_OBJECT (nvdec, "parser failed");
gst_buffer_unmap (frame->input_buffer, &map_info);
@ -984,7 +984,7 @@ gst_nvdec_flush (GstVideoDecoder * decoder)
packet.payload = NULL;
packet.flags = CUVID_PKT_ENDOFSTREAM;
if (!cuda_OK (cuvidParseVideoData (nvdec->parser, &packet)))
if (!cuda_OK (CuvidParseVideoData (nvdec->parser, &packet)))
GST_WARNING_OBJECT (nvdec, "parser failed");
handle_pending_frames (nvdec);
@ -1004,7 +1004,7 @@ gst_nvdec_drain (GstVideoDecoder * decoder)
packet.payload = NULL;
packet.flags = CUVID_PKT_ENDOFSTREAM;
if (!cuda_OK (cuvidParseVideoData (nvdec->parser, &packet)))
if (!cuda_OK (CuvidParseVideoData (nvdec->parser, &packet)))
GST_WARNING_OBJECT (nvdec, "parser failed");
return handle_pending_frames (nvdec);

View file

@ -30,7 +30,8 @@
#include <gst/gl/gl.h>
#include <gst/gl/gstglfuncs.h>
#include "nvcuvid.h"
#include "gstcuvidloader.h"
#include "gstcudaloader.h"
#include <cudaGL.h>
G_BEGIN_DECLS

View file

@ -283,7 +283,7 @@ gst_nvenc_create_cuda_context (guint device_id)
GST_INFO ("Initialising CUDA..");
cres = cuInit (0);
cres = CuInit (0);
if (cres != CUDA_SUCCESS) {
GST_WARNING ("Failed to initialise CUDA, error code: 0x%08x", cres);
@ -292,7 +292,7 @@ gst_nvenc_create_cuda_context (guint device_id)
GST_INFO ("Initialised CUDA");
cres = cuDeviceGetCount (&dev_count);
cres = CuDeviceGetCount (&dev_count);
if (cres != CUDA_SUCCESS || dev_count == 0) {
GST_WARNING ("No CUDA devices detected");
return NULL;
@ -300,11 +300,11 @@ gst_nvenc_create_cuda_context (guint device_id)
GST_INFO ("%d CUDA device(s) detected", dev_count);
for (i = 0; i < dev_count; ++i) {
if (cuDeviceGet (&cdev, i) == CUDA_SUCCESS
&& cuDeviceGetName (name, sizeof (name), cdev) == CUDA_SUCCESS
&& cuDeviceGetAttribute (&maj,
if (CuDeviceGet (&cdev, i) == CUDA_SUCCESS
&& CuDeviceGetName (name, sizeof (name), cdev) == CUDA_SUCCESS
&& CuDeviceGetAttribute (&maj,
CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cdev) == CUDA_SUCCESS
&& cuDeviceGetAttribute (&min,
&& CuDeviceGetAttribute (&min,
CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR,
cdev) == CUDA_SUCCESS) {
GST_INFO ("GPU #%d supports NVENC: %s (%s) (Compute SM %d.%d)", i,
@ -321,12 +321,12 @@ gst_nvenc_create_cuda_context (guint device_id)
return NULL;
}
if (cuCtxCreate (&cuda_ctx, 0, cuda_dev) != CUDA_SUCCESS) {
if (CuCtxCreate (&cuda_ctx, 0, cuda_dev) != CUDA_SUCCESS) {
GST_WARNING ("Failed to create CUDA context for cuda device %d", cuda_dev);
return NULL;
}
if (cuCtxPopCurrent (&old_ctx) != CUDA_SUCCESS) {
if (CuCtxPopCurrent (&old_ctx) != CUDA_SUCCESS) {
return NULL;
}
@ -339,7 +339,7 @@ gboolean
gst_nvenc_destroy_cuda_context (CUcontext ctx)
{
GST_INFO ("Destroying CUDA context %p", ctx);
return (cuCtxDestroy (ctx) == CUDA_SUCCESS);
return (CuCtxDestroy (ctx) == CUDA_SUCCESS);
}
static gboolean
@ -362,31 +362,27 @@ load_nvenc_library (void)
return TRUE;
}
static gboolean
plugin_init (GstPlugin * plugin)
gboolean
gst_nvenc_plugin_init (GstPlugin * plugin)
{
gboolean ret = TRUE;
GST_DEBUG_CATEGORY_INIT (gst_nvenc_debug, "nvenc", 0, "Nvidia NVENC encoder");
nvenc_api.version = NV_ENCODE_API_FUNCTION_LIST_VER;
if (!load_nvenc_library ())
return FALSE;
return TRUE;
if (nvEncodeAPICreateInstance (&nvenc_api) != NV_ENC_SUCCESS) {
GST_ERROR ("Failed to get NVEncodeAPI function table!");
} else {
GST_INFO ("Created NVEncodeAPI instance, got function table");
gst_element_register (plugin, "nvh264enc", GST_RANK_PRIMARY * 2,
ret &= gst_element_register (plugin, "nvh264enc", GST_RANK_PRIMARY * 2,
gst_nv_h264_enc_get_type ());
gst_element_register (plugin, "nvh265enc", GST_RANK_PRIMARY * 2,
ret &= gst_element_register (plugin, "nvh265enc", GST_RANK_PRIMARY * 2,
gst_nv_h265_enc_get_type ());
}
return TRUE;
return ret;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
nvenc,
"GStreamer NVENC plugin",
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -23,8 +23,8 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstcudaloader.h"
#include "nvEncodeAPI.h"
#include <cuda.h>
GST_DEBUG_CATEGORY_EXTERN (gst_nvenc_debug);
@ -36,4 +36,7 @@ gboolean gst_nvenc_cmp_guid (GUID g1, GUID g2);
NV_ENC_BUFFER_FORMAT gst_nvenc_get_nv_buffer_format (GstVideoFormat fmt);
gboolean gst_nvenc_plugin_init (GstPlugin * plugin);
#endif /* __GST_NVENC_H_INCLUDED__ */

View file

@ -30,17 +30,10 @@
GST_DEBUG_CATEGORY_STATIC (gst_nv_h264_enc_debug);
#define GST_CAT_DEFAULT gst_nv_h264_enc_debug
#if HAVE_NVENC_GST_GL
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>
#include <gst/gl/gl.h>
#endif
#define parent_class gst_nv_h264_enc_parent_class
G_DEFINE_TYPE (GstNvH264Enc, gst_nv_h264_enc, GST_TYPE_NV_BASE_ENC);
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
#define GL_CAPS_STR \
";" \
"video/x-raw(memory:GLMemory), " \

View file

@ -31,17 +31,10 @@
GST_DEBUG_CATEGORY_STATIC (gst_nv_h265_enc_debug);
#define GST_CAT_DEFAULT gst_nv_h265_enc_debug
#if HAVE_NVENC_GST_GL
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>
#include <gst/gl/gl.h>
#endif
#define parent_class gst_nv_h265_enc_parent_class
G_DEFINE_TYPE (GstNvH265Enc, gst_nv_h265_enc, GST_TYPE_NV_BASE_ENC);
#if HAVE_NVENC_GST_GL
#if HAVE_NVCODEC_GST_GL
#define GL_CAPS_STR \
";" \
"video/x-raw(memory:GLMemory), " \

102
sys/nvcodec/meson.build Normal file
View file

@ -0,0 +1,102 @@
nvcodec_sources = [
'plugin.c',
'gstnvenc.c',
'gstnvbaseenc.c',
'gstnvh264enc.c',
'gstnvh265enc.c',
'gstcudaloader.c',
]
nvdec_sources = [
'gstnvdec.c',
'gstcuvidloader.c',
]
use_nvcodec_gl = false
extra_c_args = []
cuda_dep = dependency('', required : false)
cuda_header_dep = dependency('', required : false)
cuda_incdir = ''
nvcodec_option = get_option('nvcodec')
if nvcodec_option.disabled()
subdir_done()
endif
cuda_versions = [
'10.1',
'10.0',
'9.2',
'9.1',
'9.0',
'8.0',
'7.5',
'7.0',
'6.5',
]
cuda_ver = ''
# FIXME: use break syntax when we use meson >= '0.49'
foreach v : cuda_versions
if cuda_ver == ''
cuda_dep = dependency('cuda-' + v, required: false)
if cuda_dep.found()
cuda_ver = v
endif
endif
endforeach
if cuda_dep.found()
if cc.has_header('cuda.h', dependencies: cuda_dep)
cuda_header_dep = cuda_dep.partial_dependency(compile_args : true, includes : true)
endif
endif
if not cuda_header_dep.found()
cuda_root = run_command(python3, '-c', 'import os; print(os.environ.get("CUDA_PATH"))').stdout().strip()
if cuda_root != '' and cuda_root != 'None'
cuda_incdir = join_paths (cuda_root, 'include')
if cc.has_header('cuda.h', args: '-I' + cuda_incdir)
cuda_header_dep = declare_dependency(include_directories: include_directories(cuda_incdir))
endif
endif
endif
if not cuda_header_dep.found()
if nvcodec_option.enabled()
error('The nvcodec plugin was enabled explicitly, but required CUDA dependency was not found.')
endif
subdir_done()
endif
if gstgl_dep.found()
if cuda_dep.found()
if cc.has_header('cudaGL.h', dependencies: cuda_dep)
use_nvcodec_gl = true
endif
else
if cc.has_header('cudaGL.h', args: '-I' + cuda_incdir)
use_nvcodec_gl = true
endif
endif
endif
if use_nvcodec_gl
# FIXME: make nvdec usable without OpenGL dependency
nvcodec_sources += nvdec_sources
extra_c_args += ['-DHAVE_NVCODEC_GST_GL=1']
endif
gstnvcodec = library('gstnvcodec',
nvcodec_sources,
c_args : gst_plugins_bad_args + extra_c_args,
include_directories : [configinc],
dependencies : [gstbase_dep, gstvideo_dep, gstpbutils_dep, gstgl_dep, cuda_header_dep, gmodule_dep],
install : true,
install_dir : plugins_install_dir,
)
pkgconfig.generate(gstnvcodec, install_dir : plugins_pkgconfig_install_dir)
plugins += [gstnvcodec]

View file

@ -29,15 +29,33 @@
#include "config.h"
#endif
#if HAVE_NVCODEC_GST_GL
#include "gstnvdec.h"
#endif
#include "gstnvenc.h"
static gboolean
plugin_init (GstPlugin * plugin)
{
return gst_element_register (plugin, "nvdec", GST_RANK_PRIMARY,
GST_TYPE_NVDEC);
gboolean ret = TRUE;
if (!gst_cuda_load_library ())
return TRUE;
#if HAVE_NVCODEC_GST_GL
/* FIXME: make nvdec usable without OpenGL dependency */
if (gst_cuvid_load_library ()) {
ret &= gst_element_register (plugin, "nvdec", GST_RANK_PRIMARY,
GST_TYPE_NVDEC);
}
#endif
ret &= gst_nvenc_plugin_init (plugin);
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, nvdec,
"GStreamer NVDEC plugin", plugin_init, VERSION, "BSD",
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, nvcodec,
"GStreamer NVCODEC plugin", plugin_init, VERSION, "LGPL",
GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)

View file

@ -1,28 +0,0 @@
plugin_LTLIBRARIES = libgstnvdec.la
libgstnvdec_la_SOURCES = \
gstnvdec.c \
plugin.c
noinst_HEADERS = \
cuviddec.h \
gstnvdec.h \
nvcuvid.h
libgstnvdec_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_GL_CFLAGS) \
$(GST_PBUTILS_CFLAGS) \
$(GST_VIDEO_CFLAGS) \
$(GST_CFLAGS) \
$(CUDA_CFLAGS)
libgstnvdec_la_LIBADD = \
$(GST_GL_LIBS) \
$(GST_PBUTILS_LIBS) \
$(GST_VIDEO_LIBS) \
$(GST_LIBS)
libgstnvdec_la_LIBADD += $(CUDA_LIBS) -lnvcuvid
libgstnvdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -1,51 +0,0 @@
nvdec_sources = [
'gstnvdec.c',
'plugin.c'
]
nvcuvid_dep_found = false
nvcuvid_incdirs = []
nvdec_option = get_option('nvdec')
if nvdec_option.disabled()
subdir_done()
endif
if host_machine.system() == 'windows'
cuda_libdirs = [cuda_libdir]
# NOTE: Newer CUDA toolkit versions do not ship with the nvcuvid library, and
# you must get it from the Nvidia Video Codec SDK. The SDK ships as a zip
# file, so there's no installer and you have to set this env var yourself.
video_sdk_root = run_command(python3, '-c', 'import os; print(os.environ.get("NVIDIA_VIDEO_CODEC_SDK_PATH"))').stdout().strip()
if video_sdk_root != '' and video_sdk_root != 'None'
cuda_libdirs += [join_paths(video_sdk_root, 'Samples', 'NvCodec', 'Lib', arc)]
nvcuvid_incdirs = include_directories(join_paths(video_sdk_root, 'Samples', 'NvCodec', 'NvDecoder'))
endif
nvcuvid_lib = cc.find_library('nvcuvid', dirs: cuda_libdirs, required: nvdec_option)
else
nvcuvid_lib = cc.find_library('nvcuvid', required: nvdec_option)
endif
if nvcuvid_lib.found() and cc.has_function('cuvidCtxLock', dependencies: nvcuvid_lib)
nvcuvid_dep = declare_dependency(dependencies: nvcuvid_lib,
include_directories: nvcuvid_incdirs)
nvcuvid_dep_found = true
endif
if nvdec_option.enabled() and not nvcuvid_dep_found
error('The nvdec plugin was enabled explicitly, but required nvcuvid library was not found.')
endif
if nvcuvid_dep_found
gstnvdec = library('gstnvdec',
nvdec_sources,
c_args : gst_plugins_bad_args,
include_directories : [configinc],
dependencies : [gstbase_dep, gstvideo_dep, gstpbutils_dep, gstgl_dep, cuda_dep, cudart_dep, nvcuvid_dep],
install : true,
install_dir : plugins_install_dir,
)
pkgconfig.generate(gstnvdec, install_dir : plugins_pkgconfig_install_dir)
plugins += [gstnvdec]
endif

View file

@ -1,34 +0,0 @@
plugin_LTLIBRARIES = libgstnvenc.la
libgstnvenc_la_SOURCES = \
gstnvenc.c \
gstnvbaseenc.c \
gstnvh264enc.c \
gstnvh265enc.c
noinst_HEADERS = \
gstnvenc.h \
gstnvbaseenc.h \
gstnvh264enc.h \
gstnvh265enc.h \
nvEncodeAPI.h
libgstnvenc_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_PBUTILS_CFLAGS) \
$(GST_VIDEO_CFLAGS) \
$(GST_CFLAGS) \
$(CUDA_CFLAGS)
libgstnvenc_la_LIBADD = \
$(GST_PBUTILS_LIBS) \
$(GST_VIDEO_LIBS) \
$(GST_LIBS) \
$(CUDA_LIBS) \
$(GMODULE_NO_EXPORT_LIBS)
if USE_NVENC_GST_GL
libgstnvenc_la_CFLAGS += $(GST_GL_CFLAGS)
libgstnvenc_la_LIBADD += $(GST_GL_LIBS)
endif
libgstnvenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -1,30 +0,0 @@
This plugin is intended for use with NVIDIA hardware. Specifically, the NVENC
block available in recent NVIDIA GPU hardware. This is provided by a
libnvidia-encode library provided by NVIDIA graphic drivers.
Requirements
------------
Cuda > 6.5
NVENC 5.0
See https://developer.nvidia.com/nvidia-video-codec-sdk for a list of
supported GPU's.
Building
--------
1. Retrieve the NVENC SDK
from https://developer.nvidia.com/nvidia-video-codec-sdk
- http://developer.download.nvidia.com/compute/nvenc/v5.0/nvenc_5.0.1_sdk.zip
2. unzip this somewhere and retreive or note the location of the
nvEncodeAPI.h under nvenc_api-5.0.1/Samples/common/inc/
3. Retreive a version of cuda from
https://developer.nvidia.com/cuda-downloads and install somewhere noting
the installation prefix (typically /opt/cuda or /usr/local/cuda)
4. Now that the dependencies are sorted, there are a couple of
environment variables and/or or configure arguments that are needed to
detect the necessary libraries/headers.
More information is available from the following locations
[1] - https://developer.nvidia.com/cuda-downloads
[2] - https://developer.nvidia.com/nvidia-video-codec-sdk

View file

@ -1,11 +0,0 @@
- check supported encoding formats (H.264 etc.), don't assume H.264
- check performance (time taken) of first cuInit()
- provide buffer pool
- more formats
- renegotiation
- support outputting of AVC as well as byte-stream, negotiate automatically

View file

@ -1,41 +0,0 @@
nvenc_sources = [
'gstnvbaseenc.c',
'gstnvenc.c',
'gstnvh264enc.c',
'gstnvh265enc.c',
]
use_nvenc_gl = false
extra_c_args = []
nvenc_option = get_option('nvenc')
if nvenc_option.disabled()
subdir_done()
endif
if cuda_dep.type_name() == 'internal'
if cc.has_header('cuda_gl_interop.h', args: '-I' + cuda_incdir)
use_nvenc_gl = true
endif
else
if cc.has_header('cuda_gl_interop.h', dependencies: cuda_dep)
use_nvenc_gl = true
endif
endif
if use_nvenc_gl
nvenc_gl_dep = gstgl_dep
extra_c_args += ['-DHAVE_NVENC_GST_GL=1']
endif
gstnvenc = library('gstnvenc',
nvenc_sources,
c_args : gst_plugins_bad_args + extra_c_args,
include_directories : [configinc],
dependencies : [gstbase_dep, gstvideo_dep, gstpbutils_dep, nvenc_gl_dep, cuda_dep, cudart_dep, gmodule_dep],
install : true,
install_dir : plugins_install_dir,
)
pkgconfig.generate(gstnvenc, install_dir : plugins_pkgconfig_install_dir)
plugins += [gstnvenc]

View file

@ -234,7 +234,7 @@ else
check_msdk=
endif
if USE_NVENC
if USE_NVCODEC
check_nvenc=elements/nvenc
else
check_nvenc=

View file

@ -14,15 +14,6 @@ exif_dep = dependency('libexif', version : '>= 0.6.16', required : false)
enable_gst_player_tests = get_option('gst_player_tests')
# Need explicit dependency listing for nvenc on Windows
nvenc_test_deps = []
if cuda_dep.found() and cudart_dep.found()
nvenc_test_deps += [cuda_dep, cudart_dep, gmodule_dep, gstgl_dep]
if use_nvenc_gl
nvenc_test_deps += gstgl_dep
endif
endif
# name, condition when to skip the test and extra dependencies
base_tests = [
[['elements/aiffparse.c']],
@ -43,7 +34,7 @@ base_tests = [
[['elements/msdkh264enc.c'], not have_msdk, [msdk_dep]],
[['elements/mxfdemux.c']],
[['elements/mxfmux.c']],
[['elements/nvenc.c'], not cuda_dep.found() or not cudart_dep.found(), nvenc_test_deps],
[['elements/nvenc.c'], not cuda_header_dep.found(), [gmodule_dep, gstgl_dep]],
[['elements/pcapparse.c'], false, [libparser_dep]],
[['elements/pnm.c']],
[['elements/rtponvifparse.c']],