DeepStream SDK FAQ

37.[ALL_dGPU_APP] How to reconnect http stream in deepstream-app ?

We take mjpeg over http as an example, add mjpeg-over-http=1 in [sourcex] group.

  1. Remove the uridecodebin, which will cause errors to be incorrectly passed in the pipeline.

  2. Monitor and reconnect the http stream in deepstream_source_bin.c

  3. Process EOS messages in bus_callback of deepstream_app.c
    Here is the entire patch:

For apps-common

diff --git a/sources/apps/apps-common/includes/deepstream_config_file_parser.h b/sources/apps/apps-common/includes/deepstream_config_file_parser.h
index e219563..3967b88 100644
--- a/sources/apps/apps-common/includes/deepstream_config_file_parser.h
+++ b/sources/apps/apps-common/includes/deepstream_config_file_parser.h
@@ -112,6 +112,7 @@ extern "C"
 #define CONFIG_GROUP_SOURCE_SMART_RECORD_DEFAULT_DURATION "smart-rec-default-duration"
 #define CONFIG_GROUP_SOURCE_SMART_RECORD_DURATION "smart-rec-duration"
 #define CONFIG_GROUP_SOURCE_SMART_RECORD_INTERVAL "smart-rec-interval"
+#define CONFIG_GROUP_SOURCE_MJPEG_OVER_HTTP "mjpeg-over-http"
 
 /**
  * Function to parse class label file. Parses the labels into a 2D-array of
diff --git a/sources/apps/apps-common/includes/deepstream_sources.h b/sources/apps/apps-common/includes/deepstream_sources.h
index 0416d05..a94d363 100644
--- a/sources/apps/apps-common/includes/deepstream_sources.h
+++ b/sources/apps/apps-common/includes/deepstream_sources.h
@@ -83,6 +83,7 @@ typedef struct
   gchar* alsa_device;
   /** Video format to be applied at nvvideoconvert source pad. */
   gchar* video_format;
+  gboolean mjpeg_over_http;
 } NvDsSourceConfig;
 
 typedef struct NvDsSrcParentBin NvDsSrcParentBin;
