【Deepstream-gst-metadata-test例子解析】

 0. 背景介绍

deepstream-gst-metadata-test例子向我们展示了如何在streammux插件之前添加用户自定义的metadata数据到GstBuffer中,并在nvinfer插件的src pad上添加probe回调函数解析这个自定义的metadata。

        总的来说,该sample向我们展示了如何使用deepstream metadata extension中类和函数。具体实现:

  1. 在h264parse插件的src pad中添加回调函数h264parse_src_pad_buffer_probe来向GstBuffer中添加H264parseMeta数据
  2. 在nvv4l2decoder插件的src pad中添加回调函数nvdecoder_src_pad_buffer_probe来向GstBuffer中添加NvDecoderMeta数据
  3. 在nvinfer插件的src pad中添加回调函数nvinfer_src_pad_buffer_probe来分别解析H264parseMeta和NvDecoderMeta数据

pipeline的具体工作流程如下图所示:

 1. 向GstBuffer中添加自定义的 DeepSteam metadata

在element的probe回调函数中添加自定义的NvDsMeta类型数据,大体流程可分为如下几步:

  1. 定义用户自定义的deepstream metadata
  2. 编写NvDsMetaCopyFuncNvDsMetaReleaseFunc两个函数
  3. 调用gst_buffer_add_nvds_meta函数将用户自定义的metadata,返回NvDsMeta的对象指针
  4. 完成NvDsMeta的相关属性

1.1 h264parse element中添加H264parseMeta数据

1.1.1 定义metadata结构                

        通常情况下,我们只需要将帧数据相关的属性添加到GstBuffer中,例如:文件名,当前帧数等等。因此,我们只需要构建一个结构体将相关的信息添加到结构体中,即可在后续的element中访问这些数据做相应的操作。

typedef struct _H264parseMeta
{
  guint parser_frame_num;
} H264parseMeta;

 1.1.2 编写copy和destroy函数

copy函数是在metadata拷贝时调用,release函数是在metadata销毁时调用。

/* gst meta copy function set by user */
static gpointer h264parse_meta_copy_func(gpointer data, gpointer user_data)
{
  H264parseMeta *src_h264parse_meta = (H264parseMeta *)data;
  H264parseMeta *dst_h264parse_meta = (H264parseMeta*)g_malloc0(
      sizeof(H264parseMeta));
  memcpy(dst_h264parse_meta, src_h264parse_meta, sizeof(H264parseMeta));
  return (gpointer)dst_h264parse_meta;
}

/* gst meta release function set by user */
static void h264parse_meta_release_func(gpointer data, gpointer user_data)
{
  H264parseMeta *h264parse_meta = (H264parseMeta *)data;
  if(h264parse_meta) {
    g_free(h264parse_meta);
    h264parse_meta = NULL;
  }
}

 1.1.3 向gstbuffer中添加H264parseMeta数据

 gst_buffer_add_nvds_meta函数的作用是:将用户自定义的metadata添加到GstBuffer中,并返回一个NvDsMeta对象。

/* Attach decoder metadata to gst buffer using gst_buffer_add_nvds_meta() */
  meta = gst_buffer_add_nvds_meta (buf, h264parse_meta, NULL,
      h264parse_meta_copy_func, h264parse_meta_release_func);

 NvDsMeta   是一个deepstream metadata, 应该是deep stream框架中自定义的一个custom metadata数据。下述为NvDsMeta的定义,相应的我们需要完善其属性。

1.1.4 完善  NvDsMeta相关属性

/* Set metadata type */
meta->meta_type = (GstNvDsMetaType)NVDS_GST_META_BEFORE_DECODER_EXAMPLE;

/* Set transform function to transform decoder metadata from Gst meta to
   * nvds meta */
meta->gst_to_nvds_meta_transform_func = h264parse_gst_to_nvds_meta_transform_func;

/* Set release function to release the transformed nvds metadata */
meta->gst_to_nvds_meta_release_func = h264parse_gst_nvds_meta_release_func;

 nvds_get_user_meta_type函数的作用是基于一个给定的string字符串生成一个unique的user metadata类型来描述用户自定义的metadata。而string字符串的命名格式是:ORG_NAME.COMPONENT_NAME.METADATA_DESCRIPTION。例如:NVIDIA.NVINFER.TENSOR_METADATA。

#define NVDS_GST_META_BEFORE_DECODER_EXAMPLE 
(nvds_get_user_meta_type("NVIDIA.DECODER.GST_META_BEFORE_DECODER"))

/* Set metadata type */
meta->meta_type = (GstNvDsMetaType)NVDS_GST_META_BEFORE_DECODER_EXAMPLE;
g_print("H264parse GstNvDsMetaType:%d\n", meta->meta_type);
/* gst to nvds transform function set by user. "data" holds a pointer to NvDsUserMeta */
static gpointer h264parse_gst_to_nvds_meta_transform_func(gpointer data, gpointer user_data)
{
  NvDsUserMeta *user_meta = (NvDsUserMeta *)data;
  H264parseMeta *src_h264parse_meta =
    (H264parseMeta*)user_meta->user_meta_data;
  H264parseMeta *dst_h264parse_meta =
    (H264parseMeta *)h264parse_meta_copy_func(src_h264parse_meta, NULL);
  return (gpointer)dst_h264parse_meta;
}

/* release function set by user to release gst to nvds transformed metadata.
 * "data" holds a pointer to NvDsUserMeta */
