Streammux can not stop

  1. I use test3 to modify the source code
    2.The change is that pipeline add the streamdemux.
    3.The pipeline is that 4 uridecodebin → streamux → infer → streamdemux → 4 rtsp-server

The problem is that pipeline set “GST_STATE_NULL”, which can not stop, when video stream is off.

Further exploration found that the streammux process did not stop. as bellow

Hi,
This may not be the cases we have verified in the releases. Please share the patch to deepstream-test3 and steps so that we can replicate the issue and do investigation. And is your system on r32.4.4/DS5.0.1?

The source is bellow:

/*
 * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <gst/gst.h>
#include <glib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/time.h>
#include <gst/rtsp-server/rtsp-server.h>
#include "gstnvdsmeta.h"
#include <stdlib.h>
#include <ctype.h>

//#include "gstnvstreammeta.h"
#ifndef PLATFORM_TEGRA
#include "gst-nvmessage.h"
#endif

#define MAX_DISPLAY_LEN 64

/* The muxer output resolution must be set if the input streams will be of
 * different resolution. The muxer will scale all the input frames to this
 * resolution. */
#define MUXER_OUTPUT_WIDTH 1920
#define MUXER_OUTPUT_HEIGHT 1080

#define TILED_OUTPUT_WIDTH 1920
#define TILED_OUTPUT_HEIGHT 1080

/* Muxer batch formation timeout, for e.g. 40 millisec. Should ideally be set
 * based on the fastest source's framerate. */
#define MUXER_BATCH_TIMEOUT_USEC 40000

/* NVIDIA Decoder source pad memory feature. This feature signifies that source
 * pads having this capability will push GstBuffers containing cuda buffers. */
#define GST_CAPS_FEATURES_NVMM "memory:NVMM"

#define bufSize 1024
#define MaxKeyLength 80

#define CONFIG_PATH "/home/user/XM_COSO_RTG/Broad.conf"

#define FPS_PRINT_INTERVAL 300
//static struct timeval start_time = { };

//static guint probe_counter = 0;

/* tiler_sink_pad_buffer_probe  will extract metadata received on OSD sink pad
 * and update params for drawing rectangle, object information etc. */
 
/* *
 * @param buf
 * @desc 删除buf中的制表符以及注释
 * */
char *trimSp(char *buf)
{
    char tbuf[bufSize] = {'\0'};
    if (buf == NULL || strlen(buf) == 0)
    {
        return NULL;
    }
    int len = strlen(buf);
    int i = 0, j = 0;
    while (i < len)
    {
        //此处注释使用 //
        //若注释使用 # 则使用以下代码代替
        //if (buf[i] == '#')
        //    break;
        //if (buf[i] == '/' && buf[i + 1] == '/')
            //break;
 
        if (iscntrl(buf[i]) == 0 && isspace(buf[i]) == 0)
        {
            tbuf[j] = buf[i];
            j++;
        }
 
        i++;
    }
 
    //将结果复制到buf
    memset(buf, '\0', len);
    strncpy(buf, tbuf, strlen(tbuf));
    return buf;
}


/***
 * @param buf
 * @desc 获取 = 在字符串中的位置
 **/
int getPos(char *buf)
{
    if (buf == NULL || strlen(buf) == 0)
    {
        return -1;
    }
    int len = strlen(buf);
    int i = 0;
    while (i < len)
    {
        if (buf[i] == '=')
        {
            break;
        }
        i++;
    }
    return i++;
}



/* *
 * @param file
 * @param AppName
 * @param KeyName
 * @param KeyVal
 * @desc  从文件‘file’中的[AppName]中读取属性KeyName的值KeyVal
 * */
