Problem creating an usb-cam inference pipeline

Hi,
i’m trying to build an app starting from deepstream-test-2.

I would like my application to input a video stream coming from a USB camera. but I get this error:

ERROR from element src_elem: Internal data stream error.
Error details: gstbasesrc.c(3055): gst_base_src_loop (): /GstPipeline:dstest2-pipeline/GstBin:source-bin-00/GstV4l2Src:src_elem:
streaming stopped, reason not-negotiated (-4)

And at the beginning i got this warning:

GStreamer-WARNING **: 13:05:53.362: Name 'src_cap_filter' is not unique in bin 'source-bin-00', not adding

I can’t understand what I’m wrong.
To create camera_source_bin I use the following function:

static GstElement *
create_camera_source_bin (guint index, gchar * uri)
{
  GstElement *bin = NULL;
  GstCaps *caps = NULL;
  gboolean ret = FALSE;

  gchar bin_name[16] = { };
  g_snprintf (bin_name, 15, "source-bin-%02d", index);
  bin = gst_bin_new (bin_name);

  GstElement *src_elem = gst_element_factory_make ("v4l2src", "src_elem");
  if (!src_elem)
  {
    g_printerr ("Could not create 'src_elem'\n");
    return NULL;
  }

  GstElement *cap_filter = gst_element_factory_make ("capsfilter", "src_cap_filter");
  if (!cap_filter){
    g_printerr ("Could not create 'src_cap_filter'\n");
    return NULL;
  }

 caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", 
		  "width", G_TYPE_INT, 480, "height", G_TYPE_INT, 640, 
		  "framerate", GST_TYPE_FRACTION, 30, 1, NULL);

  GstElement *nvvidconv1, *nvvidconv2;
  GstCapsFeatures *feature = NULL;

  nvvidconv1 = gst_element_factory_make ("videoconvert", "nvvidconv1");
  if (!nvvidconv1){
    g_printerr ("Failed to create 'nvvidcovn1'\n");
    return NULL;
  }

  feature = gst_caps_features_new ("memory:NVMM", NULL);
  gst_caps_set_features (caps, 0, feature);
  g_object_set (G_OBJECT (cap_filter), "caps", caps, NULL);

  nvvidconv2 = gst_element_factory_make ("nvvideoconvert", "nvvidconv2");
  if (!nvvidconv2){
    g_printerr ("Failed to create 'nvvidcovn2'\n");
    return NULL;
  }

  g_object_set (G_OBJECT (nvvidconv2), "gpu-id", 0, NULL);

  gst_bin_add_many (GST_BIN (bin), src_elem, cap_filter, nvvidconv1, nvvidconv2, cap_filter, NULL);

  //NVGSTDS_LINK_ELEMENT (src_elem, nvvidconv1);
  //NVGSTDS_LINK_ELEMENT (nvvidconv1, nvvidconv2);
  //NVGSTDS_LINK_ELEMENT (nvvidconv2, cap_filter);
  if (!gst_element_link (src_elem,nvvidconv1)){
    g_printerr ("Failed to link 'src_elem, nvvidcovn1'\n");
    return NULL;
  }
  if (!gst_element_link (nvvidconv1,nvvidconv2)){
    g_printerr ("Failed to link 'nvvidcovn1, nvvidcovn2'\n");
    return NULL;
  }
  if (!gst_element_link (nvvidconv2, cap_filter)){
    g_printerr ("Failed to link 'nvvidcovn2, cap_filter'\n");
    return NULL;
  }

  // NVGSTDS_BIN_ADD_GHOST_PAD (bin, cap_filter, "src");
  GstPad *gstpad = gst_element_get_static_pad (cap_filter, "src");
  gst_element_add_pad (bin, gst_ghost_pad_new ("src", gstpad));
  gst_object_unref(gstpad);

  gchar device[64];
  g_snprintf (device, sizeof (device), "/dev/video%d", 0);
  g_object_set (G_OBJECT (src_elem), "device", device, NULL);

  return bin;
}

And i use that function in this way:

 GstPad *sinkpad, *srcpad;
    gchar pad_name[16] = { };
    GstElement *source_bin = create_camera_source_bin (0, argv[1]);

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

    gst_bin_add (GST_BIN (pipeline), source_bin);

    g_snprintf (pad_name, 15, "sink_%u", 1);
    sinkpad = gst_element_get_request_pad (streammux, pad_name);
    if (!sinkpad) {
      g_printerr ("Streammux request sink pad failed. Exiting3.\n");
      return -1;
    }

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

    if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
      g_printerr ("Failed to link source bin to stream muxer. Exiting5.\n");
      return -1;
    }

    gst_object_unref (srcpad);
    gst_object_unref (sinkpad);

For your information, I also attach all the main function

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

  #ifdef PLATFORM_TEGRA
  GstElement * transform = NULL;
  #endif
  GstBus * bus = NULL;
  guint bus_watch_id = 0;
  GstPad * osd_sink_pad = NULL;

  /* Check input arguments */
  if (argc != 2) {
    g_printerr("Usage: %s <elementary H264 filename>\n", argv[0]);
    return -1;
  }

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

  /* Create gstreamer elements */

  /* Create Pipeline element that will be a container of other elements */
  pipeline = gst_pipeline_new("dstest2-pipeline");

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

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

	  gst_bin_add (GST_BIN (pipeline), streammux);

