Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Seungha Yang
gst-plugins-bad
Commits
e463d0ac
Commit
e463d0ac
authored
Nov 24, 2018
by
Seungha Yang
🐑
Browse files
nvenc: Port to GstCudaContext
... and add support CUDA context sharing similar to glcontext sharing.
parent
76406e9f
Changes
4
Hide whitespace changes
Inline
Side-by-side
sys/nvcodec/gstnvbaseenc.c
View file @
e463d0ac
...
...
@@ -22,6 +22,7 @@
#endif
#include
"gstnvbaseenc.h"
#include
"gstcudautils.h"
#include
<gst/pbutils/codec-utils.h>
...
...
@@ -399,10 +400,9 @@ gst_nv_base_enc_open (GstVideoEncoder * enc)
{
GstNvBaseEnc
*
nvenc
=
GST_NV_BASE_ENC
(
enc
);
nvenc
->
cuda_ctx
=
gst_nvenc_create_cuda_context
(
nvenc
->
cuda_device_id
);
if
(
nvenc
->
cuda_ctx
==
NULL
)
{
GST_ELEMENT_ERROR
(
enc
,
LIBRARY
,
INIT
,
(
NULL
),
(
"Failed to create CUDA context, perhaps CUDA is not supported."
));
if
(
!
gst_cuda_ensure_element_context
(
GST_ELEMENT_CAST
(
enc
),
&
nvenc
->
cuda_ctx
,
nvenc
->
cuda_device_id
))
{
GST_ERROR_OBJECT
(
nvenc
,
"failed to create CUDA context"
);
return
FALSE
;
}
...
...
@@ -412,13 +412,12 @@ gst_nv_base_enc_open (GstVideoEncoder * enc)
params
.
version
=
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER
;
params
.
apiVersion
=
NVENCAPI_VERSION
;
params
.
device
=
nvenc
->
cuda_ctx
;
params
.
device
=
gst_cuda_context_get_context
(
nvenc
->
cuda_ctx
)
;
params
.
deviceType
=
NV_ENC_DEVICE_TYPE_CUDA
;
nv_ret
=
NvEncOpenEncodeSessionEx
(
&
params
,
&
nvenc
->
encoder
);
if
(
nv_ret
!=
NV_ENC_SUCCESS
)
{
GST_ERROR
(
"Failed to create NVENC encoder session, ret=%d"
,
nv_ret
);
if
(
gst_nvenc_destroy_cuda_context
(
nvenc
->
cuda_ctx
))
nvenc
->
cuda_ctx
=
NULL
;
gst_clear_object
(
&
nvenc
->
cuda_ctx
);
return
FALSE
;
}
GST_INFO
(
"created NVENC encoder %p"
,
nvenc
->
encoder
);
...
...
@@ -437,9 +436,13 @@ gst_nv_base_enc_open (GstVideoEncoder * enc)
static
void
gst_nv_base_enc_set_context
(
GstElement
*
element
,
GstContext
*
context
)
{
#if HAVE_NVENC_GST_GL
GstNvBaseEnc
*
nvenc
=
GST_NV_BASE_ENC
(
element
);
if
(
gst_cuda_handle_set_context
(
element
,
context
,
&
nvenc
->
cuda_ctx
,
nvenc
->
cuda_device_id
))
{
goto
done
;
}
#if HAVE_NVENC_GST_GL
gst_gl_handle_set_context
(
element
,
context
,
(
GstGLDisplay
**
)
&
nvenc
->
display
,
(
GstGLContext
**
)
&
nvenc
->
other_context
);
...
...
@@ -448,21 +451,24 @@ gst_nv_base_enc_set_context (GstElement * element, GstContext * context)
SUPPORTED_GL_APIS
);
#endif
done:
GST_ELEMENT_CLASS
(
parent_class
)
->
set_context
(
element
,
context
);
}
static
gboolean
gst_nv_base_enc_sink_query
(
GstVideoEncoder
*
enc
,
GstQuery
*
query
)
{
#if HAVE_NVENC_GST_GL
GstNvBaseEnc
*
nvenc
=
GST_NV_BASE_ENC
(
enc
);
#endif
switch
(
GST_QUERY_TYPE
(
query
))
{
#if HAVE_NVENC_GST_GL
case
GST_QUERY_CONTEXT
:{
gboolean
ret
;
if
(
gst_cuda_handle_context_query
(
GST_ELEMENT
(
nvenc
),
query
,
nvenc
->
cuda_ctx
))
return
TRUE
;
#if HAVE_NVENC_GST_GL
ret
=
gst_gl_handle_context_query
((
GstElement
*
)
nvenc
,
query
,
nvenc
->
display
,
NULL
,
nvenc
->
other_context
);
if
(
nvenc
->
display
)
...
...
@@ -471,9 +477,9 @@ gst_nv_base_enc_sink_query (GstVideoEncoder * enc, GstQuery * query)
if
(
ret
)
return
ret
;
#endif
break
;
}
#endif
default:
break
;
}
...
...
@@ -629,11 +635,7 @@ gst_nv_base_enc_close (GstVideoEncoder * enc)
nvenc
->
encoder
=
NULL
;
}
if
(
nvenc
->
cuda_ctx
)
{
if
(
!
gst_nvenc_destroy_cuda_context
(
nvenc
->
cuda_ctx
))
return
FALSE
;
nvenc
->
cuda_ctx
=
NULL
;
}
gst_clear_object
(
&
nvenc
->
cuda_ctx
);
GST_OBJECT_LOCK
(
nvenc
);
if
(
nvenc
->
input_formats
)
...
...
@@ -974,7 +976,7 @@ gst_nv_base_enc_free_buffers (GstNvBaseEnc * nvenc)
if
(
nvenc
->
gl_input
)
{
struct
gl_input_resource
*
in_gl_resource
=
nvenc
->
input_bufs
[
i
];
CuCtxPushCurrent
(
nvenc
->
cuda_ctx
);
gst_cuda_context_push
(
nvenc
->
cuda_ctx
);
if
(
in_gl_resource
->
mapped
)
{
GST_LOG_OBJECT
(
nvenc
,
"Unmap resource %p"
,
in_gl_resource
);
...
...
@@ -1003,7 +1005,7 @@ gst_nv_base_enc_free_buffers (GstNvBaseEnc * nvenc)
}
g_free
(
in_gl_resource
);
CuCtxPopCurrent
(
NULL
);
gst_cuda_context_pop
(
);
}
else
#endif
{
...
...
@@ -1298,7 +1300,7 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state)
pixel_depth
+=
GST_VIDEO_INFO_COMP_DEPTH
(
info
,
i
);
}
CuCtxPushCurrent
(
nvenc
->
cuda_ctx
);
gst_cuda_context_push
(
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
);
...
...
@@ -1345,7 +1347,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
);
gst_cuda_context_pop
(
);
}
else
#endif
{
...
...
@@ -1494,12 +1496,11 @@ struct map_gl_input
static
void
_map_gl_input_buffer
(
GstGLContext
*
context
,
struct
map_gl_input
*
data
)
{
cudaError_t
cuda_ret
;
guint8
*
data_pointer
;
guint
i
;
CUDA_MEMCPY2D
param
;
CuCtxPushCurrent
(
data
->
nvenc
->
cuda_ctx
);
gst_cuda_context_push
(
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
;
...
...
@@ -1524,30 +1525,28 @@ _map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data)
GST_LOG_OBJECT
(
data
->
nvenc
,
"attempting to copy texture %u into cuda"
,
gl_mem
->
mem
.
tex_id
);
cuda_ret
=
CuGraphicsGLRegisterBuffer
(
&
data
->
in_gl_resource
->
cuda_texture
,
gl_buf_obj
->
id
,
cudaGraphicsRegisterFlagsReadOnly
);
if
(
cuda_ret
!=
cudaSuccess
)
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to register GL texture %u to cuda "
"ret :%d"
,
gl_mem
->
mem
.
tex_id
,
cuda_ret
);
if
(
!
gst_cuda_result
(
CuGraphicsGLRegisterBuffer
(
&
data
->
in_gl_resource
->
cuda_texture
,
gl_buf_obj
->
id
,
cudaGraphicsRegisterFlagsReadOnly
)))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to register GL texture %u to cuda"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
cuda_ret
=
CuGraphicsMapResources
(
1
,
&
data
->
in_gl_resource
->
cuda_texture
,
0
);
if
(
cuda_ret
!=
cudaSuccess
)
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to map GL texture %u into cuda "
"ret :%d"
,
gl_mem
->
mem
.
tex_id
,
cuda_ret
);
if
(
!
gst_cuda_result
(
CuGraphicsMapResources
(
1
,
&
data
->
in_gl_resource
->
cuda_texture
,
0
)))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to map GL texture %u into cuda"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
cuda_ret
=
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
)
{
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
);
if
(
!
gst_cuda_result
(
CuGraphicsResourceGetMappedPointer
(
&
data
->
in_gl_resource
->
cuda_plane_pointers
[
i
],
&
data
->
in_gl_resource
->
cuda_num_bytes
,
data
->
in_gl_resource
->
cuda_texture
)
))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to get mapped pointer of map GL
texture %u"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
...
...
@@ -1569,26 +1568,23 @@ _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
)
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to copy GL texture %u into cuda "
"ret :%d"
,
gl_mem
->
mem
.
tex_id
,
cuda_ret
);
if
(
!
gst_cuda_result
(
CuMemcpy2D
(
&
param
)))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to copy GL texture %u into cuda"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
cuda_ret
=
CuGraphicsUnmapResources
(
1
,
&
data
->
in_gl_resource
->
cuda_texture
,
0
);
if
(
cuda_ret
!=
cudaSuccess
)
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to unmap GL texture %u from cuda "
"ret :%d"
,
gl_mem
->
mem
.
tex_id
,
cuda_ret
);
if
(
!
gst_cuda_result
(
CuGraphicsUnmapResources
(
1
,
&
data
->
in_gl_resource
->
cuda_texture
,
0
)))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to unmap GL texture %u from cuda"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
cuda_ret
=
CuGraphicsUnregisterResource
(
data
->
in_gl_resource
->
cuda_texture
);
if
(
cuda_ret
!=
cudaSuccess
)
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to unregister GL texture %u from "
"cuda ret :%d"
,
gl_mem
->
mem
.
tex_id
,
cuda_ret
);
if
(
!
gst_cuda_result
(
CuGraphicsUnregisterResource
(
data
->
in_gl_resource
->
cuda_texture
)))
{
GST_ERROR_OBJECT
(
data
->
nvenc
,
"failed to unregister GL texture %u from cuda"
,
gl_mem
->
mem
.
tex_id
);
g_assert_not_reached
();
}
...
...
@@ -1597,7 +1593,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
);
gst_cuda_context_pop
(
);
}
#endif
...
...
sys/nvcodec/gstnvbaseenc.h
View file @
e463d0ac
...
...
@@ -23,6 +23,7 @@
#include
"gstnvenc.h"
#include
<gst/video/gstvideoencoder.h>
#include
"gstcudacontext.h"
#define GST_TYPE_NV_BASE_ENC \
(gst_nv_base_enc_get_type())
...
...
@@ -71,7 +72,7 @@ typedef struct {
guint
bitrate
;
gint
gop_size
;
CUc
ontext
cuda_ctx
;
GstCudaC
ontext
*
cuda_ctx
;
void
*
encoder
;
/* the supported input formats */
...
...
sys/nvcodec/gstnvenc.c
View file @
e463d0ac
...
...
@@ -270,78 +270,6 @@ gst_nvenc_get_nv_buffer_format (GstVideoFormat fmt)
return
NV_ENC_BUFFER_FORMAT_UNDEFINED
;
}
CUcontext
gst_nvenc_create_cuda_context
(
guint
device_id
)
{
CUcontext
cuda_ctx
,
old_ctx
;
CUresult
cres
=
CUDA_SUCCESS
;
CUdevice
cdev
=
0
,
cuda_dev
=
-
1
;
int
dev_count
=
0
;
char
name
[
256
];
int
min
=
0
,
maj
=
0
;
int
i
;
GST_INFO
(
"Initialising CUDA.."
);
cres
=
CuInit
(
0
);
if
(
cres
!=
CUDA_SUCCESS
)
{
GST_WARNING
(
"Failed to initialise CUDA, error code: 0x%08x"
,
cres
);
return
NULL
;
}
GST_INFO
(
"Initialised CUDA"
);
cres
=
CuDeviceGetCount
(
&
dev_count
);
if
(
cres
!=
CUDA_SUCCESS
||
dev_count
==
0
)
{
GST_WARNING
(
"No CUDA devices detected"
);
return
NULL
;
}
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
,
CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR
,
cdev
)
==
CUDA_SUCCESS
&&
CuDeviceGetAttribute
(
&
min
,
CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR
,
cdev
)
==
CUDA_SUCCESS
)
{
GST_INFO
(
"GPU #%d supports NVENC: %s (%s) (Compute SM %d.%d)"
,
i
,
(((
maj
<<
4
)
+
min
)
>=
0x30
)
?
"yes"
:
"no"
,
name
,
maj
,
min
);
if
(
i
==
device_id
)
{
cuda_dev
=
cdev
;
}
}
}
if
(
cuda_dev
==
-
1
)
{
GST_WARNING
(
"Device with id %d does not exist or does not support NVENC"
,
device_id
);
return
NULL
;
}
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
)
{
return
NULL
;
}
GST_INFO
(
"Created CUDA context %p"
,
cuda_ctx
);
return
cuda_ctx
;
}
gboolean
gst_nvenc_destroy_cuda_context
(
CUcontext
ctx
)
{
GST_INFO
(
"Destroying CUDA context %p"
,
ctx
);
return
(
CuCtxDestroy
(
ctx
)
==
CUDA_SUCCESS
);
}
static
gboolean
load_nvenc_library
(
void
)
{
...
...
sys/nvcodec/gstnvenc.h
View file @
e463d0ac
...
...
@@ -28,10 +28,6 @@
GST_DEBUG_CATEGORY_EXTERN
(
gst_nvenc_debug
);
CUcontext
gst_nvenc_create_cuda_context
(
guint
device_id
);
gboolean
gst_nvenc_destroy_cuda_context
(
CUcontext
ctx
);
gboolean
gst_nvenc_cmp_guid
(
GUID
g1
,
GUID
g2
);
NV_ENC_BUFFER_FORMAT
gst_nvenc_get_nv_buffer_format
(
GstVideoFormat
fmt
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment