Thanks for your fast reply. I use 4 rtsp 2560*1440 25fps sources.
I have the python code as follows. It is a strange problem because the same code sometimes works fine for up to 5 hours and then frozen. And then I killed the python program and restart the program, it become frozen immediately after the program started. When frozen, the usage of cpu, gpu, vic is very low seen from jtop.
Thanks for your help.
def main(sourceUrls=[]):
bitrate = 4000000
is_live = False
platform_info = PlatformInfo()
GObject.threads_init()
Gst.init(None)
# Create gstreamer elements
# Create Pipeline element that will form a connection of other elements
pipeline = Gst.Pipeline()
if not pipeline:
sys.stderr.write(" Unable to create Pipeline \n")
# Create nvstreammux instance to form batches from one or more sources.
streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
if not streammux:
sys.stderr.write(" Unable to create NvStreamMux \n")
streammux.set_property("batched-push-timeout",int(1000000/60))
pipeline.add(streammux)
number_sources = len(sourceUrls)
source_bins = []
uri_decode_bins = []
for i in range(number_sources):
sourceUrl = sourceUrls[i]
if sourceUrl.find("rtsp://") == 0:
is_live = True
source_bin,uri_decode_bin = create_source_bin(i,Gst, sourceUrl,outputPath)
source_bins.append(source_bin)
uri_decode_bins.append(uri_decode_bin)
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)
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")
queue8 = Gst.ElementFactory.make("queue", "queue8")
queue9 = Gst.ElementFactory.make("queue", "queue9")
queue10 = Gst.ElementFactory.make("queue", "queue10")
queue11 = Gst.ElementFactory.make("queue", "queue11")
pipeline.add(queue1)
pipeline.add(queue2)
pipeline.add(queue3)
pipeline.add(queue4)
pipeline.add(queue5)
pipeline.add(queue6)
pipeline.add(queue7)
pipeline.add(queue8)
pipeline.add(queue9)
pipeline.add(queue10)
pipeline.add(queue11)
# Use nvinfer to run inferencing on decoder's output,
# behaviour of inferencing is set through config file
pgie = Gst.ElementFactory.make("nvinfer", "primary-inference")
if not pgie:
sys.stderr.write(" Unable to create pgie \n")
tracker = Gst.ElementFactory.make("nvtracker", "tracker")
if not tracker:
sys.stderr.write(" Unable to create tracker \n")
sgie1 = Gst.ElementFactory.make("nvinfer", "secondary1-nvinference-engine")
if not sgie1:
sys.stderr.write(" Unable to make sgie1 \n")
caps1 = Gst.Caps.from_string("video/x-raw(memory:NVMM), format=RGBA")
filter1 = Gst.ElementFactory.make("capsfilter", "filter1")
if not filter1:
sys.stderr.write(" Unable to get the caps filter1 \n")
filter1.set_property("caps", caps1)
tilterRowNum = int((number_sources-1)/2)+1
tilterColNum = 2
print(tilterRowNum,tilterColNum)
if number_sources > 1:
tiler = Gst.ElementFactory.make("nvmultistreamtiler", "nvtiler")
if not tiler:
sys.stderr.write(" Unable to create tiler \n")
tiler.set_property("rows", tilterRowNum)
tiler.set_property("columns",tilterColNum)
tiler.set_property("width", tilterOutputWidth*tilterColNum)
tiler.set_property("height", tilterOutputHeight*tilterRowNum)
tiler.set_property("compute-hw", 1) #gpu 1, vic 2
pipeline.add(tiler)
nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
if not nvvidconv:
sys.stderr.write(" Unable to create nvvidconv \n")
# Create OSD to draw on the converted RGBA buffer
nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
if not nvosd:
sys.stderr.write(" Unable to create nvosd \n")
tee = Gst.ElementFactory.make("tee","tee")
if not tee:
sys.stderr.write(" Unable to create tee \n")
nvvidconv_postosd = Gst.ElementFactory.make("nvvideoconvert", "convertor_postosd")
if not nvvidconv_postosd:
sys.stderr.write(" Unable to create nvvidconv_postosd \n")
# Create a caps filter
caps = Gst.ElementFactory.make("capsfilter", "filter")
caps.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM), format=I420"))
encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder")
encoder.set_property('bitrate', rtspEncodeBitRate)
encoder.set_property('preset-level', 1)
encoder.set_property('insert-sps-pps', 1)
encoder.set_property("insert-vui",1)
rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")
updsink_port_num = 5400
sinkRtsp = Gst.ElementFactory.make("udpsink", "udpsink")
if not sinkRtsp:
sys.stderr.write(" Unable to create udpsink")
sinkRtsp.set_property('host', '192.168.25.100')
sinkRtsp.set_property('port', updsink_port_num)
sinkRtsp.set_property('async', True)
sinkRtsp.set_property('sync', 0)
nvvidconv1 = Gst.ElementFactory.make("nvvideoconvert", "convertor1")
if not nvvidconv1:
sys.stderr.write(" Unable to create nvvidconv1 \n")
# Finally render the osd output
sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
sink.set_property('async', 1)
sink.set_property('sync', 0)
tee2 = Gst.ElementFactory.make("tee","tee2")
if not tee2:
sys.stderr.write(" Unable to create tee2 \n")
h264parse = Gst.ElementFactory.make("h264parse", "h264-parse")
qtmux = Gst.ElementFactory.make("mp4mux", "qtmux")
fileSink = Gst.ElementFactory.make("filesink", "filesink")
fileSink.set_property("location",
f"{outputPath}/record_{datetime.datetime.now().strftime('%Y%m%d_%H:%M:%S')}.mp4")
fileSink.set_property("sync",0)
fileSink.set_property("async",1)
if is_live:
streammux.set_property('live-source', 1)
streammux.set_property('width', frameWidth)
streammux.set_property('height', frameHeight)
streammux.set_property('batch-size',number_sources )
streammux.set_property('batched-push-timeout', MUXER_BATCH_TIMEOUT_USEC)
# streammux.set_property('nvbuf-memory-type',0)
streammux.set_property('buffer-pool-size',100)
streammux.set_property('attach-sys-ts',1)
streammux.set_property('compute-hw',1) #gpu1,vic2
streammux.set_property('sync-inputs',0)
# Set properties of pgie and sgie
pgie.set_property('config-file-path', "./configFiles/config_jetson_infer_primary_yoloV8.txt")
sgie1.set_property('config-file-path',"./configFiles/config_jetson_infer_secondary_yoloV8_bib.txt")
# Set properties of tracker
config = configparser.ConfigParser()
config.read('./gtyStream/configFiles/dstest2_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)
tracker.set_property('user-meta-pool-size', 64)
nvosd.set_property('process-mode',0) # 0,cpu模式;1,gpu模式;2.vic模式
pipeline.add(pgie)
pipeline.add(tracker)
pipeline.add(sgie1)
pipeline.add(nvvidconv)
pipeline.add(filter1)
pipeline.add(nvvidconv1)
pipeline.add(nvosd)
pipeline.add(sink)
pipeline.add(tee)
pipeline.add(nvvidconv_postosd)
pipeline.add(caps)
pipeline.add(encoder)
pipeline.add(rtppay)
pipeline.add(sinkRtsp)
pipeline.add(tee2)
pipeline.add(h264parse)
pipeline.add(qtmux)
pipeline.add(fileSink)
streammux.link(queue1)
queue1.link(pgie)
pgie.link(queue2)
queue2.link(tracker)
tracker.link(sgie1)
sgie1.link(queue3)
queue3.link(nvvidconv1)
nvvidconv1.link(queue4)
queue4.link(filter1)
filter1.link(queue5)
if number_sources>1:
queue5.link(tiler)
tiler.link(nvvidconv)
else:
queue5.link(nvvidconv)
nvvidconv.link(queue6)
queue6.link(nvosd)
nvosd.link(queue7)
queue7.link(tee)
tee.link(queue8)
queue8.link(sink)
tee.link(queue9)
queue9.link(nvvidconv_postosd)
nvvidconv_postosd.link(caps)
caps.link(encoder)
encoder.link(tee2)
tee2.link(queue10)
queue10.link(rtppay)
rtppay.link(sinkRtsp)
tee2.link(queue11)
queue11.link(h264parse)
h264parse.link(qtmux)
qtmux.link(fileSink)
# create and event loop and feed gstreamer bus mesages to it
loop = GLib.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
# RTSP
rtsp_port_num = 8554
server = GstRtspServer.RTSPServer.new()
server.props.service = "%d" % rtsp_port_num
server.attach(None)
factory = GstRtspServer.RTSPMediaFactory.new()
factory.set_launch(
"( udpsrc name=pay0 port=%d buffer-size=524288 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)%s, payload=96 \" )" % (
updsink_port_num, "H264"))
factory.set_shared(True)
server.get_mount_points().add_factory("/"+rtspLinkFile, factory)
#nvvidconv1
nvvidconv1_sink_pad = nvvidconv1.get_static_pad("sink")
if not nvvidconv1_sink_pad:
sys.stderr.write(" Unable to get src pad \n")
else:
nvvidconv1_sink_pad.add_probe(Gst.PadProbeType.BUFFER, nvvidconv1_sink_pad_buffer_probe, gtyData)
if number_sources>1:
tiler_sink_pad = tiler.get_static_pad("sink")
else:
tiler_sink_pad = nvvidconv.get_static_pad("sink")
if not tiler_sink_pad:
sys.stderr.write(" Unable to get src pad \n")
else:
tiler_sink_pad.add_probe(Gst.PadProbeType.BUFFER, tiler_sink_pad_buffer_probe, gtyData)
osdsinkpad = nvosd.get_static_pad("sink")
if not osdsinkpad:
sys.stderr.write(" Unable to get sink pad of nvosd \n")
else:
osdsinkpad.add_probe(Gst.PadProbeType.BUFFER, osd_sink_pad_buffer_probe, gtyData)
Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, "pipeline")
# start play back and listed to events
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except KeyboardInterrupt:
print("keyboard interrupt received, shutting down")
for uri_decode_bin in uri_decode_bins:
uri_decode_bin.emit('stop-sr',0)
qtmux.send_event(Gst.Event.new_eos())
bus.timed_pop_filtered(Gst.SECOND*10, Gst.MessageType.EOS)
pipeline.set_state(Gst.State.NULL)
finally:
pipeline.set_state(Gst.State.NULL)
# cleanup
pipeline.set_state(Gst.State.NULL)