Thank you very much for your reply!
I have already used the deepstream app to zoom in and display the specified video source, and analyzed the source code. The zoom in display of deepstream test5 is the same as the programming of the deepstream app, but this method does not seem to be suitable for me.
Because I only have two video sources (640 * 512), but my tiler is 2 * 2 (tiler: 1920 * 1080), and the positions of the two video sources in the tiler display are (0, 0, 960, 540) and (960, 0, 960, 540) respectively.As shown in the following figure:
If I choose to zoom in on video source 1, it will enlarge to the (0,0,1920, 540) area instead of the full screen area (0,0, 1920, 1080).
The core code I am using is:
g_object_set (G_OBJECT (tiler), "show-source", source_id, NULL);
I tried another method, which is to add a probe function on the src pad of the OSD in the deepstream pipeline, obtain the entire image in the probe function, then select the image of video source 1 area and zoom in. After zooming in, I put the enlarged image of video source 1 area back into the buffer of the current frame.
The core code I am using is:
static GstPadProbeReturn
nvosd_queue_sink_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
gpointer u_data)
{
static gint dump_count = 0;
static gint frame_number = 0;
cv::Mat region_image;
cv::Mat image_clone;
GstBuffer *original_gstbuf = (GstBuffer *) info->data;
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (original_gstbuf);
// Get original raw data
GstMapInfo in_map_info;
if (!gst_buffer_map (original_gstbuf, &in_map_info, GST_MAP_READ)) {
g_print ("Error: Failed to map gst buffer\n");
gst_buffer_unmap (original_gstbuf, &in_map_info);
return GST_PAD_PROBE_OK;
}
NvBufSurface *surface = (NvBufSurface *) in_map_info.data;
NvBufSurfaceMap(surface, -1, -1, NVBUF_MAP_READ_WRITE);
NvBufSurfaceSyncForCpu(surface, 0, 0);
guint surface_height = surface->surfaceList[0].height;
guint surface_width = surface->surfaceList[0].width;
cv::Mat original_image= cv::Mat(surface_height*3/2, surface_width, CV_8UC1, surface->surfaceList[0].mappedAddr.addr[0], surface->surfaceList[0].pitch);
if(original_image.empty()) return GST_PAD_PROBE_OK;
cv::Mat original_image_temp;
original_image_temp=original_image;
// Press the button for the first time to switch to interface 1 in the upper left corner
if(show_source==1)
{
g_print("in show_source 1\n");
// choose the region
cv::Rect selectedRegion(0, 0, surface_width / 2, surface_height / 2);
region_image = original_image(selectedRegion);
// NV12 to BGR
cv::Mat bgr_region_image;
cv::cvtColor(region_image, bgr_region_image, cv::COLOR_YUV2BGR_NV12);
// expend to 1920*1080
cv::Mat resized_bgr_region_image;
cv::resize(bgr_region_image, resized_bgr_region_image, cv::Size(surface_width, surface_height));
//BGR TO I420
cv::Mat I420_original_image = cv::Mat(resized_bgr_region_image.rows * 3 / 2, resized_bgr_region_image.cols, CV_8UC1);
cv::cvtColor(resized_bgr_region_image, I420_original_image, cv::COLOR_BGR2YUV_I420);
//I420 TO NV12
int I420_width= I420_original_image.cols;
int I420_height= I420_original_image.rows *2/3;
int yuvNV12_size = I420_height * I420_width * 3 / 2;
unsigned char *nv12_buffer = (unsigned char *)malloc(yuvNV12_size*sizeof(uchar));
ConvertYUV_I420_to_NV12(I420_original_image,nv12_buffer);
cv::Mat NV12_original_image(cv::Size(I420_width, I420_height * 3 / 2), CV_8UC1, nv12_buffer);
NV12_original_image.copyTo(original_image);
free(nv12_buffer);
// if((!NV12_original_image.empty()))
// memcpy(original_image.data, NV12_original_image.data, NV12_original_image.total());
}
// When the button is pressed for the second time, the original image is displayed
if(show_source==-1)
{
original_image=original_image_temp;
// memcpy(original_image.data, original_image.data, original_image.total());
}
frame_number++;
NvBufSurfaceUnMap(surface, -1, -1);
gst_buffer_unmap(original_gstbuf, &in_map_info);
return GST_PAD_PROBE_OK;
}
Excuse me, is there any problem with me writing the program this way?