Hello,
I am using DeepStream 6.0.1 (official container) and the Python API on a Tesla T4. Recently, I introduced some code to support different secondary models on different cameras (as explained below). After this modification, my code started to show some “Python 3 Core dumped” errors without any further explanation. The application usually runs for at least a few minutes / hours and then it crashes.
Below, I am going to explain what I added to the code in order to support multiple cameras. Before this modification, I didn’t have any error.
Suppose I am processing 2 cameras. Both cameras needs to be processed by the same pgie
but:
-
camera1
needs to runsgie1
-
camera2
needs to runsgie2
Here’s what I have done: I set both sgie1
and sgie2
to run on the pgie
by setting gie-unique-id=1
for pgie and operate-on-gie-id=1
for sgie1
and sgie2
. Then, I use some Gstreamer identify
elements to change the pgie
of each object before and after sgie1
and sgie2
so that the secondary models will run only on the desired objects.
More specifically:
- Before and after every secondary model, I added a GStreamer
identity
element with a probe. So the pipeline looks like this:... -> nvstreammux -> pgie -> pre_sgie1_identity -> sgie1 -> post_sgie1_identity -> pre_sgie2_identity -> sgie2 -> post_sgie2_identity
- In the probe of
pre_sgie1_identity
I set thepgie
of each object related tocamera2
toobj_meta.unique_component_id=-1
so thatsgie1
won’t run on objects fromcamera2
- In the probe of
pre_sgie2_identity
I set thepgie
of each object related tocamera1
toobj_meta.unique_component_id=-1
so thatsgie2
won’t run on objects fromcamera1
- In the probes of
post_sgie1_identity
andpost_sgie2_identity
I set all theobj_meta.unique_component_id
of every object (all cameras) toobj_meta.unique_component_id=1
to “reset” the status of the data
Here’s the probe that I use:
def _identity_src_buffer_probe(self, pad, info, u_data):
gst_buffer = info.get_buffer()
if not gst_buffer:
logger.error("Unable to get GstBuffer ")
return
# 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))
# Acquire lock
pyds.nvds_acquire_meta_lock(batch_meta)
# Get frame list
l_frame = batch_meta.frame_meta_list
batch_index = 0
while l_frame is not None:
# logger.info("Batch index", batch_index)
batch_index += 1
try:
# Note that l_frame.data needs a cast to pyds.NvDsFrameMeta
# 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)
except StopIteration:
break
# Get pgie_id
pgie_id = ......... # function to get the id of the pgie, it can return either 1 or -1
# Iterate over objects
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)
except StopIteration:
break
# Change ID of the primary model
obj_meta.unique_component_id = pgie_id
try:
l_obj = l_obj.next
except StopIteration:
break
try:
l_frame = l_frame.next
except StopIteration:
break
# Release lock
pyds.nvds_release_meta_lock(batch_meta)
return Gst.PadProbeReturn.OK
As explained above, after introducing the identity
elements and their probes, I see some Python 3 Core dumped
error. I am assuming this is happening because the probe access the metadata and maybe, after thousands / millions of execution, an edge case is found which falls into a bug. It might not be the case, but I wanted to ask you if you think that the code above is correct from a theoretical standpoint.
I also realized that I don’t know if and when nvds_acquire_meta_lock
is needed. I thought it would create a lock to prevent two parts of code to access the same metadata. However the following code can acquire two locks on the same NvDsBatchMeta
instance:
import pyds
batch_meta = pyds.nvds_create_batch_meta(max_batch_size=16)
pyds.nvds_acquire_meta_lock(batch_meta)
print('acquiring lock 1')
pyds.nvds_acquire_meta_lock(batch_meta)
print('acquiring lock 2')
This code will print both “acquiring lock 1” and “acquiring lock 2”. Is this expected (the reason being that both calls of nvds_acquire_meta_lock
origins from the same thread)? Am I using it correctly in the code above? The documentation only says that it is a lock to be acquired before updating metadata
. However, it does not seem to lock anything.
As always, thank you for your help!