int ReadConf(char *file, char *AppName, char *KeyName, char *KeyVal)
{
    char buf[bufSize] = {'\0'};
    int find_app_name = 0;
 
    if (file == NULL || strlen(file) == 0) //文件名(路径)检查
    {
        return -1;
    }
    FILE *fp = fopen(file, "r"); //打开文件
 
    if (fp == NULL) //文件句柄检查
    {
        return -1;
    }
 
    while (fgets(buf, bufSize, fp) != NULL)
    {
        char *tbuf = trimSp(buf);
        int pos = getPos(tbuf);
        int len = strlen(tbuf);
 
        //printf("string:%s\n", tbuf);
 
        //查找到 [NAME]
        if (len > 0 && len == pos && tbuf[0] == '[' && tbuf[len - 1] == ']')
        {
            //存放NAME
            char *t_appname = (char *)malloc(len - 1);
            memset(t_appname, '\0', len - 1);
            strncpy(t_appname, tbuf + 1, len - 2);
 
            //查找到AppName
            if (strncmp(t_appname, AppName, strlen(t_appname)) == 0)
                find_app_name = 1;
            else
                find_app_name = 0;
 
            //注意释放空间,防止内存泄露
            free(t_appname);
        }
        else
        {
            //属性名 与 属性值
            if (len > 0 && pos != len && find_app_name)
            {
                char *val = tbuf + pos + 1;//属性值
                tbuf[pos] = '\0';//将=替换为\0  用以分割属性名 与 属性值
                char *key = tbuf;//属性名
 
                //查找到属性名
                if (strncmp(key, KeyName, strlen(key)) == 0)
                {
                    //将值复制到 KeyVal
                    strncpy(KeyVal, val, strlen(val));
                    break;
                }
            }
        }
    }
    //关闭文件句柄
    if (fp != NULL)
    {
        fclose(fp);
    }
 
    return 1;
}

static GstPadProbeReturn
tiler_src_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
    gpointer u_data)
{
    GstBuffer *buf = (GstBuffer *) info->data;
    NvDsObjectMeta *obj_meta = NULL;
    NvDsMetaList * l_frame = NULL;
    NvDsMetaList * l_obj = NULL;
    NvDsDisplayMeta *display_meta = NULL;

    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);
        int offset = 0;
		
		if(frame_meta->obj_meta_list != NULL)
		{
			display_meta = nvds_acquire_display_meta_from_pool(batch_meta);
			NvOSD_TextParams *txt_params  = &display_meta->text_params[0];
			display_meta->num_labels = 1;
			txt_params->display_text = g_malloc0 (MAX_DISPLAY_LEN);
			offset = snprintf(txt_params->display_text, MAX_DISPLAY_LEN, "WARMMING");

			/* Now set the offsets where the string should appear */
			txt_params->x_offset = 10;
			txt_params->y_offset = 12;

			/* Font , font-color and font-size */
			txt_params->font_params.font_name = "Courier";
			txt_params->font_params.font_size = 25;
			txt_params->font_params.font_color.red = 1.0;
			txt_params->font_params.font_color.green = 0.0;
			txt_params->font_params.font_color.blue = 0.0;
			txt_params->font_params.font_color.alpha = 1.0;

			/* Text background color */
			txt_params->set_bg_clr = 1;
			txt_params->text_bg_clr.red = 0.0;
			txt_params->text_bg_clr.green = 0.0;
			txt_params->text_bg_clr.blue = 0.0;
			txt_params->text_bg_clr.alpha = 0.0;

			nvds_add_display_meta_to_frame(frame_meta, display_meta);
		}
    }
	
    return GST_PAD_PROBE_OK;
}

