• Hardware Platform (Jetson / GPU) Jetson
• DeepStream Version 6.3
• JetPack Version (valid for Jetson only) 5.1.2
Hello, I’m building custom element by using nvdsvideotemplate. In this element, I received a buffer from upstream. and do some processing using cv::cuda and I should make a new GstBuffer from this cv::cuda::GpuMat.
my output cv::cuda::GpuMat is output_nv12_mat
NvBufSurfaceCreateParams create_params = {0};
create_params.gpuId = 0;
create_params.width = m_video_width;
create_params.height = m_video_height;
create_params.colorFormat = NVBUF_COLOR_FORMAT_NV12;
create_params.layout = NVBUF_LAYOUT_PITCH;
create_params.memType = NVBUF_MEM_CUDA_UNIFIED;
new_surf->numFilled = 1;
cudaMemcpy2DAsync(new_surf->surfaceList[0].dataPtr, new_surf->surfaceList[0].pitch,
output_nv12_mat.data, output_nv12_mat.step, m_video_width,
m_video_height, cudaMemcpyDeviceToDevice,
m_config_params.cuda_stream);
// Copy UV plane
cudaMemcpy2DAsync(static_cast<uint8_t *>(new_surf->surfaceList[0].dataPtr) +
new_surf->surfaceList[0].pitch * m_video_height,
new_surf->surfaceList[0].pitch,
output_nv12_mat.data + output_nv12_mat.step * m_video_height,
output_nv12_mat.step, m_video_width, m_video_height / 2,
cudaMemcpyDeviceToDevice, m_config_params.cuda_stream);
cudaStreamSynchronize(m_config_params.cuda_stream);
NvBufSurfTransformSetSessionParams(&m_config_params);
GstBuffer *newGstOutBuf = NULL;
gst_buffer_pool_acquire_buffer(m_dsBufferPool, &newGstOutBuf, NULL);
NvBufSurface *out_surf = getNvBufSurface(newGstOutBuf);
out_surf->numFilled = new_surf->numFilled;
out_surf->batchSize = new_surf->batchSize;//
NvBufSurfTransformParams transform_params;
transform_params.transform_flag = NVBUFSURF_TRANSFORM_FILTER;
transform_params.transform_flip = NvBufSurfTransform_None;
transform_params.transform_filter = NvBufSurfTransformInter_Default;
NvBufSurfTransform(new_surf, out_surf, &transform_params);
NvBufSurfaceDestroy(new_surf);
This is working code, And after passing this buffer to encoder, I was able to save correct image.
But it seems to make a unnecessary memory copy because, I made NvBufSurface with NVBUF_MEM_CUDA_UNIFIED memory and convert this to NVBUF_MEM_SURFACE_ARRAY. And I set config params as below, So It seems to use GPU for this transform.
m_config_params.compute_mode = NvBufSurfTransformCompute_GPU;
m_config_params.gpu_id = params->m_gpuId;
m_config_params.cuda_stream = params->m_cudaStream;
So I tried to set NVBUF_MEM_SURFACE_ARRAY to create_params.memType and allocate output matrix to NvBufSurface by using below code.
m_egl_image = new_surf->surfaceList[0].mappedAddr.eglImage;
if (cuGraphicsEGLRegisterImage(&m_cuda_resource, m_egl_image,
CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE) != CUDA_SUCCESS) {
std::cerr << "Failed to register CUDA resource" << std::endl;
return false;
}
if (cuGraphicsResourceGetMappedEglFrame(&m_egl_frame, m_cuda_resource, 0, 0) !=
CUDA_SUCCESS) {
std::cerr << "Failed to get mapped EGL frame" << std::endl;
return false;
}
cv::cuda::GpuMat d_y(new_surf->surfaceList[0].height, new_surf->surfaceList[0].width, CV_8UC1, m_egl_frame.frame.pPitch[0]);
cv::cuda::GpuMat d_uv(new_surf->surfaceList[0].height / 2, new_surf->surfaceList[0].width, CV_8UC1, m_egl_frame.frame.pPitch[1]);
output_nv12_mat.copyTo(d_y);
output_nv12_map.copyTo(d_uv);
And When i parse cv::cuda::GpuMat again from this NvBufSurface and checked image, It looks okay. But after NvBufSurfTransform and attache GstBuffer and checked a video at the downstream, image was crashed.
So overall,
- I’d like to avoid memory copy as much as possible. Can i directly make a GstBuffer from cv::cuda::GpuMat?