Please provide complete information as applicable to your setup.
• Hardware Platform (Jetson / GPU) GPU
• DeepStream Version 6.0
• VPI Version 1.2
I did some changes on dsexample element to apply perspective warp on specific parts of the input frames using VPI. I got inspiration from this post.
Here’s the pipeline I am running:
gst-launch-1.0 filesrc location=/sample_video.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! muxer.sink_0 nvstreammux name=muxer width=1280 height=720 batch-size=1 ! nvvideoconvert ! "video/x-raw(memory:NVMM), format=RGBA" ! dsexample ! nvvideoconvert ! nvdsosd ! nveglglessink sync=1
And here’s a snippet from transform_ip
function in dsexample:
GstDsExample *dsexample = GST_DSEXAMPLE (btrans);
GstMapInfo in_map_info;
GstFlowReturn flow_ret = GST_FLOW_ERROR;
NvBufSurface *surface = NULL;
int idx = 0;
VPIImageData img_data_src;
int width, height;
cv::Mat outFrame;
std::string vpi_status_str;
VPIPerspectiveTransform h1 = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0005, 0.0003, 1.0}};
dsexample->frame_num++;
CHECK_CUDA_STATUS(cudaSetDevice(dsexample->gpu_id), "Unable to set cuda device");
memset(&in_map_info, 0, sizeof(in_map_info));
if (!gst_buffer_map(inbuf, &in_map_info, GST_MAP_READ)) {
g_print("Error: Failed to map gst buffer\n");
goto error;
}
nvds_set_input_system_timestamp(inbuf, GST_ELEMENT_NAME(dsexample));
surface = (NvBufSurface *)in_map_info.data;
width = surface->surfaceList[0].width;
height = surface->surfaceList[0].height;
if (!dsexample->vpi_rgba8_out)
CHECK_STATUS(
vpiImageCreate(width / 2, height / 2, VPI_IMAGE_FORMAT_RGBA8, VPI_BACKEND_CUDA, &dsexample->vpi_rgba8_out));
if (!dsexample->vpi_bgr8_out)
CHECK_STATUS(vpiImageCreate(width / 2, height / 2, VPI_IMAGE_FORMAT_BGRA8, 0, &dsexample->vpi_bgr8_out));
memset(&img_data_src, 0, sizeof(img_data_src));
img_data_src.format = VPI_IMAGE_FORMAT_RGBA8;
img_data_src.numPlanes = surface->surfaceList[idx].planeParams.num_planes;
for (int32_t j = 0; j < img_data_src.numPlanes; j++) {
img_data_src.planes[j].width = width / 2;
img_data_src.planes[j].height = height / 2;
img_data_src.planes[j].pitchBytes = width * 4; // state the full stride of image from which you are cropping
// set arbitrary offset
int offset = img_data_src.planes[j].pitchBytes * height / 3 + (width / 2) * 4;
img_data_src.planes[j].data = (uint8_t *)surface->surfaceList[0].dataPtr + offset;
}
if (!dsexample->vpi_rgba8_in || !dsexample->vpi_rgba8_out) {
CHECK_STATUS(vpiImageCreateCUDAMemWrapper(&img_data_src, 0, &dsexample->vpi_rgba8_in));
} else {
CHECK_STATUS(vpiImageSetWrappedCUDAMem(dsexample->vpi_rgba8_in, &img_data_src));
}
CHECK_STATUS(vpiSubmitPerspectiveWarp(dsexample->stream, 0, dsexample->warp, dsexample->vpi_rgba8_in, h1,
dsexample->vpi_rgba8_out, VPI_INTERP_LINEAR, VPI_BORDER_ZERO, 0));
CHECK_STATUS(vpiStreamSync(dsexample->stream));
// Convert output back to BGR using CUDA
CHECK_STATUS(vpiSubmitConvertImageFormat(dsexample->stream, VPI_BACKEND_CUDA, dsexample->vpi_rgba8_out,
dsexample->vpi_bgr8_out, NULL));
CHECK_STATUS(vpiStreamSync(dsexample->stream));
// Write it on disk
VPIImageData imgdata;
CHECK_STATUS(vpiImageLock(dsexample->vpi_bgr8_out, VPI_LOCK_READ, &imgdata));
CHECK_STATUS(vpiImageDataExportOpenCVMat(imgdata, &outFrame));
cv::imwrite("test.jpg", outFrame);
CHECK_STATUS(vpiImageUnlock(dsexample->vpi_bgr8_out));
Here I am trying to apply perspective warp on only part of the input frame (a crop) by adding offset to the data pointer and write it on the disk separately. I made sure that input to dsexample is in rgba format so that the offset I am adding would make sense.
The thing is, it only works when I set muxer resolution to (1280 x 720) but when I switch to (1920 x 1080) I get
VPI_ERROR_INTERNAL: cudaErrorInvalidValue: cudaCreateTextureObject(...)
.
The exception is thrown from vpiStreamSync
interface. I should also mention that not all offset values work with (1280 x 720), some offset values (still inside of frame bounds) break it too.
Any idea why I am getting this exception?