diff --git a/sources/apps/apps-common/src/deepstream_config_file_parser.c b/sources/apps/apps-common/src/deepstream_config_file_parser.c
index 5d99503..c20fdff 100644
--- a/sources/apps/apps-common/src/deepstream_config_file_parser.c
+++ b/sources/apps/apps-common/src/deepstream_config_file_parser.c
@@ -402,6 +402,7 @@ parse_source (NvDsSourceConfig * config, GKeyFile * key_file, gchar * group,
   gchar **key = NULL;
   GError *error = NULL;
   static GList *camera_id_list = NULL;
+  config->mjpeg_over_http = false;
 
   if (g_strcmp0 (group, CONFIG_GROUP_SOURCE_ALL)) {
     if (g_key_file_get_integer (key_file, group,
@@ -656,6 +657,11 @@ parse_source (NvDsSourceConfig * config, GKeyFile * key_file, gchar * group,
             g_key_file_get_integer(key_file, CONFIG_GROUP_SOURCE,
             CONFIG_GROUP_SOURCE_EXTRACT_SEI_TYPE5_DATA, &error);
         CHECK_ERROR(error);
+    } else if (!g_strcmp0(*key, CONFIG_GROUP_SOURCE_MJPEG_OVER_HTTP)) {
+        config->mjpeg_over_http =
+            g_key_file_get_integer(key_file, group,
+            CONFIG_GROUP_SOURCE_MJPEG_OVER_HTTP, &error);
+        CHECK_ERROR(error);
     }
     else {
       NVGSTDS_WARN_MSG_V ("Unknown key '%s' for group [%s]", *key, group);
diff --git a/sources/apps/apps-common/src/deepstream_source_bin.c b/sources/apps/apps-common/src/deepstream_source_bin.c
index 002d2ee..8c5dae3 100644
--- a/sources/apps/apps-common/src/deepstream_source_bin.c
+++ b/sources/apps/apps-common/src/deepstream_source_bin.c
@@ -652,7 +652,8 @@ check_rtsp_reconnection_attempts (NvDsSrcBin * src_bin)
   gboolean remove_probe = TRUE;
   guint i = 0;
   for (i = 0; i < src_bin->parent_bin->num_bins; i++) {
-    if (src_bin->parent_bin->sub_bins[i].config->type != NV_DS_SOURCE_RTSP)
+    if (src_bin->parent_bin->sub_bins[i].config->type != NV_DS_SOURCE_RTSP || 
+        src_bin->parent_bin->sub_bins[i].config->type != NV_DS_SOURCE_URI)
       continue;
     if (src_bin->parent_bin->sub_bins[i].have_eos &&
         (src_bin->parent_bin->sub_bins[i].rtsp_reconnect_interval_sec == 0 ||
@@ -1292,42 +1293,87 @@ create_uridecode_src_bin (NvDsSourceConfig * config, NvDsSrcBin * bin)
   GstCaps *caps = NULL;
   GstCapsFeatures *feature = NULL;
   bin->config = config;
+  GstElement *jpegparse = NULL;
+  GstElement *v4l2dec = NULL;
+  GstElement *filter = NULL;
 
-  bin->src_elem = gst_element_factory_make (NVDS_ELEM_SRC_URI, "src_elem");
-  if (!bin->src_elem) {
-    NVGSTDS_ERR_MSG_V ("Could not create element 'src_elem'");
-    goto done;
-  }
+  bin->rtsp_reconnect_interval_sec = config->rtsp_reconnect_interval_sec;
+  bin->rtsp_reconnect_attempts = config->rtsp_reconnect_attempts;
 
-  if (config->dewarper_config.enable) {
-    if (!create_dewarper_bin (&config->dewarper_config, &bin->dewarper_bin)) {
-      g_print ("Creating Dewarper bin failed \n");
+  if (config->mjpeg_over_http) {
+    bin->src_elem = gst_element_factory_make ("souphttpsrc", "src_elem");
+    if (!bin->src_elem) {
+      NVGSTDS_ERR_MSG_V ("Could not create element 'src_elem'");
       goto done;
     }
-  }
-  bin->latency = config->latency;
-  bin->udp_buffer_size = config->udp_buffer_size;
+    g_object_set (G_OBJECT (bin->src_elem), "location", config->uri, NULL);
+    GstCaps *caps = gst_caps_new_simple ("image/jpeg", "framerate", GST_TYPE_FRACTION, 15, 1, NULL);
+    filter = gst_element_factory_make (NVDS_ELEM_CAPS_FILTER, "filter0");
+    if (!filter) {
+      NVGSTDS_ERR_MSG_V ("Could not create 'filter'");
+      goto done;
+    }
+    g_object_set (G_OBJECT (filter), "caps", caps, NULL);
+    gst_caps_unref (caps);
 
-  if (g_strrstr (config->uri, "file:/")) {
-    config->live_source = FALSE;
-  }
-  if (g_strrstr (config->uri, "rtsp://") == config->uri) {
-    configure_source_for_ntp_sync (bin->src_elem);
+    jpegparse = gst_element_factory_make ("jpegparse", "jpegparse");
+    if (!jpegparse) {
+      NVGSTDS_ERR_MSG_V ("Could not create element 'jpegparse'");
+      goto done;
+    }
+    v4l2dec = gst_element_factory_make ("nvv4l2decoder", "nvv4l2decoder");
+    if (!v4l2dec) {
+      NVGSTDS_ERR_MSG_V ("Could not create element 'nvv4l2decoder'");
+      goto done;
+    }
+    g_object_set (G_OBJECT (v4l2dec), "mjpeg", true, NULL);
+  } else {
+    bin->src_elem = gst_element_factory_make (NVDS_ELEM_SRC_URI, "src_elem");
+    if (!bin->src_elem) {
+      NVGSTDS_ERR_MSG_V ("Could not create element 'src_elem'");
+      goto done;
+    }
+
+    if (config->dewarper_config.enable) {
+      if (!create_dewarper_bin (&config->dewarper_config, &bin->dewarper_bin)) {
+        g_print ("Creating Dewarper bin failed \n");
+        goto done;
+      }
+    }
+    bin->latency = config->latency;
+    bin->udp_buffer_size = config->udp_buffer_size;
+
+    if (g_strrstr (config->uri, "file:/")) {
+      config->live_source = FALSE;
+    }
+    if (g_strrstr (config->uri, "rtsp://") == config->uri) {
+      configure_source_for_ntp_sync (bin->src_elem);
+    }
+
+    g_object_set (G_OBJECT (bin->src_elem), "uri", config->uri, NULL);
+    g_signal_connect (G_OBJECT (bin->src_elem), "pad-added",
+        G_CALLBACK (cb_newpad), bin);
+    g_signal_connect (G_OBJECT (bin->src_elem), "child-added",
+        G_CALLBACK (decodebin_child_added), bin);
+    g_signal_connect (G_OBJECT (bin->src_elem), "source-setup",
+        G_CALLBACK (cb_sourcesetup), bin);
   }
 
-  g_object_set (G_OBJECT (bin->src_elem), "uri", config->uri, NULL);
-  g_signal_connect (G_OBJECT (bin->src_elem), "pad-added",
-      G_CALLBACK (cb_newpad), bin);
-  g_signal_connect (G_OBJECT (bin->src_elem), "child-added",
-      G_CALLBACK (decodebin_child_added), bin);
-  g_signal_connect (G_OBJECT (bin->src_elem), "source-setup",
-      G_CALLBACK (cb_sourcesetup), bin);
   bin->cap_filter = gst_element_factory_make (NVDS_ELEM_QUEUE, "queue");
   if (!bin->cap_filter) {
     NVGSTDS_ERR_MSG_V ("Could not create 'queue'");
     goto done;
   }
 
+  if (bin->rtsp_reconnect_interval_sec > 0) {
+    NVGSTDS_ELEM_ADD_PROBE(bin->rtspsrc_monitor_probe, bin->cap_filter, "sink", rtspsrc_monitor_probe_func, GST_PAD_PROBE_TYPE_BUFFER, bin);
+    install_mux_eosmonitor_probe = TRUE;
+  } else {
+    NVGSTDS_ELEM_ADD_PROBE (bin->rtspsrc_monitor_probe, bin->cap_filter,
+        "sink", rtspsrc_monitor_probe_func,
+        GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, bin);
+  }
+
   bin->nvvidconv =
       gst_element_factory_make (NVDS_ELEM_VIDEO_CONV, "nvvidconv_elem");
   if (!bin->nvvidconv) {
@@ -1358,8 +1404,17 @@ create_uridecode_src_bin (NvDsSourceConfig * config, NvDsSrcBin * bin)
 
   g_object_set_data (G_OBJECT (bin->cap_filter), SRC_CONFIG_KEY, config);
 
-  gst_bin_add_many (GST_BIN (bin->bin), bin->src_elem, bin->cap_filter,
-      bin->nvvidconv, bin->cap_filter1, NULL);
+  if (config->mjpeg_over_http) {
+    gst_bin_add_many (GST_BIN (bin->bin), bin->src_elem, filter, jpegparse, v4l2dec, bin->cap_filter,
+        bin->nvvidconv, bin->cap_filter1, NULL);
+    NVGSTDS_LINK_ELEMENT (bin->src_elem, filter);
+    NVGSTDS_LINK_ELEMENT (filter, jpegparse);
+    NVGSTDS_LINK_ELEMENT (jpegparse, v4l2dec);
+    NVGSTDS_LINK_ELEMENT (v4l2dec, bin->cap_filter);
+  } else {
+    gst_bin_add_many (GST_BIN (bin->bin), bin->src_elem, bin->cap_filter,
+        bin->nvvidconv, bin->cap_filter1, NULL);
+  }
 
   NVGSTDS_BIN_ADD_GHOST_PAD (bin->bin, bin->cap_filter1, "src");
 
@@ -1402,6 +1457,8 @@ create_uridecode_src_bin (NvDsSourceConfig * config, NvDsSrcBin * bin)
 
   ret = TRUE;
 
+  g_timeout_add (1000, watch_source_status, bin);
+
   GST_CAT_DEBUG (NVDS_APP,
       "Decode bin created. Waiting for a new pad from decodebin to link");

For deepstream-app.c,If the first parameter of g_timeout_add is 0, it will reconnect continuously. You need to configure the parameter according to your needs.

diff --git a/sources/apps/sample_apps/deepstream-app/deepstream_app.c b/sources/apps/sample_apps/deepstream-app/deepstream_app.c
index 044cfbc..98a9a83 100644
--- a/sources/apps/sample_apps/deepstream-app/deepstream_app.c
+++ b/sources/apps/sample_apps/deepstream-app/deepstream_app.c
@@ -236,14 +236,15 @@ bus_callback (GstBus * bus, GstMessage * message, gpointer data)
       }
 
       if ((i != bin->num_bins) &&
-          (appCtx->config.multi_source_config[0].type == NV_DS_SOURCE_RTSP)) {
+          ((appCtx->config.multi_source_config[0].type == NV_DS_SOURCE_RTSP) || 
+          (appCtx->config.multi_source_config[0].type == NV_DS_SOURCE_URI))) {
         // Error from one of RTSP source.
         NvDsSrcBin *subBin = &bin->sub_bins[i];
 
         if (!subBin->reconfiguring ||
             g_strrstr (debuginfo, "500 (Internal Server Error)")) {
           subBin->reconfiguring = TRUE;
-          g_timeout_add (0, reset_source_pipeline, subBin);
+          g_timeout_add (10000, reset_source_pipeline, subBin);
         }
         g_error_free (error);
         g_free (debuginfo);

38. [ALL_dGPU_APP] Supplement of NTP Timestamp in DeepStream

The following link explains how to use NTP timestamp in DeepStream.
Here are some additional information based on deepstream-test3.

https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_NTP_Timestamp.html#ntp-timestamp-in-deepstream

1.If you want to use rtcp’s ntp timestamp in nvstreammux, you need to set both attachment-sys-ts and frame-duration to 0.

2.After creating an rtspsrc element or an uridecodebin element, application must call configure_source_for_ntp_sync() function and pass the GstElement pointer to this API.

3.Access the ntp_timestamp member in framemeta. ntp_timestamp has been converted to UNIX time (nanoseconds since 1970.1.1)

Here is the complete patch for deepstream-test3

diff --git a/sources/apps/sample_apps/deepstream-test3/deepstream_test3_app.c b/sources/apps/sample_apps/deepstream-test3/deepstream_test3_app.c
index 4c2cf00..e9d46e4 100644
--- a/sources/apps/sample_apps/deepstream-test3/deepstream_test3_app.c
+++ b/sources/apps/sample_apps/deepstream-test3/deepstream_test3_app.c
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <sys/time.h>
 #include <cuda_runtime_api.h>
+#include <inttypes.h>
 
 #include "gstnvdsmeta.h"
 #include "nvds_yml_parser.h"
@@ -101,6 +102,13 @@ tiler_src_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
                 num_rects++;
             }
         }
+
+        // GstClockTime
+        struct timeval tv;
+        gettimeofday(&tv, NULL);
+        uint64_t clock = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+        uint64_t delta = clock - frame_meta->ntp_timestamp / 1000000;
+        printf("clock = %" PRIu64 " ntp = %" PRIu64 " delta: %" PRIu64 "ms\n", clock, frame_meta->ntp_timestamp, delta);
           g_print ("Frame Number = %d Number of objects = %d "
             "Vehicle Count = %d Person Count = %d\n",
             frame_meta->frame_num, num_rects, vehicle_count, person_count);
@@ -255,6 +263,7 @@ create_source_bin (guint index, gchar * uri)
     g_object_set (G_OBJECT (uri_decode_bin), "cudadec-memtype", 0, NULL);
   } else {
     uri_decode_bin = gst_element_factory_make ("uridecodebin", "uri-decode-bin");
+    configure_source_for_ntp_sync(uri_decode_bin);
   }
 
   if (!bin || !uri_decode_bin) {
@@ -445,7 +454,8 @@ main (int argc, char *argv[])
 #ifdef __aarch64__
       sink = gst_element_factory_make ("nv3dsink", "nvvideo-renderer");
 #else
-      sink = gst_element_factory_make ("nveglglessink", "nvvideo-renderer");
+      //sink = gst_element_factory_make ("nveglglessink", "nvvideo-renderer");
+      sink = gst_element_factory_make ("fakesink", "nvvideo-renderer");
 #endif
     }
   }
@@ -532,6 +542,10 @@ main (int argc, char *argv[])
       }
   }
 
+  g_object_set (G_OBJECT (streammux), "live-source", 1, NULL);
+  g_object_set (G_OBJECT (streammux), "frame-duration", 0, NULL);
+  g_object_set (G_OBJECT (streammux), "attach-sys-ts", 0, NULL);
+
   /* we add a message handler */
   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
   bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);

Generally speaking, the following results can be obtained

TP: 2024-06-11T12:16:34.079Z(1718108194079700138). NTP diff:33364781. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.192Z
clock = 1718108194193 ntp = 1718108194079700138 delta: 114ms
0:00:15.579209610 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.607745284(6607745284) NTP: 2024-06-11T12:16:34.113Z(1718108194113064935). NTP diff:33364797. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.223Z
clock = 1718108194224 ntp = 1718108194113064935 delta: 111ms
0:00:15.613469316 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.641107884(6641107884) NTP: 2024-06-11T12:16:34.146Z(1718108194146427535). NTP diff:33362600. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.257Z
clock = 1718108194258 ntp = 1718108194146427535 delta: 112ms
0:00:15.651864745 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.674470515(6674470515) NTP: 2024-06-11T12:16:34.179Z(1718108194179790166). NTP diff:33362631. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.296Z
clock = 1718108194297 ntp = 1718108194179790166 delta: 118ms
0:00:15.680095551 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.707833179(6707833179) NTP: 2024-06-11T12:16:34.213Z(1718108194213152830). NTP diff:33362664. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.324Z
clock = 1718108194325 ntp = 1718108194213152830 delta: 112ms
0:00:15.713640264 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.741195875(6741195875) NTP: 2024-06-11T12:16:34.246Z(1718108194246515526). NTP diff:33362696. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.357Z
clock = 1718108194358 ntp = 1718108194246515526 delta: 112ms
0:00:15.755680945 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.774558602(6774558602) NTP: 2024-06-11T12:16:34.279Z(1718108194279878253). NTP diff:33362727. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.399Z
clock = 1718108194400 ntp = 1718108194279878253 delta: 121ms
0:00:15.799888705 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.807921362(6807921362) NTP: 2024-06-11T12:16:34.313Z(1718108194313241013). NTP diff:33362760. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.444Z
clock = 1718108194445 ntp = 1718108194313241013 delta: 132ms
0:00:15.819295893 32314 0x7f39f4001f40 LOG          nvstreammux_ntp gstnvstreammux_ntp.cpp:259:gst_nvds_ntp_calculator_get_buffer_ntp:<stream-muxer> Frame NTP calculated. mode: RTCP SR. source 0: PTS:0:00:06.841284153(6841284153) NTP: 2024-06-11T12:16:34.346Z(1718108194346603804). NTP diff:33362791. ntp_time_epoch_ns = 2024-06-11T12:16:32.977Z(1718108192977646331) ntp_frame_timestamp = 0:00:05.472326680(5472326680) System Time: 2024-06-11T12:16:34.463Z
clock = 1718108194464 ntp = 1718108194346603804 delta: 118ms

39.[DS7.0_pyds]Fix for incompatibility problem between the TensorRT Python API and the DeepStream pyds
If you use the TensorRT Python API and DeepStream pyds at the same time,
there may be crash problems when using some APIs because the version of PyGObject is too low.
We recommend that you upgrade the PyGObject.

python3 -m pip install --upgrade pygobject

40.[ ALL_Python_APP]How to save a frame or object in Python

1.Add Python binding for nvds_obj_enc_process

diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt
index 7b01fb2..6df8952 100644
--- a/bindings/CMakeLists.txt
+++ b/bindings/CMakeLists.txt
@@ -98,7 +98,7 @@ function(add_ds_lib libname)
         target_link_libraries(pyds ${libname})
 endfunction()

-foreach(nvds_lib nvds_osd nvds_meta nvds_infer nvdsgst_meta nvbufsurface nvbufsurftransform nvdsgst_helper)
+foreach(nvds_lib nvds_osd nvds_meta nvds_infer nvdsgst_meta nvbufsurface nvbufsurftransform nvdsgst_helper nvds_batch_jpegenc)
         add_ds_lib(${nvds_lib})
 endforeach()

diff --git a/bindings/docstrings/functionsdoc.h b/bindings/docstrings/functionsdoc.h
index 2796605..371d77b 100644
--- a/bindings/docstrings/functionsdoc.h
+++ b/bindings/docstrings/functionsdoc.h
@@ -627,5 +627,35 @@ namespace pydsdoc

             #add this code in plugin probe function.
             num_sources_in_batch = pyds.nvds_measure_buffer_latency(hash(gst_buffer));)pyds";
-       }
+
+        constexpr const char* nvds_obj_enc_create_context=R"pyds(
+            Create context and return a handle to NvObjEncCtx.
+
+            :arg gpu_id: gpu id.
+
+            :returns: handle to NvObjEncCtx.)pyds";
+
+        constexpr const char* nvds_obj_enc_process=R"pyds(
+            Enqueue an object crop for JPEG encode.
+            This is a non-blocking call and user should call `nvds_obj_enc_finish()`
+            to make sure all enqueued object crops have been processed.
+
+            :arg context: handle to NvObjEncCtx.
+            :arg args: An object of type :class:`NvDsObjEncUsrArgs`.
+            :arg buffer: GstBuffer from which to retrieve the :class:`NvBufSurface`
+            :arg obj_meta: An object of type :class:`NvDsOjbectMeta`.
+            :arg frame_meta: An object of type :class:`NvDsFrameMeta`.
+
+            :returns: 0 for success, -1 for failure.)pyds";
+
+        constexpr const char* nvds_obj_enc_finish=R"pyds(
+            Wait for all enqueued crops to be encoded.
+
+            :arg context: handle to NvObjEncCtx.)pyds";
+
+        constexpr const char* nvds_obj_enc_destroy_context=R"pyds(
+            Destroy NvObjEncCtx context.
+
+            :arg context: handle to NvObjEncCtx.)pyds";
+    }
 }
