Errors when attaching multiple NvDsUserMeta objects to frame with Python SDK

Hi

I am seeing some different errors when I try to attach multiple NvDsUserMeta objects to the frame_meta. Some of the c errors are:

  • double free or corruption (fasttop) \n Aborted (core dumped)
  • Segmentation Fault (core dumped)

and some times I experience a error in the meta_copy_func callback:

 terminate called after throwing an instance of 'pybind11::error_already_set'
  what():  AttributeError: 'NoneType' object has no attribute 'ts'

At:
  iva_app.py(289): meta_copy_func

Aborted (core dumped)

They most often occur when I have more than one rtsp source in my gstreamer pipeline. I have not experienced the same errors yet when running with only one source.

My code:
In the probe callback

## Create user_event
                msg_meta=pyds.alloc_nvds_event_msg_meta()
                #msg_meta.frameId = frame_meta.frame_num
                #msg_meta.trackingId = msg_json['object_id']
                #msg_meta.confidence = msg_json['confidence']
                msg_meta = generate_event_msg_meta(msg_meta, msg_json,frame_meta)
                user_event_meta = pyds.nvds_acquire_user_meta_from_pool(batch_meta)                                
                if(user_event_meta):
                    user_event_meta.user_meta_data = msg_meta
                    user_event_meta.base_meta.meta_type = pyds.NvDsMetaType.NVDS_EVENT_MSG_META
                    
                    # Setting callbacks in the event msg meta. The bindings layer
                    # will wrap these callables in C functions. Currently only one
                    # set of callbacks is supported.
                    pyds.set_user_copyfunc(user_event_meta, meta_copy_func)
                    pyds.set_user_releasefunc(user_event_meta, meta_free_func)
                    pyds.nvds_add_user_meta_to_frame(frame_meta, user_event_meta)
                else:
                    print("Error in attaching event meta to buffer\n")

The generate message meta function

def generate_event_msg_meta(meta, msg_json, frame_meta):
    #meta=pyds.NvDsEventMsgMeta.cast(data)
    meta.frameId = frame_meta.frame_num
    meta.trackingId = msg_json['object_id']
    meta.confidence = msg_json['confidence']
    meta.sensorId = frame_meta.pad_index
    meta.placeId = frame_meta.pad_index
    meta.moduleId = 0 # Can be used for analytics configudation in msgconv
    meta.otherAttrs = msg_json['direction']
    meta.sensorStr =  msg_json['linecrossings']
    meta.type = pyds.NvDsEventType.NVDS_EVENT_EXIT
    meta.ts = pyds.alloc_buffer(MAX_TIME_STAMP_LEN + 1)
    pyds.generate_ts_rfc3339(meta.ts, MAX_TIME_STAMP_LEN)

    ## Object specific data
    meta.objectId = msg_json['object_type']
    
    if msg_json['object_type']== 'person':
        meta.objType = pyds.NvDsObjectType.NVDS_OBJECT_TYPE_PERSON
    else:
        meta.objType = pyds.NvDsObjectType.NVDS_OBJECT_TYPE_VEHICLE

    ### Just in case
    meta.objClassId = 0

    return meta

The copy function:

def meta_copy_func(data,user_data):
        # Cast data to pyds.NvDsUserMeta
    user_meta=pyds.NvDsUserMeta.cast(data)
    src_meta_data=user_meta.user_meta_data
    # Cast src_meta_data to pyds.NvDsEventMsgMeta
    srcmeta=pyds.NvDsEventMsgMeta.cast(src_meta_data)
    # Duplicate the memory contents of srcmeta to dstmeta
    # First use pyds.get_ptr() to get the C address of srcmeta, then
    # use pyds.memdup() to allocate dstmeta and copy srcmeta into it.
    # pyds.memdup returns C address of the allocated duplicate.
    dstmeta_ptr=pyds.memdup(pyds.get_ptr(srcmeta), sys.getsizeof(pyds.NvDsEventMsgMeta))
    # Cast the duplicated memory to pyds.NvDsEventMsgMeta
    dstmeta=pyds.NvDsEventMsgMeta.cast(dstmeta_ptr)

    # Duplicate contents of ts field. Note that reading srcmeat.ts
    # returns its C address. This allows to memory operations to be
    # performed on it.
    dstmeta.ts=pyds.memdup(srcmeta.ts, MAX_TIME_STAMP_LEN+1)

    # Copy the sensorStr. This field is a string property.
    # The getter (read) returns its C address. The setter (write)
    # takes string as input, allocates a string buffer and copies
    # the input string into it.
    # pyds.get_string() takes C address of a string and returns
    # the reference to a string object and the assignment inside the binder copies content.
    dstmeta.sensorStr=pyds.get_string(srcmeta.sensorStr)
    dstmeta.otherAttrs=pyds.get_string(srcmeta.otherAttrs)
    dstmeta.objectId=pyds.get_string(srcmeta.objectId)

    return dstmeta

The release function

def meta_free_func(data,user_data):
    user_meta=pyds.NvDsUserMeta.cast(data)
    srcmeta=pyds.NvDsEventMsgMeta.cast(user_meta.user_meta_data)

    # pyds.free_buffer takes C address of a buffer and frees the memory
    # It's a NOP if the address is NULL
    pyds.free_buffer(srcmeta.ts)
    pyds.free_buffer(srcmeta.sensorStr)
    pyds.free_buffer(srcmeta.otherAttrs)
    pyds.free_buffer(srcmeta.objectId)

Is there that one should handle multiple NvDsUserMeta when more than one object is generated in a single batch?

**• Jetson Xavier NX **
• Deepstream 5.0
• JetPack 4.4
• TensorRT 7.1.0

I also did some costumization to the nvmsgconv file. I have attached it here.

Best,
Niels

nvmsgconv.cpp (26.9 KB)

What will happen if you replace the inputs with two or more local video files?

I just ran a test and I do not see the errors when running multiple .mp4 files instead of multiple live rtsp streams.

I just tried again with multiple rtsp sources on a jetson nano. And I do not see the error there anymore either…

Could there be a device difference between Jetson Xavier NX and jetson nano somehow?

There is no update from you for a period, assuming this is not an issue any more.
Hence we are closing this topic. If need further support, please open a new one.
Thanks

They are different devices. Does this problem happen with Nano or NX? Is there method to reproduce the problem constantly?