static void h264parse_gst_nvds_meta_release_func(gpointer data, gpointer user_data)
{
  NvDsUserMeta *user_meta = (NvDsUserMeta *) data;
  H264parseMeta *h264parse_meta = (H264parseMeta *)user_meta->user_meta_data;
  h264parse_meta_release_func(h264parse_meta, NULL);
}

 1.2  nvv4l2decoder element中添加NvDecoderMeta数据

1.2.1 定义metadata结构

typedef struct _NvDecoderMeta
{
  guint frame_type;
  guint frame_num;
  gboolean dec_err;
} NvDecoderMeta;

 1.2.2 编写copy和destroy函数

/* gst meta copy function set by user */
static gpointer decoder_meta_copy_func(gpointer data, gpointer user_data)
{
  NvDecoderMeta *src_decoder_meta = (NvDecoderMeta *)data;
  NvDecoderMeta *dst_decoder_meta = (NvDecoderMeta*)g_malloc0(
      sizeof(NvDecoderMeta));
  memcpy(dst_decoder_meta, src_decoder_meta, sizeof(NvDecoderMeta));
  return (gpointer)dst_decoder_meta;
}

/* gst meta release function set by user */
static void decoder_meta_release_func(gpointer data, gpointer user_data)
{
  NvDecoderMeta *decoder_meta = (NvDecoderMeta *)data;
  if(decoder_meta) {
    g_free(decoder_meta);
    decoder_meta = NULL;
  }
}

 1.2.3 向gstbuffer中添加H264parseMeta数据

/* Attach decoder metadata to gst buffer using gst_buffer_add_nvds_meta() */
  meta = gst_buffer_add_nvds_meta (buf, decoder_meta, NULL,
      decoder_meta_copy_func, decoder_meta_release_func);

 1.2.4 完善  NvDsMeta相关属性

/* Set metadata type */
meta->meta_type = (GstNvDsMetaType)NVDS_DECODER_GST_META_EXAMPLE;

  /* Set transform function to transform decoder metadata from Gst meta to
   * nvds meta */
meta->gst_to_nvds_meta_transform_func = decoder_gst_to_nvds_meta_transform_func;

  /* Set release function to release the transformed nvds metadata */
meta->gst_to_nvds_meta_release_func = decoder_gst_nvds_meta_release_func;
#define NVDS_DECODER_GST_META_EXAMPLE 
(nvds_get_user_meta_type("NVIDIA.DECODER.GST_USER_META"))

/* Set metadata type */
meta->meta_type = (GstNvDsMetaType)NVDS_DECODER_GST_META_EXAMPLE;
/* gst to nvds transform function set by user. "data" holds a pointer to NvDsUserMeta */
static gpointer decoder_gst_to_nvds_meta_transform_func(gpointer data, gpointer user_data)
{
  NvDsUserMeta *user_meta = (NvDsUserMeta *)data;
  NvDecoderMeta *src_decoder_meta =
    (NvDecoderMeta*)user_meta->user_meta_data;
  NvDecoderMeta *dst_decoder_meta =
    (NvDecoderMeta *)decoder_meta_copy_func(src_decoder_meta, NULL);
  return (gpointer)dst_decoder_meta;
}

/* release function set by user to release gst to nvds transformed metadata.
 * "data" holds a pointer to NvDsUserMeta */
static void decoder_gst_nvds_meta_release_func(gpointer data, gpointer user_data)
{
  NvDsUserMeta *user_meta = (NvDsUserMeta *) data;
  NvDecoderMeta *decoder_meta = (NvDecoderMeta *)user_meta->user_meta_data;
  decoder_meta_release_func(decoder_meta, NULL);
}

  2. 读取自定义的metadata数据

该sample中在nvinfer element的src pad中调用probe回调函数nvinfer_src_pad_buffer_probe来分别解析H264parseMeta和NvDecoderMeta数据。

下面的代码向我们解释了如何提取使用gstnvdsmeta API加入的decoder metadata和 h264parse metadata数据。此时,decoder metadata被设置为user data包含在NvDsFrameMeta下面

for (l_user_meta = frame_meta->frame_user_meta_list; l_user_meta != NULL;
    l_user_meta = l_user_meta->next) 
{
    user_meta = (NvDsUserMeta *) (l_user_meta->data);
    if(user_meta->base_meta.meta_type == NVDS_DECODER_GST_META_EXAMPLE)   // decoder
    {
    decoder_meta = (NvDecoderMeta *)user_meta->user_meta_data;
    g_print("Dec Meta retrieved as NVDS USER METADTA For Frame_Num = %d  \n",
        decoder_meta->frame_num);
    g_print("Retrieved Decoder Metadata: frame type = %d, frame_num = %d decode_error_status = %d\n\n",
        decoder_meta->frame_type, decoder_meta->frame_num,
        decoder_meta->dec_err);
    }

    if(user_meta->base_meta.meta_type == NVDS_GST_META_BEFORE_DECODER_EXAMPLE)  // parser
    {
    h264parse_meta = (H264parseMeta *)user_meta->user_meta_data;
    g_print("Parser Meta retrieved For Frame_Num = %d  \n",
        h264parse_meta->parser_frame_num);
    g_print("Retrieved Metadata attached before decoder: parsed frame_num = %d\n\n",
        h264parse_meta->parser_frame_num);
    }
}

 3. 有用的链接

Attaching custom type metadata to gstreamer buffer on src pad causing sudden crash

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值