Please provide complete information as applicable to your setup.
• Hardware Platform (Jetson / GPU): Jetson AGX Xavier
• DeepStream Version: 5.0
• JetPack Version (valid for Jetson only): 4.4.1
• TensorRT Version: 7.1.3
• NVIDIA GPU Driver Version (valid for GPU only)
• Issue Type( questions, new requirements, bugs): questions,
I refer to deepstream-user-metadata-test app to add metadata to each frame, bellow are the code extract:
/* {Attach metadata to frame API*/
#define NVDS_USER_FRAME_META_EXAMPLE (nvds_get_user_meta_type("NVIDIA.NVINFER.USER_META"))
#define USER_ARRAY_SIZE 16
void *set_metadata_ptr(void);
static gpointer copy_user_meta(gpointer data, gpointer user_data);
static void release_user_meta(gpointer data, gpointer user_data);
void *set_metadata_ptr()
{
int i = 0;
gchar *user_metadata = (gchar*)g_malloc0(USER_ARRAY_SIZE);
g_print("\n**************** Setting user metadata array of 16 on nvinfer src pad\n");
for(i = 0; i < USER_ARRAY_SIZE; i++) {
user_metadata[i] = rand() % 255;
g_print("user_meta_data [%d] = %d\n", i, user_metadata[i]);
}
return (void *)user_metadata;
}
/* copy function set by user. "data" holds a pointer to NvDsUserMeta*/
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;
}
}
static GstPadProbeReturn
attach_metadata_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
gpointer u_data)
{
GstBuffer *buf = (GstBuffer *) info->data;
NvDsMetaList * l_frame = NULL;
NvDsUserMeta *user_meta = NULL;
NvDsMetaType user_meta_type = NVDS_USER_FRAME_META_EXAMPLE;
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);
/* Acquire NvDsUserMeta user meta from pool */
user_meta = nvds_acquire_user_meta_from_pool(batch_meta);
/* Set NvDsUserMeta below */
user_meta->user_meta_data = (void *)set_metadata_ptr();
user_meta->base_meta.meta_type = user_meta_type;
user_meta->base_meta.copy_func = (NvDsMetaCopyFunc)copy_user_meta;
user_meta->base_meta.release_func = (NvDsMetaReleaseFunc)release_user_meta;
/* We want to add NvDsUserMeta to frame level */
nvds_add_user_meta_to_frame(frame_meta, user_meta);
}
return GST_PAD_PROBE_OK;
}
/* Attach metadata to frame API} */
// create live source bin
static GstElement *
create_live_source_bin(guint index, gboolean basler, pipeline_config p_config, latency_measure *latency_measure, gboolean add_probe)
{
GstElement *bin = NULL,
*source = NULL,
*vidconv = NULL,
*nvvidconv = NULL,
*cap_filter1 = NULL,
*cap_filter2 = NULL;
GstPad *real_pad, *ghost_pad;
GstCaps *caps1, *caps2 = NULL;
/* Create a source GstBin to abstract this bin's content from the rest of the pipeline */
gchar bin_name[16] = {};
g_snprintf(bin_name, 15, "source-bin-%02d", index);
bin = gst_bin_new(bin_name);
/* Create elements in the bin */
if (basler)
{
source = gst_element_factory_make("pylonsrc", "camera");
if (!bin || !source)
{
g_printerr("One element in source bin could not be created.\n");
return NULL;
}
g_object_set(G_OBJECT(source),
"camera", index,
"imageformat", "rgb8",
"width", p_config.camera_output_width,
"height", p_config.camera_output_height,
"continuous", p_config.basler_continuous,
NULL);
}
else
{
source = gst_element_factory_make("v4l2src", "camera");
cap_filter1 = gst_element_factory_make("capsfilter", "cap_filter1");
if (!bin || !source || !cap_filter1)
{
g_printerr("One element in source bin could not be created.\n");
return NULL;
}
gchar device_name[16] = {};
g_snprintf(device_name, 15, "/dev/video%d", index);
g_object_set(G_OBJECT(source), "device", device_name, NULL);
// we need this cap for v4l2src so that it capture video at our specified config
caps1 = gst_caps_from_string("video/x-raw, width=640, height=480, framerate=30/1");
g_object_set(G_OBJECT(cap_filter1), "caps", caps1, NULL);
gst_caps_unref(caps1);
}
vidconv = gst_element_factory_make("videoconvert", "vidconv");
nvvidconv = gst_element_factory_make("nvvideoconvert", "nvvidconv");
cap_filter2 = gst_element_factory_make("capsfilter", "cap_filter2");
if (!vidconv || !nvvidconv || !cap_filter2)
{
g_printerr("One element in source bin could not be created.\n");
return NULL;
}
/* Set elements properties */
g_object_set(G_OBJECT(nvvidconv), "nvbuf-memory-type", 0, NULL);
caps2 = gst_caps_from_string("video/x-raw(memory:NVMM), format=NV12");
g_object_set(G_OBJECT(cap_filter2), "caps", caps2, NULL);
gst_caps_unref(caps2);
if (basler)
{
/* Add elements to the bin */
gst_bin_add_many(GST_BIN(bin), source, vidconv, nvvidconv, cap_filter2, NULL);
/* Link elements in the bin*/
if (!gst_element_link_many(source, vidconv, nvvidconv, cap_filter2, NULL))
{
g_printerr("One element in source bin could not be linked.\n");
return NULL;
}
}
else
{
/* Add elements to the bin */
gst_bin_add_many(GST_BIN(bin), source, cap_filter1, vidconv, nvvidconv, cap_filter2, NULL);
/* Link elements in the bin*/
if (!gst_element_link_many(source, cap_filter1, vidconv, nvvidconv, cap_filter2, NULL))
{
g_printerr("One element in source bin could not be linked.\n");
return NULL;
}
}
// add user metadata probe
if(add_probe){
GstPad *start_probe_pad = gst_element_get_static_pad(source, "src");
if (!start_probe_pad)
{
g_print("Unable to get source pad\n");
}
else
{
gst_pad_add_probe(start_probe_pad, GST_PAD_PROBE_TYPE_BUFFER, attach_metadata_buffer_probe, NULL, NULL);
}
gst_object_unref(start_probe_pad);
}
/* We need to create a ghost pad for the bin,
since this is a source bin, the ghost pad acts as
a proxy of the source pad of the last element in the bin
*/
real_pad = gst_element_get_static_pad(cap_filter2, "src");
ghost_pad = gst_ghost_pad_new("src", real_pad);
gst_pad_set_active(ghost_pad, TRUE);
if (!gst_element_add_pad(bin, ghost_pad))
{
g_printerr("Failed to add ghost pad in source bin\n");
return NULL;
}
gst_object_unref(real_pad);
return bin;
}
// inside main()
/* Set up source bins (must done this after streammux is added to the pipeline) */
for (guint i = 0; i < num_sources; i++)
{
GstElement *source_bin = NULL;
if (live_src)
{
source_bin = create_live_source_bin(i, basler, p_config, g_ptr_array_index(p_config.latency_measure, i), TRUE);
}
else if (image_src)
{
source_bin = create_multifile_source_bin(i);
}
else
{
g_printerr("Unsupported source. Exiting.\n");
}
if (!source_bin)
{
g_printerr("Failed to create source bin. Exiting.\n");
return EXIT_FAILURE;
}
// add each source bin to the pipeline
gst_bin_add(GST_BIN(pipeline), source_bin);
// manually link streammux to each source bin
GstPad *sinkpad, *srcpad;
gchar pad_name[16] = {};
g_snprintf(pad_name, 15, "sink_%u", i);
sinkpad = gst_element_get_request_pad(streammux, pad_name);
if (!sinkpad)
{
g_printerr("Streammux request sink pad failed. Exiting.\n");
return EXIT_FAILURE;
}
srcpad = gst_element_get_static_pad(source_bin, "src");
if (!srcpad)
{
g_printerr("Failed to get src pad of source bin. Exiting.\n");
return EXIT_FAILURE;
}
if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK)
{
g_printerr("Failed to link source bin to stream muxer. Exiting.\n");
return EXIT_FAILURE;
}
gst_object_unref(srcpad);
gst_object_unref(sinkpad);
}
image from dot file:
When I attached attach_metadata_buffer_probe
to the src
pad of the source element of each source bin, I got Segmentation fault (core dumped)
. Any advice on how to solve this error?