static gboolean
bus_call (GstBus * bus, GstMessage * msg, gpointer data)
{
  GMainLoop *loop = (GMainLoop *) data;
  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_EOS:
      g_print ("End of stream\n");
      g_main_loop_quit (loop);
      break;
    case GST_MESSAGE_WARNING:
    {
      gchar *debug;
      GError *error;
      gst_message_parse_warning (msg, &error, &debug);
      g_printerr ("WARNING from element %s: %s\n",
          GST_OBJECT_NAME (msg->src), error->message);
      g_free (debug);
      g_printerr ("Warning: %s\n", error->message);
      g_error_free (error);
      break;
    }
    case GST_MESSAGE_ERROR:
    {
      gchar *debug;
      GError *error;
      gst_message_parse_error (msg, &error, &debug);
      g_printerr ("ERROR from element %s: %s\n",
          GST_OBJECT_NAME (msg->src), error->message);
      if (debug)
        g_printerr ("Error details: %s\n", debug);
      g_free (debug);
      g_error_free (error);
      g_main_loop_quit (loop);
      break;
    }
#ifndef PLATFORM_TEGRA
    case GST_MESSAGE_ELEMENT:
    {
      if (gst_nvmessage_is_stream_eos (msg)) {
        guint stream_id;
        if (gst_nvmessage_parse_stream_eos (msg, &stream_id)) {
          g_print ("Got EOS from stream %d\n", stream_id);
        }
      }
      break;
    }
#endif
    default:
      break;
  }
  return TRUE;
}

static void
cb_newpad (GstElement * decodebin, GstPad * decoder_src_pad, gpointer data)
{
  g_print ("In cb_newpad\n");
  GstCaps *caps = gst_pad_get_current_caps (decoder_src_pad);
  const GstStructure *str = gst_caps_get_structure (caps, 0);
  const gchar *name = gst_structure_get_name (str);
  GstElement *source_bin = (GstElement *) data;
  GstCapsFeatures *features = gst_caps_get_features (caps, 0);

  /* Need to check if the pad created by the decodebin is for video and not
   * audio. */
  if (!strncmp (name, "video", 5)) {
    /* Link the decodebin pad only if decodebin has picked nvidia
     * decoder plugin nvdec_*. We do this by checking if the pad caps contain
     * NVMM memory features. */
    if (gst_caps_features_contains (features, GST_CAPS_FEATURES_NVMM)) {
      /* Get the source bin ghost pad */
      GstPad *bin_ghost_pad = gst_element_get_static_pad (source_bin, "src");
      if (!gst_ghost_pad_set_target (GST_GHOST_PAD (bin_ghost_pad),
              decoder_src_pad)) {
        g_printerr ("Failed to link decoder src pad to source bin ghost pad\n");
      }
      gst_object_unref (bin_ghost_pad);
    } else {
      g_printerr ("Error: Decodebin did not pick nvidia decoder plugin.\n");
    }
  }
}

static void
decodebin_child_added (GstChildProxy * child_proxy, GObject * object,
    gchar * name, gpointer user_data)
{
  g_print ("Decodebin child added: %s\n", name);
  if (g_strrstr (name, "decodebin") == name) {
    g_signal_connect (G_OBJECT (object), "child-added",
        G_CALLBACK (decodebin_child_added), user_data);
  }
  if (g_strstr_len (name, -1, "nvv4l2decoder") == name) {
    g_print ("Seting bufapi_version\n");
    g_object_set (object, "bufapi-version", TRUE, NULL);
  }
}

