NvVideoConverter artifacts appears

Hello,

I have a problem with the NvVideoConverter on the Jetson AGX Xavier.
JetPack 4.5.1 : nvidia-l4t-jetson-multimedia-api_32.5.1-20210219084708_arm64
R32 (release), REVISION: 5.1, GCID: 27362550, BOARD: t186ref, EABI: aarch64, DATE: Wed May 19 18:16:00 UTC 2021

It seems that some pixels of my image are becoming 0 once converted to another format.

To simplify the problem to the maximum I convert the format of my image from V4L2_PIX_FMT_UYVY to V4L2_PIX_FMT_UYVY, and yet the artifacts are still appearing. As you can see on the pictures below:

Camera.bmp (4.5 MB)
VideoConverter.bmp (4.5 MB)

Here is my code without error handling.

m_inPixFmt = m_outPixFmt = V4L2_PIX_FMT_UYVY;
m_width = 1456;
m_height = 1088;

m_conv = NvVideoConverter::createVideoConverter("conv0");
m_conv->setOutputPlaneFormat(m_inPixFmt, m_width, m_height, V4L2_NV_BUFFER_LAYOUT_PITCH);
m_conv->setCapturePlaneFormat(m_outPixFmt, m_width, m_height, V4L2_NV_BUFFER_LAYOUT_PITCH);
m_conv->output_plane.setupPlane(V4L2_MEMORY_MMAP, m_outputPlaneBufferNbr, true, false);
m_conv->capture_plane.setupPlane(V4L2_MEMORY_MMAP, m_capturePlaneBufferNbr, true, false);
m_conv->output_plane.setStreamStatus(true);
m_conv->capture_plane.setStreamStatus(true);
m_conv->capture_plane.setDQThreadCallback(capturePlaneCallback);
m_conv->capture_plane.startDQThread(this);
m_conv->output_plane.setDQThreadCallback(outputPlaneCallback);
m_conv->output_plane.startDQThread(this);

// Enqueue all the empty capture plane buffers.
for (uint32_t buffer_idx = 0; buffer_idx < m_conv->capture_plane.getNumBuffers(); buffer_idx++)
{
    queueOutputBuffer(buffer_idx); // Queue capture plane buffers (output of the converter)
}

Then to write on the output plane buffer (input buffer of the converter)
I get the list of output plane buffers.

for(int bufferIndex = 0; bufferIndex < nBuffers; bufferIndex++)
{
    NvBuffer *pBuffer = inputBuffers[bufferIndex];
    VmbUchar_t *pMemory = pBuffer->planes[0].data;
    VmbInt64_t nBufferSize = pBuffer->planes[0].length;
    pBuffer->planes[0].bytesused = 3168256; // payload size of my image (width * height * 2 bytes per pixel)
}

And I write the image into my pMemory pointer.

My end goal is to convert the image into other format V4L2_PIX_FMT_YUV420M, but it has the same issue.
Also I use the same method to save the bmp file from the capture_plane.buffers.planes[0].data. So I’m pretty sure the issue is from the converter. I do it in the callback “capturePlaneCallback”.

Thank you in advance for your answers.

I figured it out.

I forgot about the stride, my camera was dumping its buffer without respecting the stride imposed by the converter’s NvBuffer. And when I wrote the bitmap exporter I did not consider the stride as well.

I had to memcpy the buffer of my camera line per line to consider the padding of the stride. It is a waste of computational power however.

// Converter input buffer
NvBuffer* inputBuffer = m_pVideoConverter->getNextAvailableInputBuffer();
unsigned char* in_data = inputBuffer->planes[0].data;

// Converter input buffer format
NvBuffer::NvBufferPlaneFormat& fmt = inputBuffer->planes[0].fmt;
uint32_t stride = fmt.stride;
uint32_t bpp = fmt.bytesperpixel;
uint32_t width = fmt.width;
uint32_t height = fmt.height;
            
// Camera output buffer
VmbUchar_t* out_data;
pFrame->GetImage(out_data);
            
// Copy while respecting the stride
for(unsigned int y = 0; y < height; y++) {
    std::memcpy(in_data, out_data, width * bpp);
    in_data += stride;
    out_data += width * bpp;
}

inputBuffer->planes[0].bytesused = stride * height;

My problem is solved, hope it can help.

Glad to know you resolved it, thanks for the update.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.