Bug Summary: While using the Nvidia NVBuffer API to crop an NVBuffer surface into another surface, we have observed inaccurate transformation of the output surface. The resulting surface after the transformation does not accurately represent the cropped region of the input surface.
Steps to Reproduce:
Allocate memory for the source and destination NVBuffer surfaces using the NvBufSurfaceFromFd function.
Set the parameters for the NvBufSurfTransform function to crop the source surface into the destination surface.
Call the NvBufSurfTransform function to perform the transformation.
Observe the resulting surface and compare it with the expected output.
Expected Result: The resulting surface after the transformation should accurately represent the cropped region of the input surface. The output surface should have the same width and height as the cropped region of the input surface.
Actual Result: The resulting surface after the transformation does not accurately represent the cropped region of the input surface. While the output surface has correct dimensions the pixels are misaligned or incorrect.
Environment: The bug was observed while using the Nvidia NVBuffer API on an Ubuntu 18.04 system with an Nvidia Jetson AGX Xavier module.
Code Snippet:
NvBufSurface* nvbuf_srcsurf;
if (0 != NvBufSurfaceFromFd(alloc.dmabuf_, (void**)(&nvbuf_srcsurf))) {
vlog_error(VCAT_IMG, "Could not get information on dmabuf for srcAlloc on nvbuf ROI");
return false;
}
// Allocate destination surf
NvBufSurface* nvbuf_dstsurf;
if (0 != NvBufSurfaceFromFd(dst.alloc.dmabuf_, (void**)(&nvbuf_dstsurf))) {
vlog_error(VCAT_IMG, "Could not get information on dmabuf for dstAlloc on nvbuf ROI");
return false;
}
// Set NvBufferTransform Params
NvBufSurfTransformParams params{};
NvBufSurfTransformRect srcRect = {(uint32_t)src_y, (uint32_t)src_x, (uint32_t)dst.alloc.width_,
(uint32_t)dst.alloc.height_};
params.transform_flag = NVBUFSURF_TRANSFORM_CROP_SRC;
params.src_rect = &srcRect;
// Call NvBufSurfTransform
if (auto err = NvBufSurfTransform(nvbuf_srcsurf, nvbuf_dstsurf, ¶ms);
err != NvBufSurfTransformError_Success) {
vlog_error(VCAT_IMG, "NVbuf ROI between buffers failed : %d", err);
return false;
}
Hi @DaneLLL , in my application I want to copy a region of interest from a source dmabuf to a destination dmabuf without more then 1 copy. The function dump_dmabuf() with following definition from NvUtils.h doesn’t fit to my application. Is there any other definition for it or any other possible solutions?
/**
* @brief Writes a plane of data from the buffer to a file.
*
* @param[in] dmabuf_fd The DMABUF file descriptor of the buffer.
* @param[in] plane Index of the video frame plane.
* @param[in] stream A pointer to the output file stream.
* @return 0 if successful, or -1 otherwise.
*/
int dump_dmabuf(int dmabuf_fd, unsigned int plane, std::ofstream * stream);
Hi,
You can allocate NvBufSurface same size as the region, and call NvBufSurfTransform() to copy the region to the buffer. This is done on hardware converter so there’s no additional CPU usage.
That’s exactly what we’ve been doing in the reported bug if you see the code snippet in the original bug report. Unfortunately that doesn’t give the correct output. Is there a way to incorporate pitch with NvBufSurfTransform() or any other solution?
Re-posting code snippet for ref:
NvBufSurface* nvbuf_srcsurf;
if (0 != NvBufSurfaceFromFd(alloc.dmabuf_, (void**)(&nvbuf_srcsurf))) {
vlog_error(VCAT_IMG, "Could not get information on dmabuf for srcAlloc on nvbuf ROI");
return false;
}
// Allocate destination surf
NvBufSurface* nvbuf_dstsurf;
if (0 != NvBufSurfaceFromFd(dst.alloc.dmabuf_, (void**)(&nvbuf_dstsurf))) {
vlog_error(VCAT_IMG, "Could not get information on dmabuf for dstAlloc on nvbuf ROI");
return false;
}
// Set NvBufferTransform Params
NvBufSurfTransformParams params{};
NvBufSurfTransformRect srcRect = {(uint32_t)src_y, (uint32_t)src_x, (uint32_t)dst.alloc.width_,
(uint32_t)dst.alloc.height_};
params.transform_flag = NVBUFSURF_TRANSFORM_CROP_SRC;
params.src_rect = &srcRect;
// Call NvBufSurfTransform
if (auto err = NvBufSurfTransform(nvbuf_srcsurf, nvbuf_dstsurf, ¶ms);
err != NvBufSurfTransformError_Success) {
vlog_error(VCAT_IMG, "NVbuf ROI between buffers failed : %d", err);
return false;
}