Copy OpenCV GpuMat data to an NvBuffer

Hi,

I have implemented OpenCV processing in the 12_camera_v4l2_cuda example by passing the CUeglFrame pPitch[0] to a GpuMat constructor. However, this modifies the existing buffer.

I have some extra processing in OpenCV to do, after which I have a final GpuMat that is not mapped to any existing NvBuffer. I can create a new NvBuffer for my output, but I need to copy/map my GpuMat to that NvBuffer so that I can pass it into a NvVideoEncoder later.

Would appreciate any assistance in this matter.

Hi
Since NvVideoEncoder requires data in NvBuffer, you would need to allocate NvBuffer and map it to final GpuMat. You may call NvBufferTransform() to copy data between two NvBuffers.

Hi Dane,

How do I map a GpuMat that has the image I need to use, to an NvBuffer? I know how to map an NvBuffer to a GpuMat, which is how I added opencv processing to camera_v4l2_cuda. But for my output I need the other way around, from GpuMat to NvBuffer, hence my question.

Hi,
Mapping GpuMat to NvBuffer is not supported. You would need to create NvBuffer and move data from the final GpuMat to the NvBuffer.

Hi Dane,

Yes, that is what I was thinking. However since I’m new to the MMAPI, I was hoping that you could point me to an example of how the data is copied from a GpuMat to NvBuffer.

Hi,
By referring to this post:
c++ - OpenCV - Copy GpuMat into cuda device data - Stack Overflow

Should be able to get CUDA pointer of a GpuMat and then call cudaMemcpy().

I managed to figure it out, so posting the solution here just in case anyone like me ever needs to use it.

uint8_t *imgPtr;
NvBufferMemMap(output_dmabuf_fd, 0, NvBufferMem_Write, (void**)&imgPtr);
cudaMemcpy(imgPtr, gpumat.ptr<uint8_t>(), (gpumat.rows * gpumat.step), cudaMemcpyDefault);
1 Like

Hi,
Good to know you figured out a solution and thanks for the sharing.

Not sure but gpumat.ptr<uint8_t>() looks to be a CUDA pointer. You may try the function calls to get CUDA pointer of an NvBuffer:

NvEGLImageFromFd();
cuGraphicsEGLRegisterImage();
cuGraphicsResourceGetMappedEglFrame();

So that you can call cudaMemcpy() with cudaMemcpyDeviceToDevice .

Hi Dane,

So that’s the first way I tried to get a mapping between the CUDA pointer and the NvBuffer pointer, since that is exactly how I am getting GpuMat from the camera NvBuffer.

However, when I try to register the output NvBuffer’s EGLImage, I get the following error:

cuGraphicsEGLRegisterImage failed: 999, cuda process stop

I am not sure why the cuGraphicsEGLRegisterImage function is failing for the output buffer but not the camera buffers, since the buffers are created and registered in the same way.

Hi Dane,

Sorry, please ignore the last comment. I was making a silly typo (forgetting the address-of operator in one place). You were right, the cuda device-to-device copy is much better, thanks.