//AAAAAAAAAAA

    GstPad *sinkpad, *srcpad;
    gchar pad_name[16] = { };
    GstElement *source_bin = create_camera_source_bin (0, argv[1]);

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

    gst_bin_add (GST_BIN (pipeline), source_bin);

    g_snprintf (pad_name, 15, "sink_%u", 1);
    sinkpad = gst_element_get_request_pad (streammux, pad_name);
    if (!sinkpad) {
      g_printerr ("Streammux request sink pad failed. Exiting3.\n");
      return -1;
    }

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

    if (gst_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK) {
      g_printerr ("Failed to link source bin to stream muxer. Exiting5.\n");
      return -1;
    }

    gst_object_unref (srcpad);
    gst_object_unref (sinkpad);
  
//AAAAAAAAAAA

  /* Use nvinfer to run inferencing on decoder's output,
   * behaviour of inferencing is set through config file */
  pgie = gst_element_factory_make("nvinfer", "primary-nvinference-engine");

  /* We need to have a tracker to track the identified objects */

  nvtracker = gst_element_factory_make("nvtracker", "tracker");
  g_print("TRACKER ATTIVO!!!\n");

  /* Use convertor to convert from NV12 to RGBA as required by nvosd */
  nvvidconv = gst_element_factory_make("nvvideoconvert", "nvvideo-converter");

  /* Create OSD to draw on the converted RGBA buffer */
  nvosd = gst_element_factory_make("nvdsosd", "nv-onscreendisplay");

  /* Finally render the osd output */
  #ifdef PLATFORM_TEGRA
  transform = gst_element_factory_make("nvegltransform", "nvegl-transform");
  #endif
  sink = gst_element_factory_make("nveglglessink", "nvvideo-renderer");

  if (!pgie ||
    !nvtracker|| !nvvidconv || !nvosd || !sink) {
    g_printerr("One element could not be created. Exiting.6\n");
    return -1;
  }

  #ifdef PLATFORM_TEGRA
  if (!transform) {
    g_printerr("One tegra element could not be created. Exiting.7\n");
    return -1;
  }
  #endif

  /* Set the input filename to the source element */
  //g_object_set(G_OBJECT(source), "location", argv[1], NULL);

  g_object_set(G_OBJECT(streammux), "batch-size", 1, NULL);

  g_object_set(G_OBJECT(streammux), "width", MUXER_OUTPUT_WIDTH, "height",
    MUXER_OUTPUT_HEIGHT,
    "batched-push-timeout", MUXER_BATCH_TIMEOUT_USEC, NULL);

  /* Set all the necessary properties of the nvinfer element,
   * the necessary ones are : */
  g_object_set(G_OBJECT(pgie), "config-file-path", PGIE_CONFIG_FILE, NULL);


  /* Set necessary properties of the tracker element. */
  if (!set_tracker_properties(nvtracker)) {
    g_printerr("Failed to set tracker properties. Exiting.\n");
    return -1;
  }

  /* 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);

  /* Set up the pipeline */
  /* we add all elements into the pipeline */
  /* decoder | pgie1 | nvtracker| etc.. */
  #ifdef PLATFORM_TEGRA
  gst_bin_add_many(GST_BIN(pipeline),
    pgie, nvtracker,
    nvvidconv, nvosd, transform, sink, NULL);
  #else
  gst_bin_add_many(GST_BIN(pipeline),
    pgie, nvtracker,
    nvvidconv, nvosd, sink, NULL);
  #endif

 
  #ifdef PLATFORM_TEGRA
  if (!gst_element_link_many(streammux, pgie, nvtracker,

      nvvidconv, nvosd, transform, sink, NULL)) {
    g_printerr("Elements could not be linked. Exiting.\n");
    return -1;
  }
  #else
  if (!gst_element_link_many(streammux, pgie, nvtracker,
 
      nvvidconv, nvosd, sink, NULL)) {
    g_printerr("Elements could not be linked. Exiting.\n");
    return -1;
  } 
  #endif

  /* Lets add probe to get informed of the meta data generated, we add probe to
   * the sink pad of the osd element, since by that time, the buffer would have
   * had got all the metadata. */
  osd_sink_pad = gst_element_get_static_pad(nvosd, "sink");
  if (!osd_sink_pad)
    g_print("Unable to get sink pad\n");
  else
    gst_pad_add_probe(osd_sink_pad, GST_PAD_PROBE_TYPE_BUFFER,
      osd_sink_pad_buffer_probe, NULL, NULL);

  /* Set the pipeline to "playing" state */
  g_print("Now playing: %s\n", argv[1]);
  gst_element_set_state(pipeline, GST_STATE_PLAYING);

  /* Iterate */
  g_print("Running...\n");
  g_main_loop_run(loop);

  /* Out of the main loop, clean up nicely */
  g_print("Returned, stopping playback\n");
  gst_element_set_state(pipeline, GST_STATE_NULL);
  g_print("Deleting pipeline\n");
  gst_object_unref(GST_OBJECT(pipeline));
  g_source_remove(bus_watch_id);
  g_main_loop_unref(loop);
  return 0;
}

Thanks you all

Hi,
Can you try this pipeline:

gst-launch-1.0 v4l2src device=/dev/video0 !\
nvvideoconvert !\
"video/x-raw(memory:NVMM),format=NV12" !\
queue !\
nvstreammux0.sink_0 nvstreammux name=nvstreammux0 batch-size=1 batched-push-timeout=40000 width=1280 height=720 live-source=TRUE !\
queue !\
nvvideoconvert !\
queue !\
nvinfer config-file-path=/opt/nvidia/deepstream/deepstream-5.0/samples/configs/deepstream-app/config_infer_primary.txt !\
queue !\
nvdsosd process-mode=HW_MODE !\
queue !\
nvoverlaysink sync=false

how should i change the c file to set this pipeline?
Thanks

You need to add a nvvideoconvert after the source:

nvvidconv0 = gst_element_factory_make ("nvvideoconvert", "nvvidconv0");