\ No newline at end of file
diff --git a/bindings/docstrings/utilsdoc.h b/bindings/docstrings/utilsdoc.h
new file mode 100644
index 0000000..866c21f
--- /dev/null
+++ b/bindings/docstrings/utilsdoc.h
@@ -0,0 +1,44 @@
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2021-2023 NVIDIA CORPORATION &
+ * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace pydsdoc {
+namespace utilsdoc {
+namespace NvDsObjEncUsrArgsDoc {
+constexpr const char *descr = R"pyds(
+                user parameters for a nvds_obj_enc_process call
+
+                :ivar numDims: *int*, Number of dimesions of the layer.
+                :ivar numElements: *int*, Number of elements in the layer including all dimensions.
+                :ivar d: *np.array of int*, Size of the layer in each dimension.)pyds";
+
+constexpr const char *cast =
+    R"pyds(cast given object/data to :class:`NvDsObjEncUsrArgs`, call pyds.NvDsObjEncUsrArgs.cast(data))pyds";
+} // namespace NvDsObjEncUsrArgsDoc
+
+namespace NvDsObjEncOutParamsDoc {
+constexpr const char *descr = R"pyds(
+                output parameters of NVDS_CROP_IMAGE_META
+
+                :ivar outBuffer: *int*, The output buffer JPEG Encoded Object.)pyds";
+
+constexpr const char *cast =
+    R"pyds(cast given object/data to :class:`NvDsObjEncOutParams`, call pyds.NvDsObjEncOutParams.cast(data))pyds";
+} // namespace NvDsObjEncOutParamsDoc
+} // namespace utilsdoc
+} // namespace pydsdoc
\ No newline at end of file
diff --git a/bindings/include/utils.hpp b/bindings/include/utils.hpp
index f713b9b..223be0a 100644
--- a/bindings/include/utils.hpp
+++ b/bindings/include/utils.hpp
@@ -43,6 +43,9 @@ namespace pydeepstream {
     pybind11::arg operator ""_a(const char *str, size_t len);
 }

+namespace pydeepstream {
+    void bindutils(py::module &m);
+}

 namespace pydeepstream::utils {

diff --git a/bindings/src/bindfunctions.cpp b/bindings/src/bindfunctions.cpp
index cc2c9cc..88e7163 100644
--- a/bindings/src/bindfunctions.cpp
+++ b/bindings/src/bindfunctions.cpp
@@ -17,6 +17,7 @@

 #include "bind_string_property_definitions.h"
 #include "bindfunctions.hpp"
+#include "nvds_obj_encode.h"

 namespace py = pybind11;
 using namespace std;
@@ -839,5 +840,49 @@ namespace pydeepstream {
               },
               "gst_buffer"_a, py::return_value_policy::reference,
               pydsdoc::methodsDoc::nvds_measure_buffer_latency);
+
+        m.def("nvds_obj_enc_create_context",
+            [](int gpu_id) -> size_t {
+                auto handle = nvds_obj_enc_create_context(gpu_id);
+                std::cout << "nvds_obj_enc_create_context: " << handle << std::endl;
+                return reinterpret_cast<size_t>(handle);
+            }, py::return_value_policy::reference,
+            pydsdoc::methodsDoc::nvds_obj_enc_create_context);
+
+        m.def("nvds_obj_enc_process",
+            [](size_t ctx, NvDsObjEncUsrArgs *args,
+                size_t gst_buffer, NvDsObjectMeta *obj_meta, NvDsFrameMeta *frame_meta) -> bool {
+                auto *buffer = reinterpret_cast<GstBuffer *>(gst_buffer);
+                auto *handle = reinterpret_cast<NvDsObjEncCtxHandle>(ctx);
+                if (buffer == nullptr || handle == nullptr) {
+                    std::cout << "buffer: " << buffer << " handle: " << handle << std::endl;
+                    return false;
+                }
+
+                GstMapInfo inmap;
+                gst_buffer_map(buffer, &inmap, GST_MAP_READ);
+                auto *inputnvsurface = reinterpret_cast<NvBufSurface *>(inmap.data);
+                gst_buffer_unmap(buffer, &inmap);
+
+                return nvds_obj_enc_process(handle, args, inputnvsurface, obj_meta, frame_meta);
+            }, "ctx"_a, "args"_a, "gst_buffer"_a, "obj_meta"_a, "frame_meta"_a,
+            py::return_value_policy::reference,
+            pydsdoc::methodsDoc::nvds_obj_enc_process);
+
+        m.def("nvds_obj_enc_finish",
+            [](size_t ctx) {
+                auto *handle = reinterpret_cast<NvDsObjEncCtxHandle>(ctx);
+                if (handle != nullptr) {
+                    nvds_obj_enc_finish(handle);
+                }
+            }, "ctx"_a, pydsdoc::methodsDoc::nvds_obj_enc_finish);
+
+        m.def("nvds_obj_enc_destroy_context",
+            [](size_t ctx) {
+                auto *handle = reinterpret_cast<NvDsObjEncCtxHandle>(ctx);
+                if (handle != nullptr) {
+                    nvds_obj_enc_destroy_context(handle);
+                }
+            }, "ctx"_a, pydsdoc::methodsDoc::nvds_obj_enc_destroy_context);
     }
 }
diff --git a/bindings/src/pyds.cpp b/bindings/src/pyds.cpp
index 30d02ff..d1ac84e 100644
--- a/bindings/src/pyds.cpp
+++ b/bindings/src/pyds.cpp
@@ -63,6 +63,7 @@ namespace pydeepstream {
         bindnvbufsurface(m);
         bindnvdsinfer(m);
         bindopticalflowmeta(m);
+        bindutils(m);
         bindcustom(m);

     }   // end PYBIND11_MODULE(pyds, m)
