You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不共享自定义元数据类的情况下为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 21:45:43