• Hardware Platform (Jetson / GPU) GPU
• DeepStream Version 6.1
• JetPack Version (valid for Jetson only)
• TensorRT Version 8.2.5-1+cuda11.4
• NVIDIA GPU Driver Version (valid for GPU only) 510.68.02
• Issue Type( questions, new requirements, bugs) questions
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)
When pause the pipeline, the origin pipeline like:
src->streammux->pgie->track->demux->rtmpsink
i want infer engine be removed from the pipeline,
like:
src->streammux->demux->rtmpsink
so it can push origin stream to the rtmp server. I refer to gstreamer pipeline manipulation doc to delete the infer engine dynamically . Link streammux and streamdemux, and unlink the element they link before. But the rtmp server can`t receive data from the pipeline. (I use tcpdump to catch the datapack) It looks the data be blocked by some element. But it shows normally through the pipeline pic. All the elements are in playing state in the pipeline. There are no block pads also.
Here is the changed pipeline pic:
I also save the debug log:
1.tar.gz (38.8 MB)
Here are some key code:
static GstPadProbeReturn
event_probe_cb(GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
AppCtx appCtx = (AppCtx)user_data;
GstPad *last_ele_src_pad = NULL;
char pad_name[15];
gboolean pad_status;
if (GST_EVENT_TYPE(GST_PAD_PROBE_INFO_DATA(info)) != GST_EVENT_EOS) {
NVGSTDS_INFO_MSG_V(" Get not eos event ");
return GST_PAD_PROBE_PASS;
}
GstState cur;
GstState pending;
gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
gchar* name = gst_element_get_name(appCtx->first_elem);
NVGSTDS_INFO_MSG_V(" first_elem name %s ",name);
g_free(name);
gst_element_unlink(appCtx->pipeline.multi_src_bin.bin, appCtx->first_elem);
NVGSTDS_INFO_MSG_V("src_bin first_elem unlink ");
gst_element_unlink(appCtx->last_elem, appCtx->pipeline.demuxer);
NVGSTDS_INFO_MSG_V("last_elem demux unlink ");
gchar* last_name = gst_element_get_name(appCtx->last_elem);
NVGSTDS_INFO_MSG_V(" last_elem name %s ", last_name);
g_free(last_name);
/* remove unlinks automatically */
//gst_bin_remove(GST_BIN(pipeline), cur_effect);
guint tee_pads_num = appCtx->last_elem->numpads;
NVGSTDS_INFO_MSG_V("tee pad num: '%u'", tee_pads_num);
g_snprintf(pad_name, 15, "src_%u", tee_pads_num - 2);
last_ele_src_pad = gst_element_get_static_pad(appCtx->last_elem, pad_name);
if (last_ele_src_pad) {
//NVGSTDS_INFO_MSG_V("Find last_ele_src_pad");
gst_element_release_request_pad(appCtx->last_elem, last_ele_src_pad);
gst_object_unref(last_ele_src_pad);
}
if (!gst_element_link(appCtx->pipeline.multi_src_bin.bin, appCtx->pipeline.demuxer)) {
GstCaps *src_caps, *sink_caps;
src_caps = gst_pad_query_caps((GstPad *)(appCtx->pipeline.multi_src_bin.bin)->srcpads->data, NULL);
sink_caps = gst_pad_query_caps((GstPad *)(appCtx->pipeline.demuxer)->sinkpads->data, NULL);
NVGSTDS_ERR_MSG_V("Failed to link '%s' (%s) and '%s' (%s)", \
GST_ELEMENT_NAME(appCtx->pipeline.multi_src_bin.bin), \
gst_caps_to_string(src_caps), \
GST_ELEMENT_NAME(appCtx->pipeline.demuxer), \
gst_caps_to_string(sink_caps));
}
GstPad *demux_sink_pad = NULL;
demux_sink_pad = gst_element_get_static_pad(appCtx->pipeline.demuxer, "sink");
//gst_pad_send_event(demux_sink_pad, gst_event_new_flush_stop(TRUE));
//NVGSTDS_INFO_MSG_V(" Send flush stop event ");
gst_element_get_state(appCtx->pipeline.pipeline, &cur, &pending,
GST_CLOCK_TIME_NONE);
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(appCtx->pipeline.pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pause-pipeline");
NVGSTDS_INFO_MSG_V("After stop ai analysis");
print_status_of_all(appCtx->pipeline.pipeline);
pad_status = gst_pad_is_blocking(demux_sink_pad);
NVGSTDS_INFO_MSG_V(" Demux sink pad status '%d' ",pad_status);
GstPad *streammux_sink_pad = NULL;
streammux_sink_pad = gst_element_get_static_pad(appCtx->pipeline.multi_src_bin.bin, "src");
pad_status = gst_pad_is_blocking(streammux_sink_pad);
NVGSTDS_INFO_MSG_V(" Streammux sink pad status '%d' ", pad_status);
return GST_PAD_PROBE_DROP;
}
static GstPadProbeReturn
pad_probe_cb(GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
{
GstPad srcpad, sinkpad;
gchar last_elem_name[15];
gchar pad_name = gst_pad_get_name(pad);
NVGSTDS_INFO_MSG_V(" pad name %s ", pad_name);
g_free(pad_name);
NVGSTDS_INFO_MSG_V(“pad is blocked now”);
AppCtx appCtx = (AppCtx*)user_data;
/* remove the probe first */
gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
guint tee_pads_num = appCtx->last_elem->numpads;
NVGSTDS_INFO_MSG_V("tee pad num: '%u'", tee_pads_num);
g_snprintf(last_elem_name, 15, "src_%u", tee_pads_num - 2);
srcpad = gst_element_get_static_pad(appCtx->last_elem, last_elem_name);
/* install new probe for EOS */
//srcpad = gst_element_get_static_pad(appCtx->first_elem, "src");
gulong probe_id = gst_pad_add_probe(srcpad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BLOCK |
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), event_probe_cb, user_data, NULL);
NVGSTDS_INFO_MSG_V("first elem probe id: %lu",probe_id);
gst_object_unref(srcpad);
/* push EOS into the element, the probe will be fired when the
* EOS leaves the effect and it has thus drained all of its data */
sinkpad = gst_element_get_static_pad(appCtx->first_elem, "sink");
gst_pad_send_event(sinkpad, gst_event_new_eos());
gst_object_unref(sinkpad);
NVGSTDS_INFO_MSG_V("pad_probe_cb return");
//return GST_PAD_PROBE_REMOVE;
return GST_PAD_PROBE_OK;
}
The appCtx->first_elem repres the first elem after nvstreammux , last_elem repres the elem before nvdemux. When the grpc server receive a pause request, I would invoke:
GstPad *streammux_src_pad = NULL;
streammux_src_pad = gst_element_get_static_pad(appCtx->pipeline.multi_src_bin.bin, “src”);
gst_pad_add_probe(streammux_src_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
pad_probe_cb, appCtx, NULL)
Thus, the callback can be executed.
I can`t find a solution even through the debug log . Could u please give me some advices?