static GstElement *
create_source_bin (guint index, gchar  *uri)
{
  GstElement *bin = NULL, *uri_decode_bin = NULL;
  gchar bin_name[16] = { };

  g_snprintf (bin_name, 15, "source-bin-%02d", index);
  /* Create a source GstBin to abstract this bin's content from the rest of the
   * pipeline */
  bin = gst_bin_new (bin_name);

  /* Source element for reading from the uri.
   * We will use decodebin and let it figure out the container format of the
   * stream and the codec and plug the appropriate demux and decode plugins. */
  uri_decode_bin = gst_element_factory_make ("uridecodebin", "uri-decode-bin");

  if (!bin || !uri_decode_bin) {
    g_printerr ("One element in source bin could not be created.\n");
    return NULL;
  }

  /* We set the input uri to the source element */
  g_object_set (G_OBJECT (uri_decode_bin), "uri", uri, "async-handling", 1, NULL);
  /* Connect to the "pad-added" signal of the decodebin which generates a
   * callback once a new pad for raw data has beed created by the decodebin */
  g_signal_connect (G_OBJECT (uri_decode_bin), "pad-added",
      G_CALLBACK (cb_newpad), bin);
  g_signal_connect (G_OBJECT (uri_decode_bin), "child-added",
      G_CALLBACK (decodebin_child_added), bin);

  gst_bin_add (GST_BIN (bin), uri_decode_bin);

  /* We need to create a ghost pad for the source bin which will act as a proxy
   * for the video decoder src pad. The ghost pad will not have a target right
   * now. Once the decode bin creates the video decoder and generates the
   * cb_newpad callback, we will set the ghost pad target to the video decoder
   * src pad. */
  if (!gst_element_add_pad (bin, gst_ghost_pad_new_no_target ("src",
              GST_PAD_SRC))) {
    g_printerr ("Failed to add ghost pad in source bin\n");
    return NULL;
  }

  return bin;
}

static gboolean
start_rtsp_streaming (guint rtsp_port_num, guint updsink_port_num)
{
  GstRTSPServer *server;
  GstRTSPMountPoints *mounts;
  GstRTSPMediaFactory *factory;
  char udpsrc_pipeline[512];

  char port_num_Str[64] = { 0 };
  char *encoder_name;

  encoder_name = "H264";
  
  sprintf (udpsrc_pipeline,
      "( udpsrc name=pay0 port=%d caps=\"application/x-rtp, media=video, "
      "clock-rate=90000, encoding-name=%s, payload=96 \" )",
      updsink_port_num, encoder_name);

  sprintf (port_num_Str, "%d", rtsp_port_num);

  server = gst_rtsp_server_new ();
  g_object_set (server, "service", port_num_Str, NULL);

  mounts = gst_rtsp_server_get_mount_points (server);

  factory = gst_rtsp_media_factory_new ();
  gst_rtsp_media_factory_set_launch (factory, udpsrc_pipeline);
  gst_rtsp_media_factory_set_shared (factory, TRUE);
  gst_rtsp_mount_points_add_factory (mounts, "/ds-test", factory);

  g_object_unref (mounts);

  gst_rtsp_server_attach (server, NULL);

  g_print
      ("\n *** DeepStream: Launched RTSP Streaming at rtsp://localhost:%d/ds-test ***\n\n",
      rtsp_port_num);

  return TRUE;
}

