如何在不共享自定义元数据类的情况下为GstBuffer附加元数据?
跨组件为GstBuffer附加自定义元数据的实现方案
方法一:使用GstStructure作为元数据载体(推荐)
GstStructure是GStreamer内置的通用键值对结构,无需在发送/接收端共享自定义类,仅需约定好元数据的键名和类型即可实现跨组件传递。
发送端实现
创建GstStructure并填充自定义数据,将其作为通用元数据附加到GstBuffer:
// 创建自定义元数据结构,约定键名与对应类型 GstStructure *meta_struct = gst_structure_new("com.yourdomain.CustomMeta", "frame_id", G_TYPE_UINT, 123, "capture_ts", G_TYPE_UINT64, g_get_real_time(), "extra_info", G_TYPE_STRING, "custom_payload", NULL); // 将结构附加到buffer的元数据中 GstMeta *meta = gst_buffer_add_meta(buffer, gst_meta_get_info("GstMetaStructure"), NULL); gst_meta_structure_set_structure(GST_META_STRUCTURE(meta), meta_struct); // 释放结构引用 gst_structure_unref(meta_struct);
接收端实现
遍历buffer元数据,通过约定的结构名称和键名提取数据:
// 查找GstMetaStructure类型的元数据 GstMeta *meta = gst_buffer_find_meta(buffer, gst_meta_get_info("GstMetaStructure"), NULL); if (meta) { GstStructure *meta_struct = gst_meta_structure_get_structure(GST_META_STRUCTURE(meta)); // 验证结构名称是否匹配约定 if (g_strcmp0(gst_structure_get_name(meta_struct), "com.yourdomain.CustomMeta") == 0) { guint frame_id; guint64 capture_ts; gchar *extra_info; // 提取字段数据,自动处理类型匹配 if (gst_structure_get_uint(meta_struct, "frame_id", &frame_id) && gst_structure_get_uint64(meta_struct, "capture_ts", &capture_ts) && gst_structure_get_string(meta_struct, "extra_info", &extra_info)) { // 处理提取到的元数据 g_print("Frame ID: %u, Capture TS: %" G_GUINT64_FORMAT ", Extra: %s\n", frame_id, capture_ts, extra_info); } } }
方法二:动态注册GstMetaInfo,通过序列化数据传递
如果需要更高效的内存使用,可以动态注册自定义GstMetaInfo,无需共享自定义结构,而是通过序列化字节数组存储数据(需严格约定数据格式)。
发送端实现
// 仅发送端可见的元数据结构 typedef struct _SerializedMeta { GstMeta meta; guint data_len; guint8 *data; } SerializedMeta; // 元数据初始化函数 static gboolean serialized_meta_init(GstMeta *meta, gpointer params, GstBuffer *buffer) { SerializedMeta *m = (SerializedMeta *)meta; m->data_len = 0; m->data = NULL; return TRUE; } // 元数据释放函数 static void serialized_meta_free(GstMeta *meta, GstBuffer *buffer) { SerializedMeta *m = (SerializedMeta *)meta; g_free(m->data); } // 注册自定义元数据类型 static const GstMetaInfo *serialized_meta_get_info(void) { static const GstMetaInfo *info = NULL; if (!info) { info = gst_meta_register("SerializedCustomMeta", sizeof(SerializedMeta), serialized_meta_init, serialized_meta_free, NULL); } return info; } // 将自定义数据序列化后添加到buffer void add_serialized_meta(GstBuffer *buffer, guint frame_id, guint64 ts) { SerializedMeta *m = (SerializedMeta *)gst_buffer_add_meta(buffer, serialized_meta_get_info(), NULL); // 序列化数据:按约定格式打包字段 m->data_len = sizeof(guint) + sizeof(guint64); m->data = g_malloc(m->data_len); memcpy(m->data, &frame_id, sizeof(guint)); memcpy(m->data + sizeof(guint), &ts, sizeof(guint64)); }
接收端实现
// 查找指定名称的自定义元数据 GstMeta *meta = gst_buffer_find_meta(buffer, gst_meta_get_info("SerializedCustomMeta"), NULL); if (meta) { // 按约定的内存偏移读取数据(需注意字节序与平台兼容性) guint8 *data = ((guint8 *)meta) + sizeof(GstMeta); guint frame_id = *(guint *)data; guint64 ts = *(guint64 *)(data + sizeof(guint)); // 处理提取到的数据 g_print("Deserialized: Frame ID %u, TS %" G_GUINT64_FORMAT "\n", frame_id, ts); }
注意:方法二需要严格约定数据的字节序和内存布局,跨平台场景下需额外处理端序问题,通用性不如方法一。
内容的提问来源于stack exchange,提问作者lfk
相关产品推荐
相关产品推荐

