I am pulling frames from a cuEGLStreamConsumer and creating surfaces from its luminance and chrominance plane. I then pass these through a cudaKernel to convert the NV12 to RGB.
Here’s the code:
CUgraphicsResource cudaResource = 0;
CUstream cudaStream = 0;
CUresult cuResult;
cuResult = cuEGLStreamConsumerAcquireFrame(&cudaConnection, &cudaResource, &cudaStream, -1);
if(cuResult != CUDA_SUCCESS) break;
// Get the CUDA EGL frame.
CUeglFrame cudaEGLFrame;
cuResult = cuGraphicsResourceGetMappedEglFrame(&cudaEGLFrame, cudaResource, 0, 0);
if(cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to get the CUDA EGL frame (CUresult %s).",
getCudaErrorString(cuResult));
}y
CUDA_RESOURCE_DESC cudaResourceDesc;
CUsurfObject cudaSurfLuma = 0;
CUsurfObject cudaSurfChroma = 0;
memset(&cudaResourceDesc, 0, sizeof(cudaResourceDesc));
cudaResourceDesc.resType = CU_RESOURCE_TYPE_ARRAY;
// Create a surface from the luminance plane
cudaResourceDesc.res.array.hArray = cudaEGLFrame.frame.pArray[0];
cuResult = cuSurfObjectCreate(&cudaSurfLuma, &cudaResourceDesc);
if(cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to create the luma surface object (CUresult %s)",
getCudaErrorString(cuResult));
}
// Create a surface from the chrominance plane
cudaResourceDesc.res.array.hArray = cudaEGLFrame.frame.pArray[1];
cuResult = cuSurfObjectCreate(&cudaSurfChroma, &cudaResourceDesc);
if(cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to create the chroma surface object (CUresult %s)",
getCudaErrorString(cuResult));
}
pthread_mutex_lock(ctx->frame_mutex);
cudaConvertNV12(
cudaSurfLuma,
cudaSurfChroma,
ctx->rgb_cuda,
ctx->rgba_cuda,
ctx->width,
ctx->height);
*ctx->new_frame = true;
pthread_mutex_unlock(ctx->frame_mutex);
cuResult = cuSurfObjectDestroy(cudaSurfLuma);
if(cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to destroy the luma surface object (CUresult %s)",
getCudaErrorString(cuResult));
}
cuResult = cuSurfObjectDestroy(cudaSurfChroma);
if(cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to destroy the chroma surface object (CUresult %s)",
getCudaErrorString(cuResult));
}
cuResult = cuEGLStreamConsumerReleaseFrame(&cudaConnection, cudaResource, &cudaStream);
if (cuResult != CUDA_SUCCESS)
{
ORIGINATE_ERROR("Unable to release the last frame (CUresult %s).",
getCudaErrorString(cuResult));
}
I have noticed I get black horizontal streaks in my image after conversion. At first I thought it was my kernel, but I simplified my kernel down to creating the greyscale image just from the values of the lumanance plane and I still see the streaks.
Here’s my kernel:
__global__ void ConvertNV12(
cudaSurfaceObject_t surfLuma,
cudaSurfaceObject_t surfChroma,
uchar3* RGB,
float4* RGBAf,
uint32_t width,
uint32_t height)
{
const uint32_t x = blockIdx.x * blockDim.x + threadIdx.x;
const uint32_t y = blockIdx.y * blockDim.y + threadIdx.y;
if(x >= width || y >= height) return;
uint8_t Y = surf2Dread<uint8_t>(surfLuma, x, y);
uint8_t red = Y;
uint8_t green = Y;
uint8_t blue = Y;
RGB[y * width + x] = make_uchar3(red, green, blue);
RGBAf[y * width + x] = make_float4(red, green, blue, 1.0f);
}
cudaError_t cudaConvertNV12(
cudaSurfaceObject_t surfLuma,
cudaSurfaceObject_t surfChroma,
uchar3* RGB,
float4* RGBAf,
uint32_t width,
uint32_t height )
{
if(!RGB || !RGBAf)
return cudaErrorInvalidDevicePointer;
if(width == 0 || height == 0)
return cudaErrorInvalidValue;
const dim3 block(8, 8, 1);
const dim3 grid(width/block.x+1, height/block.y+1, 1);
ConvertNV12<<<grid, block>>>(surfLuma, surfChroma, RGB, RGBAf, width, height );
return CUDA(cudaGetLastError());
}
Has anyone seen this before? Is it something I’m doing wrong? I don’t think it’s my sensor, as streaming with nvcamerasrc does not produce the lines.