Please provide complete information as applicable to your setup.
• Hardware Platform - GPU
• DeepStream Version - 7.0
• TensorRT Version - 10.6.0
• NVIDIA GPU Driver Version - 560.35.03
• Issue Type - questions
**• How to reproduce the issue ? **
I ran my DeepStream application, but after processing 33 frames, I received the PERF {stream:0.0}
message.
code :
import argparse
import configparser
import ctypes
import json
import sys
sys.path.append('../')
import gi
from utils import read_yaml,get_current_epoch_in_syd,epoch_to_datetime_str,convert_syd_epoch_to_datetime_str,send_message_to_iothub
gi.require_version('Gst', '1.0')
from gi.repository import GLib, Gst
import sys
from optparse import OptionParser
from common.platform_info import PlatformInfo
from common.bus_call import bus_call
from common.FPS import PERF_DATA
from common.utils import long_to_uint64
import pyds
import pytz
from datetime import datetime
import os
MAX_DISPLAY_LEN = 64
MAX_TIME_STAMP_LEN = 32
PGIE_CLASS_ID_VEHICLE = 0
PGIE_CLASS_ID_BICYCLE = 1
PGIE_CLASS_ID_PERSON = 2
PGIE_CLASS_ID_ROADSIGN = 3
MUXER_OUTPUT_WIDTH = 1920
MUXER_OUTPUT_HEIGHT = 1080
OSD_PROCESS_MODE= 0
OSD_DISPLAY_TEXT= 1
MUXER_BATCH_TIMEOUT_USEC = 33000
input_file = None
schema_type = 0
proto_lib = None
conn_str = "localhost;2181;testTopic"
cfg_file = None
topic = None
no_display = False
PGIE_CONFIG_FILE = "dstest4_pgie_config.txt"
MSCONV_CONFIG_FILE = "dstest4_msgconv_config.txt"
pgie_classes_str = ["Vehicle", "TwoWheeler", "Person", "Roadsign"]
def parse_args():
parser = OptionParser()
parser.add_option("-c", "--cfg_file", dest="cfg_file",
help="Set the adaptor config file. Optional if "
"connection string has relevant details.",
metavar="FILE")
parser.add_option("-i", "--input-file", dest="input_file",
help="Set the input H264 file", metavar="FILE")
parser.add_option("-p", "--proto-lib", dest="proto_lib",
help="Absolute path of adaptor library", metavar="PATH")
parser.add_option("", "--conn-str", dest="conn_str",
help="Connection string of backend server. Optional if "
"it is part of config file.", metavar="STR")
parser.add_option("-s", "--schema-type", dest="schema_type", default="0",
help="Type of message schema (0=Full, 1=minimal), "
"default=0", metavar="<0|1>")
parser.add_option("-t", "--topic", dest="topic",
help="Name of message topic. Optional if it is part of "
"connection string or config file.", metavar="TOPIC")
parser.add_option("", "--no-display", action="store_true",
dest="no_display", default=False,
help="Disable display")
(options, args) = parser.parse_args()
cfg_file = options.cfg_file
input_file = options.input_file
proto_lib = options.proto_lib
conn_str = options.conn_str
topic = options.topic
no_display = options.no_display
if not (proto_lib and input_file):
print("Usage: python3 deepstream_test_4.py -i <H264 filename> -p "
"<Proto adaptor library> --conn-str=<Connection string>")
return 1
schema_type = 0 if options.schema_type == "0" else 1
return {"input_file": input_file,"proto_lib": proto_lib,"cfg_file": cfg_file,"topic": topic,
"schema_type": schema_type,"no_display":no_display,"conn_str": conn_str,}
syd_tz = pytz.timezone('Australia/Sydney')
yaml_con = read_yaml("main_config.yaml")
cap_fps = int(yaml_con["fps"])
json_write_ther = int(yaml_con["json_write_ther"])
base_json_dir_name = yaml_con["base_json_dir_name"]
base_video_dir_name = yaml_con["base_video_dir_name"]
sec_to_get_data = int(yaml_con["sec_to_get_data"])
iot_hub_connection_string = yaml_con["iot_hub_connection_string"]
no_min_to_write_video = int(yaml_con["no_min_to_write_video"])
one_min_counter = 60*cap_fps
args = parse_args()
args_streams = args["input_file"]
args_streams = ["file:///bi3-ds/deepstream_python_apps/apps/deepstream-nvdsanalytics/2024-09-27__15-09-59.mp4"]
cfg_file = args["cfg_file"]
proto_lib = args["proto_lib"]
conn_str = args["conn_str"]
topic = args["topic"]
no_display = args["no_display"]
print(f"{args_streams=}")
start_time = {i:get_current_epoch_in_syd() for i in range(len(args_streams))}
one_min_start_time = {i:get_current_epoch_in_syd() for i in range(len(args_streams))}
current_date = datetime.fromtimestamp(get_current_epoch_in_syd(), syd_tz).strftime('%Y-%m-%d')
video_dir_paths = {i:os.path.join(base_video_dir_name,f"{i}",current_date) for i in range(len(args_streams))}
dir_names = {i:os.path.join(base_json_dir_name,f"{i}",current_date) for i in range(len(args_streams))}
[os.makedirs(dir_names[i],exist_ok=True) for i in range(len(args_streams))]
[os.makedirs(video_dir_paths[i],exist_ok=True) for i in range(len(args_streams)) ]
data_dict = { i:{"people_crossing":[],"people_crossing_frame":[],"people_count":[]} for i in range(len(args_streams)) }
camera_ids = {idx:cam_id for idx,cam_id in enumerate(["C1085","C2034","C2035"])}
data_dict_1_min = { i:{"people_crossing_cumulative":[],"people_crossing_frame":[],"people_count":[],"track_ids":[],"camera_id":camera_ids[i]} for i in range(len(args_streams)) }
object_track_id_conf = {i:{} for i in range(len(args_streams)) }
def generate_vehicle_meta(data):
obj = pyds.NvDsVehicleObject.cast(data)
obj.type = "sedan"
obj.color = "blue"
obj.make = "Bugatti"
obj.model = "M"
obj.license = "XX1234"
obj.region = "CA"
return obj
def generate_person_meta(data):
obj = pyds.NvDsPersonObject.cast(data)
obj.age = 45
obj.cap = "none"
obj.hair = "black"
obj.gender = "male"
obj.apparel = "formal"
return obj
def generate_event_msg_meta(data, class_id):
meta = pyds.NvDsEventMsgMeta.cast(data)
meta.sensorId = 0
meta.placeId = 0
meta.moduleId = 0
meta.sensorStr = "sensor-0"
meta.ts = pyds.alloc_buffer(MAX_TIME_STAMP_LEN + 1)
pyds.generate_ts_rfc3339(meta.ts, MAX_TIME_STAMP_LEN)
if class_id == PGIE_CLASS_ID_VEHICLE:
meta.type = pyds.NvDsEventType.NVDS_EVENT_MOVING
meta.objType = pyds.NvDsObjectType.NVDS_OBJECT_TYPE_VEHICLE
meta.objClassId = PGIE_CLASS_ID_VEHICLE
obj = pyds.alloc_nvds_vehicle_object()
obj = generate_vehicle_meta(obj)
meta.extMsg = obj
meta.extMsgSize = sys.getsizeof(pyds.NvDsVehicleObject)
if class_id == PGIE_CLASS_ID_PERSON:
meta.type = pyds.NvDsEventType.NVDS_EVENT_ENTRY
meta.objType = pyds.NvDsObjectType.NVDS_OBJECT_TYPE_PERSON
meta.objClassId = PGIE_CLASS_ID_PERSON
obj = pyds.alloc_nvds_person_object()
obj = generate_person_meta(obj)
meta.extMsg = obj
meta.extMsgSize = sys.getsizeof(pyds.NvDsPersonObject)
return meta
def osd_sink_pad_buffer_probe(pad, info, u_data):
print("================================= inside the osd_sink_pad_buffer_probe =================================")
frame_number = 0
obj_counter = {
PGIE_CLASS_ID_VEHICLE: 0,
PGIE_CLASS_ID_PERSON: 0,
PGIE_CLASS_ID_BICYCLE: 0,
PGIE_CLASS_ID_ROADSIGN: 0
}
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
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
is_first_object = True
frame_number = frame_meta.frame_num
l_obj = frame_meta.obj_meta_list
while l_obj is not None:
try:
obj_meta = pyds.NvDsObjectMeta.cast(l_obj.data)
except StopIteration:
continue
txt_params = obj_meta.text_params
txt_params.display_text = pgie_classes_str[obj_meta.class_id]
obj_counter[obj_meta.class_id] += 1
txt_params.font_params.font_name = "Serif"
txt_params.font_params.font_size = 10
txt_params.font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
txt_params.set_bg_clr = 1
txt_params.text_bg_clr.set(0.0, 0.0, 0.0, 1.0)
if is_first_object and (frame_number % 30) == 0:
print(f"================================= inside the send IOT {frame_number=} =================================")
user_event_meta = pyds.nvds_acquire_user_meta_from_pool(
batch_meta)
if user_event_meta:
msg_meta = pyds.alloc_nvds_event_msg_meta(user_event_meta)
msg_meta.bbox.top = obj_meta.rect_params.top
msg_meta.bbox.left = obj_meta.rect_params.left
msg_meta.bbox.width = obj_meta.rect_params.width
msg_meta.bbox.height = obj_meta.rect_params.height
msg_meta.frameId = frame_number
msg_meta.trackingId = long_to_uint64(obj_meta.object_id)
msg_meta.confidence = obj_meta.confidence
msg_meta = generate_event_msg_meta(msg_meta, obj_meta.class_id)
user_event_meta.user_meta_data = msg_meta
user_event_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_EVENT_MSG_META
pyds.nvds_add_user_meta_to_frame(frame_meta,
user_event_meta)
else:
print("Error in attaching event meta to buffer\n")
is_first_object = False
try:
l_obj = l_obj.next
except StopIteration:
break
try:
l_frame = l_frame.next
except StopIteration:
break
print("Frame Number =", frame_number, "Vehicle Count =",
obj_counter[PGIE_CLASS_ID_VEHICLE], "Person Count =",
obj_counter[PGIE_CLASS_ID_PERSON])
return Gst.PadProbeReturn.OK
def format_location_callback(splitmuxsink, fragment_id, video_dir_path, stream_id):
current_epoch = get_current_epoch_in_syd()
current_time_str = convert_syd_epoch_to_datetime_str(current_epoch)
return os.path.join(video_dir_path, f"{current_time_str}.mp4")
def add_video_saving(pipeline, i, video_dir_path, no_min_to_write_video):
"""
Add video saving elements to the pipeline.
"""
queue = Gst.ElementFactory.make("queue", f"queue_{i}")
nvvidconv = Gst.ElementFactory.make("nvvideoconvert", f"convertor_{i}")
capsfilter = Gst.ElementFactory.make("capsfilter", f"capsfilter_{i}")
encoder = Gst.ElementFactory.make("avenc_mpeg4", f"encoder_{i}")
codeparser = Gst.ElementFactory.make("mpeg4videoparse", f"codeparser_{i}")
splitmuxsink = Gst.ElementFactory.make("splitmuxsink", f"splitmuxsink_{i}")
muxer = Gst.ElementFactory.make("qtmux", f"muxer_{i}")
if not all([queue, nvvidconv, capsfilter, encoder, codeparser, splitmuxsink, muxer]):
sys.stderr.write("Unable to create video saving elements\n")
return None
caps = Gst.Caps.from_string("video/x-raw, format=I420")
capsfilter.set_property("caps", caps)
encoder.set_property("bitrate", 2000000)
splitmuxsink.set_property("max-size-time", (no_min_to_write_video * 60) * Gst.SECOND) # File duration in seconds
splitmuxsink.set_property("muxer", muxer)
splitmuxsink.connect("format-location", format_location_callback, video_dir_path, i)
pipeline.add(queue)
pipeline.add(nvvidconv)
pipeline.add(capsfilter)
pipeline.add(encoder)
pipeline.add(codeparser)
pipeline.add(splitmuxsink)
queue.link(nvvidconv)
nvvidconv.link(capsfilter)
capsfilter.link(encoder)
encoder.link(codeparser)
codeparser.link(splitmuxsink)
return queue
def cb_newpad(decodebin, decoder_src_pad,data):
print("In cb_newpad\n")
caps=decoder_src_pad.get_current_caps()
gststruct=caps.get_structure(0)
gstname=gststruct.get_name()
source_bin=data
features=caps.get_features(0)
print("gstname=",gstname)
if(gstname.find("video")!=-1):
print("features=",features)
if features.contains("memory:NVMM"):
bin_ghost_pad=source_bin.get_static_pad("src")
if not bin_ghost_pad.set_target(decoder_src_pad):
sys.stderr.write("Failed to link decoder src pad to source bin ghost pad\n")
else:
sys.stderr.write(" Error: Decodebin did not pick nvidia decoder plugin.\n")
def decodebin_child_added(child_proxy,Object,name,user_data):
print("Decodebin child added:", name, "\n")
if(name.find("decodebin") != -1):
Object.connect("child-added",decodebin_child_added,user_data)
def create_source_bin(index,uri):
print("Creating source bin")
bin_name="source-bin-%02d" %index
print(bin_name)
nbin=Gst.Bin.new(bin_name)
if not nbin:
sys.stderr.write(" Unable to create source bin \n")
uri_decode_bin=Gst.ElementFactory.make("uridecodebin", "uri-decode-bin")
if not uri_decode_bin:
sys.stderr.write(" Unable to create uri decode bin \n")
uri_decode_bin.set_property("uri",uri)
uri_decode_bin.connect("pad-added",cb_newpad,nbin)
uri_decode_bin.connect("child-added",decodebin_child_added,nbin)
Gst.Bin.add(nbin,uri_decode_bin)
bin_pad=nbin.add_pad(Gst.GhostPad.new_no_target("src",Gst.PadDirection.SRC))
if not bin_pad:
sys.stderr.write(" Failed to add ghost pad in source bin \n")
return None
return nbin
def make_element(element_name, i):
element = Gst.ElementFactory.make(element_name, element_name)
if not element:
sys.stderr.write(" Unable to create {0}".format(element_name))
element.set_property("name", "{0}-{1}".format(element_name, str(i)))
return element
def main(args):
input_sources = args
number_sources = len(input_sources)
global perf_data
perf_data = PERF_DATA(number_sources)
platform_info = PlatformInfo()
Gst.init(None)
print("Creating Pipeline \n ")
pipeline = Gst.Pipeline()
is_live = False
if not pipeline:
sys.stderr.write(" Unable to create Pipeline \n")
print("Creating streamux \n ")
streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
if not streammux:
sys.stderr.write(" Unable to create NvStreamMux \n")
pipeline.add(streammux)
msgconv = Gst.ElementFactory.make("nvmsgconv", "nvmsg-converter")
if not msgconv:
sys.stderr.write(" Unable to create msgconv \n")
msgbroker = Gst.ElementFactory.make("nvmsgbroker", "nvmsg-broker")
if not msgbroker:
sys.stderr.write(" Unable to create msgbroker \n")
msgconv.set_property('config', MSCONV_CONFIG_FILE)
msgconv.set_property('payload-type', schema_type)
msgbroker.set_property('proto-lib', proto_lib)
msgbroker.set_property('conn-str', conn_str)
if cfg_file is not None:
msgbroker.set_property('config', cfg_file)
if topic is not None:
msgbroker.set_property('topic', topic)
msgbroker.set_property('sync', False)
pipeline.add(msgconv)
pipeline.add(msgbroker)
for i in range(number_sources):
print("Creating source_bin ",i," \n ")
uri_name=args[i]
if uri_name.find("rtsp://") == 0 :
is_live = True
source_bin=create_source_bin(i, uri_name)
if not source_bin:
sys.stderr.write("Unable to create source bin \n")
pipeline.add(source_bin)
padname="sink_%u" %i
sinkpad= streammux.request_pad_simple(padname)
if not sinkpad:
sys.stderr.write("Unable to create sink pad bin \n")
srcpad=source_bin.get_static_pad("src")
if not srcpad:
sys.stderr.write("Unable to create src pad bin \n")
srcpad.link(sinkpad)
streammux.set_property('width', 1920)
streammux.set_property('height', 1080)
streammux.set_property('batch-size', number_sources)
streammux.set_property('batched-push-timeout', MUXER_BATCH_TIMEOUT_USEC)
queue1=Gst.ElementFactory.make("queue","queue1")
queue2=Gst.ElementFactory.make("queue","queue2")
queue3=Gst.ElementFactory.make("queue","queue3")
queue4=Gst.ElementFactory.make("queue","queue4")
queue5=Gst.ElementFactory.make("queue","queue5")
queue6=Gst.ElementFactory.make("queue","queue6")
queue7=Gst.ElementFactory.make("queue","queue7")
pipeline.add(queue1)
pipeline.add(queue2)
pipeline.add(queue3)
pipeline.add(queue4)
pipeline.add(queue5)
pipeline.add(queue6)
pipeline.add(queue7)
print("Creating Pgie")
pgie = Gst.ElementFactory.make("nvinfer", "primary-inference")
if not pgie:
sys.stderr.write(" Unable to create pgie \n")
pgie.set_property('config-file-path', "dsnvanalytics_pgie_config.txt")
pgie_batch_size=pgie.get_property("batch-size")
if(pgie_batch_size != number_sources):
print("WARNING: Overriding infer-config batch-size",pgie_batch_size," with number of sources ", number_sources," \n")
pgie.set_property("batch-size",number_sources)
print("Creating nvtracker")
tracker = Gst.ElementFactory.make("nvtracker", "tracker")
if not tracker:
sys.stderr.write(" Unable to create tracker \n")
config = configparser.ConfigParser()
config.read('dsnvanalytics_tracker_config.txt')
config.sections()
for key in config['tracker']:
if key == 'tracker-width' :
tracker_width = config.getint('tracker', key)
tracker.set_property('tracker-width', tracker_width)
if key == 'tracker-height' :
tracker_height = config.getint('tracker', key)
tracker.set_property('tracker-height', tracker_height)
if key == 'gpu-id' :
tracker_gpu_id = config.getint('tracker', key)
tracker.set_property('gpu_id', tracker_gpu_id)
if key == 'll-lib-file' :
tracker_ll_lib_file = config.get('tracker', key)
tracker.set_property('ll-lib-file', tracker_ll_lib_file)
if key == 'll-config-file' :
tracker_ll_config_file = config.get('tracker', key)
tracker.set_property('ll-config-file', tracker_ll_config_file)
print("Creating nvdsanalytics")
nvanalytics = Gst.ElementFactory.make("nvdsanalytics", "analytics")
if not nvanalytics:
sys.stderr.write(" Unable to create nvanalytics \n")
nvanalytics.set_property("config-file", "config_nvdsanalytics.txt")
print("Creating nvvidconv")
nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
if not nvvidconv:
sys.stderr.write(" Unable to create nvvidconv \n")
print("Creating nvosd ")
nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
if not nvosd:
sys.stderr.write(" Unable to create nvosd \n")
nvosd.set_property('process-mode',OSD_PROCESS_MODE)
nvosd.set_property('display-text',OSD_DISPLAY_TEXT)
print("Creating nvstreamdemux")
nvstreamdemux = Gst.ElementFactory.make("nvstreamdemux", "nvstreamdemux")
if not nvstreamdemux:
sys.stderr.write(" Unable to create nvstreamdemux \n")
pipeline.add(pgie)
pipeline.add(tracker)
pipeline.add(nvanalytics)
pipeline.add(nvstreamdemux)
streammux.link(queue1)
queue1.link(pgie)
pgie.link(tracker)
tracker.link(nvanalytics)
nvanalytics.link(nvstreamdemux)
tee = Gst.ElementFactory.make("tee", "nvsink-tee")
if not tee:
sys.stderr.write(" Unable to create tee \n")
pipeline.add(tee)
queue_msg = Gst.ElementFactory.make("queue", "queue-msg")
pipeline.add(queue_msg)
nvanalytics.link(tee)
tee_msg_pad = tee.request_pad_simple('src_%u')
queue_msg_sink_pad = queue_msg.get_static_pad("sink")
tee_msg_pad.link(queue_msg_sink_pad)
queue_msg.link(msgconv)
msgconv.link(msgbroker)
for i in range(number_sources):
queue = make_element("queue", i)
pipeline.add(queue)
nvvideoconvert = make_element("nvvideoconvert", i)
pipeline.add(nvvideoconvert)
nvdsosd = make_element("nvdsosd", i)
pipeline.add(nvdsosd)
nvdsosd.set_property("process-mode", OSD_PROCESS_MODE)
nvdsosd.set_property("display-text", OSD_DISPLAY_TEXT)
padname = "src_%u" % i
demuxsrcpad = nvstreamdemux.request_pad_simple(padname)
if not demuxsrcpad:
sys.stderr.write("Unable to create demux src pad \n")
queuesinkpad = queue.get_static_pad("sink")
if not queuesinkpad:
sys.stderr.write("Unable to create queue sink pad \n")
demuxsrcpad.link(queuesinkpad)
queue10 = make_element("queue", f"queue10_{i}")
nvvidconv2 = make_element("nvvideoconvert", f"nvvideoconvert_{i}")
capsfilter = make_element("capsfilter", f"capsfilter_{i}")
caps = Gst.Caps.from_string("video/x-raw, format=I420")
capsfilter.set_property("caps", caps)
encoder = make_element("avenc_mpeg4", f"encode_{i}")
encoder.set_property("bitrate", 2000000)
codeparser = make_element("mpeg4videoparse", f"mpeg4-parser_{i}")
splitmuxsink = Gst.ElementFactory.make("splitmuxsink", f"splitmuxsink_{i}")
if not splitmuxsink:
sys.stderr.write("Unable to create splitmuxsink\n")
current_date = datetime.now().strftime("%Y-%m-%d")
splitmuxsink.connect("format-location", format_location_callback, video_dir_paths[i], i)
splitmuxsink.set_property("max-size-time", (no_min_to_write_video*60) * Gst.SECOND) # 1-minute file duration
muxer = Gst.ElementFactory.make("qtmux", "mp4mux")
splitmuxsink.set_property("muxer", muxer) # Assign the muxer to splitmuxsink
pipeline.add(queue10)
pipeline.add(nvvidconv2)
pipeline.add(capsfilter)
pipeline.add(encoder)
pipeline.add(codeparser)
pipeline.add(splitmuxsink)
queue.link(nvvideoconvert)
nvvideoconvert.link(nvdsosd)
nvdsosd.link(queue10)
queue10.link(nvvidconv2)
nvvidconv2.link(capsfilter)
capsfilter.link(encoder)
encoder.link(codeparser)
codeparser.link(splitmuxsink)
loop = GLib.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect ("message", bus_call, loop)
nvanalytics_src_pad=nvanalytics.get_static_pad("src")
if not nvanalytics_src_pad:
sys.stderr.write(" Unable to get src pad \n")
else:
nvanalytics_src_pad.add_probe(Gst.PadProbeType.BUFFER,
osd_sink_pad_buffer_probe, 0)
GLib.timeout_add(50000, perf_data.perf_print_callback)
print("Now playing...")
for i, source in enumerate(args):
if (i != 0):
print(i, ": ", source)
print("Starting pipeline \n")
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except:
pass
# cleanup
print("Exiting app\n")
pipeline.set_state(Gst.State.NULL)
if __name__ == '__main__':
args_streams = parse_args()
args_streams = ["file:///bi3-ds/deepstream_python_apps/apps/deepstream-nvdsanalytics/2024-09-27__15-09-59.mp4"]
sys.exit(main(args_streams))