diff --git a/bindings/src/utils.cpp b/bindings/src/utils.cpp
index 356ff8a..9bafe24 100644
--- a/bindings/src/utils.cpp
+++ b/bindings/src/utils.cpp
@@ -24,8 +24,13 @@
 #include <functional>
 #include <iostream>
 #include "gstnvdsmeta.h"
+#include "pyds.hpp"
 #include "nvdsmeta_schema.h"
 #include "utils.hpp"
+#include "nvds_obj_encode.h"
+#include "bind_string_property_definitions.h"
+#include "../../docstrings/utilsdoc.h"
+
 /**
  * Specifies the type of function to copy meta data.
  * It is passed the pointer to meta data and user specific data.
@@ -44,12 +49,53 @@ using COPYFUNC_SIG = gpointer(gpointer, gpointer);
  */
 using RELEASEFUNC_SIG = void(gpointer, gpointer);

+namespace py = pybind11;
+
 namespace pydeepstream {
     pybind11::arg operator ""_a(const char *str, size_t len) {
         return pybind11::arg(str);
     }
 }

+namespace pydeepstream {
+    void bindutils(py::module &m) {
+        py::class_<NvDsObjEncOutParams>(m, "NvDsObjEncOutParams",
+                                        pydsdoc::utilsdoc::NvDsObjEncOutParamsDoc::descr)
+                .def(py::init<>())
+                .def("outBuffer", [](const NvDsObjEncOutParams &self) {
+                    // Use this if the C++ buffer should NOT be deallocated
+                    // once Python no longer has a reference to it
+                    py::capsule buffer_handle([](){});
+                    return py::array(self.outLen, self.outBuffer, buffer_handle);
+                })
+                .def("cast", [](void *data) {
+                         return (NvDsObjEncOutParams *) data;
+                     },
+                     py::return_value_policy::reference,
+                     pydsdoc::utilsdoc::NvDsObjEncOutParamsDoc::cast);
+
+        py::class_<NvDsObjEncUsrArgs>(m, "NvDsObjEncUsrArgs",
+                                     pydsdoc::utilsdoc::NvDsObjEncUsrArgsDoc::descr)
+                .def(py::init<>())
+                .def_readwrite("saveImg", &NvDsObjEncUsrArgs::saveImg)
+                .def_readwrite("attachUsrMeta", &NvDsObjEncUsrArgs::attachUsrMeta)
+                .def_readwrite("scaleImg", &NvDsObjEncUsrArgs::scaleImg)
+                .def_readwrite("scaledWidth", &NvDsObjEncUsrArgs::scaledWidth)
+                .def_readwrite("scaledHeight", &NvDsObjEncUsrArgs::scaledHeight)
+                .def_property("fileNameImg", STRING_CHAR_ARRAY(NvDsObjEncUsrArgs, fileNameImg))
+                .def_readwrite("objNum", &NvDsObjEncUsrArgs::objNum)
+                .def_readwrite("quality", &NvDsObjEncUsrArgs::quality)
+                .def_readwrite("isFrame", &NvDsObjEncUsrArgs::isFrame)
+                .def_readwrite("calcEncodeTime", &NvDsObjEncUsrArgs::calcEncodeTime)
+                .def("cast",
+                     [](void *data) {
+                         return (NvDsObjEncUsrArgs *) data;
+                     },
+                     py::return_value_policy::reference,
+                     pydsdoc::utilsdoc::NvDsObjEncUsrArgsDoc::cast);
+    }
+}
+
 namespace pydeepstream::utils {

     std::unordered_map<std::string, std::shared_ptr<char>> font_name_memory;

2.recompile and reinstall pyds

cd /deepstream_python_apps/bindings/build
make -j 
# If you use jetson, please replace it with the correct `whl` name
pip3 install --force-reinstall ./pyds-1.1.11-py3-none-linux_x86_64.whl

3.How to use the bindings? Here we use deepstream-test1.py as an example.
You can also compare the native sample code, the code is located at
/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-image-meta-test

diff --git a/apps/deepstream-test1/deepstream_test_1.py b/apps/deepstream-test1/deepstream_test_1.py
index 1367fb4..1d92204 100755
--- a/apps/deepstream-test1/deepstream_test_1.py
+++ b/apps/deepstream-test1/deepstream_test_1.py
@@ -34,9 +34,75 @@ PGIE_CLASS_ID_PERSON = 2
 PGIE_CLASS_ID_ROADSIGN = 3
 MUXER_BATCH_TIMEOUT_USEC = 33000

+def pgie_src_pad_buffer_probe(pad, info, u_data):
+    gst_buffer = info.get_buffer()
+    if not gst_buffer:
+        print("Unable to get GstBuffer ")
+        return
+
+    obj_ctx_handle = u_data
+    # Retrieve batch metadata from the gst_buffer
+    # Note that pyds.gst_buffer_get_nvds_batch_meta() expects the
+    # C address of gst_buffer as input, which is obtained with hash(gst_buffer)
+    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
+    l_frame = batch_meta.frame_meta_list
+    while l_frame is not None:
+        try:
+            # Note that l_frame.data needs a cast to pyds.NvDsFrameMeta
+            # The casting is done by pyds.NvDsFrameMeta.cast()
+            # The casting also keeps ownership of the underlying memory
+            # in the C code, so the Python garbage collector will leave
+            # it alone.
+            frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
+            frame_number=frame_meta.frame_num
+            if frame_number < 3:
+                frameData = pyds.NvDsObjEncUsrArgs()
+                frameData.isFrame = 1
+                frameData.saveImg = False
+                frameData.attachUsrMeta = True
+                frameData.scaleImg = False
+                frameData.scaledWidth = 0
+                frameData.scaledHeight = 0
+                frameData.quality = 80
+                frameData.calcEncodeTime = 1
+                ret = pyds.nvds_obj_enc_process (obj_ctx_handle, frameData, hash(gst_buffer), None, frame_meta)
+        except StopIteration:
+            break
+        l_obj=frame_meta.obj_meta_list
+        num_rects = 0
+        while l_obj is not None:
+            try:
+                # Casting l_obj.data to pyds.NvDsObjectMeta
+                # For demonstration, we will encode the first object in the frame
+                obj_meta=pyds.NvDsObjectMeta.cast(l_obj.data)
+                if frame_number < 3 and obj_meta.class_id == PGIE_CLASS_ID_VEHICLE and num_rects == 0:
+                    num_rects += 1
+                    objData = pyds.NvDsObjEncUsrArgs()
+                    objData.saveImg = False
+                    objData.attachUsrMeta = True
+                    objData.scaleImg = False
+                    objData.scaledWidth = 0
+                    objData.scaledHeight = 0
+                    objData.objNum = num_rects
+                    objData.quality = 80
+                    objData.calcEncodeTime = 1
+                    ret = pyds.nvds_obj_enc_process (obj_ctx_handle, objData, hash(gst_buffer), obj_meta, frame_meta)
+            except StopIteration:
+                break
+            try:
+                l_obj=l_obj.next
+            except StopIteration:
+                break
+        try:
+            l_frame=l_frame.next
+        except StopIteration:
+            break
+        pyds.nvds_obj_enc_finish(obj_ctx_handle)
+    return Gst.PadProbeReturn.OK
+
 def osd_sink_pad_buffer_probe(pad,info,u_data):
-    frame_number=0
     num_rects=0
+    frame_number=0

     gst_buffer = info.get_buffer()
     if not gst_buffer:
@@ -56,6 +122,21 @@ def osd_sink_pad_buffer_probe(pad,info,u_data):
             # in the C code, so the Python garbage collector will leave
             # it alone.
             frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
+            frame_number=frame_meta.frame_num
+            fusrMetaList = frame_meta.frame_user_meta_list
+            while fusrMetaList is not None:
+                try:
+                    fuser_meta = pyds.NvDsUserMeta.cast(fusrMetaList.data)
+                    if fuser_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDS_CROP_IMAGE_META:
+                        fenc_output = pyds.NvDsObjEncOutParams.cast(fuser_meta.user_meta_data)
+                        foutput = fenc_output.outBuffer()
+                        foutput.tofile(f"{frame_number}-out.jpg")
+                except StopIteration:
+                    break
+                try:
+                    fusrMetaList = fusrMetaList.next
+                except StopIteration:
+                    break
         except StopIteration:
             break

@@ -66,17 +147,31 @@ def osd_sink_pad_buffer_probe(pad,info,u_data):
             PGIE_CLASS_ID_BICYCLE:0,
             PGIE_CLASS_ID_ROADSIGN:0
         }
-        frame_number=frame_meta.frame_num
         num_rects = frame_meta.num_obj_meta
         l_obj=frame_meta.obj_meta_list
         while l_obj is not None:
             try:
                 # Casting l_obj.data to pyds.NvDsObjectMeta
                 obj_meta=pyds.NvDsObjectMeta.cast(l_obj.data)
+                obj_counter[obj_meta.class_id] += 1
+                obj_meta.rect_params.border_color.set(0.0, 0.0, 1.0, 0.8) #0.8 is alpha (opacity)
+
+                usrMetaList = obj_meta.obj_user_meta_list
+                while usrMetaList is not None:
+                    try:
+                        user_meta = pyds.NvDsUserMeta.cast(usrMetaList.data)
+                        if user_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDS_CROP_IMAGE_META:
+                            enc_output = pyds.NvDsObjEncOutParams.cast(user_meta.user_meta_data)
+                            output = enc_output.outBuffer()
+                            output.tofile(f"{frame_number}-{num_rects}-out.jpg")
+                    except StopIteration:
+                        break
+                    try:
+                        usrMetaList = usrMetaList.next
+                    except StopIteration:
+                        break
             except StopIteration:
                 break
