Guest User

Untitled

a guest
Jan 4th, 2020
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 33.49 KB | None | 0 0
  1. #include <gst/gst.h>
  2. #include <glib.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <time.h>
  6. #include <sys/timeb.h>
  7.  
  8. #include "gstnvdsmeta.h"
  9. #include "nvdsmeta_schema.h"
  10.  
  11. #define MAX_DISPLAY_LEN 64
  12. #define MAX_TIME_STAMP_LEN 32
  13.  
  14. #define MAPPING "/ds"
  15. #define SERVICE "554"
  16.  
  17. #define PGIE_CLASS_ID_VEHICLE 0
  18. #define PGIE_CLASS_ID_PERSON 2
  19.  
  20. #define MAX_TRACKING_ID_LEN 16
  21. #define TRACKER_CONFIG_FILE "dstest2_tracker_config.txt"
  22. #define PGIE_CONFIG_FILE  "dstest4_pgie_config.txt"
  23. #define MSCONV_CONFIG_FILE "dstest4_msgconv_config.txt"
  24.  
  25. /* The muxer output resolution must be set if the input streams will be of
  26.  * different resolution. The muxer will scale all the input frames to this
  27.  * resolution. */
  28. #define MUXER_OUTPUT_WIDTH 1920
  29. #define MUXER_OUTPUT_HEIGHT 1080
  30.  
  31. /* Muxer batch formation timeout, for e.g. 40 millisec. Should ideally be set
  32.  * based on the fastest source's framerate. */
  33. #define MUXER_BATCH_TIMEOUT_USEC 4000000
  34.  
  35. static gchar *cfg_file = NULL;
  36. static gchar *input_file = NULL;
  37. static gchar *topic = NULL;
  38. static gchar *conn_str = NULL;
  39. static gchar *proto_lib = NULL;
  40. static gint schema_type = 1;
  41. static gboolean display_off = FALSE;
  42.  
  43. gint frame_number = 0;
  44. gchar pgie_classes_str[4][32] = { "Vehicle", "TwoWheeler", "Person",
  45.   "Roadsign"
  46. };
  47.  
  48. GOptionEntry entries[] = {
  49.   {"cfg-file", 'c', 0, G_OPTION_ARG_FILENAME, &cfg_file,
  50.    "Set the adaptor config file. Optional if connection string has relevant  details.", NULL},
  51.   {"input-file", 'i', 0, G_OPTION_ARG_FILENAME, &input_file,
  52.    "Set the input H264 file", NULL},
  53.   {"topic", 't', 0, G_OPTION_ARG_STRING, &topic,
  54.    "Name of message topic. Optional if it is part of connection string or config file.", NULL},
  55.   {"conn-str", 0, 0, G_OPTION_ARG_STRING, &conn_str,
  56.    "Connection string of backend server. Optional if it is part of config file.", NULL},
  57.   {"proto-lib", 'p', 0, G_OPTION_ARG_STRING, &proto_lib,
  58.    "Absolute path of adaptor library", NULL},
  59.   {"schema", 's', 0, G_OPTION_ARG_INT, &schema_type,
  60.    "Type of message schema (0=Full, 1=minimal), default=0", NULL},
  61.   {"no-display", 0, 0, G_OPTION_ARG_NONE, &display_off, "Disable display", NULL},
  62.   {NULL}
  63. };
  64.  
  65. static void generate_ts_rfc3339 (char *buf, int buf_size)
  66. {
  67.   time_t tloc;
  68.   struct tm tm_log;
  69.   struct timespec ts;
  70.   char strmsec[6]; //.nnnZ\0
  71.  
  72.   clock_gettime(CLOCK_REALTIME,  &ts);
  73.   memcpy(&tloc, (void *)(&ts.tv_sec), sizeof(time_t));
  74.   gmtime_r(&tloc, &tm_log);
  75.   strftime(buf, buf_size,"%Y-%m-%dT%H:%M:%S", &tm_log);
  76.   int ms = ts.tv_nsec/1000000;
  77.   g_snprintf(strmsec, sizeof(strmsec),".%.3dZ", ms);
  78.   strncat(buf, strmsec, buf_size);
  79. }
  80.  
  81. static gpointer meta_copy_func (gpointer data, gpointer user_data)
  82. {
  83.   NvDsUserMeta *user_meta = (NvDsUserMeta *) data;
  84.   NvDsEventMsgMeta *srcMeta = (NvDsEventMsgMeta *) user_meta->user_meta_data;
  85.   NvDsEventMsgMeta *dstMeta = NULL;
  86.  
  87.   dstMeta = g_memdup (srcMeta, sizeof(NvDsEventMsgMeta));
  88.  
  89.   if (srcMeta->ts)
  90.     dstMeta->ts = g_strdup (srcMeta->ts);
  91.  
  92.   if (srcMeta->sensorStr)
  93.     dstMeta->sensorStr = g_strdup (srcMeta->sensorStr);
  94.  
  95.   if (srcMeta->objSignature.size > 0) {
  96.     dstMeta->objSignature.signature = g_memdup (srcMeta->objSignature.signature,
  97.                                                 srcMeta->objSignature.size);
  98.     dstMeta->objSignature.size = srcMeta->objSignature.size;
  99.   }
  100.  
  101.   if(srcMeta->objectId) {
  102.     dstMeta->objectId = g_strdup (srcMeta->objectId);
  103.   }
  104.  
  105.   if (srcMeta->extMsgSize > 0) {
  106.     if (srcMeta->objType == NVDS_OBJECT_TYPE_VEHICLE) {
  107.       NvDsVehicleObject *srcObj = (NvDsVehicleObject *) srcMeta->extMsg;
  108.       NvDsVehicleObject *obj = (NvDsVehicleObject *) g_malloc0 (sizeof (NvDsVehicleObject));
  109.       if (srcObj->type)
  110.         obj->type = g_strdup (srcObj->type);
  111.       if (srcObj->make)
  112.         obj->make = g_strdup (srcObj->make);
  113.       if (srcObj->model)
  114.         obj->model = g_strdup (srcObj->model);
  115.       if (srcObj->color)
  116.         obj->color = g_strdup (srcObj->color);
  117.       if (srcObj->license)
  118.         obj->license = g_strdup (srcObj->license);
  119.       if (srcObj->region)
  120.         obj->region = g_strdup (srcObj->region);
  121.  
  122.       dstMeta->extMsg = obj;
  123.       dstMeta->extMsgSize = sizeof (NvDsVehicleObject);
  124.     } else if (srcMeta->objType == NVDS_OBJECT_TYPE_PERSON) {
  125.       NvDsPersonObject *srcObj = (NvDsPersonObject *) srcMeta->extMsg;
  126.       NvDsPersonObject *obj = (NvDsPersonObject *) g_malloc0 (sizeof (NvDsPersonObject));
  127.  
  128.       obj->age = srcObj->age;
  129.  
  130.       if (srcObj->gender)
  131.         obj->gender = g_strdup (srcObj->gender);
  132.       if (srcObj->cap)
  133.         obj->cap = g_strdup (srcObj->cap);
  134.       if (srcObj->hair)
  135.         obj->hair = g_strdup (srcObj->hair);
  136.       if (srcObj->apparel)
  137.         obj->apparel = g_strdup (srcObj->apparel);
  138.       dstMeta->extMsg = obj;
  139.       dstMeta->extMsgSize = sizeof (NvDsVehicleObject);
  140.     }
  141.   }
  142.  
  143.   return dstMeta;
  144. }
  145.  
  146. static void meta_free_func (gpointer data, gpointer user_data)
  147. {
  148.   NvDsUserMeta *user_meta = (NvDsUserMeta *) data;
  149.   NvDsEventMsgMeta *srcMeta = (NvDsEventMsgMeta *) user_meta->user_meta_data;
  150.  
  151.   g_free (srcMeta->ts);
  152.   g_free (srcMeta->sensorStr);
  153.  
  154.   if (srcMeta->objSignature.size > 0) {
  155.     g_free (srcMeta->objSignature.signature);
  156.     srcMeta->objSignature.size = 0;
  157.   }
  158.  
  159.   if(srcMeta->objectId) {
  160.     g_free (srcMeta->objectId);
  161.   }
  162.  
  163.   if (srcMeta->extMsgSize > 0) {
  164.     if (srcMeta->objType == NVDS_OBJECT_TYPE_VEHICLE) {
  165.       NvDsVehicleObject *obj = (NvDsVehicleObject *) srcMeta->extMsg;
  166.       if (obj->type)
  167.         g_free (obj->type);
  168.       if (obj->color)
  169.         g_free (obj->color);
  170.       if (obj->make)
  171.         g_free (obj->make);
  172.       if (obj->model)
  173.         g_free (obj->model);
  174.       if (obj->license)
  175.         g_free (obj->license);
  176.       if (obj->region)
  177.         g_free (obj->region);
  178.     } else if (srcMeta->objType == NVDS_OBJECT_TYPE_PERSON) {
  179.       NvDsPersonObject *obj = (NvDsPersonObject *) srcMeta->extMsg;
  180.  
  181.       if (obj->gender)/*
  182.  * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
  183.  *
  184.  * Permission is hereby granted, free of charge, to any person obtaining a
  185.  * copy of this software and associated documentation files (the "Software"),
  186.  * to deal in the Software without restriction, including without limitation
  187.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  188.  * and/or sell copies of the Software, and to permit persons to whom the
  189.  * Software is furnished to do so, subject to the following conditions:
  190.  *
  191.  * The above copyright notice and this permission notice shall be included in
  192.  * all copies or substantial portions of the Software.
  193.  *
  194.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  195.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  196.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  197.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  198.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  199.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  200.  * DEALINGS IN THE SOFTWARE.
  201.  */
  202.  
  203.         g_free (obj->gender);
  204.       if (obj->cap)
  205.         g_free (obj->cap);
  206.       if (obj->hair)
  207.         g_free (obj->hair);/*
  208.  * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
  209.  *
  210.  * Permission is hereby granted, free of charge, to any person obtaining a
  211.  * copy of this software and associated documentation files (the "Software"),
  212.  * to deal in the Software without restriction, including without limitation
  213.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  214.  * and/or sell copies of the Software, and to permit persons to whom the
  215.  * Software is furnished to do so, subject to the following conditions:
  216.  *
  217.  * The above copyright notice and this permission notice shall be included in
  218.  * all copies or substantial portions of the Software.
  219.  *
  220.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  221.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  222.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  223.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  224.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  225.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  226.  * DEALINGS IN THE SOFTWARE.
  227.  */
  228.  
  229.       if (obj->apparel)
  230.         g_free (obj->apparel);
  231.     }
  232.     g_free (srcMeta->extMsg);
  233.     srcMeta->extMsgSize = 0;
  234.   }
  235.   g_free (user_meta->user_meta_data);
  236.   user_meta->user_meta_data = NULL;
  237. }
  238.  
  239. static void
  240. generate_vehicle_meta (gpointer data)
  241. {
  242.   NvDsVehicleObject *obj = (NvDsVehicleObject *) data;
  243.  
  244.   obj->type = g_strdup ("sedan");
  245.   obj->color = g_strdup ("blue");
  246.   obj->make = g_strdup ("Bugatti");
  247.   obj->model = g_strdup ("M");
  248.   obj->license = g_strdup ("XX1234");
  249.   obj->region = g_strdup ("CA");
  250. }
  251.  
  252. static void
  253. generate_person_meta (gpointer data)
  254. {
  255.   NvDsPersonObject *obj = (NvDsPersonObject *) data;
  256.   obj->age = 45;
  257.   obj->cap = g_strdup ("none");
  258.   obj->hair = g_strdup ("black");
  259.   obj->gender = g_strdup ("male");
  260.   obj->apparel= g_strdup ("formal");
  261. }
  262.  
  263. static void
  264. generate_event_msg_meta (gpointer data, gint class_id, NvDsObjectMeta * obj_params)
  265. {
  266.   NvDsEventMsgMeta *meta = (NvDsEventMsgMeta *) data;/*
  267.  * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
  268.  *
  269.  * Permission is hereby granted, free of charge, to any person obtaining a
  270.  * copy of this software and associated documentation files (the "Software"),
  271.  * to deal in the Software without restriction, including without limitation
  272.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  273.  * and/or sell copies of the Software, and to permit persons to whom the
  274.  * Software is furnished to do so, subject to the following conditions:
  275.  *
  276.  * The above copyright notice and this permission notice shall be included in
  277.  * all copies or substantial portions of the Software.
  278.  *
  279.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  280.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  281.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  282.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  283.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  284.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  285.  * DEALINGS IN THE SOFTWARE.
  286.  */
  287.  
  288.   meta->sensorId = 0;
  289.   meta->placeId = 0;
  290.   meta->moduleId = 0;
  291.   meta->sensorStr = g_strdup ("sensor-0");
  292.  
  293.   meta->ts = (gchar *) g_malloc0 (MAX_TIME_STAMP_LEN + 1);
  294.   meta->objectId = (gchar *) g_malloc0 (MAX_LABEL_SIZE);
  295.  
  296.   strncpy(meta->objectId, obj_params->obj_label, MAX_LABEL_SIZE);
  297.  
  298.   generate_ts_rfc3339(meta->ts, MAX_TIME_STAMP_LEN);
  299.  
  300.   /*
  301.    * This demonstrates how to attach custom objects.
  302.    * Any custom object as per requirement can be generated and attached
  303.    * like NvDsVehicleObject / NvDsPersonObject. Then that object should
  304.    * be handled in payload generator library (nvmsgconv.cpp) accordingly.
  305.    */
  306.   if (class_id == PGIE_CLASS_ID_VEHICLE) {
  307.     meta->type = NVDS_EVENT_MOVING;
  308.     meta->objType = NVDS_OBJECT_TYPE_VEHICLE;
  309.     meta->objClassId = PGIE_CLASS_ID_VEHICLE;
  310.  
  311.     NvDsVehicleObject *obj = (NvDsVehicleObject *) g_malloc0 (sizeof (NvDsVehicleObject));
  312.     generate_vehicle_meta (obj);
  313.  
  314.     meta->extMsg = obj;
  315.     meta->extMsgSize = sizeof (NvDsVehicleObject);
  316.   } else if (class_id == PGIE_CLASS_ID_PERSON) {/*
  317.  * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
  318.  *
  319.  * Permission is hereby granted, free of charge, to any person obtaining a
  320.  * copy of this software and associated documentation files (the "Software"),
  321.  * to deal in the Software without restriction, including without limitation
  322.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  323.  * and/or sell copies of the Software, and to permit persons to whom the
  324.  * Software is furnished to do so, subject to the following conditions:
  325.  *
  326.  * The above copyright notice and this permission notice shall be included in
  327.  * all copies or substantial portions of the Software.
  328.  *
  329.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  330.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  331.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  332.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  333.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  334.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  335.  * DEALINGS IN THE SOFTWARE.
  336.  */
  337.  
  338.     meta->type = NVDS_EVENT_ENTRY;
  339.     meta->objType = NVDS_OBJECT_TYPE_PERSON;
  340.     meta->objClassId = PGIE_CLASS_ID_PERSON;
  341.  
  342.     NvDsPersonObject *obj = (NvDsPersonObject *) g_malloc0 (sizeof (NvDsPersonObject));
  343.     generate_person_meta (obj);
  344.  
  345.     meta->extMsg = obj;
  346.     meta->extMsgSize = sizeof (NvDsPersonObject);
  347.   }
  348. }
  349.  
  350. /* osd_sink_pad_buffer_probe  will extract metadata received on OSD sink pad
  351.  * and update params for drawing rectangle, object information etc. */
  352.  
  353. static GstPadProbeReturn
  354. osd_sink_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
  355.     gpointer u_data)
  356. {
  357.   GstBuffer *buf = (GstBuffer *) info->data;
  358.   NvDsFrameMeta *frame_meta = NULL;
  359.   NvOSD_TextParams *txt_params = NULL;
  360.   guint vehicle_count = 0;
  361.   guint person_count = 0;
  362.   gboolean is_first_object = TRUE;
  363.   NvDsMetaList *l_frame, *l_obj;
  364.  
  365.   NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
  366.   if (!batch_meta) {/*
  367.  * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
  368.  *
  369.  * Permission is hereby granted, free of charge, to any person obtaining a
  370.  * copy of this software and associated documentation files (the "Software"),
  371.  * to deal in the Software without restriction, including without limitation
  372.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  373.  * and/or sell copies of the Software, and to permit persons to whom the
  374.  * Software is furnished to do so, subject to the following conditions:
  375.  *
  376.  * The above copyright notice and this permission notice shall be included in
  377.  * all copies or substantial portions of the Software.
  378.  *
  379.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  380.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  381.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  382.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  383.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  384.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  385.  * DEALINGS IN THE SOFTWARE.
  386.  */
  387.  
  388.     // No batch meta attached.
  389.     return GST_PAD_PROBE_OK;
  390.   }
  391.  
  392.   for (l_frame = batch_meta->frame_meta_list; l_frame; l_frame = l_frame->next) {
  393.     frame_meta = (NvDsFrameMeta *) l_frame->data;
  394.  
  395.     if (frame_meta == NULL) {
  396.       // Ignore Null frame meta.
  397.       continue;
  398.     }
  399.  
  400.     is_first_object = TRUE;
  401.  
  402.     for (l_obj = frame_meta->obj_meta_list; l_obj; l_obj = l_obj->next) {
  403.       NvDsObjectMeta *obj_meta = (NvDsObjectMeta *) l_obj->data;
  404.  
  405.       if (obj_meta == NULL) {
  406.         // Ignore Null object.
  407.         continue;
  408.       }
  409.  
  410.       txt_params = &(obj_meta->text_params);
  411.       if (txt_params->display_text)
  412.         g_free (txt_params->display_text);
  413.  
  414.       txt_params->display_text = g_malloc0 (MAX_DISPLAY_LEN);
  415.  
  416.       g_snprintf (txt_params->display_text, MAX_DISPLAY_LEN, "%s ",
  417.                   pgie_classes_str[obj_meta->class_id]);
  418.  
  419.       if (obj_meta->class_id == PGIE_CLASS_ID_VEHICLE)
  420.         vehicle_count++;
  421.       if (obj_meta->class_id == PGIE_CLASS_ID_PERSON)
  422.         person_count++;
  423.  
  424.       /* Now set the offsets where the string should appear */
  425.       txt_params->x_offset = obj_meta->rect_params.left;
  426.       txt_params->y_offset = obj_meta->rect_params.top - 25;
  427.  
  428.       /* Font , font-color and font-size */
  429.       txt_params->font_params.font_name = "Serif";
  430.       txt_params->font_params.font_size = 10;
  431.       txt_params->font_params.font_color.red = 1.0;
  432.       txt_params->font_params.font_color.green = 1.0;
  433.       txt_params->font_params.font_color.blue = 1.0;
  434.       txt_params->font_params.font_color.alpha = 1.0;
  435.  
  436.       /* Text background color */
  437.       txt_params->set_bg_clr = 1;
  438.       txt_params->text_bg_clr.red = 0.0;
  439.       txt_params->text_bg_clr.green = 0.0;
  440.       txt_params->text_bg_clr.blue = 0.0;
  441.       txt_params->text_bg_clr.alpha = 1.0;
  442.  
  443.       /*
  444.        * Ideally NVDS_EVENT_MSG_META should be attached to buffer by the
  445.        * component implementing detection / recognition logic.
  446.        * Here it demonstrates how to use / attach that meta data.
  447.        */
  448.       if (is_first_object && !(frame_number % 5)) {
  449.         /* Frequency of messages to be send will be based on use case.
  450.          * Here message is being sent for first object every 30 frames.
  451.          */
  452.  
  453.         NvDsEventMsgMeta *msg_meta = (NvDsEventMsgMeta *) g_malloc0 (sizeof (NvDsEventMsgMeta));
  454.         msg_meta->bbox.top = obj_meta->rect_params.top;
  455.         msg_meta->bbox.left = obj_meta->rect_params.left;
  456.         msg_meta->bbox.width = obj_meta->rect_params.width;
  457.         msg_meta->bbox.height = obj_meta->rect_params.height;
  458.         msg_meta->frameId = frame_number;
  459.         msg_meta->trackingId = obj_meta->object_id;
  460.         msg_meta->confidence = obj_meta->confidence;
  461.         generate_event_msg_meta (msg_meta, obj_meta->class_id, obj_meta);
  462.  
  463.         NvDsUserMeta *user_event_meta = nvds_acquire_user_meta_from_pool (batch_meta);
  464.         if (user_event_meta) {
  465.           user_event_meta->user_meta_data = (void *) msg_meta;
  466.           user_event_meta->base_meta.meta_type = NVDS_EVENT_MSG_META;
  467.           user_event_meta->base_meta.copy_func = (NvDsMetaCopyFunc) meta_copy_func;
  468.           user_event_meta->base_meta.release_func = (NvDsMetaReleaseFunc) meta_free_func;
  469.           nvds_add_user_meta_to_frame(frame_meta, user_event_meta);
  470.         } else {
  471.           g_print ("Error in attaching event meta to buffer\n");
  472.         }
  473.         is_first_object = FALSE;
  474.       }
  475.     }
  476.   }
  477.   // g_print ("Frame Number = %d "
  478.       // "Vehicle Count = %d Person Count = %d\n",
  479.       // frame_number, vehicle_count, person_count);
  480.   frame_number++;
  481.  
  482.   return GST_PAD_PROBE_OK;
  483. }
  484.  
  485. static gboolean
  486. bus_call (GstBus * bus, GstMessage * msg, gpointer data)
  487. {
  488.   GMainLoop *loop = (GMainLoop *) data;
  489.   switch (GST_MESSAGE_TYPE (msg)) {
  490.     case GST_MESSAGE_EOS:
  491.       g_print ("End of stream\n");
  492.       g_main_loop_quit (loop);
  493.       break;
  494.     case GST_MESSAGE_ERROR:{
  495.       gchar *debug;
  496.       GError *error;
  497.       gst_message_parse_error (msg, &error, &debug);
  498.       g_printerr ("ERROR from element %s: %s\n",
  499.           GST_OBJECT_NAME (msg->src), error->message);
  500.       if (debug)
  501.         g_printerr ("Error details: %s\n", debug);
  502.       g_free (debug);
  503.       g_error_free (error);
  504.       g_main_loop_quit (loop);
  505.       break;
  506.     }
  507.     default:
  508.       break;
  509.   }
  510.   return TRUE;
  511. }
  512.  
  513. /* Tracker config parsing */
  514.  
  515. #define CHECK_ERROR(error) \
  516.     if (error) { \
  517.         g_printerr ("Error while parsing config file: %s\n", error->message); \
  518.         goto done; \
  519.     }
  520.  
  521. #define CONFIG_GROUP_TRACKER "tracker"
  522. #define CONFIG_GROUP_TRACKER_WIDTH "tracker-width"
  523. #define CONFIG_GROUP_TRACKER_HEIGHT "tracker-height"
  524. #define CONFIG_GROUP_TRACKER_LL_CONFIG_FILE "ll-config-file"
  525. #define CONFIG_GROUP_TRACKER_LL_LIB_FILE "ll-lib-file"
  526. #define CONFIG_GROUP_TRACKER_ENABLE_BATCH_PROCESS "enable-batch-process"
  527. #define CONFIG_GPU_ID "gpu-id"
  528.  
  529. static gchar *
  530. get_absolute_file_path (gchar *cfg_file_path, gchar *file_path)
  531. {
  532.   gchar abs_cfg_path[PATH_MAX + 1];
  533.   gchar *abs_file_path;
  534.   gchar *delim;
  535.  
  536.   if (file_path && file_path[0] == '/') {
  537.     return file_path;
  538.   }
  539.  
  540.   if (!realpath (cfg_file_path, abs_cfg_path)) {
  541.     g_free (file_path);
  542.     return NULL;
  543.   }
  544.  
  545.   // Return absolute path of config file if file_path is NULL.
  546.   if (!file_path) {
  547.     abs_file_path = g_strdup (abs_cfg_path);
  548.     return abs_file_path;
  549.   }
  550.  
  551.   delim = g_strrstr (abs_cfg_path, "/");
  552.   *(delim + 1) = '\0';
  553.  
  554.   abs_file_path = g_strconcat (abs_cfg_path, file_path, NULL);
  555.   g_free (file_path);
  556.  
  557.   return abs_file_path;
  558. }
  559.  
  560. static gboolean
  561. set_tracker_properties (GstElement *nvtracker)
  562. {
  563.   gboolean ret = FALSE;
  564.   GError *error = NULL;
  565.   gchar **keys = NULL;
  566.   gchar **key = NULL;
  567.   GKeyFile *key_file = g_key_file_new ();
  568.  
  569.   if (!g_key_file_load_from_file (key_file, TRACKER_CONFIG_FILE, G_KEY_FILE_NONE,
  570.           &error)) {
  571.     g_printerr ("Failed to load config file: %s\n", error->message);
  572.     return FALSE;
  573.   }
  574.  
  575.   keys = g_key_file_get_keys (key_file, CONFIG_GROUP_TRACKER, NULL, &error);
  576.   CHECK_ERROR (error);
  577.  
  578.   for (key = keys; *key; key++) {
  579.     if (!g_strcmp0 (*key, CONFIG_GROUP_TRACKER_WIDTH)) {
  580.       gint width =
  581.           g_key_file_get_integer (key_file, CONFIG_GROUP_TRACKER,
  582.           CONFIG_GROUP_TRACKER_WIDTH, &error);
  583.       CHECK_ERROR (error);
  584.       g_object_set (G_OBJECT (nvtracker), "tracker-width", width, NULL);
  585.     } else if (!g_strcmp0 (*key, CONFIG_GROUP_TRACKER_HEIGHT)) {
  586.       gint height =
  587.           g_key_file_get_integer (key_file, CONFIG_GROUP_TRACKER,
  588.           CONFIG_GROUP_TRACKER_HEIGHT, &error);
  589.       CHECK_ERROR (error);
  590.       g_object_set (G_OBJECT (nvtracker), "tracker-height", height, NULL);
  591.     } else if (!g_strcmp0 (*key, CONFIG_GPU_ID)) {
  592.       guint gpu_id =
  593.           g_key_file_get_integer (key_file, CONFIG_GROUP_TRACKER,
  594.           CONFIG_GPU_ID, &error);
  595.       CHECK_ERROR (error);
  596.       g_object_set (G_OBJECT (nvtracker), "gpu_id", gpu_id, NULL);
  597.     } else if (!g_strcmp0 (*key, CONFIG_GROUP_TRACKER_LL_CONFIG_FILE)) {
  598.       char* ll_config_file = get_absolute_file_path (TRACKER_CONFIG_FILE,
  599.                 g_key_file_get_string (key_file,
  600.                     CONFIG_GROUP_TRACKER,
  601.                     CONFIG_GROUP_TRACKER_LL_CONFIG_FILE, &error));
  602.       CHECK_ERROR (error);
  603.       g_object_set (G_OBJECT (nvtracker), "ll-config-file", ll_config_file, NULL);
  604.     } else if (!g_strcmp0 (*key, CONFIG_GROUP_TRACKER_LL_LIB_FILE)) {
  605.       char* ll_lib_file = get_absolute_file_path (TRACKER_CONFIG_FILE,
  606.                 g_key_file_get_string (key_file,
  607.                     CONFIG_GROUP_TRACKER,
  608.                     CONFIG_GROUP_TRACKER_LL_LIB_FILE, &error));
  609.       CHECK_ERROR (error);
  610.       g_object_set (G_OBJECT (nvtracker), "ll-lib-file", ll_lib_file, NULL);
  611.     } else if (!g_strcmp0 (*key, CONFIG_GROUP_TRACKER_ENABLE_BATCH_PROCESS)) {
  612.       gboolean enable_batch_process =
  613.           g_key_file_get_integer (key_file, CONFIG_GROUP_TRACKER,
  614.           CONFIG_GROUP_TRACKER_ENABLE_BATCH_PROCESS, &error);
  615.       CHECK_ERROR (error);
  616.       g_object_set (G_OBJECT (nvtracker), "enable_batch_process",
  617.                     enable_batch_process, NULL);
  618.     } else {
  619.       g_printerr ("Unknown key '%s' for group [%s]", *key,
  620.           CONFIG_GROUP_TRACKER);
  621.     }
  622.   }
  623.  
  624. ret = TRUE;
  625. done:
  626.   if (error) {
  627.     g_error_free (error);
  628.   }
  629.   if (keys) {
  630.     g_strfreev (keys);
  631.   }
  632.   if (!ret) {
  633.     g_printerr ("%s failed", __func__);
  634.   }
  635.   return ret;
  636. }
  637.  
  638.  
  639.  
  640. int
  641. main (int argc, char *argv[])
  642. {
  643.   GMainLoop *loop = NULL;
  644.   GstElement *pipeline = NULL, *source = NULL, *h264parser = NULL,
  645.       *decoder = NULL, *sink = NULL, *pgie = NULL, *nvvidconv = NULL,
  646.       *nvosd = NULL, *nvstreammux , *nvtracker = NULL,* encoder = NULL,
  647.       * capsfilter = NULL,* rtsp =NULL ;
  648.   GstElement *msgconv = NULL, *msgbroker = NULL, *tee = NULL;
  649.   GstElement *queue1 = NULL, *queue2 = NULL;
  650.   GstCaps * caps;
  651.   g_print ("\nWith tracker & RTSP sink & one model only\n");
  652. #ifdef PLATFORM_TEGRA
  653.   GstElement *transform = NULL;
  654. #endif
  655.   GstBus *bus = NULL;
  656.   guint bus_watch_id;
  657.   GstPad *osd_sink_pad = NULL;
  658.   GstPad *tee_render_pad = NULL;
  659.   GstPad *tee_msg_pad = NULL;
  660.   GstPad *sink_pad = NULL;
  661.   GstPad *src_pad = NULL;
  662.   GOptionContext *ctx = NULL;
  663.   GOptionGroup *group = NULL;
  664.   GError *error = NULL;
  665.  
  666.  
  667.   ctx = g_option_context_new ("Nvidia DeepStream Test4");
  668.   group = g_option_group_new ("test4", NULL, NULL, NULL, NULL);
  669.   g_option_group_add_entries (group, entries);
  670.  
  671.   g_option_context_set_main_group (ctx, group);
  672.   g_option_context_add_group (ctx, gst_init_get_option_group ());
  673.  
  674.  
  675.   if (!g_option_context_parse (ctx, &argc, &argv, &error)) {
  676.     g_option_context_free (ctx);
  677.     g_printerr ("%s", error->message);
  678.     return -1;
  679.   }
  680.   g_option_context_free (ctx);
  681.  
  682.   if (!proto_lib || !input_file) {
  683.     g_printerr("missing arguments\n");
  684.     g_printerr ("Usage: %s -i <H264 filename> -p <Proto adaptor library> --conn-str=<Connection string>\n", argv[0]);
  685.     return -1;
  686.   }
  687.  
  688.   loop = g_main_loop_new (NULL, FALSE);
  689.  
  690.   /* Create gstreamer elements */
  691.   /* Create Pipeline element that will form a connection of other elements */
  692.   pipeline = gst_pipeline_new ("dstest4-pipeline");
  693.  
  694.   /* Source element for reading from the file */
  695.   source = gst_element_factory_make ("filesrc", "file-source");
  696.  
  697.   /* Since the data format in the input file is elementary h264 stream,
  698.    * we need a h264parser */
  699.   h264parser = gst_element_factory_make ("h264parse", "h264-parser");
  700.  
  701.   /* Use nvdec_h264 for hardware accelerated decode on GPU */
  702.   decoder = gst_element_factory_make ("nvv4l2decoder", "nvv4l2-decoder");
  703.  
  704.   nvstreammux = gst_element_factory_make ("nvstreammux", "nvstreammux");
  705.  
  706.   /* Use nvinfer to run inferencing on decoder's output,
  707.    * behaviour of inferencing is set through config file */
  708.   pgie = gst_element_factory_make ("nvinfer", "primary-nvinference-engine");
  709.  
  710.    /* We need to have a tracker to track the identified objects */
  711.   nvtracker = gst_element_factory_make ("nvtracker", "tracker");
  712.  
  713.   /* Use convertor to convert from NV12 to RGBA as required by nvosd */
  714.   nvvidconv = gst_element_factory_make ("nvvideoconvert", "nvvideo-converter");
  715.  
  716.   /* Create OSD to draw on the converted RGBA buffer */
  717.   nvosd = gst_element_factory_make ("nvdsosd", "nv-onscreendisplay");
  718.  
  719.   /* Create msg converter to generate payload from buffer metadata */
  720.   msgconv = gst_element_factory_make ("nvmsgconv", "nvmsg-converter");
  721.  
  722.   /* Create msg broker to send payload to server */
  723.   msgbroker = gst_element_factory_make ("nvmsgbroker", "nvmsg-broker");
  724.  
  725.   /* Create tee to render buffer and send message simultaneously*/
  726.   tee = gst_element_factory_make ("tee", "nvsink-tee");
  727.  
  728.   /*Create encoder for streaming over RTSP*/
  729.   encoder = gst_element_factory_make ("x264enc", "x264enc");
  730.  
  731.   /*Create capsfilter */
  732.   capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
  733.   caps = gst_caps_from_string ("video/x-h264,mapping=" MAPPING);
  734.   g_object_set (capsfilter, "caps", caps, NULL);
  735.   gst_caps_unref (caps);
  736.  
  737.   /*Create rtsp sink*/
  738.   rtsp = gst_element_factory_make ("rtspsink", "rtspsink");
  739.   if (!rtsp) {
  740.     g_printerr ("Unable to create rtspsink\n");
  741.   }
  742.   g_object_set (rtsp, "service", SERVICE, NULL);
  743.  
  744.   /* Create queues */
  745.   queue1 = gst_element_factory_make ("queue", "nvtee-que1");
  746.   queue2 = gst_element_factory_make ("queue", "nvtee-que2");
  747.  
  748.   /* Finally render the osd output */
  749.   if (display_off) {
  750.     sink = gst_element_factory_make ("fakesink", "nvvideo-renderer");
  751.   } else {
  752.     sink = gst_element_factory_make ("nveglglessink", "nvvideo-renderer");
  753.  
  754. #ifdef PLATFORM_TEGRA
  755.     transform = gst_element_factory_make ("nvegltransform", "nvegl-transform");
  756.     if (!transform) {
  757.       g_printerr ("nvegltransform element could not be created. Exiting.\n");
  758.       return -1;
  759.     }
  760. #endif
  761.   }
  762.  
  763.   if (!pipeline || !source || !h264parser || !decoder || !nvstreammux || !pgie ||
  764.       !nvtracker || !nvvidconv || !nvosd || !msgconv || !msgbroker || !tee
  765.       || !queue1 || !queue2 || !sink) {
  766.     g_printerr ("One element could not be created. Exiting.\n");
  767.     return -1;
  768.   }
  769.   // Set Encoder properties
  770.   g_object_set (encoder, "speed-preset", 1, "key-int-max", 10, NULL);
  771.   /* we set the input filename to the source element */
  772.   g_object_set (G_OBJECT (source), "location", input_file, NULL);
  773.  
  774.   g_object_set (G_OBJECT (nvstreammux), "width", MUXER_OUTPUT_WIDTH, "height",
  775.       MUXER_OUTPUT_HEIGHT, "batch-size", 1,
  776.       "batched-push-timeout", MUXER_BATCH_TIMEOUT_USEC, NULL);
  777.  
  778.   /* Set all the necessary properties of the nvinfer element,
  779.    * the necessary ones are : */
  780.   g_object_set (G_OBJECT (pgie),
  781.       "config-file-path", PGIE_CONFIG_FILE, NULL);
  782.  
  783.   /* Set necessary properties of the tracker element. */
  784.   if (!set_tracker_properties(nvtracker)) {
  785.     g_printerr ("Failed to set tracker properties. Exiting.\n");
  786.     return -1;
  787.   }
  788.  
  789.   g_object_set (G_OBJECT(msgconv), "config", MSCONV_CONFIG_FILE, NULL);
  790.   g_object_set (G_OBJECT(msgconv), "payload-type", schema_type, NULL);
  791.  
  792.   g_object_set (G_OBJECT(msgbroker), "proto-lib", proto_lib,
  793.                 "conn-str", conn_str, "config", cfg_file, "topic", topic, "sync", FALSE, NULL);
  794.  
  795.   g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);
  796.  
  797.   /* we add a message handler */
  798.   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  799.   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
  800.   gst_object_unref (bus);
  801.  
  802.   /* Set up the pipeline */
  803.   /* we add all elements into the pipeline */
  804.   gst_bin_add_many (GST_BIN (pipeline),
  805.       source, h264parser, decoder, nvstreammux, pgie, nvtracker,
  806.       nvvidconv, nvosd, tee, queue1, queue2, msgconv,
  807.       msgbroker,encoder, capsfilter, rtsp, NULL);
  808.  
  809. #ifdef PLATFORM_TEGRA
  810.   if (!display_off)
  811.     gst_bin_add (GST_BIN (pipeline), transform);
  812. #endif
  813.   /* we link the elements together */
  814.   /* file-source -> h264-parser -> nvh264-decoder -> nvstreammux ->
  815.    * nvinfer -> nvvidconv -> nvosd -> tee -> video-renderer
  816.    *                                      |
  817.    *                                      |-> msgconv -> msgbroker  */
  818.  
  819.   sink_pad = gst_element_get_request_pad (nvstreammux, "sink_0");
  820.   if (!sink_pad) {
  821.     g_printerr ("Streammux request sink pad failed. Exiting.\n");
  822.     return -1;
  823.   }
  824.  
  825.   src_pad = gst_element_get_static_pad (decoder, "src");
  826.   if (!src_pad) {
  827.     g_printerr ("Decoder request src pad failed. Exiting.\n");
  828.     return -1;
  829.   }
  830.  
  831.   if (gst_pad_link (src_pad, sink_pad) != GST_PAD_LINK_OK) {
  832.     g_printerr ("Failed to link decoder to stream muxer. Exiting.\n");
  833.     return -1;
  834.   }
  835.  
  836.   gst_object_unref (sink_pad);
  837.   gst_object_unref (src_pad);
  838.  
  839.   if (!gst_element_link_many (source, h264parser, decoder, NULL)) {
  840.     g_printerr ("Elements could not be linked. Exiting.\n");
  841.     return -1;
  842.   }
  843.  
  844.   if (!gst_element_link_many (nvstreammux, pgie, nvtracker,nvvidconv, nvosd, tee, NULL)) {
  845.     g_printerr ("Elements could not be linked. Exiting.\n");
  846.     return -1;
  847.   }
  848.  
  849.   if (!gst_element_link_many (queue1, msgconv, msgbroker, NULL)) {
  850.     g_printerr ("Elements could not be linked. Exiting.\n");
  851.     return -1;
  852.   }
  853.  
  854. #ifdef PLATFORM_TEGRA
  855.   if (!display_off) {
  856.     if (!gst_element_link_many (queue2, transform, rtsp, NULL)) {
  857.       g_printerr ("Elements could not be linked. Exiting.\n");
  858.       return -1;
  859.     }
  860.   } else {
  861.     if (!gst_element_link (queue2, rtsp)) {
  862.       g_printerr ("Elements could not be linked. Exiting.\n");
  863.       return -1;
  864.     }
  865.   }
  866. #else
  867.   if (!gst_element_link (queue2, rtsp)) {
  868.     g_printerr ("Elements could not be linked. Exiting.\n");
  869.     return -1;
  870.   }
  871. #endif
  872.  
  873.   sink_pad = gst_element_get_static_pad (queue1, "sink");
  874.   tee_msg_pad = gst_element_get_request_pad (tee, "src_%u");
  875.   tee_render_pad = gst_element_get_request_pad (tee, "src_%u");
  876.   if (!tee_msg_pad || !tee_render_pad) {
  877.     g_printerr ("Unable to get request pads\n");
  878.     return -1;
  879.   }
  880.  
  881.   if (gst_pad_link (tee_msg_pad, sink_pad) != GST_PAD_LINK_OK) {
  882.     g_printerr ("Unable to link tee and message converter\n");
  883.     gst_object_unref (sink_pad);
  884.     return -1;
  885.   }
  886.  
  887.   gst_object_unref (sink_pad);
  888.  
  889.   sink_pad = gst_element_get_static_pad (queue2, "sink");
  890.   if (gst_pad_link (tee_render_pad, sink_pad) != GST_PAD_LINK_OK) {
  891.     g_printerr ("Unable to link tee and render\n");
  892.     gst_object_unref (sink_pad);
  893.     return -1;
  894.   }
  895.  
  896.   gst_object_unref (sink_pad);
  897.  
  898.   /* Lets add probe to get informed of the meta data generated, we add probe to
  899.    * the sink pad of the osd element, since by that time, the buffer would have
  900.    * had got all the metadata. */
  901.   osd_sink_pad = gst_element_get_static_pad (nvosd, "sink");
  902.   if (!osd_sink_pad)
  903.     g_print ("Unable to get sink pad\n");
  904.   else
  905.     gst_pad_add_probe (osd_sink_pad, GST_PAD_PROBE_TYPE_BUFFER,
  906.         osd_sink_pad_buffer_probe, NULL, NULL);
  907.  
  908.   /* Set the pipeline to "playing" state */
  909.   g_print ("Now playing: %s\n", input_file);
  910.   gst_element_set_state (pipeline, GST_STATE_PLAYING);
  911.   g_print ("New RTSP stream started at rtsp://127.0.0.1:" SERVICE MAPPING "\n");
  912.   /* Wait till pipeline encounters an error or EOS */
  913.   g_print ("Running...\n");
  914.   g_main_loop_run (loop);
  915.  
  916.   /* Out of the main loop, clean up nicely */
  917.   g_print ("Returned, stopping playback\n");
  918.  
  919.   g_free (cfg_file);
  920.   g_free (input_file);
  921.   g_free (topic);
  922.   g_free (conn_str);
  923.   g_free (proto_lib);
  924.  
  925.   /* Release the request pads from the tee, and unref them */
  926.   gst_element_release_request_pad (tee, tee_msg_pad);
  927.   gst_element_release_request_pad (tee, tee_render_pad);
  928.   gst_object_unref (tee_msg_pad);
  929.   gst_object_unref (tee_render_pad);
  930.  
  931.   gst_element_set_state (pipeline, GST_STATE_NULL);
  932.   g_print ("Deleting pipeline\n");
  933.   gst_object_unref (GST_OBJECT (pipeline));
  934.   g_source_remove (bus_watch_id);
  935.   g_main_loop_unref (loop);
  936.   return 0;
  937. }
Add Comment
Please, Sign In to add comment