static GstElement *
create_rtsp_bin (guint index){
  GstElement *bin = NULL, *queue_out = NULL, *nvvidconv = NULL, *nvosd = NULL, *transform = NULL, *cap_filter = NULL, 
  *encoder = NULL, *rtppay = NULL, *sink = NULL;

  GstCaps *caps = NULL;
  gchar bin_name[16] = {};

  g_snprintf (bin_name, 15, "rtsp-bin-%02d", index);
  g_print ("create rtsp_bin: %s\n", bin_name);
  bin = gst_bin_new (bin_name);
  
  g_snprintf (bin_name, 15, "queue_out-%02d", index);
  queue_out = gst_element_factory_make ("queue", bin_name);
  g_snprintf (bin_name, 15, "nvvidconv-%02d", index);
  nvvidconv = gst_element_factory_make ("nvvideoconvert", bin_name);
  g_snprintf (bin_name, 15, "nvosd-%02d", index);
  nvosd = gst_element_factory_make ("nvdsosd", bin_name);
   
  g_snprintf (bin_name, 15, "transform-%02d", index);
  transform = gst_element_factory_make ("nvvideoconvert", bin_name);
  g_snprintf (bin_name, 15, "filter-%02d", index);
  cap_filter = gst_element_factory_make ("capsfilter", bin_name);
  g_snprintf (bin_name, 15, "h264-encoder-%02d", index);
  encoder = gst_element_factory_make ("nvv4l2h264enc", bin_name);
  g_snprintf (bin_name, 15, "rtppay-h264-%02d", index);
  rtppay = gst_element_factory_make ("rtph264pay", bin_name);
  g_snprintf (bin_name, 15, "udpsink-%02d", index);
  sink = gst_element_factory_make ("udpsink", bin_name);

  gst_bin_add_many (GST_BIN (bin), queue_out, nvvidconv, nvosd, transform, cap_filter, encoder, rtppay, sink, NULL);

  caps = gst_caps_from_string ("video/x-raw(memory:NVMM), format=I420");
  g_object_set (G_OBJECT (cap_filter), "caps", caps, NULL);
  g_object_set (G_OBJECT (encoder), "bitrate", 4000000, NULL);
  g_object_set (G_OBJECT (encoder), "preset-level", 1, NULL);
  g_object_set (G_OBJECT (encoder), "insert-sps-pps", 1, NULL);
  g_object_set (G_OBJECT (encoder), "bufapi-version", 1, NULL);
  gst_caps_unref(caps);

  g_object_set (G_OBJECT (sink), "port", 5400+index, "async", 1, "sync", 0, NULL);
  if (!gst_element_link_many (queue_out, nvvidconv, nvosd, transform, cap_filter, encoder, rtppay, sink, NULL)) {
    g_printerr ("Elements could not be linked: 3. Exiting.\n");
    return NULL;
  }

  gboolean ret = TRUE;

  ret = start_rtsp_streaming (8554+index, 5400+index);
  if (ret != TRUE) {
    g_print ("%s: start_rtsp_straming function failed\n", __func__);
  }

  GstPad *queue_out_sink = gst_element_get_static_pad (queue_out, "sink");
  gst_element_add_pad(bin, gst_ghost_pad_new("sink",queue_out_sink));
  gst_object_unref(queue_out_sink);

  return bin;
}