-            obj_counter[obj_meta.class_id] += 1
-            obj_meta.rect_params.border_color.set(0.0, 0.0, 1.0, 0.8) #0.8 is alpha (opacity)
             try:
                 l_obj=l_obj.next
             except StopIteration:
@@ -191,7 +286,8 @@ def main(args):
             sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
         else:
             print("Creating EGLSink \n")
-            sink = Gst.ElementFactory.make("nveglglessink", "nvvideo-renderer")
+            sink = Gst.ElementFactory.make("fakesink", "nv3d-sink")
+            #sink = Gst.ElementFactory.make("nveglglessink", "nvvideo-renderer")
         if not sink:
             sys.stderr.write(" Unable to create egl sink \n")

@@ -222,6 +318,9 @@ def main(args):
     source.link(h264parser)
     h264parser.link(decoder)

+    # Create Context for Object Encoding.
+    # Takes GPU ID as a parameter.
+    obj_ctx_handle = pyds.nvds_obj_enc_create_context (0)
     sinkpad = streammux.request_pad_simple("sink_0")
     if not sinkpad:
         sys.stderr.write(" Unable to get the sink pad of streammux \n")
@@ -240,6 +339,11 @@ def main(args):
     bus.add_signal_watch()
     bus.connect ("message", bus_call, loop)

+    pgiesrcpad = pgie.get_static_pad("src")
+    if not pgiesrcpad:
+        sys.stderr.write(" Unable to get src pad of pgie \n")
+    pgiesrcpad.add_probe(Gst.PadProbeType.BUFFER, pgie_src_pad_buffer_probe, obj_ctx_handle)
+
     # Lets add probe to get informed of the meta data generated, we add probe to
     # the sink pad of the osd element, since by that time, the buffer would have
     # had got all the metadata.
@@ -258,6 +362,8 @@ def main(args):
         pass
     # cleanup
     pipeline.set_state(Gst.State.NULL)
+    # Destroy context for Object Encoding
+    pyds.nvds_obj_enc_destroy_context (obj_ctx_handle)

 if __name__ == '__main__':

41. Triton Backend Sample In DeepStream (Thanks for the sharing!)
python backend
deepstream-rtsp-in-rtsp-out (Thanks @ajithkumar.ak95)
deepstream-rtsp-in-rtsp-out-ensemble (Thanks @ajithkumar.ak95)

42. How to convert NvDsInferTensorMeta output data to numpy ndarray

1.Get NvDsInferTensorMeta from user meta

tensor_meta = pyds.NvDsInferTensorMeta.cast(user_meta.user_meta_data)

# Boxes in the tensor meta should be in network resolution which is
# found in tensor_meta.network_info. Use this info to scale boxes to
# the input frame resolution.
layers_info = []

for i in range(tensor_meta.num_output_layers):
    layer = pyds.get_nvds_LayerInfo(tensor_meta, i)
    layers_info.append(layer)

2.Find the specified output layer

def layer_finder(output_layer_info, name):
    """ Return the layer contained in output_layer_info which corresponds
        to the given name.
    """
    for layer in output_layer_info:
        # dataType == 0 <=> dataType == FLOAT
        if layer.dataType == 0 and layer.layerName == name:
            return layer
    return None

3.Convert the tensor buffer of the output layer to numpy.ndarray

def layer_tensor_to_ndarray(layer: pyds.NvDsInferLayerInfo) -> np.ndarray:
    import ctypes
    if layer.dataType == pyds.NvDsInferDataType.FLOAT:
        # print(f"int_addr {type(pyds.get_ptr(layer.buffer))}") <class 'int'>
        addr = pyds.get_ptr(layer.buffer)
        if addr == 0:
            print("Buffer address is 0")
            return None
        # print(f"addr {type(addr)}") <class 'ctypes.c_int'>
        data_ptr = ctypes.cast(addr, ctypes.POINTER(ctypes.c_float))
        num_dims = layer.inferDims.numDims
        shape = []
        for i in range(num_dims):
            shape.append(layer.inferDims.d[i])
        # print(f"{shape}")
        layer_array = np.ctypeslib.as_array(data_ptr, shape=shape)
        # print(f"layer_array {type(layer_array)}")
        layer_ny = np.frombuffer(layer_array, dtype=np.float32)
        # print(f"boxes {type(layer_ny)}")
        return layer_ny
    return None

43. [DS7.1_Jetson_Docker] DeepStream 7.1 Triton Docker Triton Backend Setup Script Patch
For the following DeepStream 7.1 L4T dockers, the Triton backend setup script needs to be updated to download boost package from the correct link.

nvcr.io/nvidia/deepstream:7.1-triton-multiarch
nvcr.io/nvidia/deepstream:7.1-samples-multiarch

The patch is attached. Please apply the patch to /opt/nvidia/deepstream/deepstream-7.1/samples/triton_backend_setup.sh script before using the script to install the Triton backend.
setup.patch (558 Bytes)

44. [DSx_All_App] How to extract specific class on deepstream with nvinferserver

diff --git a/sources/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp b/sources/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp
index d13a005..39c7336 100755
--- a/sources/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp
+++ b/sources/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp
@@ -105,6 +105,11 @@ attachDetectionMetadata(
             }
         }
 
+        const auto& ids = config.output_control().filter_out_class_ids();
+        if (!ids.empty() &&
+            (std::find(ids.begin(), ids.end(), obj.classIndex) != ids.end()))
+            continue;
+
         /* Scale the bounding boxes proportionally based on how the object/frame
          * was scaled during input. */
         obj.left = (obj.left - offsetLeft) / scaleX + roiLeft;
diff --git a/sources/gst-plugins/gst-nvinferserver/nvdsinferserver_plugin.proto b/sources/gst-plugins/gst-nvinferserver/nvdsinferserver_plugin.proto
index 3d39caf..3843ec8 100755
--- a/sources/gst-plugins/gst-nvinferserver/nvdsinferserver_plugin.proto
+++ b/sources/gst-plugins/gst-nvinferserver/nvdsinferserver_plugin.proto
@@ -124,6 +124,8 @@ message PluginControl {
       /* Classifier type of a particular nvinferserver component. */
       string classifier_type = 3;
     }
+    /* Filter specified class IDs */
+    repeated int32 filter_out_class_ids = 4;
   }
# /opt/nvidia/deepstream/deepstream/sources/includes/nvdsinferserver_plugin.proto also needs to be modified
make CUDA_VER=xxx install 

Finally, add this to your application configuration file

output_control {
  filter_out_class_ids: [1, 2, 3]
}

45. [DSx_All_nvdanalytics] How to set different properties for each ROI in the same [algo-stream-n]
Currently, all ROIs in the same [algo-stream-n] share the same properties. Taking the following configurations for example, How to set class-id=0 for roi-RF1 and class-id=2 for roi-RF2?

[roi-filtering-stream-0]
enable=1
#ROI to filter select objects, and remove from meta data
roi-RF1=200;523;779;524;779;1028;200;1028
roi-RF2=1000;643;1350;634;1350;913;1000;913
class-id=0;2
inverse-roi=0

Because the nvdanalytics plugin is opensource, you can modify the configuration parsing code to customize. the following code makes the different ROIs to use different classids.

// in nvdsanalytics_parse_roi_filtering_group of nvdsanalytics_property_parser.cpp
for (ROIInfo & roi:roi_vec) {
   roi.enable = enable;
   roi.inverse_roi = inverse_roi;
   roi.operate_on_class = operate_on_class_vec;
 }
// new code
 int i=0;
 for (ROIInfo & roi:roi_vec) {
   if(i == 0) {
     roi.operate_on_class[0] = 0;
   } else {
     roi.operate_on_class[0] = 2;
   }
   i++;
 }
//--new code

Then build the library according to /opt/nvidia/deepstream/deepstream/sources/gst-plugins/gst-nvdsanalytics/readme and replace /opt/nvidia/deepstream/deepstream/lib/gst-plugins/libnvdsgst_dsanalytics.so.
related topic:
[Multiple ROI filtering with different class ID]
[Custom Payload for Kafka Integration in DeepStream App on Kubernetes]

46. [DS6.x_All_test4] Memory leak in deepstream-test4

The memory leak of deepstream-test4 is a legacy version issue, including 6.x/7.x versions, python/native need to be patched both.

1. Native code.
You can refer to the following patch to modify the local code, and recompile and install
/opt/nvidia/deepstream/deepstream/sources/libs/nvmsgconv and /opt/nvidia/deepstream/deepstream/sources/gst-plugins/gst-nvurisrcbin

diff --git a/src/gst-plugins/gst-nvurisrcbin/gstdsnvurisrcbin.cpp b/src/gst-plugins/gst-nvurisrcbin/gstdsnvurisrcbin.cpp
index da8bc70..db2883a 100644
--- a/src/gst-plugins/gst-nvurisrcbin/gstdsnvurisrcbin.cpp
+++ b/src/gst-plugins/gst-nvurisrcbin/gstdsnvurisrcbin.cpp
@@ -782,9 +782,17 @@
       config->smart_record = (NvDsUriSrcBinSRType) g_value_get_enum (value);
       break;
     case PROP_SMART_RECORD_DIR_PATH:
