deepstream-queue.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. # Import required libraries
  2. import sys
  3. sys.path.append('../')
  4. sys.path.append('../source_code')
  5. import gi
  6. import configparser
  7. gi.require_version('Gst', '1.0')
  8. from gi.repository import GObject, Gst
  9. from gi.repository import GLib
  10. from ctypes import *
  11. import time
  12. import sys
  13. import math
  14. import platform
  15. from common.bus_call import bus_call
  16. from common.FPS import GETFPS
  17. import pyds
  18. # Define variables to be used later
  19. fps_streams={}
  20. PGIE_CLASS_ID_VEHICLE = 0
  21. PGIE_CLASS_ID_BICYCLE = 1
  22. PGIE_CLASS_ID_PERSON = 2
  23. PGIE_CLASS_ID_ROADSIGN = 3
  24. MUXER_OUTPUT_WIDTH=1920
  25. MUXER_OUTPUT_HEIGHT=1080
  26. TILED_OUTPUT_WIDTH=1920
  27. TILED_OUTPUT_HEIGHT=1080
  28. OSD_PROCESS_MODE= 0
  29. OSD_DISPLAY_TEXT= 0
  30. pgie_classes_str= ["Vehicle", "TwoWheeler", "Person","RoadSign"]
  31. ################ Three Stream Pipeline ###########
  32. # Define Input and output Stream information
  33. num_sources = 3
  34. INPUT_VIDEO_1 = '/opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_720p.h264'
  35. INPUT_VIDEO_2 = '/opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_720p.h264'
  36. INPUT_VIDEO_3 = '/opt/nvidia/deepstream/deepstream-5.0/samples/streams/sample_720p.h264'
  37. # Define variables to be used later
  38. fps_streams={}
  39. # Initialise FPS
  40. for i in range(0,num_sources):
  41. fps_streams["stream{0}".format(i)]=GETFPS(i)
  42. # Standard GStreamer initialization
  43. Gst.init(None)
  44. # Create gstreamer elements */
  45. # Create Pipeline element that will form a connection of other elements
  46. print("Creating Pipeline \n ")
  47. pipeline = Gst.Pipeline()
  48. if not pipeline:
  49. sys.stderr.write(" Unable to create Pipeline \n")
  50. ## Make Element or Print Error and any other detail
  51. def make_elm_or_print_err(factoryname, name, printedname, detail=""):
  52. print("Creating", printedname)
  53. elm = Gst.ElementFactory.make(factoryname, name)
  54. if not elm:
  55. sys.stderr.write("Unable to create " + printedname + " \n")
  56. if detail:
  57. sys.stderr.write(detail)
  58. return elm
  59. # src_pad_buffer_probe
  60. def src_pad_buffer_probe(pad,info,u_data):
  61. #Intiallizing object counter with 0.
  62. obj_counter = {
  63. PGIE_CLASS_ID_VEHICLE:0,
  64. PGIE_CLASS_ID_PERSON:0,
  65. PGIE_CLASS_ID_BICYCLE:0,
  66. PGIE_CLASS_ID_ROADSIGN:0
  67. }
  68. # Set frame_number & rectangles to draw as 0
  69. frame_number=0
  70. num_rects=0
  71. gst_buffer = info.get_buffer()
  72. if not gst_buffer:
  73. print("Unable to get GstBuffer ")
  74. return
  75. # Retrieve batch metadata from the gst_buffer
  76. # Note that pyds.gst_buffer_get_nvds_batch_meta() expects the
  77. # C address of gst_buffer as input, which is obtained with hash(gst_buffer)
  78. batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
  79. l_frame = batch_meta.frame_meta_list
  80. while l_frame is not None:
  81. try:
  82. # Note that l_frame.data needs a cast to pyds.NvDsFrameMeta
  83. frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
  84. except StopIteration:
  85. break
  86. # Get frame number , number of rectables to draw and object metadata
  87. frame_number=frame_meta.frame_num
  88. num_rects = frame_meta.num_obj_meta
  89. l_obj=frame_meta.obj_meta_list
  90. while l_obj is not None:
  91. try:
  92. # Casting l_obj.data to pyds.NvDsObjectMeta
  93. obj_meta=pyds.NvDsObjectMeta.cast(l_obj.data)
  94. except StopIteration:
  95. break
  96. # Increment Object class by 1
  97. obj_counter[obj_meta.class_id] += 1
  98. try:
  99. l_obj=l_obj.next
  100. except StopIteration:
  101. break
  102. print("Frame Number={} Number of Objects={} Vehicle_count={} Person_count={}".format(frame_number, num_rects, obj_counter[PGIE_CLASS_ID_VEHICLE], obj_counter[PGIE_CLASS_ID_PERSON]))
  103. # FPS Probe
  104. fps_streams["stream{0}".format(frame_meta.pad_index)].get_fps()
  105. try:
  106. l_frame=l_frame.next
  107. except StopIteration:
  108. break
  109. return Gst.PadProbeReturn.OK
  110. ########### Create Elements required for the Pipeline ###########
  111. ######### Defining Stream 1
  112. # Source element for reading from the file
  113. source1 = make_elm_or_print_err("filesrc", "file-source-1",'file-source-1')
  114. # Since the data format in the input file is elementary h264 stream,we need a h264parser
  115. h264parser1 = make_elm_or_print_err("h264parse", "h264-parser-1","h264-parser-1")
  116. # Use nvdec_h264 for hardware accelerated decode on GPU
  117. decoder1 = make_elm_or_print_err("nvv4l2decoder", "nvv4l2-decoder-1","nvv4l2-decoder-1")
  118. ##########
  119. ########## Defining Stream 2
  120. # Source element for reading from the file
  121. source2 = make_elm_or_print_err("filesrc", "file-source-2","file-source-2")
  122. # Since the data format in the input file is elementary h264 stream, we need a h264parser
  123. h264parser2 = make_elm_or_print_err("h264parse", "h264-parser-2", "h264-parser-2")
  124. # Use nvdec_h264 for hardware accelerated decode on GPU
  125. decoder2 = make_elm_or_print_err("nvv4l2decoder", "nvv4l2-decoder-2","nvv4l2-decoder-2")
  126. ###########
  127. ########## Defining Stream 3
  128. # Source element for reading from the file
  129. source3 = make_elm_or_print_err("filesrc", "file-source-3","file-source-3")
  130. # Since the data format in the input file is elementary h264 stream, we need a h264parser
  131. h264parser3 = make_elm_or_print_err("h264parse", "h264-parser-3", "h264-parser-3")
  132. # Use nvdec_h264 for hardware accelerated decode on GPU
  133. decoder3 = make_elm_or_print_err("nvv4l2decoder", "nvv4l2-decoder-3","nvv4l2-decoder-3")
  134. ###########
  135. # Create nvstreammux instance to form batches from one or more sources.
  136. streammux = make_elm_or_print_err("nvstreammux", "Stream-muxer","Stream-muxer")
  137. # Use nvinfer to run inferencing on decoder's output, behaviour of inferencing is set through config file
  138. pgie = make_elm_or_print_err("nvinfer", "primary-inference" ,"pgie")
  139. # Use nvtracker to give objects unique-ids
  140. tracker = make_elm_or_print_err("nvtracker", "tracker",'tracker')
  141. # Seconday inference for Finding Car Color
  142. sgie1 = make_elm_or_print_err("nvinfer", "secondary1-nvinference-engine",'sgie1')
  143. # Seconday inference for Finding Car Make
  144. sgie2 = make_elm_or_print_err("nvinfer", "secondary2-nvinference-engine",'sgie2')
  145. # # Seconday inference for Finding Car Type
  146. sgie3 = make_elm_or_print_err("nvinfer", "secondary3-nvinference-engine",'sgie3')
  147. # Create Sink for storing the output
  148. fakesink = make_elm_or_print_err("fakesink", "fakesink", "Sink")
  149. # Queues to enable buffering
  150. queue1=make_elm_or_print_err("queue","queue1","queue1")
  151. queue2=make_elm_or_print_err("queue","queue2","queue2")
  152. queue3=make_elm_or_print_err("queue","queue3","queue3")
  153. queue4=make_elm_or_print_err("queue","queue4","queue4")
  154. queue5=make_elm_or_print_err("queue","queue5","queue5")
  155. queue6=make_elm_or_print_err("queue","queue6","queue6")
  156. ############ Set properties for the Elements ############
  157. # Set Input Video files
  158. source1.set_property('location', INPUT_VIDEO_1)
  159. source2.set_property('location', INPUT_VIDEO_2)
  160. source3.set_property('location', INPUT_VIDEO_3)
  161. # Set Input Width , Height and Batch Size
  162. streammux.set_property('width', 1920)
  163. streammux.set_property('height', 1080)
  164. streammux.set_property('batch-size', 1)
  165. # Timeout in microseconds to wait after the first buffer is available
  166. # to push the batch even if a complete batch is not formed.
  167. streammux.set_property('batched-push-timeout', 4000000)
  168. # Set configuration file for nvinfer
  169. # Set Congifuration file for nvinfer
  170. pgie.set_property('config-file-path', "../source_code/N1/dstest4_pgie_config.txt")
  171. sgie1.set_property('config-file-path', "../source_code/N1/dstest4_sgie1_config.txt")
  172. sgie2.set_property('config-file-path', "../source_code/N1/dstest4_sgie2_config.txt")
  173. sgie3.set_property('config-file-path', "../source_code/N1/dstest4_sgie3_config.txt")
  174. #Set properties of tracker from tracker_config
  175. config = configparser.ConfigParser()
  176. config.read('../source_code/N1/dstest4_tracker_config.txt')
  177. config.sections()
  178. for key in config['tracker']:
  179. if key == 'tracker-width' :
  180. tracker_width = config.getint('tracker', key)
  181. tracker.set_property('tracker-width', tracker_width)
  182. if key == 'tracker-height' :
  183. tracker_height = config.getint('tracker', key)
  184. tracker.set_property('tracker-height', tracker_height)
  185. if key == 'gpu-id' :
  186. tracker_gpu_id = config.getint('tracker', key)
  187. tracker.set_property('gpu_id', tracker_gpu_id)
  188. if key == 'll-lib-file' :
  189. tracker_ll_lib_file = config.get('tracker', key)
  190. tracker.set_property('ll-lib-file', tracker_ll_lib_file)
  191. if key == 'll-config-file' :
  192. tracker_ll_config_file = config.get('tracker', key)
  193. tracker.set_property('ll-config-file', tracker_ll_config_file)
  194. if key == 'enable-batch-process' :
  195. tracker_enable_batch_process = config.getint('tracker', key)
  196. tracker.set_property('enable_batch_process', tracker_enable_batch_process)
  197. # Fake sink properties
  198. fakesink.set_property("sync", 0)
  199. fakesink.set_property("async", 0)
  200. ########## Add and Link ELements in the Pipeline ##########
  201. print("Adding elements to Pipeline \n")
  202. pipeline.add(source1)
  203. pipeline.add(h264parser1)
  204. pipeline.add(decoder1)
  205. pipeline.add(source2)
  206. pipeline.add(h264parser2)
  207. pipeline.add(decoder2)
  208. pipeline.add(source3)
  209. pipeline.add(h264parser3)
  210. pipeline.add(decoder3)
  211. pipeline.add(streammux)
  212. pipeline.add(queue1)
  213. pipeline.add(pgie)
  214. pipeline.add(queue2)
  215. pipeline.add(tracker)
  216. pipeline.add(queue3)
  217. pipeline.add(sgie1)
  218. pipeline.add(queue4)
  219. pipeline.add(sgie2)
  220. pipeline.add(queue5)
  221. pipeline.add(sgie3)
  222. pipeline.add(queue6)
  223. pipeline.add(fakesink)
  224. print("Linking elements in the Pipeline \n")
  225. source1.link(h264parser1)
  226. h264parser1.link(decoder1)
  227. ###### Create Sink pad and connect to decoder's source pad
  228. sinkpad1 = streammux.get_request_pad("sink_0")
  229. if not sinkpad1:
  230. sys.stderr.write(" Unable to get the sink pad of streammux \n")
  231. srcpad1 = decoder1.get_static_pad("src")
  232. if not srcpad1:
  233. sys.stderr.write(" Unable to get source pad of decoder \n")
  234. srcpad1.link(sinkpad1)
  235. ######
  236. ###### Create Sink pad and connect to decoder's source pad
  237. source2.link(h264parser2)
  238. h264parser2.link(decoder2)
  239. sinkpad2 = streammux.get_request_pad("sink_1")
  240. if not sinkpad2:
  241. sys.stderr.write(" Unable to get the sink pad of streammux \n")
  242. srcpad2 = decoder2.get_static_pad("src")
  243. if not srcpad2:
  244. sys.stderr.write(" Unable to get source pad of decoder \n")
  245. srcpad2.link(sinkpad2)
  246. ######
  247. ###### Create Sink pad and connect to decoder's source pad
  248. source3.link(h264parser3)
  249. h264parser3.link(decoder3)
  250. sinkpad3 = streammux.get_request_pad("sink_2")
  251. if not sinkpad2:
  252. sys.stderr.write(" Unable to get the sink pad of streammux \n")
  253. srcpad3 = decoder3.get_static_pad("src")
  254. if not srcpad3:
  255. sys.stderr.write(" Unable to get source pad of decoder \n")
  256. srcpad3.link(sinkpad3)
  257. ######
  258. streammux.link(pgie)
  259. # queue1.link(pgie)
  260. pgie.link(tracker)
  261. tracker.link(sgie1)
  262. # queue3.link(sgie1)
  263. sgie1.link(sgie2)
  264. # queue4.link(sgie2)
  265. sgie2.link(sgie3)
  266. # queue5.link(sgie3)
  267. sgie3.link(fakesink)
  268. # queue6.link(fakesink)
  269. # create an event loop and feed gstreamer bus mesages to it
  270. loop = GLib.MainLoop()
  271. bus = pipeline.get_bus()
  272. bus.add_signal_watch()
  273. bus.connect ("message", bus_call, loop)
  274. print("Added and Linked elements to pipeline")
  275. src_pad=sgie3.get_static_pad("src")
  276. if not src_pad:
  277. sys.stderr.write(" Unable to get src pad \n")
  278. else:
  279. src_pad.add_probe(Gst.PadProbeType.BUFFER, src_pad_buffer_probe, 0)
  280. # List the sources
  281. print("Now playing...")
  282. print("Starting pipeline \n")
  283. # start play back and listed to events
  284. pipeline.set_state(Gst.State.PLAYING)
  285. start_time = time.time()
  286. try:
  287. loop.run()
  288. except:
  289. pass
  290. # cleanup
  291. print("Exiting app\n")
  292. pipeline.set_state(Gst.State.NULL)
  293. print("--- %s seconds ---" % (time.time() - start_time))