int
main (int argc, char *argv[])
{
  GMainLoop *loop = NULL;
  GstElement *pipeline = NULL, *streammux = NULL, *streamdemux = NULL, *pgie = NULL;

  GstCaps *caps = NULL;
  GstBus *bus = NULL;
  guint bus_watch_id;
  GstPad *tiler_src_pad = NULL;
  guint i,num_sources;
  guint pgie_batch_size;
  guint tiler_rows, tiler_columns;
  gchar KeyValue[MaxKeyLength];
  gchar rtsp_source [MaxKeyLength];
  GMutex struct_lock;
  
  memset(KeyValue,'\0',MaxKeyLength);
  ReadConf(CONFIG_PATH, "source", "num", KeyValue);
  num_sources = atoi(KeyValue);
  g_printerr("sourceNum is %d\n", num_sources);

  /* Standard GStreamer initialization */
  gst_init (&argc, &argv);
  loop = g_main_loop_new (NULL, FALSE);

  /* Create gstreamer elements */
  /* Create Pipeline element that will form a connection of other elements */
  pipeline = gst_pipeline_new ("dstest3-pipeline");

  /* Create nvstreammux instance to form batches from one or more sources. */
  streammux = gst_element_factory_make ("nvstreammux", "stream-muxer");
  streamdemux = gst_element_factory_make ("nvstreamdemux", "stream-demuxer");

  if (!pipeline || !streammux) {
    g_printerr ("One element could not be created. Exiting.\n");
    return -1;
  }
  gst_bin_add (GST_BIN (pipeline), streammux);
  gst_bin_add (GST_BIN (pipeline), streamdemux);

  for (i = 0; i < num_sources; i++) {
    GstPad *sinkpad, *srcpad;
    gchar pad_name[16] = {};
	gchar source_name[8] ={};
	
	g_snprintf (source_name, 7, "url_%1d", i);
	memset(rtsp_source,'\0',MaxKeyLength);
    ReadConf(CONFIG_PATH, "camera", source_name, rtsp_source);
    g_printerr("rtsp_source is %s\n", rtsp_source);  
    GstElement *source_bin = create_source_bin (i, rtsp_source);
	GstElement *rtsp_bin = create_rtsp_bin (i);

    if (!source_bin) {
      g_printerr ("Failed to create source bin. Exiting.\n");
      return -1;
    }

    gst_bin_add (GST_BIN (pipeline), source_bin);
    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 -1;
    }

    srcpad = gst_element_get_static_pad (source_bin, "src");
    if (!srcpad) {
      g_printerr ("Failed to get src pad of source bin. Exiting.\n");
      return -1;
    }

    if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
      g_printerr ("Failed to link source bin to stream muxer. Exiting.\n");
      return -1;
    }
	
    //demux
	if(! rtsp_bin)
	{
	  g_printerr ("Failed to create source bin. Exiting.\n");
      return -1;
	}
    gst_bin_add (GST_BIN (pipeline), rtsp_bin);
    g_snprintf (pad_name, 15, "src_%u", i);
    srcpad = gst_element_get_request_pad (streamdemux, pad_name);
    if (!srcpad) {
      g_printerr ("Streamdemux request src pad failed. Exiting.\n");
      return -1;
    }

    sinkpad = gst_element_get_static_pad (rtsp_bin, "sink");
    if (!sinkpad) {
      g_printerr ("Failed to get sink pad of rtsp_bin. Exiting.\n");
      return -1;
    }

    if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
      g_printerr ("Failed to link streamdemuxbin to rtsp_bin. Exiting.\n");
      return -1;
    }

    gst_object_unref (srcpad);
    gst_object_unref (sinkpad);
	
  }

  /* Use nvinfer to infer on batched frame. */
  pgie = gst_element_factory_make ("nvinfer", "primary-nvinference-engine");

  if (!pgie ) {
    g_printerr ("One element could not be created. Exiting.\n");
    return -1;
  }

  g_object_set (G_OBJECT (streammux), "width", MUXER_OUTPUT_WIDTH, "height",
      MUXER_OUTPUT_HEIGHT, "batch-size", num_sources, "live-source", 1,
      "batched-push-timeout", MUXER_BATCH_TIMEOUT_USEC, NULL);
  g_object_set (G_OBJECT (pgie),
      "config-file-path", "/home/user/XM_COSO_RTG/dstest3_pgie_config.txt","batch-size", num_sources, NULL);

  /* we add a message handler */
  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
  gst_object_unref (bus);


  gst_bin_add_many (GST_BIN (pipeline), pgie, NULL);
  if (!gst_element_link_many (streammux, pgie, streamdemux, NULL)) {
    g_printerr ("Elements could not be linked. Exiting.\n");
    return -1;
  }

  /* Set the pipeline to "playing" state */
  g_print ("Now playing:");
  for (i = 0; i < num_sources; i++) {
    g_print (" %s,", argv[i + 1]);
  }
  g_print ("\n");
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  /* Wait till pipeline encounters an error or EOS */
  g_print ("Running...\n");
  GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
                GST_DEBUG_GRAPH_SHOW_ALL, "ds-app-playing");
  g_main_loop_run (loop);
  
  //g_mutex_lock (&struct_lock);
  /* Out of the main loop, clean up nicely */
  g_print ("Returned, stopping playback\n");
  gst_element_set_state (pipeline, GST_STATE_NULL);
  //g_mutex_unlock (&struct_lock);
  g_print ("Deleting pipeline\n");
  gst_object_unref (GST_OBJECT (pipeline));
  g_source_remove (bus_watch_id);
  g_main_loop_unref (loop);
  return 0;
}

and deepstream is 4.0.2

Hi,
Could you try r32.4.4/DS5.0.1? See if it happens in latest release.

On DS4.0.2, you probably can try the patch:

In the condition the CPU usage goes to100%. Looks similar to your usecase.