Hello, I’m trying to use NvDsUserMeta to pass some data to downstream elements. Following example app 4 from deepstream_python_apps I allocate NvDsEventMsgMeta in a pad probe on nvstreammux sink pad and put a string in one of its gchar* fields, otherAttrs to be specific. In another pad downstream (fakesink’s src pad) I read this data. This works fine with pipeline filesrc → h264parse → nvv4l2decoder → nvstreammux → fakesink. Environment is nvidia’s deepstream:4.0.2-19.12-devel container.
However, as I add elements to this pipeline I start getting segfaults. For example, here’s my code with queue added (filesrc → h264parse → nvv4l2decoder → nvstreammux → queue → fakesink):
import sys
import os
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstBase', '1.0')
from gi.repository import Gst, GObject, GstBase
syspath = os.getenv('PYDSBIDS_PATH', '.')
sys.path.append(os.path.join(syspath, 'x86_64'))
import pyds
def bus_call(bus, message, loop):
t = message.type
if t == Gst.MessageType.EOS:
Gst.info("End-of-stream")
loop.quit()
elif t == Gst.MessageType.WARNING:
err, debug = message.parse_warning()
Gst.warning("Warning: %s: %s" % (err, debug))
elif t == Gst.MessageType.ERROR:
err, debug = message.parse_error()
Gst.error("Error: %s: %s" % (err, debug))
loop.quit()
return True
def fill_user_meta(meta: pyds.NvDsUserMeta, msg: str):
data = pyds.alloc_nvds_event_msg_meta()
data.otherAttrs = msg
meta.user_meta_data = data
meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_EVENT_MSG_META
pyds.set_user_copyfunc(meta, meta_copy_callback)
pyds.set_user_releasefunc(meta, meta_free_callback)
def meta_copy_callback(data, user_data):
user_meta = pyds.glist_get_nvds_user_meta(data)
src_meta = pyds.glist_get_nvds_event_msg_meta(user_meta.user_meta_data)
dst_meta_ptr = pyds.memdup(pyds.get_ptr(src_meta), sys.getsizeof(pyds.NvDsEventMsgMeta))
dst_meta = pyds.glist_get_nvds_event_msg_meta(dst_meta_ptr)
dst_meta.otherAttrs = pyds.get_string(dst_meta.otherAttrs)
return dst_meta
def meta_free_callback(data, user_data):
user_meta = pyds.glist_get_nvds_user_meta(data)
src_meta = pyds.glist_get_nvds_event_msg_meta(user_meta.user_meta_data)
pyds.free_buffer(src_meta.otherAttrs)
def streammux_src_pad_buffer_probe(pad, info, u_data):
gst_buffer = info.get_buffer()
if not gst_buffer:
Gst.warning("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
pyds.nvds_acquire_meta_lock(batch_meta)
l_frame = batch_meta.frame_meta_list
while l_frame is not None:
try:
frame_meta = pyds.glist_get_nvds_frame_meta(l_frame.data)
except StopIteration:
continue
user_meta = pyds.nvds_acquire_user_meta_from_pool(batch_meta)
if user_meta:
Gst.info('adding user meta')
fill_user_meta(user_meta, 'test message')
pyds.nvds_add_user_meta_to_frame(frame_meta, user_meta)
else:
Gst.warning('failed to acquire user meta')
try:
l_frame = l_frame.next
except StopIteration:
break
pyds.nvds_release_meta_lock(batch_meta)
return Gst.PadProbeReturn.OK
def fakesink_sink_pad_buffer_probe(pad, info, u_data):
gst_buffer = info.get_buffer()
if not gst_buffer:
Gst.warning("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
pyds.nvds_acquire_meta_lock(batch_meta)
l_frame = batch_meta.frame_meta_list
while l_frame is not None:
try:
frame_meta = pyds.glist_get_nvds_frame_meta(l_frame.data)
except StopIteration:
continue
l_usr = frame_meta.frame_user_meta_list
while l_usr is not None:
try:
user_meta = pyds.glist_get_nvds_user_meta(l_usr.data)
except StopIteration:
continue
if user_meta.base_meta.meta_type == pyds.NVDS_EVENT_MSG_META:
event_msg_meta = pyds.glist_get_nvds_event_msg_meta(user_meta.user_meta_data)
Gst.info(f'event msg meta, otherAttrs = {pyds.get_string(event_msg_meta.otherAttrs)}')
try:
l_usr = l_usr.next
except StopIteration:
break
try:
l_frame = l_frame.next
except StopIteration:
break
pyds.nvds_release_meta_lock(batch_meta)
return Gst.PadProbeReturn.OK
def main():
GObject.threads_init()
Gst.init(None)
pipeline = Gst.Pipeline()
if not pipeline:
Gst.error(" Unable to create Pipeline")
source = Gst.ElementFactory.make("filesrc", "file-source")
if not source:
Gst.error(" Unable to create Source")
h264parser = Gst.ElementFactory.make("h264parse", "h264-parser")
if not h264parser:
Gst.error(" Unable to create h264 parser")
decoder = Gst.ElementFactory.make("nvv4l2decoder", "nvv4l2-decoder")
if not decoder:
Gst.error(" Unable to create Nvv4l2 Decoder")
streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
if not streammux:
Gst.error(" Unable to create NvStreamMux")
queue = Gst.ElementFactory.make("queue", "queue")
if not queue:
Gst.error(" Unable to create queue")
sink = Gst.ElementFactory.make("fakesink", "fakesink")
if not sink:
Gst.error(" Unable to create fakesink")
input_loc = '/root/deepstream_sdk/samples/streams/sample_720p.h264'
Gst.info("Playing file %s " % input_loc)
source.set_property('location', input_loc)
streammux.set_property('width', 1280)
streammux.set_property('height', 720)
streammux.set_property('batch-size', 1)
Gst.info("Adding elements to Pipeline")
pipeline.add(source)
pipeline.add(h264parser)
pipeline.add(decoder)
pipeline.add(streammux)
pipeline.add(queue)
pipeline.add(sink)
Gst.info("Linking elements in the Pipeline")
source.link(h264parser)
h264parser.link(decoder)
sinkpad = streammux.get_request_pad("sink_0")
if not sinkpad:
Gst.error(" Unable to get the sink pad of streammux")
srcpad = decoder.get_static_pad("src")
if not srcpad:
Gst.error(" Unable to get source pad of decoder(source)")
srcpad.link(sinkpad)
streammux.link(queue)
queue.link(sink)
loop = GObject.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_call, loop)
streammux_src_pad = streammux.get_static_pad('src')
if not streammux_src_pad:
Gst.error(" Unable to get sink pad of sink")
streammux_src_pad.add_probe(Gst.PadProbeType.BUFFER, streammux_src_pad_buffer_probe, 0)
fakesink_sink_pad = sink.get_static_pad('sink')
if not fakesink_sink_pad:
Gst.error(" Unable to get sink pad of sink")
fakesink_sink_pad.add_probe(Gst.PadProbeType.BUFFER, fakesink_sink_pad_buffer_probe, 0)
Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, 'graph')
Gst.info("Starting pipeline")
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except:
pass
# cleanup
pyds.unset_callback_funcs()
pipeline.set_state(Gst.State.NULL)
if __name__ == '__main__':
main()
This app gives following output:
root@WS066:/data# GST_DEBUG=python:4 python test_app.py
0:00:00.035147220 508 0x26d4190 INFO python test_app.py:171:main: Playing file /root/deepstream_sdk/samples/streams/sample_720p.h264
0:00:00.035220747 508 0x26d4190 INFO python test_app.py:178:main: Adding elements to Pipeline
0:00:00.035285339 508 0x26d4190 INFO python test_app.py:186:main: Linking elements in the Pipeline
0:00:00.036042708 508 0x26d4190 INFO python test_app.py:218:main: Starting pipeline
0:00:00.216177997 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.217436469 508 0x23cf400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.217970188 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.219190741 508 0x23cf400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.220552197 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.221502660 508 0x23cf400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.222127604 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.222816112 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.223647844 508 0x23cf400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.224177818 508 0x23cfcf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
Segmentation fault (core dumped)
Or, randomly:
root@WS066:/data# GST_DEBUG=python:4 python test_app.py
0:00:00.032427120 518 0x262e190 INFO python test_app.py:171:main: Playing file /root/deepstream_sdk/samples/streams/sample_720p.h264
0:00:00.032499476 518 0x262e190 INFO python test_app.py:178:main: Adding elements to Pipeline
0:00:00.032564069 518 0x262e190 INFO python test_app.py:186:main: Linking elements in the Pipeline
0:00:00.033343305 518 0x262e190 INFO python test_app.py:218:main: Starting pipeline
0:00:00.199216978 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.200024770 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.201412275 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.202080490 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.203387152 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.204006595 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.205162689 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.205830197 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.206770506 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.207630312 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.208503194 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.209196667 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
0:00:00.210111048 518 0x2329400 INFO python test_app.py:122:fakesink_sink_pad_buffer_probe: event msg meta, otherAttrs = test message
0:00:00.210710040 518 0x2329cf0 INFO python test_app.py:79:streammux_src_pad_buffer_probe: adding user meta
terminate called after throwing an instance of 'pybind11::error_already_set'
what(): TypeError: '' object is not callable
Aborted (core dumped)
As soon as I comment out adding NvDsEventMsgMeta to NvDsUserMeta:
...
# fill_user_meta(user_meta, 'test message')
...
app correctly reaches end of stream. I think there might be some problem with memory management of deepstream meta data. Perhaps my copy/release callback are incorrect, though as far as I can see they are similar to example.
Any advice?