+      if (config->smart_rec_dir_path != NULL) {
+        g_free (config->smart_rec_dir_path);
+        config->smart_rec_dir_path = NULL;
+      }
       config->smart_rec_dir_path = g_value_dup_string (value);
       break;
     case PROP_SMART_RECORD_FILE_PREFIX:
+      if (config->smart_rec_file_prefix != NULL) {
+        g_free (config->smart_rec_file_prefix);
+        config->smart_rec_file_prefix = NULL;
+      }
       config->smart_rec_file_prefix = g_value_dup_string (value);
       break;
     case PROP_SMART_RECORD_VIDEO_CACHE:
@@ -854,6 +862,10 @@
       config->ipc_buffer_timestamp_copy = g_value_get_boolean (value);
       break;
     case PROP_IPC_SOCKET_PATH:
+      if (config->ipc_socket_path != NULL) {
+        g_free(config->ipc_socket_path);
+        config->ipc_socket_path = NULL;
+      }
       config->ipc_socket_path = g_value_dup_string (value);
       break;
     case PROP_IPC_CONNECTION_ATTEMPTS:
@@ -1063,12 +1075,23 @@
 {
   GstDsNvUriSrcBin *nvurisrcbin = GST_DS_NVURISRC_BIN (object);
 
-  if (nvurisrcbin->config->ipc_socket_path) {
-    g_free(nvurisrcbin->config->ipc_socket_path);
-    nvurisrcbin->config->ipc_socket_path = NULL;
+  if (nvurisrcbin->config) {
+    if (nvurisrcbin->config->ipc_socket_path) {
+      g_free(nvurisrcbin->config->ipc_socket_path);
+      nvurisrcbin->config->ipc_socket_path = NULL;
+    }
+    if (nvurisrcbin->config->smart_rec_dir_path) {
+      g_free(nvurisrcbin->config->smart_rec_dir_path);
+      nvurisrcbin->config->smart_rec_dir_path = NULL;
+    }
+    if (nvurisrcbin->config->smart_rec_file_prefix) {
+      g_free(nvurisrcbin->config->smart_rec_file_prefix);
+      nvurisrcbin->config->smart_rec_file_prefix = NULL;
+    }
+    g_free (nvurisrcbin->config);
+    nvurisrcbin->config = NULL;
   }
 
-  g_free (nvurisrcbin->config);
   destroy_smart_record_bin (nvurisrcbin);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
diff --git a/src/utils/nvmsgconv/deepstream_schema/eventmsg_payload.cpp b/src/utils/nvmsgconv/deepstream_schema/eventmsg_payload.cpp
index 39c72ab..a06925e 100644
--- a/src/utils/nvmsgconv/deepstream_schema/eventmsg_payload.cpp
+++ b/src/utils/nvmsgconv/deepstream_schema/eventmsg_payload.cpp
@@ -689,8 +689,8 @@
   json_object_set_object_member (objectObj, "pose", pobject);
 
   //===Embedding model full schema data population===
-  jobject = json_object_new ();
   if (meta->embedding.embedding_vector && meta->embedding.embedding_length) {
+    jobject = json_object_new ();
     json_object_set_int_member(jobject, "embedding_length", meta->embedding.embedding_length);
     JsonArray *embeddingArray = json_array_sized_new (meta->embedding.embedding_length);
     for (guint idx = 0; idx<meta->embedding.embedding_length; idx++){
@@ -701,8 +701,8 @@
   }
 
   // Single-view 3D Tracking metadata
-  jobject = json_object_new ();
   if(meta->has3DTracking) {
+    jobject = json_object_new ();
     json_object_set_double_member (jobject, "visibility", meta->singleView3DTracking.visibility);
 
     JsonArray *footLoc2DArray = json_array_sized_new (2);

2. Apply this patch for bindschema.cpp, then recompile and install pyds

diff --git a/bindings/src/bindschema.cpp b/bindings/src/bindschema.cpp
index 7085d3d..a163dd9 100644
--- a/bindings/src/bindschema.cpp
+++ b/bindings/src/bindschema.cpp
@@ -160,6 +160,7 @@ namespace pydeepstream {
                     g_free (srcData->extMsg);
                     srcData->extMsgSize = 0;
                 }
+                g_free(srcData);
             }
         }
     }

47.[DS 6.4 above_dGPU_App] How to enable software H264 encoder?
For some GPUs do not support Nvidia hardware video encoder Video Encode and Decode GPU Support Matrix | NVIDIA Developer. The software encoder can be enabled and be used with DeepStream pipeline.

The commands(please remove the “sudo” from the commands if you are running with root privilege) for enabling x264enc in Ubuntu 22.04:
a. Install x264enc library

sudo apt install --reinstall libx264-dev libx264-163 
sudo apt install --reinstall gstreamer1.0-plugins-ugly

b. Clean the gstreamer cache

sudo rm -rf  ~/.cache/gstreamer-1.0

c. Check whether the SW video encoder is available

gst-inspect-1.0 x264enc

48.[DSx_All_App] How to get the classification model labels longer than 128 bytes?
Our nvinfer plugin does not support obtaining classification model labels longer than 128 bytes by default. If the label exceeds this length, please refer to the following patch. After the modification, you can obtain them from the pResult_label field in NvDsLabelInfo .

$cd deepstream\sources\gst-plugins\gst-nvinfer
$vim gstnvinfer_meta_utils.cpp

void
attach_metadata_classifier (GstNvInfer * nvinfer, GstMiniObject * tensor_out_object,
    GstNvInferFrame & frame, GstNvInferObjectInfo & object_info)
{
...
    if (attr.attributeLabel) {
-      g_strlcpy (label_info->result_label, attr.attributeLabel, MAX_LABEL_SIZE);
+      if(strlen(attr.attributeLabel) <= MAX_LABEL_SIZE ) {
+       g_strlcpy (label_info->result_label, attr.attributeLabel, MAX_LABEL_SIZE);
+      } else {
+        label_info->pResult_label=g_strdup(attr.attributeLabel);
+     }
      if (object_info.label.length() == 0)
        string_label.append (attr.attributeLabel).append(" ");
    }
...
}

$make
$make install

49.[DSx_All_App] How to render segmentation when testing segmentation models using nvdspreprocess?
Testing the segmentation model with nvdspreprocess, both nvinfer and nvinferserver only attach the segmentation meta to ROI meta. Here is a patch for rendering the segmentation.

  1. If using nvinfer
--- a/src/gst-plugins/gst-nvinfer/gstnvinfer_meta_utils.cpp
+++ b/src/gst-plugins/gst-nvinfer/gstnvinfer_meta_utils.cpp
@@ -425,6 +425,7 @@ attach_metadata_segmentation (GstNvInfer * nvinfer, GstMiniObject * tensor_out_o

   if (nvinfer->input_tensor_from_meta) {
     nvds_add_user_meta_to_roi (frame.roi_meta, user_meta);
+    nvds_add_user_meta_to_frame (frame.frame_meta, user_meta);
   } else if (nvinfer->process_full_frame) {
     nvds_add_user_meta_to_frame (frame.frame_meta, user_meta);
   } else {
  1. if using nvinferserver
--- a/src/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp
+++ b/src/gst-plugins/gst-nvinferserver/gstnvinferserver_meta_utils.cpp
@@ -419,6 +419,7 @@ attachSegmentationMetadata(

     if (roiMeta) {
         nvds_add_user_meta_to_roi(roiMeta, user_meta);
+        nvds_add_user_meta_to_frame(frameMeta, user_meta);
     } else if (objMeta) {
         nvds_add_user_meta_to_obj(objMeta, user_meta);
     } else {

related topic:
[Inference chaining using Deepstream and Triton]

50.[DSx_dGPU_App] How to insert SEI in bitstream using nvdsmetainsert in pyds?

1.Add nvdsmetainsert element upstream of nvv4l2h264enc/nvv4l2h265enc and set the serialize-lib property value

nvdsmetainsert.set_property('serialize-lib', '/opt/nvidia/deepstream/deepstream/lib/libnvds_sei_serialization.so')

2.Add python bindings for NVDS_CUSTOM_PAYLOAD in pyds native code and recompile and reinstall pyds-*.whl

+typedef struct _NVDS_CUSTOM_PAYLOAD
+{
+   uint32_t payloadType;
+   uint32_t payloadSize;
+   uint8_t  *payload;
+} NVDS_CUSTOM_PAYLOAD;

3.Add user meta of type NVDS_DUMMY_BBOX_META(libnvds_sei_serialization.so is open source, modify it according to your needs)

+            data.payload = pyds.alloc_buffer(len(sei_payload))
+
+            ctypes.memmove(data.payload, sei_payload, len(sei_payload))
+
+            data.payloadSize = len(sei_payload)
 
             user_meta.user_meta_data = data
-            user_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_USER_META
+            user_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_DUMMY_BBOX_META

The complete solution below

diff --git a/apps/deepstream-custom-binding-test/deepstream_custom_binding_test.py b/apps/deepstream-custom-binding-test/deepstream_custom_binding_test.py
index 5e41846c..c4d8b28a 100644
--- a/apps/deepstream-custom-binding-test/deepstream_custom_binding_test.py
+++ b/apps/deepstream-custom-binding-test/deepstream_custom_binding_test.py
@@ -20,6 +20,8 @@
 import sys
 import os
 import gi
+import uuid
+import ctypes
 
 gi.require_version('Gst', '1.0')
 from gi.repository import Gst, GLib
@@ -40,6 +42,9 @@ def bus_call(bus, message, loop):
         loop.quit()
     return True
 
+KLV_PAYLOAD_TYPE = 0x01  # Example payload type for KLV data

 def streammux_src_pad_buffer_probe(pad, info, u_data):
     gst_buffer = info.get_buffer()
     if not gst_buffer:
@@ -64,15 +69,21 @@ def streammux_src_pad_buffer_probe(pad, info, u_data):
 
         if user_meta:
             print('adding user meta')
-            test_string = 'test message ' + str(frame_number)
+            uuid_bytes = uuid.UUID("550e8400-e29b-41d4-a716-446655440000").bytes
+            klv_data_buffer = " this is a test KLV data buffer for frame " + str(frame_number)
+            sei_payload = uuid_bytes + klv_data_buffer.encode('utf-8')
+
+            print(f"type of sei_payload: {type(sei_payload)} len: {len(sei_payload)}")
             data = pyds.alloc_custom_struct(user_meta)
-            data.message = test_string
-            data.message = pyds.get_string(data.message)
-            data.structId = frame_number
-            data.sampleInt = frame_number + 1
+            data.payload = pyds.alloc_buffer(len(sei_payload))
+
+            ctypes.memmove(data.payload, sei_payload, len(sei_payload))
+
+            data.payloadSize = len(sei_payload)
+            data.payloadType = KLV_PAYLOAD_TYPE
 
             user_meta.user_meta_data = data
-            user_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_USER_META
+            user_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_DUMMY_BBOX_META
 
             pyds.nvds_add_user_meta_to_frame(frame_meta, user_meta)
         else:
@@ -87,52 +98,6 @@ def streammux_src_pad_buffer_probe(pad, info, u_data):
     return Gst.PadProbeReturn.OK
 
 
-def fakesink_sink_pad_buffer_probe(pad, info, u_data):
-    gst_buffer = info.get_buffer()
-    if not gst_buffer:
-        print("Unable to get GstBuffer ")
-        return
-    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
-
-    if not batch_meta:
-        return Gst.PadProbeReturn.OK
-
-    pyds.nvds_acquire_meta_lock(batch_meta)
-
-    l_frame = batch_meta.frame_meta_list
-    while l_frame is not None:
-        try:
-            frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
-        except StopIteration:
-            continue
-
-        l_usr = frame_meta.frame_user_meta_list
-        while l_usr is not None:
-            try:
-                user_meta = pyds.NvDsUserMeta.cast(l_usr.data)
-            except StopIteration:
-                continue
-
-            if user_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDS_USER_META:
-                custom_msg_meta = pyds.CustomDataStruct.cast(user_meta.user_meta_data)
-                print(f'event msg meta, otherAttrs = {pyds.get_string(custom_msg_meta.message)}')
-                print('custom meta structId:: ', custom_msg_meta.structId)
-                print('custom meta msg:: ', pyds.get_string(custom_msg_meta.message))
-                print('custom meta sampleInt:: ', custom_msg_meta.sampleInt)
-            try:
-                l_usr = l_usr.next
-            except StopIteration:
-                break
-
-        try:
-            l_frame = l_frame.next
-        except StopIteration:
-            break
-
-    pyds.nvds_release_meta_lock(batch_meta)
-    return Gst.PadProbeReturn.OK
-
-
 def main(args):
     # Check input arguments
     if len(args) != 2:
@@ -164,12 +129,22 @@ def main(args):
     queue = Gst.ElementFactory.make("queue", "queue")
     if not queue:
         sys.stderr.write(" Unable to create queue")
+
+    nvdsmetainsert = Gst.ElementFactory.make("nvdsmetainsert", "nvds-meta-insert")
+    if not nvdsmetainsert:
+        sys.stderr.write(" Unable to create NvDsMetaInsert")
+
     queue1 = Gst.ElementFactory.make("queue", "queue1")
     if not queue1:
         sys.stderr.write(" Unable to create queue")
-    sink = Gst.ElementFactory.make("fakesink", "fakesink")
+
+    nvv4l2h264enc = Gst.ElementFactory.make("nvv4l2h264enc", "nvv4l2-h264-encoder")
+    if not nvv4l2h264enc:
+        sys.stderr.write(" Unable to create Nvv4l2 H264 Encoder")
+
+    sink = Gst.ElementFactory.make("filesink", "filesink")
     if not sink:
-        sys.stderr.write(" Unable to create fake sink \n")
+        sys.stderr.write(" Unable to create filesink \n")
     print("reading input")
     print("Playing file %s " %args[1])
     source.set_property('location', args[1])
@@ -184,9 +159,16 @@ def main(args):
     pipeline.add(decoder)
     pipeline.add(streammux)
     pipeline.add(queue)
+    pipeline.add(nvdsmetainsert)
     pipeline.add(queue1)
+    pipeline.add(nvv4l2h264enc)
     pipeline.add(sink)
 
+    print("Setting properties of elements")
+    nvdsmetainsert.set_property('serialize-lib', '/opt/nvidia/deepstream/deepstream/lib/libnvds_sei_serialization.so')
+    nvv4l2h264enc.set_property('bitrate', 4000000)
+    sink.set_property('location', 'output.h264')
+
     print("Linking elements in the Pipeline")
     source.link(h264parser)
     h264parser.link(decoder)
@@ -201,8 +183,10 @@ def main(args):
     srcpad.link(sinkpad)
 
     streammux.link(queue)
-    queue.link(queue1)
-    queue1.link(sink)
+    queue.link(nvdsmetainsert)
+    nvdsmetainsert.link(queue1)
+    queue1.link(nvv4l2h264enc)
+    nvv4l2h264enc.link(sink)
 
     loop = GLib.MainLoop()
     bus = pipeline.get_bus()
@@ -214,10 +198,6 @@ def main(args):
         sys.stderr.write(" Unable to get src pad of streammux")
     streammux_src_pad.add_probe(Gst.PadProbeType.BUFFER, streammux_src_pad_buffer_probe, 0)
 
-    fakesink_sink_pad = sink.get_static_pad('sink')
-    if not fakesink_sink_pad:
-        sys.stderr.write(" Unable to get sink pad of fakesink")
-    fakesink_sink_pad.add_probe(Gst.PadProbeType.BUFFER, fakesink_sink_pad_buffer_probe, 0)
     Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, 'graph')
     print("Starting pipeline")
 
diff --git a/bindings/src/bindnvdsmeta.cpp b/bindings/src/bindnvdsmeta.cpp
index a644665a..9621f940 100644
--- a/bindings/src/bindnvdsmeta.cpp
+++ b/bindings/src/bindnvdsmeta.cpp
@@ -85,6 +85,7 @@ namespace pydeepstream {
                        pydsdoc::nvmeta::MetaTypeDoc::NVDS_FORCE32_META)
                 .value("NVDS_PREPROCESS_BATCH_META", NVDS_PREPROCESS_BATCH_META,
                        pydsdoc::nvmeta::MetaTypeDoc::NVDS_PREPROCESS_BATCH_META)
+                .value("NVDS_DUMMY_BBOX_META", nvds_get_user_meta_type("NVIDIA.DUMMY.BBOX.META"))
                 .export_values();
 
 
diff --git a/bindings/src/custom_binding/bindcustom.cpp b/bindings/src/custom_binding/bindcustom.cpp
index 5e0a253b..d0665611 100644
--- a/bindings/src/custom_binding/bindcustom.cpp
+++ b/bindings/src/custom_binding/bindcustom.cpp
@@ -24,18 +24,16 @@ namespace py = pybind11;
 
 namespace pydeepstream {
 
-    CustomDataStruct * copy_custom_struct(void* data, void* user_data) {
+    NVDS_CUSTOM_PAYLOAD * copy_custom_struct(void* data, void* user_data) {
         NvDsUserMeta * srcMeta = (NvDsUserMeta*) data;
-        CustomDataStruct * srcData = (CustomDataStruct *) srcMeta->user_meta_data;
-        CustomDataStruct *destData = (CustomDataStruct *) g_malloc0(
-                        sizeof(CustomDataStruct));
-        destData->structId = srcData->structId;
-        destData->sampleInt = srcData->sampleInt;
-        if (srcData->message != nullptr) {
-            char* srcString = (char *) srcData->message;
-            int strSize = strlen(srcString);
-            destData->message = (char*)calloc(strSize + 1, sizeof(char));
-            strcpy(destData->message, srcData->message);
+        NVDS_CUSTOM_PAYLOAD * srcData = (NVDS_CUSTOM_PAYLOAD *) srcMeta->user_meta_data;
+        NVDS_CUSTOM_PAYLOAD *destData = (NVDS_CUSTOM_PAYLOAD *) g_malloc0(
+                        sizeof(NVDS_CUSTOM_PAYLOAD));
+        destData->payloadType = srcData->payloadType;
+        destData->payloadSize = srcData->payloadSize;
+        if (srcData->payload != nullptr) {
+            destData->payload = (uint8_t*)calloc(srcData->payloadSize, sizeof(uint8_t));
+            memcpy(destData->payload, srcData->payload, srcData->payloadSize);
         }
         return destData;
     }
@@ -43,14 +41,10 @@ namespace pydeepstream {
     void release_custom_struct(void * data, void * user_data) {
         NvDsUserMeta * srcMeta = (NvDsUserMeta*) data;
         if (srcMeta != nullptr) {
-            CustomDataStruct * srcData = (CustomDataStruct *) srcMeta->user_meta_data;
+            NVDS_CUSTOM_PAYLOAD * srcData = (NVDS_CUSTOM_PAYLOAD *) srcMeta->user_meta_data;
             if (srcData != nullptr) {
-                auto * message = srcData->message;
-                srcData->structId = 0;
-                srcData->sampleInt = 0;
-                if (srcData->message != nullptr)
-                {
-                    free(srcData->message);
+                if (srcData->payload != nullptr) {
+                    free(srcData->payload);
                 }
                 g_free(srcData);
             }
@@ -59,30 +53,33 @@ namespace pydeepstream {
 
     void bindcustom(py::module &m) {
                 /* CustomDataStruct bindings to be used with NvDsUserMeta */
-                py::class_<CustomDataStruct>(m, "CustomDataStruct",
-                                pydsdoc::custom::CustomDataStructDoc::descr)
+                py::class_<NVDS_CUSTOM_PAYLOAD>(m, "NVDS_CUSTOM_PAYLOAD")
                 .def(py::init<>())
-                .def_readwrite("structId", &CustomDataStruct::structId)
-                .def_property("message", STRING_FREE_EXISTING(CustomDataStruct, message))
-                .def_readwrite("sampleInt", &CustomDataStruct::sampleInt)
+                .def_readwrite("payloadType", &NVDS_CUSTOM_PAYLOAD::payloadType)
+                .def_readwrite("payloadSize", &NVDS_CUSTOM_PAYLOAD::payloadSize)
+                .def_property("payload", 
+                    [](const NVDS_CUSTOM_PAYLOAD &self) -> size_t {
+                        return (size_t)self.payload;
+                    },
+                    [](NVDS_CUSTOM_PAYLOAD& self, size_t ptr) {
+                        self.payload = (uint8_t *) ptr;
+                    }, py::return_value_policy::reference)
 
                 .def("cast",
                      [](void *data) {
-                         return (CustomDataStruct *) data;
+                         return (NVDS_CUSTOM_PAYLOAD *) data;
                      },
-                     py::return_value_policy::reference,
-                     pydsdoc::custom::CustomDataStructDoc::cast);
+                     py::return_value_policy::reference);
 
         m.def("alloc_custom_struct",
               [](NvDsUserMeta *meta) {
-                  auto *mem = (CustomDataStruct *) g_malloc0(
-                          sizeof(CustomDataStruct));
+                  auto *mem = (NVDS_CUSTOM_PAYLOAD *) g_malloc0(
+                          sizeof(NVDS_CUSTOM_PAYLOAD));
                   meta->base_meta.copy_func = (NvDsMetaCopyFunc) pydeepstream::copy_custom_struct;
                   meta->base_meta.release_func = (NvDsMetaReleaseFunc) pydeepstream::release_custom_struct;
                   return mem;
               },
-              py::return_value_policy::reference,
-              pydsdoc::methodsDoc::alloc_custom_struct);
+              py::return_value_policy::reference);
 
     }
 
diff --git a/bindings/src/custom_binding/include/custom_data.hpp b/bindings/src/custom_binding/include/custom_data.hpp
index a9abe44e..aeb271fb 100644
--- a/bindings/src/custom_binding/include/custom_data.hpp
+++ b/bindings/src/custom_binding/include/custom_data.hpp
@@ -18,8 +18,9 @@
 
 using namespace std;
 
-struct CustomDataStruct {
-  int structId;
-  char* message;
-  int sampleInt;
-};
\ No newline at end of file
+typedef struct _NVDS_CUSTOM_PAYLOAD
+{
+   uint32_t payloadType;
+   uint32_t payloadSize;
+   uint8_t  *payload;
+} NVDS_CUSTOM_PAYLOAD;
\ No newline at end of file

Refer to this topic

gstreamer-pipeline-to-insert-metadata-using-deepstream

51. [DS7.1_JetPack6.2_nvvideoconvert] How to resolve the compatibility issue of nvvideoconvert plugin in DeepStream 7.1 on Jetson 6.2 version.
When running DeepStream 7.1 on Jetpack 6.2, you may encounter some memory copy exceptions. Some failed logs are as follows.

...nvbufsurftransform_copy.cpp:341: => Failed in mem copy
...nvbufsurftransform_copy.cpp:438: => Failed in mem copy

You can try the following methods to solve this issue.

  1. Please refer to our Jetson model Platform and OS Compatibility Guide to use the Jetpack 6.1 for the DeepStream 7.1 version.
  2. If it is not convenient for you to change the version of Jetpack, you can try to set the copy-hw=2 for the nvvideoconvert in your pipeline as a workaround.

52.[DSx_All_Plugin] How to enable full color range for nvv4l2h264enc?
If full color range is set in “colorimetry” caps, nvv4l2h264enc will set ‘video_full_range_flag’ to 1 in H264 stream. Please refer to the following command line.

 gst-launch-1.0 -e  filesrc location=/home/test-input.mp4  ! qtdemux  ! h264parse ! nvv4l2decoder   ! nvvideoconvert !  'video/x-raw(memory:NVMM), format=NV12, colorimetry=(string)1:4:5:1' ! nvv4l2h264enc ! h264parse ! filesink location=test.264 -v 

Please refer to GstVideoColorimetry for how to set “colorimetry”.

related topic:
[Nvv4l2h264enc output color washed out]

53.[DS8.0_All_NvDsMeta] How to get NvDsInferTensorMeta when input-tensor-from-meta and output-tensor-meta are true?
When operating in preprocessed tensor input mode (using nvdspreprocess plugin), the inference raw tensor metadata is wrapped inside ROI metadata. First look for NVDS_ROI_META in the GstNvDsPreProcessBatchMeta’s roi_vector, then access the NvDsRoiMeta and look for NVDSINFER_TENSOR_OUTPUT_META within the ROI meta’s user meta list.
Here is a sample code.

for(NvDsMetaList *l_batch_user_meta = batch_meta->batch_user_meta_list; l_batch_user_meta != NULL;
    l_batch_user_meta = l_batch_user_meta->next) {
    NvDsUserMeta *batch_user_meta = (NvDsUserMeta *)l_batch_user_meta->data;
    if(batch_user_meta->base_meta.meta_type != NVDS_PREPROCESS_BATCH_META) continue;
    GstNvDsPreProcessBatchMeta *preprocess_batch_meta = 
        (GstNvDsPreProcessBatchMeta *)batch_user_meta->user_meta_data;
    for(auto roi_meta : preprocess_batch_meta->roi_vector) {
        for(NvDsMetaList *l_roi_user = roi_meta.roi_user_meta_list; l_roi_user != NULL;
            l_roi_user = l_roi_user->next) {
            NvDsUserMeta *roi_user_meta = (NvDsUserMeta *)l_roi_user->data;
            if(roi_user_meta->base_meta.meta_type != NVDSINFER_TENSOR_OUTPUT_META) continue;
            NvDsInferTensorMeta *meta = (NvDsInferTensorMeta *)roi_user_meta->user_meta_data;
            if (meta->unique_id == static_cast<guint>(m_gie_unique_id)) {
                for (guint i = 0; i < meta->num_output_layers; i++) {
                    NvDsInferLayerInfo *info = &meta->output_layers_info[i];
                    info->buffer = meta->out_buf_ptrs_host[i];
                }
                /* Please refer to sample deepstream-infer-tensor-meta-test for 
                parsing output tensor and filling detection results into objectList. */
            }
        }
    }
}

related topic:
[Raw output tensor for nvinfer sgie cannot be acessed]

**54.[DS8.0_All_nvdspreprocess] How to set tensor-data-type in nvdspreprocess configuration file?
‘tensor-data-type’ represents the data format for inference. As shown in the opensource nvdspreprocess code, it corresponds one-to-one with NvDsDataType.

typedef enum
{
  /** FP32 data type */
  NvDsDataType_FP32,
  /** UINT8 data type */
  NvDsDataType_UINT8,
  /** INT8 data type */
  NvDsDataType_INT8,
  /** UINT32 data type */
  NvDsDataType_UINT32,
  /** INT32 data type */
  NvDsDataType_INT32,
  /** INT64 data type */
  NvDsDataType_INT64,
  /** UINT64 data type */
  NvDsDataType_UINT64,
  /** FP16 data type */
  NvDsDataType_FP16,
} NvDsDataType;

Hence the following is the correct comment.

# 0=FP32, 1=UINT8, 2=INT8, 3=UINT32, 4=INT32, 5=INT64, 6=UINT64, 7=FP16

55.[DS8.0_dGPU_nvv4l2h264enc] Can not play RTSP sink video on DeepStream 8.0
On DS8.0, by default, SPS/PPS are missing before the video IDR frames. Therefore, the client cannot decode the stream and reports the error “Referenced non-existent PPS 0”. Here are two solutions:

  1. Set the ‘insert-sps-pps’ property of the nvv4l2h264enc plugin to 1.
  2. Set the ‘config-interval’ property of the h264parse plugin to -1.

related topic:
[Rtsp-out no data (DeepStream 8.0)]

56.[DSx_Jetson_Display] How to support VNC and remote desktop on a headless Jetson device

Thanks to the community users for providing the tutorial.

Jetson Orin Nano Headless Setup

Additionally, if you need to generate an HDMI edid, please refer to this web tool.

HDMI EDID