#include #include #include #include #include #include #include "gstcustomtiler.h" #include #include #include GST_DEBUG_CATEGORY_STATIC (gst_customtiler_debug); #define GST_CAT_DEFAULT gst_customtiler_debug #define USE_EGLIMAGE 1 #define OUTPUT_BATCH_SIZE 1 using namespace cv; using namespace std; static GQuark _dsmeta_quark = 0; bool flag = false; /* Enum to identify properties */ enum { PROP_0, PROP_UNIQUE_ID, PROP_AUTO_SCALE, PROP_PROCESSING_WIDTH, PROP_PROCESSING_HEIGHT, PROP_GPU_DEVICE_ID }; #define CHECK_NVDS_MEMORY_AND_GPUID(object, surface) \ ({ int _errtype=0;\ do { \ if ((surface->memType == NVBUF_MEM_DEFAULT || surface->memType == NVBUF_MEM_CUDA_DEVICE) && \ (surface->gpuId != object->gpu_id)) { \ GST_ELEMENT_ERROR (object, RESOURCE, FAILED, \ ("Input surface gpu-id doesnt match with configured gpu-id for element," \ " please allocate input using unified memory, or use same gpu-ids"),\ ("surface-gpu-id=%d,%s-gpu-id=%d",surface->gpuId,GST_ELEMENT_NAME(object),\ object->gpu_id)); \ _errtype = 1;\ } \ } while(0); \ _errtype; \ }) /* Default values for properties */ #define DEFAULT_UNIQUE_ID 15 #define DEFAULT_AUTO_SCALE TRUE #define DEFAULT_PROCESSING_WIDTH 1280 #define DEFAULT_PROCESSING_HEIGHT 720 #define DEFAULT_GPU_ID 0 #define RGB_BYTES_PER_PIXEL 3 #define RGBA_BYTES_PER_PIXEL 4 #define Y_BYTES_PER_PIXEL 1 #define UV_BYTES_PER_PIXEL 2 #define CHECK_NPP_STATUS(npp_status,error_str) do { \ if ((npp_status) != NPP_SUCCESS) { \ g_print ("Error: %s in %s at line %d: NPP Error %d\n", \ error_str, __FILE__, __LINE__, npp_status); \ goto error; \ } \ } while (0) #define CHECK_CUDA_STATUS(cuda_status,error_str) do { \ if ((cuda_status) != cudaSuccess) { \ g_print ("Error: %s in %s at line %d (%s)\n", \ error_str, __FILE__, __LINE__, cudaGetErrorName(cuda_status)); \ goto error; \ } \ } while (0) /* By default NVIDIA Hardware allocated memory flows through the pipeline. We * will be processing on this type of memory only. */ #define GST_CAPS_FEATURE_MEMORY_NVMM "memory:NVMM" static GstStaticPadTemplate gst_customtiler_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_NVMM, "{ NV12, RGBA, I420 }"))); static GstStaticPadTemplate gst_customtiler_src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_NVMM, "{ NV12, RGBA, I420 }"))); /* Define our element type. Standard GObject/GStreamer boilerplate stuff */ #define gst_customtiler_parent_class parent_class G_DEFINE_TYPE (GstCustomTiler, gst_customtiler, GST_TYPE_BASE_TRANSFORM); static void gst_customtiler_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_customtiler_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static gboolean gst_customtiler_set_caps (GstBaseTransform * btrans, GstCaps * incaps, GstCaps * outcaps); static gboolean gst_customtiler_start (GstBaseTransform * btrans); static gboolean gst_customtiler_stop (GstBaseTransform * btrans); static GstFlowReturn gst_customtiler_transform_ip (GstBaseTransform * btrans, GstBuffer * inbuf); static GstFlowReturn gst_customtiler_transform (GstBaseTransform * btrans, GstBuffer * inbuf, GstBuffer * outbuf); static GstFlowReturn gst_customtiler_prepare_output_buffer(GstBaseTransform * btrans, GstBuffer * inbuf, GstBuffer ** outbuf); /* Install properties, set sink and src pad capabilities, override the required * functions of the base class, These are common to all instances of the * element. */ static void gst_customtiler_class_init (GstCustomTilerClass* klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; GstBaseTransformClass *gstbasetransform_class; g_print("Start customtiler class init\n"); // Indicates we want to use DS buf api g_setenv ("DS_NEW_BUFAPI", "1", TRUE); gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gstbasetransform_class = (GstBaseTransformClass *) klass; /* Overide base class functions */ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_customtiler_set_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_customtiler_get_property); gstbasetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_customtiler_set_caps); gstbasetransform_class->start = GST_DEBUG_FUNCPTR (gst_customtiler_start); gstbasetransform_class->stop = GST_DEBUG_FUNCPTR (gst_customtiler_stop); //gstbasetransform_class->transform_ip = //GST_DEBUG_FUNCPTR (gst_customtiler_transform_ip); gstbasetransform_class->transform = GST_DEBUG_FUNCPTR (gst_customtiler_transform); gstbasetransform_class->prepare_output_buffer = GST_DEBUG_FUNCPTR(gst_customtiler_prepare_output_buffer); /* Install properties */ g_object_class_install_property (gobject_class, PROP_UNIQUE_ID, g_param_spec_uint ("unique-id", "Unique ID", "Unique ID for the element. Can be used to identify output of the" " element", 0, G_MAXUINT, DEFAULT_UNIQUE_ID, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_PROCESSING_WIDTH, g_param_spec_int ("processing-width", "Processing Width", "Width of the input buffer to algorithm", 1, G_MAXINT, DEFAULT_PROCESSING_WIDTH, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_PROCESSING_HEIGHT, g_param_spec_int ("processing-height", "Processing Height", "Height of the input buffer to algorithm", 1, G_MAXINT, DEFAULT_PROCESSING_HEIGHT, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_AUTO_SCALE, g_param_spec_boolean ("auto-scale", "Auto Scale", "Set Auto Scale Mode" "set Auto Scale Mode On,Off", DEFAULT_AUTO_SCALE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); g_object_class_install_property (gobject_class, PROP_GPU_DEVICE_ID, g_param_spec_uint ("gpu-id", "Set GPU Device ID", "Set GPU Device ID", 0,G_MAXUINT, 0, GParamFlags (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_READY))); /* Set sink and src pad capabilities */ gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_customtiler_src_template)); gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_customtiler_sink_template)); /* Set metadata describing the element */ gst_element_class_set_details_simple (gstelement_class, "CustomTiler plugin", "CustomTiler Plugin", "for IView Custom Tiler", "KIGIS" "@ "); } static void gst_customtiler_init (GstCustomTiler* customtiler) { GstBaseTransform *btrans = GST_BASE_TRANSFORM (customtiler); g_print("Start customtiler init\n"); /* We will not be generating a new buffer. Just adding / updating * metadata. */ gst_base_transform_set_in_place (GST_BASE_TRANSFORM (btrans), FALSE); /* We do not want to change the input caps. Set to passthrough. transform_ip * is still called. */ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (btrans), FALSE); /* Initialize all property variables to default values */ customtiler->unique_id = DEFAULT_UNIQUE_ID; customtiler->processing_width = DEFAULT_PROCESSING_WIDTH; customtiler->processing_height = DEFAULT_PROCESSING_HEIGHT; customtiler->auto_scale = DEFAULT_AUTO_SCALE; customtiler->gpu_id = DEFAULT_GPU_ID; /* This quark is required to identify NvDsMeta when iterating through * the buffer metadatas */ if (!_dsmeta_quark) _dsmeta_quark = g_quark_from_static_string (NVDS_META_STRING); } /* Function called when a property of the element is set. Standard boilerplate. */ static void gst_customtiler_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstCustomTiler *customtiler = GST_CUSTOMTILER (object); switch (prop_id) { case PROP_UNIQUE_ID: //g_print("set uid\n"); customtiler->unique_id = g_value_get_uint (value); break; case PROP_AUTO_SCALE: customtiler->auto_scale = g_value_get_boolean (value); break; case PROP_PROCESSING_WIDTH: //g_print("set pw\n"); customtiler->processing_width = g_value_get_int (value); break; case PROP_PROCESSING_HEIGHT: //g_print("set ph\n"); customtiler->processing_height = g_value_get_int (value); break; case PROP_GPU_DEVICE_ID: customtiler->gpu_id = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /* Function called when a property of the element is requested. Standard * boilerplate. */ static void gst_customtiler_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstCustomTiler *customtiler = GST_CUSTOMTILER (object); switch (prop_id) { case PROP_UNIQUE_ID: g_value_set_uint (value, customtiler->unique_id); break; case PROP_AUTO_SCALE: g_value_set_boolean (value, customtiler->auto_scale); break; case PROP_PROCESSING_WIDTH: g_value_set_int (value, customtiler->processing_width); break; case PROP_PROCESSING_HEIGHT: g_value_set_int (value, customtiler->processing_height); break; case PROP_GPU_DEVICE_ID: g_value_set_uint (value, customtiler->gpu_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /** * Initialize all resources and start the output thread */ static gboolean gst_customtiler_start (GstBaseTransform * btrans) { GstCustomTiler * customtiler = GST_CUSTOMTILER (btrans); NvBufSurfaceCreateParams create_params; GstQuery *queryparams = NULL; guint batch_size = 1; g_print("customtiler start\n"); // CHECK_CUDA_STATUS (cudaSetDevice (customtiler->gpu_id), // "Unable to set cuda device"); customtiler->in_batch_size = 1; queryparams = gst_nvquery_batch_size_new (); if (gst_pad_peer_query (GST_BASE_TRANSFORM_SINK_PAD (btrans), queryparams) || gst_pad_peer_query (GST_BASE_TRANSFORM_SRC_PAD (btrans), queryparams)) { if (gst_nvquery_batch_size_parse (queryparams, &batch_size)) { g_print("parsed batch size = %u\n",batch_size); customtiler->in_batch_size = batch_size; } } GST_DEBUG_OBJECT (customtiler, "Input batch-size %d \n", customtiler->batch_size); //set output batch 1 gst_nvquery_batch_size_set(queryparams, OUTPUT_BATCH_SIZE); g_print("set output batchsize %d\n", OUTPUT_BATCH_SIZE); gst_query_unref (queryparams); for(int i = 0 ; i < MAX_SWAP_SIZE ; ++i){ //allocate new batch for tiler if (customtiler->tilesurface[i]) NvBufSurfaceDestroy (customtiler->tilesurface[i]); customtiler->tilesurface[i] = NULL; create_params.gpuId = customtiler->gpu_id; create_params.width = customtiler->processing_width; create_params.height = customtiler->processing_height; create_params.size = 0; create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA; create_params.layout = NVBUF_LAYOUT_PITCH; #ifdef __aarch64__ create_params.memType = NVBUF_MEM_DEFAULT; //g_print("set surface memtype nvbuf_mem_dafault\n"); #else create_params.memType = NVBUF_MEM_CUDA_UNIFIED; #endif //Make GST Buffer if (NvBufSurfaceCreate (&(customtiler->tilesurface[i]), OUTPUT_BATCH_SIZE, &create_params) != 0) { GST_ERROR ("Error: Could not allocate internal buffer for customtiler"); goto error; } } customtiler->swap = 0; //NvBufSurfaceMemSet (customtiler->tilesurface, -1, -1, 0); g_print("customtiler end\n"); return TRUE; error: if (customtiler->host_rgb_buf) { cudaFreeHost (customtiler->host_rgb_buf); customtiler->host_rgb_buf = NULL; } if (customtiler->cuda_stream) { cudaStreamDestroy (customtiler->cuda_stream); customtiler->cuda_stream = NULL; } return FALSE; } /** * Stop the output thread and free up all the resources */ static gboolean gst_customtiler_stop (GstBaseTransform * btrans){ GstCustomTiler *customtiler = GST_CUSTOMTILER (btrans); for(int i = 0 ; i < MAX_SWAP_SIZE ; ++i){ if (customtiler->tilesurface[i]) NvBufSurfaceDestroy(customtiler->tilesurface[i]); customtiler->tilesurface[i] = NULL; } if (customtiler->cuda_stream) cudaStreamDestroy (customtiler->cuda_stream); customtiler->cuda_stream = NULL; delete customtiler->cvmat; customtiler->cvmat = NULL; if (customtiler->host_rgb_buf) { cudaFreeHost (customtiler->host_rgb_buf); customtiler->host_rgb_buf = NULL; } GST_DEBUG_OBJECT (customtiler, "deleted CV Mat \n"); return TRUE; } /** * Called when source / sink pad capabilities have been negotiated. */ static gboolean gst_customtiler_set_caps (GstBaseTransform * btrans, GstCaps * incaps, GstCaps * outcaps) { GstCustomTiler *customtiler = GST_CUSTOMTILER (btrans); /* Save the input video information, since this will be required later. */ gst_video_info_from_caps (&customtiler->video_info, incaps); CHECK_CUDA_STATUS (cudaSetDevice (customtiler->gpu_id), "Unable to set cuda device"); return TRUE; error: return FALSE; } static GstFlowReturn process_bbox(NvDsFrameMeta *inframeMeta, int orgw, int orgh, NvDsFrameMeta *outframemeta, cv::Rect rect){ //g_print("process bbox\n"); NvDsBatchMeta *outbatch = outframemeta->base_meta.batch_meta; float ratiow = rect.width / (float)orgw; float ratioh = rect.height / (float)orgh; for (NvDsMetaList * l_obj = inframeMeta->obj_meta_list; l_obj != NULL; l_obj = l_obj->next) { NvDsObjectMeta *obj = (NvDsObjectMeta *) l_obj->data; NvDsObjectMeta *resizedobj = nvds_acquire_obj_meta_from_pool(outbatch); nvds_copy_obj_meta(obj, resizedobj); resizedobj->rect_params.left *= ratiow; resizedobj->rect_params.top *= ratioh; resizedobj->rect_params.width *= ratiow; resizedobj->rect_params.height *= ratioh; resizedobj->rect_params.left = resizedobj->rect_params.left < 0 ? 0 : resizedobj->rect_params.left >= rect.width ? rect.width-1 : resizedobj->rect_params.left; resizedobj->rect_params.top = resizedobj->rect_params.top < 0 ? 0 : resizedobj->rect_params.top >= rect.height ? rect.height-1 : resizedobj->rect_params.top; resizedobj->rect_params.width = resizedobj->rect_params.left + resizedobj->rect_params.width > rect.width ? rect.width - resizedobj->rect_params.left : resizedobj->rect_params.width; resizedobj->rect_params.height = resizedobj->rect_params.top + resizedobj->rect_params.height> rect.height ? rect.height - resizedobj->rect_params.top : resizedobj->rect_params.height; resizedobj->rect_params.left += rect.x; resizedobj->rect_params.top += rect.y; // g_print("box org (%f %f %f %f) -> (%f %f %f %f)\n",obj->rect_params.left, obj->rect_params.top, obj->rect_params.width, obj->rect_params.height, // resizedobj->rect_params.left, resizedobj->rect_params.top, resizedobj->rect_params.width, resizedobj->rect_params.height); nvds_add_obj_meta_to_frame(outframemeta, resizedobj, NULL); } nvds_clear_obj_meta_list(inframeMeta, inframeMeta->obj_meta_list); return GST_FLOW_OK; } static gpointer process_resize_mat(gpointer ptr){ //g_print("s0\n"); ResizeMatGroup *group = (_ResizeMatGroup*)ptr; //g_print("s1\n"); cv::Mat resizedmat; cv::resize(*(group->src), resizedmat, cv::Size(group->rect.width, group->rect.height)); //g_print("s2\n"); //cv::Rect dest = cv::Rect(tilewidth * frame_meta->source_id, tileheight * r, tilewidth, tileheight); //g_print("copy\n"); resizedmat.copyTo((*(group->dst))(group->rect)); //g_print("s3\n"); return NULL; } static GstFlowReturn gpu_process_tiler(GstCustomTiler *customtiler, NvBufSurface *insurface, NvDsBatchMeta *inbatch, NvBufSurface *outsurface, NvDsFrameMeta *outframemeta){ //g_print("process tile\n"); cv::Mat outMat; cv::cuda::GpuMat gpuOutMat; outMat = cv::Mat (outsurface->surfaceList[0].planeParams.height[0],outsurface->surfaceList[0].planeParams.width[0], CV_8UC4, outsurface->surfaceList[0].mappedAddr.addr[0], outsurface->surfaceList[0].planeParams.pitch[0]); gpuOutMat = cv::cuda::GpuMat (outsurface->surfaceList[0].planeParams.height[0],outsurface->surfaceList[0].planeParams.width[0], CV_8UC4, outsurface->surfaceList[0].planeParams.pitch[0]); // g_print("output mat w = %d h = %d p = %d\n", outsurface->surfaceList[0].planeParams.width[0], // outsurface->surfaceList[0].planeParams.height[0], // outsurface->surfaceList[0].planeParams.pitch[0]); if(customtiler->auto_scale){ //int col = insurface->batchSize / 2; //int row = insurface->batchSize / 2; int col = 2; int row = 2; int tilewidth = customtiler->processing_width / col; int tileheight = customtiler->processing_height / row; cv::Mat inmat[insurface->batchSize]; cv::cuda::GpuMat gpuInmat[insurface->batchSize]; //g_print("input batch = %d col = %d row = %d tw = %d th = %d\n",insurface->batchSize, col, row, tilewidth, tileheight); int batch = 0; cv::Rect dest[4]; dest[0] = cv::Rect(0, 0, 1014, 720); dest[1] = cv::Rect(1014, 0, 256, 240); dest[2] = cv::Rect(1014, 240, 256, 240); dest[3] = cv::Rect(1014, 480, 256, 240); for(int r = 0 ; r < row; ++r){ for(int c = 0 ; c < col; ++c){ NvDsFrameMeta *frame_meta = nvds_get_nth_frame_meta(inbatch->frame_meta_list, batch); //g_print("input mat batch%d w = %d h = %d p %d size %u addr %p\n",batch, insurface->surfaceList[batch].planeParams.width[0], // insurface->surfaceList[batch].planeParams.height[0], // insurface->surfaceList[batch].planeParams.pitch[0], // insurface->surfaceList[batch].dataSize, // insurface->surfaceList[batch].mappedAddr.addr[0]); if(insurface->surfaceList[batch].mappedAddr.addr[0] == nullptr){ g_print("customtiler - detect nullpointer in tile process, ignore this frame batch%d\n", batch); continue; } inmat[batch] = cv::Mat (insurface->surfaceList[batch].planeParams.height[0],insurface->surfaceList[batch].planeParams.width[0], CV_8UC4, insurface->surfaceList[batch].mappedAddr.addr[0], insurface->surfaceList[batch].planeParams.pitch[0]); gpuInmat[batch] = cv::cuda::GpuMat (insurface->surfaceList[batch].planeParams.height[0],insurface->surfaceList[batch].planeParams.width[0], CV_8UC4, insurface->surfaceList[batch].planeParams.pitch[0]); gpuInmat[batch].upload(inmat[batch]); cv::Size s = inmat[batch].size(); //g_print("mat width = %d height = %d\n", s.width, s.height); //g_print("resize\n"); cv::cuda::GpuMat resizedmat; cv::cuda::resize(gpuInmat[batch], resizedmat, cv::Size(dest[frame_meta->source_id].width, dest[frame_meta->source_id].height)); //cv::Rect dest = cv::Rect(tilewidth * frame_meta->source_id, tileheight * r, tilewidth, tileheight); //g_print("copy\n"); resizedmat.copyTo(gpuOutMat(dest[frame_meta->source_id])); //g_print("batch%d pindex = %d sourceid = %d\n", batch, frame_meta->pad_index, frame_meta->source_id); process_bbox(frame_meta, insurface->surfaceList[batch].planeParams.width[0], insurface->surfaceList[batch].planeParams.height[0], outframemeta, dest[frame_meta->source_id]); ++batch; } } gpuOutMat.download(outMat); //cv::rectangle(outMat, dest[0], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[1], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[2], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[3], cv::Scalar(40, 40, 40)); //cv::imwrite("/home/team3/test.png",outMat); } else{ } return GST_FLOW_OK; } static GstFlowReturn process_tiler(GstCustomTiler *customtiler, NvBufSurface *insurface, NvDsBatchMeta *inbatch, NvBufSurface *outsurface, NvDsFrameMeta *outframemeta){ //g_print("process tile\n"); cv::Mat outMat; outMat = cv::Mat (outsurface->surfaceList[0].planeParams.height[0],outsurface->surfaceList[0].planeParams.width[0], CV_8UC4, outsurface->surfaceList[0].mappedAddr.addr[0], outsurface->surfaceList[0].planeParams.pitch[0]); // g_print("output mat w = %d h = %d p = %d\n", outsurface->surfaceList[0].planeParams.width[0], // outsurface->surfaceList[0].planeParams.height[0], // outsurface->surfaceList[0].planeParams.pitch[0]); if(customtiler->auto_scale){ //int col = insurface->batchSize / 2; //int row = insurface->batchSize / 2; int col = 2; int row = 2; int tilewidth = customtiler->processing_width / col; int tileheight = customtiler->processing_height / row; //g_print("input batch = %d col = %d row = %d tw = %d th = %d\n",insurface->batchSize, col, row, tilewidth, tileheight); int batch = 0; cv::Rect dest[4]; cv::Mat inmat[4]; #if 0 dest[0] = cv::Rect(0, 0, 1014, 720); dest[1] = cv::Rect(1014, 0, 256, 240); dest[2] = cv::Rect(1014, 240, 256, 240); dest[3] = cv::Rect(1014, 480, 256, 240); #else dest[0] = cv::Rect(0, 0, 640, 360); dest[1] = cv::Rect(640, 0, 640, 360); dest[2] = cv::Rect(0, 360, 640, 360); dest[3] = cv::Rect(640, 360, 640, 360); #endif ResizeMatGroup *group[4] = {0,}; for(int r = 0 ; r < row; ++r){ for(int c = 0 ; c < col; ++c){ NvDsFrameMeta *frame_meta = nvds_get_nth_frame_meta(inbatch->frame_meta_list, batch); group[batch] = g_new(ResizeMatGroup, 1); //g_print("input mat batch%d w = %d h = %d p %d size %u addr %p\n",batch, insurface->surfaceList[batch].planeParams.width[0], // insurface->surfaceList[batch].planeParams.height[0], // insurface->surfaceList[batch].planeParams.pitch[0], // insurface->surfaceList[batch].dataSize, // insurface->surfaceList[batch].mappedAddr.addr[0]); if(insurface->surfaceList[batch].mappedAddr.addr[0] == nullptr){ g_print("customtiler - detect nullpointer in tile process, ignore this frame batch%d\n", batch); ++batch; continue; } inmat[batch] = cv::Mat (insurface->surfaceList[batch].planeParams.height[0],insurface->surfaceList[batch].planeParams.width[0], CV_8UC4, insurface->surfaceList[batch].mappedAddr.addr[0], insurface->surfaceList[batch].planeParams.pitch[0]); group[batch]->isEmpty = FALSE; group[batch]->src = &inmat[batch]; group[batch]->dst = &outMat; group[batch]->rect = dest[frame_meta->source_id]; char title[255]; sprintf(title, "resize thread %d", batch); customtiler->processMatThread[batch] = g_thread_new(title, process_resize_mat, group[batch]); //cv::Size s = inmat[batch].size(); //g_print("mat width = %d height = %d\n", s.width, s.height); //g_print("resize\n"); //g_print("batch%d pindex = %d sourceid = %d\n", batch, frame_meta->pad_index, frame_meta->source_id); process_bbox(frame_meta, insurface->surfaceList[batch].planeParams.width[0], insurface->surfaceList[batch].planeParams.height[0], outframemeta, dest[frame_meta->source_id]); ++batch; } } for(int i = 0 ; i < 4 ; ++i){ if(!group[i]->isEmpty){ g_thread_join(customtiler->processMatThread[i]); //g_print("thrd%d=O ", i); } else { //g_print("thrd%d=X ", i); } g_free(group[i]); } //g_print("\n"); //cv::rectangle(outMat, dest[0], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[1], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[2], cv::Scalar(40, 40, 40)); //cv::rectangle(outMat, dest[3], cv::Scalar(40, 40, 40)); //cv::imwrite("/home/team3/test.png",outMat); } else{ } return GST_FLOW_OK; } static GstFlowReturn gst_customtiler_prepare_output_buffer(GstBaseTransform * btrans, GstBuffer * inbuf, GstBuffer ** outbuf) { GstCustomTiler *customtiler = GST_CUSTOMTILER (btrans); GstFlowReturn flow_ret = GST_FLOW_ERROR; GstMapInfo in_map_info; GstMapInfo out_map_info; NvBufSurface *insurface = NULL; NvBufSurface *outsurface = NULL; NvDsBatchMeta *inbatch = NULL; NvBufSurfaceCreateParams create_params; NvDsBatchMeta *batch_meta = NULL; NvDsFrameMeta *frame_meta = NULL; NvDsMeta *meta = NULL; //g_print("input customtiler\n"); inbatch = gst_buffer_get_nvds_batch_meta(inbuf); //g_print("get batch input buffer\n"); //Sync For cpu inbuf (nCh Stream after detector) memset (&in_map_info, 0, sizeof (in_map_info)); if (!gst_buffer_map (inbuf, &in_map_info, GST_MAP_READWRITE)) { g_print ("Error: Failed to out map gst buffer\n"); goto error; } insurface = (NvBufSurface *) in_map_info.data; GST_DEBUG_OBJECT (customtiler, "Processing Frame Surface %p\n",insurface); if (CHECK_NVDS_MEMORY_AND_GPUID (customtiler, insurface)) { g_print ("Error: Check NVDS Memory And Gpu id\n"); goto error; } if (NvBufSurfaceMap (insurface, -1, -1, NVBUF_MAP_READ_WRITE) != 0){ g_print("inbuf surface map Error\n"); return GST_FLOW_ERROR; } NvBufSurfaceSyncForCpu (insurface, -1, -1); //g_print("mapped all batch input streams\n"); NvBufSurfaceMemSet(customtiler->tilesurface[customtiler->swap], 0, 0, 0); customtiler->tilesurface[customtiler->swap]->numFilled = OUTPUT_BATCH_SIZE; //g_print("make new output batch meta\n"); *outbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_ZERO_PREFIXED, customtiler->tilesurface[customtiler->swap], sizeof(NvBufSurface), 0, sizeof(NvBufSurface), NULL, NULL); batch_meta = nvds_create_batch_meta(OUTPUT_BATCH_SIZE); meta = gst_buffer_add_nvds_meta (*outbuf, batch_meta, NULL, nvds_batch_meta_copy_func, nvds_batch_meta_release_func); meta->meta_type = NVDS_BATCH_GST_META; batch_meta->base_meta.batch_meta = batch_meta; batch_meta->base_meta.copy_func = nvds_batch_meta_copy_func; batch_meta->base_meta.release_func = nvds_batch_meta_release_func; batch_meta->max_frames_in_batch = OUTPUT_BATCH_SIZE; frame_meta = nvds_acquire_frame_meta_from_pool(batch_meta); nvds_add_frame_meta_to_batch(batch_meta, frame_meta); // Some important parameters to fill frame_meta->num_obj_meta = 0; frame_meta->pad_index = 0; frame_meta->source_id = 0; frame_meta->buf_pts = 0; frame_meta->ntp_timestamp = 0; frame_meta->frame_num = 0; frame_meta->batch_id = 0; frame_meta->source_frame_width = customtiler->processing_width; frame_meta->source_frame_height = customtiler->processing_height; frame_meta->num_surfaces_per_frame = OUTPUT_BATCH_SIZE; //*outbuf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_ZERO_PREFIXED, customtiler->tilesurface, sizeof(NvBufSurface), 0, sizeof(NvBufSurface), NULL, NULL); // CHECK_CUDA_STATUS (cudaSetDevice (customtiler->gpu_id), // "Unable to set cuda device"); //Sync for cpu tilesurface (make 1 batched Tiled Display using insurface) memset (&out_map_info, 0, sizeof (out_map_info)); if (!gst_buffer_map (*outbuf, &out_map_info, GST_MAP_READWRITE)) { g_print ("Error: Failed to out map gst buffer\n"); goto error; } outsurface = (NvBufSurface *) out_map_info.data; GST_DEBUG_OBJECT (customtiler,"Processing Frame Surface %p\n",outsurface); if (CHECK_NVDS_MEMORY_AND_GPUID (customtiler, outsurface)) { g_print ("Error: Check NVDS Memory And Gpu id\n"); goto error; } if (NvBufSurfaceMap (outsurface, 0, 0, NVBUF_MAP_READ_WRITE) != 0){ g_print("Tile surface map Error\n"); return GST_FLOW_ERROR; } NvBufSurfaceSyncForCpu (outsurface, 0,0); #if 1 process_tiler(customtiler, insurface, inbatch, outsurface, frame_meta); #else gpu_process_tiler(customtiler, insurface, inbatch, outsurface, frame_meta); #endif NvBufSurfaceSyncForDevice (outsurface, 0,0); if (NvBufSurfaceUnMap (outsurface, 0,0)){ g_print("Tile surface unmap Error\n"); goto error; } NvBufSurfaceSyncForDevice (insurface, -1, -1); if (NvBufSurfaceUnMap (insurface, -1, -1)){ g_print("inbuf surface unmap Error\n"); goto error; } // g_print("debug surface batchsize %u\n", outsurface->batchSize); // g_print("debug surface numfilled %u\n", outsurface->numFilled); // g_print("debug surface gpuid %u\n", outsurface->gpuId); // g_print("debug surface0 memtype %u\n", outsurface->memType); // g_print("debug surface0 color format %u\n", outsurface->surfaceList[0].colorFormat); // g_print("debug surface0 num planes %u\n", outsurface->surfaceList[0].planeParams.num_planes); // g_print("debug surface0 width %u\n", outsurface->surfaceList[0].planeParams.width[0]); // g_print("debug surface0 height %u\n", outsurface->surfaceList[0].planeParams.height[0]); // g_print("debug surface0 pitch %u\n", outsurface->surfaceList[0].planeParams.pitch[0]); // g_print("debug surface0 offset %u\n", outsurface->surfaceList[0].planeParams.offset[0]); // g_print("debug surface0 psize %u\n", outsurface->surfaceList[0].planeParams.psize[0]); // g_print("debug surface0 mapaddr %u\n", outsurface->surfaceList[0].mappedAddr.addr[0]); // g_print("debug surface0 bytesPerPix %u\n", outsurface->surfaceList[0].planeParams.bytesPerPix[0]); ++customtiler->swap; if(customtiler->swap == MAX_SWAP_SIZE){ customtiler->swap = 0; } flow_ret = GST_FLOW_OK; error: gst_buffer_unmap (*outbuf, &out_map_info); gst_buffer_unmap (inbuf, &in_map_info); return flow_ret; } static GstFlowReturn gst_customtiler_transform (GstBaseTransform * btrans, GstBuffer * inbuf, GstBuffer * outbuf) { GstCustomTiler *customtiler = GST_CUSTOMTILER (btrans); GstFlowReturn flow_ret = GST_FLOW_ERROR; flow_ret = GST_FLOW_OK; error: return flow_ret; } /** * Called when element recieves an input buffer from upstream element. */ static GstFlowReturn gst_customtiler_transform_ip (GstBaseTransform * btrans, GstBuffer * inbuf) { GstCustomTiler *customtiler = GST_CUSTOMTILER (btrans); GstMapInfo in_map_info; GstFlowReturn flow_ret = GST_FLOW_ERROR; gdouble scale_ratio = 1.0; NvBufSurface *surface = NULL; NvDsBatchMeta *batch_meta = NULL; NvDsFrameMeta *frame_meta = NULL; NvDsMetaList * l_frame = NULL; NvBufSurfaceCreateParams create_params; //int nn = 0; guint i = 0; //g_print("Transform Start\n"); customtiler->frame_num++; // batch_meta = gst_buffer_get_nvds_batch_meta (inbuf); // if (batch_meta == nullptr) { // GST_ELEMENT_ERROR (customtiler, STREAM, FAILED, // ("NvDsBatchMeta not found for input buffer."), (NULL)); // return GST_FLOW_ERROR; // } ////Process_Draw_Menu(customtiler); ////flag = !flag; // if (customtiler->process_full_frame ) { // for (l_frame = batch_meta->frame_meta_list; l_frame != NULL; // l_frame = l_frame->next) // { // frame_meta = (NvDsFrameMeta *) (l_frame->data); // NvOSD_RectParams rect_params; ////Scale the entire frame to processing resolution // rect_params.left = 0; // rect_params.top = 0; // rect_params.width = customtiler->video_info.width; // rect_params.height = customtiler->video_info.height; // g_print("Frame - %u Padidx %d batchID %u source%u bufpts %u \n",customtiler->frame_num, frame_meta->pad_index, frame_meta->batch_id, frame_meta->source_id, frame_meta->buf_pts); ////g_print("Frame - %u Padidx %d batchID %u\n",customtiler->frame_num, frame_meta->pad_index, frame_meta->batch_id); // if(frame_meta->source_id == 0) // { if (get_converted_mat (customtiler, surface, frame_meta->source_id, &rect_params, // scale_ratio, customtiler->video_info.width, // customtiler->video_info.height) != GST_FLOW_OK) { // goto error; // } // } // i++; // } // } flow_ret = GST_FLOW_OK; g_print("TransformIP OK\n"); error: //gst_buffer_unmap (inbuf, &in_map_info); return flow_ret; } /** * Boiler plate for registering a plugin and an element. */ static gboolean customtiler_plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gst_customtiler_debug, "customtiler", 0, "customtiler plugin"); return gst_element_register (plugin, "customtiler", GST_RANK_PRIMARY, GST_TYPE_CUSTOMTILER); } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, nvdsgst_customtiler, DESCRIPTION, customtiler_plugin_init, VERSION, LICENSE, BINARY_PACKAGE, URL)