I want to add/delete rtsp source during runtime for deepstream-app. The code like this:
add rtsp source:
static bool add_create_rtsp_source(AppCtx * appCtx, TCamInfo &rtsp_url){
NvDsPipeline *pipeline = &appCtx->pipeline;
NvDsConfig *config = &appCtx->config;
NvDsSourceConfig src_config;
memset(&src_config, 0, sizeof(NvDsSourceConfig));
int source_id = -1;
for(int i = 0; i < config->num_source_sub_bins; i++){
if (!config->multi_source_config[i].enable) {
source_id = i;
break;
}
}
if(source_id == -1 && config->num_source_sub_bins >= MAX_SOURCE_BINS){
std::cerr << âsource bin num exced, can not add sourceâ << std::endl;
return false;
}else if(source_id == -1){
source_id = config->num_source_sub_bins;
}
std::cout << âadd cam into " << source_id << " sourceâ << std::endl;
src_config.enable = true;
src_config.loop = 0;
src_config.live_source = true;
src_config.low_latency_mode = 0;
src_config.Intra_decode = 0;
src_config.smart_record = 0;
src_config.latency = 100;
src_config.num_decode_surfaces = 16;
src_config.num_extra_surfaces = 1;
src_config.rtsp_reconnect_attempts = -1;
src_config.source_width = IVS_FRAME_WIDTH;
src_config.source_height = IVS_FRAME_HEIGHT;
src_config.source_fps_n = 0;
src_config.rtsp_reconnect_interval_sec = 5;
src_config.type = NV_DS_SOURCE_RTSP;
src_config.gpu_id = 0;
src_config.source_id = source_id;
src_config.select_rtp_protocol = 4;
src_config.num_sources = 1;
src_config.drop_frame_interval = 2;
src_config.camera_id = rtsp_url.cam_id;
src_config.dewarper_config.enable = 0;
src_config.uri = (gchar *) g_malloc0 (sizeof (gchar *) * (rtsp_url.url.length() + 1));
memcpy(src_config.uri, &rtsp_url.url.c_str()[0], sizeof (gchar *) * (rtsp_url.url.length() + 1));
src_config.video_format = âRGBAâ;
gchar elem_name[50];
g_snprintf (elem_name, sizeof (elem_name), âsrc_sub_bin%dâ, source_id);
pipeline->multi_src_bin.sub_bins[source_id].bin = gst_bin_new (elem_name);
if (!pipeline->multi_src_bin.sub_bins[source_id].bin) {
NVGSTDS_ERR_MSG_V (âFailed to create â%sââ, elem_name);
return false;
}
pipeline->multi_src_bin.sub_bins[source_id].bin_id = pipeline->multi_src_bin.sub_bins[source_id].source_id = source_id;
pipeline->multi_src_bin.live_source = TRUE;
pipeline->multi_src_bin.sub_bins[source_id].eos_done = TRUE;
pipeline->multi_src_bin.sub_bins[source_id].reset_done = TRUE;
pipeline->multi_src_bin.sub_bins[source_id].parent_bin = &pipeline->multi_src_bin;
if (!create_rtsp_src_bin (&src_config, &pipeline->multi_src_bin.sub_bins[source_id])) {
return FALSE;
}
gst_bin_add (GST_BIN (pipeline->multi_src_bin.bin), pipeline->multi_src_bin.sub_bins[source_id].bin);
if (!link_element_to_streammux_sink_pad (pipeline->multi_src_bin.streammux,
pipeline->multi_src_bin.sub_bins[source_id].bin, source_id)) {
NVGSTDS_ERR_MSG_V (âsource %d cannot be linked to muxâs sink pad %p\nâ, source_id,
pipeline->multi_src_bin.streammux);
return false;
}
GstStateChangeReturn state_return;
state_return = gst_element_set_state (pipeline->multi_src_bin.sub_bins[source_id].bin, GST_STATE_PLAYING);
switch (state_return) {
case GST_STATE_CHANGE_SUCCESS:
g_print (âADD CAM STATE CHANGE SUCCESS\n\nâ);
break;
case GST_STATE_CHANGE_FAILURE:
g_print (âADD CAM STATE CHANGE FAILURE\n\nâ);
break;
case GST_STATE_CHANGE_ASYNC:
g_print (âADD CAM STATE CHANGE ASYNC\n\nâ);
state_return = gst_element_get_state (pipeline->multi_src_bin.sub_bins[source_id].bin, NULL, NULL, GST_CLOCK_TIME_NONE);
break;
case GST_STATE_CHANGE_NO_PREROLL:
g_print (âADD CAM STATE CHANGE NO PREROLL\n\nâ);
break;
default:
break;
}
if (src_config.dewarper_config.enable) {
g_object_set (G_OBJECT (pipeline->multi_src_bin.sub_bins[source_id].dewarper_bin.nvdewarper),
âsource-idâ, src_config.source_id, NULL);
}
config->multi_source_config[source_id] = src_config;
if(source_id == config->num_source_sub_bins){
config->num_source_sub_bins++;
}
return true;
}
delete rstp source:
static bool stop_release_source (AppCtx * appCtx, TCamInfo &rtsp_url)
{
NvDsPipeline *pipeline = &appCtx->pipeline;
NvDsConfig *config = &appCtx->config;
GstStateChangeReturn state_return;
gchar pad_name[16];
GstPad *sinkpad = NULL;
int source_id = -1;
for(int i = 0; i < config->num_source_sub_bins; i++){
std::string url = config->multi_source_config[i].uri;
if(url == rtsp_url.url){
state_return = gst_element_set_state (pipeline->multi_src_bin.sub_bins[i].bin, GST_STATE_NULL);
source_id = i;
break;
}
}
if(source_id == -1){
return false;
}
switch (state_return) {
case GST_STATE_CHANGE_SUCCESS:
g_print (âSTATE CHANGE SUCCESS\n\nâ);
g_snprintf (pad_name, 15, âsink_%uâ, source_id);
sinkpad = gst_element_get_static_pad (pipeline->multi_src_bin.streammux, pad_name);
gst_pad_send_event (sinkpad, gst_event_new_eos ());
gst_pad_send_event (sinkpad, gst_event_new_flush_stop (FALSE));
gst_element_release_request_pad (pipeline->multi_src_bin.streammux, sinkpad);
gst_object_unref (sinkpad);
//destroy_rtsp_src_bin(&config->multi_source_config[source_id], &pipeline->multi_src_bin.sub_bins[source_id]);
gst_bin_remove (GST_BIN (pipeline->multi_src_bin.bin), pipeline->multi_src_bin.sub_bins[source_id].bin);
memset(&pipeline->multi_src_bin.sub_bins[source_id], 0, sizeof(NvDsSrcBin));
free_config(&config->multi_source_config[source_id]);
g_print ("STATE CHANGE SUCCESS %p\n\n", sinkpad);
break;
case GST_STATE_CHANGE_FAILURE:
g_print ("STATE CHANGE FAILURE\n\n");
break;
case GST_STATE_CHANGE_ASYNC:
g_print ("STATE CHANGE ASYNC\n\n");
g_snprintf (pad_name, 15, "sink_%u", source_id);
sinkpad = gst_element_get_static_pad (pipeline->multi_src_bin.streammux, pad_name);
gst_pad_send_event (sinkpad, gst_event_new_eos ());
gst_pad_send_event (sinkpad, gst_event_new_flush_stop (FALSE));
gst_element_release_request_pad (pipeline->multi_src_bin.streammux, sinkpad);
gst_object_unref (sinkpad);
//destroy_rtsp_src_bin(&config->multi_source_config[source_id], &pipeline->multi_src_bin.sub_bins[source_id]);
gst_bin_remove (GST_BIN (pipeline->multi_src_bin.bin), pipeline->multi_src_bin.sub_bins[source_id].bin);
memset(&pipeline->multi_src_bin.sub_bins[source_id], 0, sizeof(NvDsSrcBin));
free_config(&config->multi_source_config[source_id]);
g_print ("STATE CHANGE ASYNC %p\n\n", sinkpad);
break;
case GST_STATE_CHANGE_NO_PREROLL:
g_print ("STATE CHANGE NO PREROLL\n\n");
break;
default:
break;
}
return true;
}
delete a rtsp source sucessed, add a rtsp source failed like this:
add cam into 0 source
ADD CAM STATE CHANGE ASYNC
** ERROR: <cb_newpad3:510>: Failed to link depay loader to rtsp src
Opening in BLOCKING MODE
NvMMLiteOpen : Block : BlockType = 261
NVMEDIA: Reading vendor.tegra.display-size : status: 6
NvMMLiteBlockCreate : Block : BlockType = 261