My ultimate goal is to convert UYVY frames coming from a v4l2-only source to GRAY8 for disparity.
tegra_multimedia_api sample #12 shows how to pull the v4l2 buffers and register them with CUDA, which works. However as soon as I try to pull the luminance plane from the mapped CUeglFrame I get a segfault. I’m assuming there’s either something I did wrong or creating a surface is not supported when the frame comes from NvEGLImageFromFd()
I already have a YUV->GRAY8 kernel using a luminance surface, but would the better solution be to just write a kernel that uses the EGLImage directly like in samples/common/algorithm/cuda/NvCudaProc.cpp?
Here is the code, based on tegra_multimedia_api sample #12 (camera_v4l2_cuda). The segfault happens at line 40, cuSurfObjectCreate().
if(poll(&fds, 1, 5000) > 0) {
// Dequeue camera buff
memset(&v4l2_buf, 0, sizeof(v4l2_buf));
v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
v4l2_buf.memory = V4L2_MEMORY_DMABUF;
if(ioctl(cam_fd, VIDIOC_DQBUF, &v4l2_buf) < 0)
ORIGINATE_ERROR("Failed to dequeue camera buff.");
// Cache sync for VIC operation
NvBufferMemSyncForDevice(
g_buff[v4l2_buf.index].dmabuff_fd, 0, (void**)&g_buff[v4l2_buf.index].start
);
// Pull EGL image
EGLImageKHR egl_image = NvEGLImageFromFd(egl_display, g_buff[v4l2_buf.index].dmabuff_fd);
// Register EGL image
CUgraphicsResource pResource;
status = cuGraphicsEGLRegisterImage(&pResource, egl_image, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
if(status != CUDA_SUCCESS) {
ORIGINATE_ERROR("Register image failed (CUresult %s)",
getCudaErrorString(status));
}
// Map EGL image
CUeglFrame cudaEGLFrame;
status = cuGraphicsResourceGetMappedEglFrame(&cudaEGLFrame, pResource, 0, 0);
if(status != CUDA_SUCCESS) {
ORIGINATE_ERROR("Mapping image failed (CUresult %s)",
getCudaErrorString(status));
}
CUDA_RESOURCE_DESC cudaResourceDesc;
memset(&cudaResourceDesc, 0, sizeof(cudaResourceDesc));
cudaResourceDesc.resType = CU_RESOURCE_TYPE_ARRAY;
// Create a surface from the luminance plane
CUsurfObject cudaSurfLuma;
cudaResourceDesc.res.array.hArray = cudaEGLFrame.frame.pArray[0];
<b>status = cuSurfObjectCreate(&cudaSurfLuma, &cudaResourceDesc); // <-- Segfault</b>
if(status != CUDA_SUCCESS) {
ORIGINATE_ERROR("Unable to create the luma surface object (CUresult %s)",
getCudaErrorString(status));
}
/****************************************
* Call kernel here on luminance plane. *
****************************************/
status = cuSurfObjectDestroy(cudaSurfLuma);
if(status != CUDA_SUCCESS) {
ORIGINATE_ERROR("Unable to destroy the luma surface object (CUresult %s)",
getCudaErrorString(status));
}
status = cuGraphicsUnregisterResource(pResource);
if(status != CUDA_SUCCESS) {
ORIGINATE_ERROR("Failed to unregister resource (CUresult %s)",
getCudaErrorString(status));
}
NvDestroyEGLImage(egl_display, egl_image);
// Enqueue camera buff
if(ioctl(cam_fd, VIDIOC_QBUF, &v4l2_buf))
ORIGINATE_ERROR("Failed to queue camera buffers");
}
Thanks!