1 Basic Metadata Structures
1.1 基础的元数据结构体
Gst Buffer是GStreamer中数据传输的基本单位。每个Gst Buffer都有关联的元数据。DeepStream SDK附加了DeepStream元数据对象NvDsBatchMeta,如下所述。要了解更多关于Gst Buffer的信息,请参阅GStreamer文档。
DeepStreamDeepStream为元数据使用了可扩展的标准结构。基本的元数据结构NvDsBatchMeta从批处理级元数据开始,它是在Gst-nvstreammux插件中创建的。附属元数据结构保存有frame、object、classifier和label数据。DeepStream还提供了一种在batch、frame或object级别添加用户特定元数据的机制。DeepStream通过附加NvDsBatchMeta结构和设置GstNvDsMetaType来将元数据附加到Gst缓冲区。在Gst-nvstreammux插件中的meta_type为NVDS_BATCH_GST_META。当应用程序处理Gst Buffer时,它可以遍历附加的元数据来找到NVDS_BATCH_GST_META。函数gst_buffer_get_nvds_batch_meta()从Gst缓冲区中提取NvDsBatchMeta。(参见sources/include/gstnvdsmeta.h中的声明。)有关此函数的使用示例,请参阅deepstream-test1示例应用程序。更多详细信息,请参阅DeepStream API指南中的DeepStream SDK API参考文档。
1.2 在NvDsBatchMeta中添加用户/自定义元数据
要在NvDsBatchMeta中以批处理、帧或对象级别附加用户特定的元数据,你必须通过调用nvds_acquire_user_meta_from_pool()从用户元数据池中获取一个NvDsUserMeta实例。(详情请参见sources/includes/nvdsmeta.h。)然后必须初始化NvDsUserMeta。必须设置的成员是user_meta_data、meta_type、copy_func和release_func。有关更多详细信息,请参见sources/apps/sample_apps/deepstream-user-metadata-test/deepstream_user_metadata_app.c中的示例应用程序源代码。
1.3 从Gst-nvstreammux上游在Gst插件中添加自定义元数据
暂时保留
2 nvdsmeta.h 基本结构
2.1 typedef GList
因为输入流N个、一帧里检测到的对象、用户数据、display、标签信息等都是N个的原因,使用了GList列表。
typedef struct _GList GList;
struct _GList
{
gpointer data;
GList *next;
GList *prev;
};
/* NvDsFrameMetaList *list;
* NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data); */
typedef GList NvDsFrameMetaList;
/* NvDsUserMeta */
typedef GList NvDsUserMetaList;
/* NvDsObjectMeta */
typedef GList NvDsObjectMetaList;
/* NvDisplayMeta */
typedef GList NvDisplayMetaList;
/* NvDsClassifierMeta */
typedef GList NvDsClassifierMetaList;
/* NvDsLabelInfo */
typedef GList NvDsLabelInfoList;
typedef GList NvDsMetaList;
2.2 NvDsBaseMeta
NvDsBaseMeta是DeepStream SDK中所有元数据对象的基类。它定义了元数据对象的基本属性和方法,是其他各种类型的元数据对象的基础。
在DeepStream SDK中,元数据是以NvDsMeta对象的形式存在的。NvDsMeta对象包含了描述特定对象的信息,例如目标检测结果、分类结果、属性等。NvDsBaseMeta类是所有NvDsMeta对象的基类,它包含了一些通用的属性和方法
/**
* Holds information about base metadata of a given metadata type.
*/
typedef struct _NvDsBaseMeta {
/** Holds a pointer to batch_meta @ref NvDsBatchMeta. */
struct _NvDsBatchMeta *batch_meta;
/** Holds the metadata type of this metadata element. */
NvDsMetaType meta_type;
/** Holds a pointer to a user context. */
void * uContext;
/** Holds a user-defined copy function. The function is called to copy
or transform metadata from one buffer to another. @a meta_data and
@a user_data are passed as arguments. */
NvDsMetaCopyFunc copy_func;
/** Holds a user-defined release function. The function is called
when @a meta_data is to be released. */
NvDsMetaReleaseFunc release_func;
} NvDsBaseMeta;
2.3 NvDsMetaPool
元数据是以NvDsMeta对象的形式存在的,每个NvDsMeta对象包含了描述特定对象的信息,例如目标检测结果、分类结果、属性等。
NvDsMetaPool维护着一个可用的NvDsMeta对象池,它可以避免频繁的内存分配和释放(避免内存碎片),从而提高系统的性能和稳定性。当需要创建新的NvDsMeta对象时,可以通过NvDsMetaPool来分配内存,而不是通过常规的内存分配方式(如malloc函数)。
typedef struct _NvDsMetaPool {
NvDsMetaType meta_type;
guint max_elements_in_pool;
guint element_size;
guint num_empty_elements;
guint num_full_elements;
NvDsMetaList * empty_list;
NvDsMetaList * full_list;
NvDsMetaCopyFunc copy_func;
NvDsMetaReleaseFunc release_func;
}NvDsMetaPool;
GstPadProbeReturn
osd_sink_pad_buffer_probe (GstPad * pad,
GstPadProbeInfo * info,
gpointer u_data) {
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL;
l_frame = l_frame->next) {
NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data);
g_print ("*****************************************************\n");
g_print ("batch_meta->frame_meta_pool->max_elements_in_pool = %d\n", batch_meta->frame_meta_pool->max_elements_in_pool);
g_print ("batch_meta->frame_meta_pool->element_size = %d\n", batch_meta->frame_meta_pool->element_size);
g_print ("batch_meta->frame_meta_pool->num_empty_elements = %d\n", batch_meta->frame_meta_pool->num_empty_elements);
g_print ("batch_meta->frame_meta_pool->num_full_elements = %d\n", batch_meta->frame_meta_pool->num_full_elements);
g_print ("batch_meta->frame_meta_pool->empty_list = %p\n", batch_meta->frame_meta_pool->empty_list);
g_print ("batch_meta->frame_meta_pool->full_list = %p\n", batch_meta->frame_meta_pool->full_list);
g_print ("batch_meta->frame_meta_pool->full_list->data = %p\n", batch_meta->frame_meta_pool->full_list->data);
g_print ("batch_meta->frame_meta_pool->copy_func = %p\n", batch_meta->frame_meta_pool->copy_func);
g_print ("batch_meta->frame_meta_pool->release_func = %p\n", batch_meta->frame_meta_pool->release_func);
g_print ("batch_meta->frame_meta_list = %p\n", batch_meta->frame_meta_list);
g_print ("batch_meta->frame_meta_list->data= %p\n", batch_meta->frame_meta_list->data);
batch_meta->frame_meta_pool->max_elements_in_pool = 1
batch_meta->frame_meta_pool->element_size = 200
batch_meta->frame_meta_pool->num_empty_elements = 0
batch_meta->frame_meta_pool->num_full_elements = 1
batch_meta->frame_meta_pool->empty_list = (nil)
batch_meta->frame_meta_pool->full_list = 0xffff3c04e6e0
batch_meta->frame_meta_pool->full_list->data = 0xffff60007370
batch_meta->frame_meta_pool->copy_func = (nil)
batch_meta->frame_meta_pool->release_func = 0xffff8861ae30
batch_meta->frame_meta_list = 0xffff3c04e760
batch_meta->frame_meta_list->data= 0xffff60007370
for (l_obj = frame_meta->obj_meta_list; l_obj != NULL;
l_obj = l_obj->next) {
obj_meta = (NvDsObjectMeta *) (l_obj->data);
g_print ("*****************************************************\n");
g_print ("batch_meta->obj_meta_pool->max_elements_in_pool = %d\n", batch_meta->obj_meta_pool->max_elements_in_pool);
g_print ("batch_meta->obj_meta_pool->element_size = %d\n", batch_meta->obj_meta_pool->element_size);
g_print ("batch_meta->obj_meta_pool->num_empty_elements = %d\n", batch_meta->obj_meta_pool->num_empty_elements);
g_print ("batch_meta->obj_meta_pool->num_full_elements = %d\n", batch_meta->obj_meta_pool->num_full_elements);
g_print ("batch_meta->obj_meta_pool->empty_list = %p\n", batch_meta->obj_meta_pool->empty_list);
g_print ("batch_meta->obj_meta_pool->full_list = %p\n", batch_meta->obj_meta_pool->full_list);
g_print ("batch_meta->obj_meta_pool->full_list->data = %p\n", batch_meta->obj_meta_pool->full_list->data);
g_print ("batch_meta->obj_meta_pool->copy_func = %p\n", batch_meta->obj_meta_pool->copy_func);
g_print ("batch_meta->obj_meta_pool->release_func = %p\n", batch_meta->obj_meta_pool->release_func);
g_print ("frame_meta->obj_meta_list = %p\n", frame_meta->obj_meta_list);
g_print ("frame_meta->obj_meta_list->data = %p\n", frame_meta->obj_meta_list->data);
batch_meta->obj_meta_pool->max_elements_in_pool = 8
batch_meta->obj_meta_pool->element_size = 544
batch_meta->obj_meta_pool->num_empty_elements = 7
batch_meta->obj_meta_pool->num_full_elements = 1
batch_meta->obj_meta_pool->empty_list = 0xfffe7c0032c0
batch_meta->obj_meta_pool->full_list = 0xffff64012b80
batch_meta->obj_meta_pool->full_list->data = 0xffff600a5e10
batch_meta->obj_meta_pool->copy_func = (nil)
batch_meta->obj_meta_pool->release_func = 0xffff8b103f40
frame_meta->obj_meta_list = 0xfffe7c002e80
frame_meta->obj_meta_list->data = 0xffff600a5e10
在_NvDsBatchMeta中的NvDsFrameMetaList *frame_meta_list和 NvDsMetaPool *frame_meta_pool最终的NvDsFrameMeta地址是一样的,也就是说NvDsFrameMetaList和frame_meta_pool->full_list列表对象不一样,但是列表对象指向的data是一致的。一般管理数据,都是通过NvDsFrameMetaList *frame_meta_list,自己添加数据子类才会通过pool请求内存。
3 NvDsBatchMeta
其中nvstreammux会创建一个NvDsBatchMeta,这一个NvDsBatchMeta包含了Frame、User、Object、Display、Classifier、LabelInfo等数据。
最主要的
NvDsFrameMeta #(链表中的data)
├── NvDsObjectMetaList *obj_meta_list; #(obj_meta_list->data)
│ ├── NvDsClassifierMetaList *classifier_meta_list;
│ └── ... #(识别对象的一些基本信息)
├── NvDisplayMetaList *display_meta_list;
├── NvDsUserMetaList *frame_user_meta_list;
└── ....#(一帧里面一些基本的信息)
typedef struct _NvDsBatchMeta {
NvDsBaseMeta base_meta;
/** Holds the maximum number of frames in the batch. */
guint max_frames_in_batch;
/** Holds the number of frames now in the batch. */
guint num_frames_in_batch;
/** Holds a pointer to a pool of pointers of type @ref NvDsFrameMeta,
representing a pool of frame metas. */
NvDsMetaPool *frame_meta_pool;
/** Holds a pointer to a pool of pointers of type NvDsObjMeta,
representing a pool of object metas. */
NvDsMetaPool *obj_meta_pool;
/** Holds a pointer to a pool of pointers of type @ref NvDsClassifierMeta,
representing a pool of classifier metas. */
NvDsMetaPool *classifier_meta_pool;
/** Holds a pointer to a pool of pointers of type @ref NvDsDisplayMeta,
representing a pool of display metas. */
NvDsMetaPool *display_meta_pool;
/** Holds a pointer to a pool of pointers of type @ref NvDsUserMeta,
representing a pool of user metas. */
NvDsMetaPool *user_meta_pool;
/** Holds a pointer to a pool of pointers of type @ref NvDsLabelInfo,
representing a pool of label metas. */
NvDsMetaPool *label_info_meta_pool;
/** Holds a pointer to a list of pointers of type NvDsFrameMeta
or NvDsAudioFrameMeta (when the batch represent audio batch),
representing frame metas used in the current batch.
*/
NvDsFrameMetaList *frame_meta_list;
/** Holds a pointer to a list of pointers of type NvDsUserMeta,
representing user metas in the current batch. */
NvDsUserMetaList *batch_user_meta_list;
/** Holds a lock to be set before accessing metadata to avoid
simultaneous update by multiple components. */
GRecMutex meta_mutex;
/** Holds an array of user-specific batch information. */
gint64 misc_batch_info[MAX_USER_FIELDS];
/** For internal use. */
gint64 reserved[MAX_RESERVED_FIELDS];
} NvDsBatchMeta;
4 Metadata Extension Structures
#include<nvdsmeta_schema.h>
typedef struct NvDsEventMsgMeta {
/** 枚举类型,用来记录事件的类型 */
NvDsEventType type;
/** 枚举类型,对象类型,如 vehicle, person, face等等 */
NvDsObjectType objType;
/** 结构体,存有bounding box(坐标位置(x、y)、长、宽) */
NvDsRect bbox;
/** 结构体,地理信息(经纬度,海拔) */
NvDsGeoLocation location;
/** 结构体,坐标(x,y,z) */
NvDsCoordinate coordinate;
/** 结构体,存放特征signature字符串和长度 */
NvDsObjectSignature objSignature;
/** 对象ID */
gint objClassId;
/** 记录传感器ID */
gint sensorId;
/** 单元ID */
gint moduleId;
/** 位置ID */
gint placeId;
/** 组件ID */
gint componentId;
/** 视频帧ID */
gint frameId;
/** 推理置信度 */
gdouble confidence;
/** 跟踪ID. */
gint trackingId;
/** 指针,时间戳 */
gchar *ts;
/** 指针,推理对象的描述信息 */
gchar *objectId;
/** 指针,传感器描述信息 */
gchar *sensorStr;
/** 指针,对象的其他描述信息 */
gchar *otherAttrs;
/** 指针,视频文件的名字 */
gchar *videoPath;
/** 扩展信息 */
gpointer extMsg;
/** 扩展信息大小*/
guint extMsgSize;
} NvDsEventMsgMeta;
5 相关操作函数
参考DeepStream提供的文件,待更