Thank you for your answer!
My new program is as follows:
static GstPadProbeReturn
nvosd_src_resized_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
gpointer u_data)
{
GstBuffer *buf = (GstBuffer *) info->data;
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
NvDsMetaList * l_frame = NULL;
char file_name[128];
static gint frame_number = 0;
// Get original raw data
GstMapInfo in_map_info;
if (!gst_buffer_map (buf, &in_map_info, GST_MAP_READ)) {
g_print ("Error: Failed to map gst buffer\n");
gst_buffer_unmap (buf, &in_map_info);
return GST_PAD_PROBE_OK;
}
NvBufSurface *surface = (NvBufSurface *)in_map_info.data;
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL;
l_frame = l_frame->next) {
NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data);
//TODO for cuda device memory we need to use cudamemcpy
NvBufSurfaceMap (surface, -1, -1, NVBUF_MAP_READ);
/* Cache the mapped data for CPU access */
NvBufSurfaceSyncForCpu (surface, 0, 0); //will do nothing for unified memory type on dGPU
guint height = surface->surfaceList[frame_meta->batch_id].height;
guint width = surface->surfaceList[frame_meta->batch_id].width;
//Create Mat from NvMM memory, refer opencv API for how to create a Mat
cv::Mat nv12_mat = cv::Mat(height*3/2, width, CV_8UC1, surface->surfaceList[frame_meta->batch_id].mappedAddr.addr[0],
surface->surfaceList[frame_meta->batch_id].pitch);
//Convert nv12 to RGBA to apply algo based on RGBA
cv::Mat rgba_mat;
cv::cvtColor(nv12_mat, rgba_mat, cv::COLOR_YUV2BGRA_NV12);
// change the frames
NvBufSurface *inter_buf = nullptr;
NvBufSurfaceCreateParams create_params;/
create_params.gpuId = surface->gpuId;
create_params.width = width;
create_params.height = height;
create_params.size = 0;
create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA; //Holds the color format of the buffer.
create_params.layout = NVBUF_LAYOUT_PITCH;
#ifdef __aarch64__
create_params.memType = NVBUF_MEM_DEFAULT;
#else
create_params.memType = NVBUF_MEM_CUDA_UNIFIED;
#endif
//Create another scratch RGBA NvBufSurface
if (NvBufSurfaceCreate (&inter_buf, 1,
&create_params) != 0) {
GST_ERROR ("Error: Could not allocate internal buffer ");
return GST_PAD_PROBE_OK;
}
// inter_buf->numFilled = 1;
if(NvBufSurfaceMap (inter_buf, 0, -1, NVBUF_MAP_READ_WRITE) != 0)
g_print("map error");
NvBufSurfaceSyncForCpu (inter_buf, -1, -1);
cv::Mat choosed_resized_mat = cv::Mat(height, width, CV_8UC4, inter_buf->surfaceList[0].mappedAddr.addr[0],inter_buf->surfaceList[0].pitch);
// Aplly your algo which works with opencv Mat, here we only rotate the Mat for demo
// rotate(rgba_mat, choosed_resized_mat, ROTATE_180);
int x = 0;
int y = 0;
int width_selected = width / 2;
int height_selected = height / 2;
// selected_region
cv::Rect selected_region(x, y, width_selected, height_selected);
cv::Mat selected_rgba = rgba_mat(selected_region);
// region resized (width, height)
cv::resize(selected_rgba, choosed_resized_mat, cv::Size(width, height));
NvBufSurfaceSyncForDevice(inter_buf, -1, -1);//Syncs the hardware memory cache for the device.
inter_buf->numFilled = 1;
NvBufSurfTransformConfigParams transform_config_params;
NvBufSurfTransformParams transform_params;
NvBufSurfTransformRect src_rect;
NvBufSurfTransformRect dst_rect;
cudaStream_t cuda_stream;
CHECK_CUDA_STATUS (cudaStreamCreate (&cuda_stream),
"Could not create cuda stream");
transform_config_params.compute_mode = NvBufSurfTransformCompute_Default;
transform_config_params.gpu_id = surface->gpuId;
transform_config_params.cuda_stream = cuda_stream;
/* Set the transform session parameters for the conversions executed in this thread. */
NvBufSurfTransform_Error err = NvBufSurfTransformSetSessionParams (&transform_config_params);
if (err != NvBufSurfTransformError_Success) {
g_print("NvBufSurfTransformSetSessionParams failed with error\n");
return GST_PAD_PROBE_OK;
}
/* Set the transform ROIs for source and destination, only do the color format conversion*/
src_rect = {0, 0, width, height};
dst_rect = {0, 0, width, height};
/* Set the transform parameters */
transform_params.src_rect = &src_rect;
transform_params.dst_rect = &dst_rect;
transform_params.transform_flag =
NVBUFSURF_TRANSFORM_FILTER | NVBUFSURF_TRANSFORM_CROP_SRC |
NVBUFSURF_TRANSFORM_CROP_DST;
transform_params.transform_filter = NvBufSurfTransformInter_Default;
/* Transformation format conversion, Transform rotated RGBA mat to NV12 memory in original input surface*/
// src:A pointer to input batched buffers to be transformed.
// dst:A pointer to a caller-allocated location where transformed output is to be stored.
err = NvBufSurfTransform (inter_buf, surface, &transform_params);
if (err != NvBufSurfTransformError_Success) {
std::cout<< "NvBufSurfTransform failed with error %d while converting buffer" << err <<std::endl;
return GST_PAD_PROBE_OK;
}
// // access the surface modified by opencv
cv::cvtColor(nv12_mat, rgba_mat, cv::COLOR_YUV2BGRA_NV12);
// //dump the original NvbufSurface
sprintf(file_name, "nvosd_probe_choose_resized_stream%2d_%03d.jpg", frame_meta->source_id, frame_number);
cv::imwrite(file_name, rgba_mat);
// cudaStreamDestroy(cuda_stream);
NvBufSurfaceUnMap(inter_buf, -1, -1);
// NvBufSurfaceDestroy(inter_buf);
NvBufSurfaceUnMap(surface, -1, -1);
frame_number++;
}
// gst_buffer_unmap(buf, &in_map_info);
return GST_PAD_PROBE_OK;
}
but when I dump the original NvbufSurface,rgba_mat cannot display images correctly。rgba_mat is showed as :
Why did this situation occur?
I am very much looking forward to receiving your reply!