How to copy an NvBuffer

I am interested in copying the output of the NvVideoConverter to a dmabuf_fd created using nvbuf_utils.h NvBufferCreateEx.

I think I’m supposed to use Raw2NvBuffer, but I can’t find any examples on proper use.

Here is the definition from nvbuf_utils.h:

/**
* This method is used to copy raw buffer plane contents to NvBuffer plane.
* @param[in] ptr pointer to the input raw plane data.
* @param[in] plane video frame plane.
* @param[in] in_width aligned width of the raw data plane.
* @param[in] in_height aligned height of the raw data plane.
* @param[in] dmabuf_fd DMABUF FD of NvBuffer.
*
* @returns 0 for success, -1 for failure.
*/
int Raw2NvBuffer (unsigned char *ptr, unsigned int plane, unsigned int in_width, unsigned int in_height, int dmabuf_fd);

I have a NvBuffer *buffer from a NvVideoConverter capture plane callback (bolded).

bool converter_capture_cb(
    struct v4l2_buffer *v4l2_buf,
    <b>NvBuffer * buffer,</b>
    NvBuffer * shared_buffer,
    void *priv)

And I have a dmabuf_fd created from NvBufferCreateEx buffer like this:

// Allocate output buffer
NvBufferCreateParams input_params;
memset(&input_params, 0, sizeof(NvBufferCreateParams));

input_params.payloadType = NvBufferPayload_SurfArray;
input_params.width = buffer->planes[0].fmt.width;
input_params.height = buffer->planes[0].fmt.height;
input_params.layout = NvBufferLayout_Pitch;
input_params.colorFormat = NvBufferColorFormat_ABGR32;
input_params.nvbuf_tag = NvBufferTag_NONE;

int fd = -1;
if(NvBufferCreateEx(&fd, &input_params) == -1) {
    DEBUG_ERROR("Failed to create output NvBuffer");
    ctx->m_conv->abort();
    break;
}

Would I then call Raw2NvBuffer like this?

Raw2NvBuffer(
    buffer->planes[0].data,       // raw data pointer
    0,                            // we always seem to use plane 0(?)
    buffer->planes[0].fmt.width,  // width
    buffer->planes[0].fmt.height, // height
    fd                            // dmabuf_fd
);

Hi,
It is NvBuffer in capture plane of NvVideoConverter, so you should call

/**
 * Transforms one DMA buffer to another DMA buffer.
 * This function can support transforms for copying, scaling, fliping, rotating, and cropping.
 * @param[in] src_dmabuf_fd DMABUF FD of source buffer
 * @param[in] dst_dmabuf_fd DMABUF FD of destination buffer
 * @param[in] transform_params transform parameters
 *
 * @return 0 for sucess, -1 for failure.
 */
int NvBufferTransform (int src_dmabuf_fd, int dst_dmabuf_fd, NvBufferTransformParams *transform_params);

src_dmabuf_fd is buffer->planes[0].fd and dst_dmabuf_fd is fd from NvBufferCreateEx().

Will NvBufferTransform handle a copy from V4L2_NV_BUFFER_LAYOUT_PITCH source to a destination created as NvBufferLayout_BlockLinear? There are kernels I want to use that don’t have a pitch input, so it would be nice not to have to modify them.

Hi,

It shall work. You can create NvBuffer in block linear.

The Pitched->BlockLinear copy doesn’t seem to work.

I have the NvVideoConverter capture plane configured for pitched ABGR32:

if(m_conv->setCapturePlaneFormat(V4L2_PIX_FMT_ABGR32, m_width, m_height, V4L2_NV_BUFFER_LAYOUT_PITCH) < 0)
    throw std::runtime_error("Could not set capture plane format");

then my buffer is created as block linear ABGR32

// Allocate new buffers
NvBufferCreateParams input_params;
memset(&input_params, 0, sizeof(NvBufferCreateParams));

input_params.payloadType = NvBufferPayload_SurfArray;
input_params.width = buffer->planes[0].fmt.width;
input_params.height = buffer->planes[0].fmt.height;
input_params.layout = NvBufferLayout_BlockLinear;
input_params.colorFormat = NvBufferColorFormat_ABGR32;
input_params.nvbuf_tag = NvBufferTag_NONE;

int fd_in = -1;
if(NvBufferCreateEx(&fd_in, &input_params) == -1) {
    DEBUG_ERROR("Failed to create input NvBuffer");
    ctx->m_conv->abort();
    break;
}

then I use NvBufferTransform to copy the pitched buffer into the blocklinear buffer:

// Copy MMAP data to dma buffer
NvBufferTransformParams transform_params;
memset(&transform_params, 0, sizeof(NvBufferTransformParams));
NvBufferTransform(buffer->planes[0].fd, fd_in, &transform_params);

then I use dump_dmabuf to check the output

// from tegra_multimedia_api/samples/00_video_decode
static int dump_dmabuf(int dmabuf_fd, unsigned int plane, std::ofstream * stream)
{
    if(dmabuf_fd <= 0)
        return -1;

    int ret = -1;
    NvBufferParams parm;
    ret = NvBufferGetParams(dmabuf_fd, &parm);

    DEBUG_VERBOSE("plane pitch=%d", parm.pitch[plane]);

    if(ret != 0)
        return -1;

    void *psrc_data;

    ret = NvBufferMemMap(dmabuf_fd, plane, NvBufferMem_Read_Write, &psrc_data);
    if(ret == 0) {
        unsigned int i = 0;
        NvBufferMemSyncForCpu(dmabuf_fd, plane, &psrc_data);
        for (i = 0; i < parm.height[plane]; ++i) {
            stream->write(
                (char *)psrc_data + i * parm.pitch[plane],
                parm.width[plane] * sizeof(uchar4)
            );

            if (!stream->good())
                return -1;
        }
        NvBufferMemUnMap(dmabuf_fd, plane, &psrc_data);
    }

    return 0;
}

Here is the Pitched->BlockLinear output converted to jpg:

Here is the Pitched->Pitched output converted to jpg:

Is there something I need to set in the TransformParams? I looked through the enums in nvbuf_utils, but they didn’t seem relevant.

This is mostly academic. I can use the pitched format, I just wanted to know if the conversion was handled automatically. I have also noticed that the pitched format’s ‘pitch’ does not seem to have any padding on it anyway.


Hi,
Block linear format is not public. If you would like to dump the frame out, please convert to pitch linear.