7. [DS 5.0GA_All_App] Enable Latency measurement for deepstream sample apps
-
If you are using deepstream-app, to check the component latency directly, you need to set the env
- export NVDS_ENABLE_COMPONENT_LATENCY_MEASUREMENT=1
export NVDS_ENABLE_LATENCY_MEASUREMENT=1
-
If you are using other deepstream sample apps such as deepstream-test3, you need to apply the following patch and set the env
- export NVDS_ENABLE_COMPONENT_LATENCY_MEASUREMENT=1
export NVDS_ENABLE_LATENCY_MEASUREMENT=1
diff --git a/apps/deepstream/sample_apps/deepstream-test3/deepstream_test3_app.c b/apps/deepstream/sample_apps/deepstream-test3/deepstream_test3_app.c
index 426bd69..c7c2472 100644
--- a/apps/deepstream/sample_apps/deepstream-test3/deepstream_test3_app.c
+++ b/apps/deepstream/sample_apps/deepstream-test3/deepstream_test3_app.c
@@ -26,6 +26,7 @@
#include <math.h>
#include <string.h>
#include <sys/time.h>
+#include <stdlib.h>
#include "gstnvdsmeta.h"
//#include "gstnvstreammeta.h"
@@ -73,6 +74,41 @@ gchar pgie_classes_str[4][32] = { "Vehicle", "TwoWheeler", "Person",
//static guint probe_counter = 0;
+typedef struct {
+ GMutex *lock;
+ int num_sources;
+}LatencyCtx;
+
+static GstPadProbeReturn
+latency_measurement_buf_prob(GstPad * pad, GstPadProbeInfo * info, gpointer u_data)
+{
+ LatencyCtx *ctx = (LatencyCtx *) u_data;
+ static int batch_num = 0;
+ guint i = 0, num_sources_in_batch = 0;
+ if(nvds_enable_latency_measurement)
+ {
+ GstBuffer *buf = (GstBuffer *) info->data;
+ NvDsFrameLatencyInfo *latency_info = NULL;
+ g_mutex_lock (ctx->lock);
+ latency_info = (NvDsFrameLatencyInfo *)
+ calloc(1, ctx->num_sources * sizeof(NvDsFrameLatencyInfo));;
+ g_print("\n************BATCH-NUM = %d**************\n",batch_num);
+ num_sources_in_batch = nvds_measure_buffer_latency(buf, latency_info);
+
+ for(i = 0; i < num_sources_in_batch; i++)
+ {
+ g_print("Source id = %d Frame_num = %d Frame latency = %lf (ms) \n",
+ latency_info[i].source_id,
+ latency_info[i].frame_num,
+ latency_info[i].latency);
+ }
+ g_mutex_unlock (ctx->lock);
+ batch_num++;
+ }
+
+ return GST_PAD_PROBE_OK;
+}
+
/* tiler_sink_pad_buffer_probe will extract metadata received on OSD sink pad
* and update params for drawing rectangle, object information etc. */
@@ -107,9 +143,9 @@ tiler_src_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
num_rects++;
}
}
- 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);
+ // 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);
#if 0
display_meta = nvds_acquire_display_meta_from_pool(batch_meta);
NvOSD_TextParams *txt_params = &display_meta->text_params;
@@ -383,7 +419,7 @@ main (int argc, char *argv[])
#ifdef PLATFORM_TEGRA
transform = gst_element_factory_make ("nvegltransform", "nvegl-transform");
#endif
- sink = gst_element_factory_make ("nveglglessink", "nvvideo-renderer");
+ sink = gst_element_factory_make ("fakesink", "nvvideo-renderer");
if (!pgie || !tiler || !nvvidconv || !nvosd || !sink) {
g_printerr ("One element could not be created. Exiting.\n");
@@ -467,6 +503,18 @@ gst_bin_add_many (GST_BIN (pipeline), queue1, pgie, queue2, tiler, queue3,
tiler_src_pad_buffer_probe, NULL, NULL);
gst_object_unref (tiler_src_pad);
+ GstPad *sink_pad = gst_element_get_static_pad (nvosd, "src");
+ if (!sink_pad)
+ g_print ("Unable to get src pad\n");
+ else {
+ LatencyCtx *ctx = (LatencyCtx *)g_malloc0(sizeof(LatencyCtx));
+ ctx->lock = (GMutex *)g_malloc0(sizeof(GMutex));
+ ctx->num_sources = num_sources;
+ gst_pad_add_probe (sink_pad, GST_PAD_PROBE_TYPE_BUFFER,
+ latency_measurement_buf_prob, ctx, NULL);
+ }
+ gst_object_unref (sink_pad);
+
/* Set the pipeline to "playing" state */
g_print ("Now playing:");
for (i = 0; i < num_sources; i++) {
3.If you use a python app such as deepstream_test_3.py, you need to apply the following patch and set the env
export NVDS_ENABLE_COMPONENT_LATENCY_MEASUREMENT=1
export NVDS_ENABLE_LATENCY_MEASUREMENT=1
pip install cffi
Then execute like below
python3 deepstream_test_3.py --no-display -i rtsp://"your_rtsp_uri_0" uri1
diff --git a/apps/deepstream-test3/deepstream_test_3.py b/apps/deepstream-test3/deepstream_test_3.py
index d81ec92..21d2f3b 100755
--- a/apps/deepstream-test3/deepstream_test_3.py
+++ b/apps/deepstream-test3/deepstream_test_3.py
@@ -36,6 +36,28 @@ from common.FPS import PERF_DATA
import pyds
+from cffi import FFI
+
+ffi = FFI()
+
+clib = None
+
+ffi.cdef("""
+typedef struct
+{
+ uint32_t source_id;
+ uint32_t frame_num;
+ double comp_in_timestamp;
+ double latency;
+} NvDsFrameLatencyInfo;
+
+uint32_t nvds_measure_buffer_latency(void *buf, NvDsFrameLatencyInfo *latency_info);
+bool nvds_get_enable_latency_measurement();
+""")
+
+# Compile the C sources to produce the following .dll (or .so under *nix)
+clib = ffi.dlopen("/opt/nvidia/deepstream/deepstream/lib/libnvdsgst_meta.so")
+
no_display = False
silent = False
file_loop = False
@@ -56,6 +78,27 @@ OSD_PROCESS_MODE= 0
OSD_DISPLAY_TEXT= 1
pgie_classes_str= ["Vehicle", "TwoWheeler", "Person","RoadSign"]
+batch_num = 0
+
+def osd_src_pad_buffer_probe(pad, info, u_data):
+ number_source = u_data
+ gst_buffer = info.get_buffer()
+ if not gst_buffer:
+ print("Unable to get GstBuffer ")
+ return
+ global batch_num
+ if clib.nvds_get_enable_latency_measurement:
+ print(f"************BATCH-NUM = {batch_num}**************")
+ c_gst_buf = ffi.cast("void *", hash(gst_buffer))
+ cNvDsFrameLatencyInfo = ffi.new(f"NvDsFrameLatencyInfo[{number_source}]")
+ sources = clib.nvds_measure_buffer_latency(c_gst_buf, cNvDsFrameLatencyInfo)
+ for i in range(sources):
+ print(f"Source id = {cNvDsFrameLatencyInfo[i].source_id} "
+ f"Frame_num = {cNvDsFrameLatencyInfo[i].frame_num} "
+ f"Frame latency = {cNvDsFrameLatencyInfo[i].latency} (ms) ")
+ batch_num += 1
+ return Gst.PadProbeReturn.OK
+
# pgie_src_pad_buffer_probe will extract metadata received on tiler sink pad
# and update params for drawing rectangle, object information etc.
def pgie_src_pad_buffer_probe(pad,info,u_data):
@@ -199,7 +242,7 @@ def create_source_bin(index,uri):
return None
return nbin
-def main(args, requested_pgie=None, config=None, disable_probe=False):
+def main(args, requested_pgie=None, config=None, disable_probe=True):
global perf_data
perf_data = PERF_DATA(len(args))
@@ -380,6 +423,12 @@ def main(args, requested_pgie=None, config=None, disable_probe=False):
# perf callback function to print fps every 5 sec
GLib.timeout_add(5000, perf_data.perf_print_callback)
+ osd_src_pad=nvosd.get_static_pad("src")
+ if not osd_src_pad:
+ sys.stderr.write(" Unable to get src pad \n")
+ else:
+ osd_src_pad.add_probe(Gst.PadProbeType.BUFFER, osd_src_pad_buffer_probe, number_sources)
+
# List the sources
print("Now playing...")
for i, source in enumerate(args):