Hi guys,I am trying add my custom data to NvDsObjectMeta.It is an angle of each detected object in each frame.With this opinion,I have seen some posts in the forum,and I see the code below:
void
add_meta_to_buffer (GstBuffer * buf, gchar * meta)
{
NvDsBatchMeta *batch_meta;
NvDsUserMeta *user_meta;
batch_meta = gst_buffer_get_nvds_batch_meta (buf);
user_meta = nvds_acquire_user_meta_from_pool (batch_meta);
if (user_meta) {
NvDsEventMsgMeta *msg_meta =
(NvDsEventMsgMeta *) g_malloc0 (sizeof (NvDsEventMsgMeta));
msg_meta->otherAttrs = meta;
msg_meta->objectId = g_strdup ("custom");
user_meta->user_meta_data = (void *) msg_meta;
user_meta->base_meta.batch_meta = batch_meta;
user_meta->base_meta.meta_type = NVDS_EVENT_MSG_META;
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc) custom_meta_copy_func;
user_meta->base_meta.release_func =
(NvDsMetaReleaseFunc) custom_meta_free_func;
nvds_add_user_meta_to_batch (batch_meta, user_meta);
}
}
The description is :
NvDsEventMsgMeta is a type of DeepStream user meta and there is a NvDsUserMetaList in the batch, frame and object levels of DeepStream metadata, so you can add message meta per-batch, per-frame, or per-object. We use it on the batch level adding a JSON as message meta
As you can see,it is on the batch level to add data.So what if it is on the object level?My initial opinion is :
for (NvDsMetaList * l_frame = batch_meta->frame_meta_list; l_frame != NULL;
l_frame = l_frame->next) {
NvDsFrameMeta *frame_meta = l_frame->data;
for (NvDsMetaList * l_obj = frame_meta->obj_meta_list; l_obj != NULL;
l_obj = l_obj->next) {
NvDsObjectMeta *obj = (NvDsObjectMeta *) l_obj->data;
user_meta = nvds_acquire_user_meta_from_pool (obj);
if (user_meta) {
NvDsEventMsgMeta *msg_meta =(NvDsEventMsgMeta *) g_malloc0 (sizeof (NvDsEventMsgMeta));
msg_meta->otherAttrs = meta;
msg_meta->objectId = g_strdup ("custom");
user_meta->user_meta_data = (void *) msg_meta;
user_meta->base_meta.batch_meta = batch_meta;
user_meta->base_meta.meta_type = NVDS_EVENT_MSG_META;
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc) custom_meta_copy_func;
user_meta->base_meta.release_func =(NvDsMetaReleaseFunc) custom_meta_free_func;
nvds_add_user_meta_to_batch (obj, user_meta);
}
So as you can see the only difference is to replace batch_meta to obj,namely the obj_meta.The angle will be the meta parameter in the above codes.I wonder if my opinion is practical
Yes, you are right.There are some code snippets in the sample application.
Such as the following code in /opt/nvidia/deepstream/deepstream/sources/gst-plugins/gst-nvtracker/nvtracker_proc.cpp
if (m_Config.outputConvexHull && pTrackedObj->convexHull.numPointsAllocated != 0)
{
NvDsUserMeta *user_meta = nvds_acquire_user_meta_from_pool (pBatchMeta);
NvDsObjConvexHull* pConvexHull = new NvDsObjConvexHull;
pConvexHull->list = new int [pTrackedObj->convexHull.numPointsAllocated * 2];
for (uint32_t i=0; i < pTrackedObj->convexHull.numPoints; i++)
{
pConvexHull->list[2*i] = (int) (pTrackedObj->convexHull.list[2*i] * scaleWidth);
pConvexHull->list[2*i+1] = (int) (pTrackedObj->convexHull.list[2*i+1] * scaleHeight);
}
pConvexHull->numPoints = pTrackedObj->convexHull.numPoints;
pConvexHull->numPointsAllocated = pTrackedObj->convexHull.numPointsAllocated;
user_meta->user_meta_data = (void *)pConvexHull;
user_meta->base_meta.meta_type = (NvDsMetaType) NVDS_OBJ_IMAGE_CONVEX_HULL;
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc) copy_nvtracker2_obj_convex_hull_meta;
user_meta->base_meta.release_func = (NvDsMetaReleaseFunc) free_nvtracker2_obj_convex_hull_meta;
nvds_add_user_meta_to_obj (pObjectMeta, user_meta);
}
Thanks,can I delete some lines of the codes I provide?For example:
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc) custom_meta_copy_func;
user_meta->base_meta.release_func =(NvDsMetaReleaseFunc) custom_meta_free_func;
Because I don’t define such custom function,if the two lines are deleted,any influence?
Beside, about this line:
user_meta->base_meta.batch_meta = batch_meta;
Is it necessary to replace the batch_meta to obj?
No, this code must be exist. These callbacks will be called when meta data is copied or released between elements.
Please refer to the example above
Thanks,could you please give me some code snippet about these callbacks?
Besides,according to your codes,this line:
user_meta->base_meta.batch_meta = batch_meta;
seems to be unnecessary?I don’t see similar code in your codes
This depends on how you use it.
If you want to find the corresponding batchmeta when accessing objmeta
, this is necessary.
Otherwise, it is not necessary.
Thanks,could you please give me some code snippet about these callbacks?namely the :
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc) custom_meta_copy_func;
user_meta->base_meta.release_func =(NvDsMetaReleaseFunc) custom_meta_free_func;
custom_meta_copy_func
and custom_meta_free_func
.I don’t know how they are defined.
1229304629:
copy_func
You can refer to /opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-user-metadata-test/deepstream_user_metadata_app.c
. Here is code snippet.
static gpointer copy_user_meta(gpointer data, gpointer user_data)
{
NvDsUserMeta *user_meta = (NvDsUserMeta *)data;
gchar *src_user_metadata = (gchar*)user_meta->user_meta_data;
gchar *dst_user_metadata = (gchar*)g_malloc0(USER_ARRAY_SIZE);
memcpy(dst_user_metadata, src_user_metadata, USER_ARRAY_SIZE);
return (gpointer)dst_user_metadata;
}
/* release function set by user. "data" holds a pointer to NvDsUserMeta*/
static void release_user_meta(gpointer data, gpointer user_data)
{
NvDsUserMeta *user_meta = (NvDsUserMeta *) data;
if(user_meta->user_meta_data) {
g_free(user_meta->user_meta_data);
user_meta->user_meta_data = NULL;
}
}
This is another sample.
ds_joints->joints[i].confidence = keypoints_confidence[i];
ds_joints->joints[i].x = p3dLifted[i].x;
ds_joints->joints[i].y = p3dLifted[i].y;
ds_joints->joints[i].z = p3dLifted[i].z;
//g_print("%d point [%f, %f, %f]\n", i, p3dLifted[i].x, p3dLifted[i].y, p3dLifted[i].z);
}
user_meta->user_meta_data = ds_joints;
user_meta->base_meta.meta_type = (NvDsMetaType) NVDS_OBJ_META;
user_meta->base_meta.release_func = release_bodypose_meta;
user_meta->base_meta.copy_func = copy_bodypose_meta;
nvds_add_user_meta_to_obj (obj_meta, user_meta);
}
}
}
/** Function to get the absolute path of a file.*/
gboolean
get_absolute_file_path_yaml (
const gchar * cfg_file_path, const gchar * file_path,
char *abs_path_str)
{