title: How to use Filesink in Deepstream test application to save video
body: <p>Hello everyone my question is related with Nvidia Deepstream-5.0 SDK,</p>
  
  <p>I am trying to run a sample test <strong>deepstream-nvdsanalytics-test</strong> which is in "/source/apps/sample_apps" in NVIDIA Deepstream container. I want to save the video file by using <strong>Filesink</strong>. I got the suggestion to look into <strong>create_encode_file_bin</strong> function which is in"/source/apps/apps-common/src/deepstream_sink_bin.c".</p>
  
  <p>I tried changing the code <strong>deepstream_nvdsanalytics_test.cpp</strong> taking create_encode_file_bin as a reference but got some errors. I am posting my pipeline, edited code and error please have a look.</p>
  
  <p>pipeline used-</p>
  
  <blockquote>
    <p>pgie->nvtracker->nvdsanalytics->tiler->nvvidconv->nvosd->nvideoconvvert->caps
    filter(x/raw)->encoder->codecparse->mux->filesink</p>
  </blockquote>
  
  <p>Error-</p>
  
  <blockquote>
    <p>(deepstream-nvdsanalytics-test:203): GStreamer-WARNING **:
    16:08:13.115: Name ‘nvvideo-converter’ is not unique in bin
    ‘nvdsanalytics-test-pipeline’, not adding</p>
    
    <p>(deepstream-nvdsanalytics-test:203): GStreamer-CRITICAL **:
    16:08:13.116: gst_element_link_pads_full: assertion ‘GST_IS_ELEMENT
    (dest)’ failed Elements could not be linked. Exiting.</p>
  </blockquote>
  
  <p>code-</p>
  
  <blockquote>
  <pre><code>#include &lt;gst/gst.h&gt;
  #include &lt;glib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;math.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/time.h&gt;
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;unordered_map&gt;
  #include "gstnvdsmeta.h"
  #include "nvds_analytics_meta.h"
  #include "deepstream_config.h"
  #ifndef PLATFORM_TEGRA
  #include "gst-nvmessage.h"
  #endif
  
  [....]
  
  int
  main (int argc, char *argv[])
  {
    GMainLoop *loop = NULL;
    GstElement *pipeline = NULL, *streammux = NULL, *sink = NULL, *pgie = NULL,
               *nvtracker = NULL, *nvdsanalytics = NULL,
        *nvvidconv = NULL, *nvosd = NULL, *nvvidconv1 = NULL, *transform1 = NULL, *cap_filter = NULL, *encoder = NULL, *codecparse = NULL, *mux = NULL, *tiler = NULL;
    GstCaps *caps = NULL;
  
  #ifdef PLATFORM_TEGRA
    GstElement *transform = NULL;
  #endif
    GstBus *bus = NULL;
    guint bus_watch_id;
    GstPad *nvdsanalytics_src_pad = NULL;
    guint i, num_sources;
    guint tiler_rows, tiler_columns;
    guint pgie_batch_size;
    gulong bitrate = 2000000;
    guint profile = 0;
  
    /* Check input arguments */
    if (argc &lt; 2) {
      g_printerr ("Usage: %s &lt;uri1&gt; [uri2] ... [uriN] \n", argv[0]);
      return -1;
    }
    num_sources = argc - 1;
  
    /* Standard GStreamer initialization */
    gst_init (&amp;argc, &amp;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 ("nvdsanalytics-test-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. Exiting.\n");
      return -1;
    }
    gst_bin_add (GST_BIN (pipeline), streammux);
  
    for (i = 0; i &lt; num_sources; i++) {
      GstPad *sinkpad, *srcpad;
      gchar pad_name[16] = { };
      GstElement *source_bin = create_source_bin (i, argv[i + 1]);
  
      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;
      }
  
      gst_object_unref (srcpad);
      gst_object_unref (sinkpad);
    }
  
    /* Use nvinfer to infer on batched frame. */
    pgie = gst_element_factory_make ("nvinfer", "primary-nvinference-engine");
  
    /* Use nvtracker to track detections on batched frame. */
    nvtracker = gst_element_factory_make ("nvtracker", "nvtracker");
  
    /* Use nvdsanalytics to perform analytics on object */
    nvdsanalytics = gst_element_factory_make ("nvdsanalytics", "nvdsanalytics");
  
    /* Use nvtiler to composite the batched frames into a 2D tiled array based
     * on the source of the frames. */
    tiler = gst_element_factory_make ("nvmultistreamtiler", "nvtiler");
  
    /* Use convertor to convert from NV12 to RGBA as required by nvosd */
    nvvidconv = gst_element_factory_make ("nvvideoconvert", "nvvideo-converter");
    if (!nvvidconv) {
      g_printerr ("nvvdiconv element could not be created. Exiting.\n");
    }
  
    /* Create OSD to draw on the converted RGBA buffer */
    nvosd = gst_element_factory_make ("nvdsosd", "nv-onscreendisplay");
    if (!nvosd) {
      g_printerr ("nvosd element could not be created. Exiting.\n");
    }
  
    /* converter to convert RGBA to NV12 */
    nvvidconv1 = gst_element_factory_make ("nvvideoconvert", "nvvideo-converter1");
    if (!nvvidconv1) {
      g_printerr ("nvvidconv1 element could not be created. Exiting.\n");
    }
    /*create cap_filter */
    cap_filter = gst_element_factory_make (NVDS_ELEM_CAPS_FILTER, "cap_filter");
    if (!cap_filter) {
      g_printerr ("cap_filter element could not be created. Exiting.\n");
    }
  
    /* create cap for filter */
    caps = gst_caps_from_string ("video/x-raw, format=I420");
    g_object_set (G_OBJECT (cap_filter), "caps", caps, NULL);
  
    /* creatge encoder*/
    encoder = gst_element_factory_make (NVDS_ELEM_ENC_H264_HW, "encoder");
    if (!encoder) {
      g_printerr ("encoder element could not be created. Exiting.\n");
    }
  
    /* create transform1 */
    transform1 = gst_element_factory_make (NVDS_ELEM_VIDEO_CONV, "transform1");
    g_object_set (G_OBJECT (transform1), "gpu-id", 0, NULL);
    if (!transform1) {
      g_printerr ("transform1 element could not be created. Exiting.\n");
    }
  
    #ifdef IS_TEGRA
      g_object_set (G_OBJECT (encoder), "bufapi-version", 1, NULL);
    #endif
  
    g_object_set (G_OBJECT (encoder), "profile", profile, NULL);
    g_object_set (G_OBJECT (encoder), "bitrate", bitrate, NULL);
  
    /* create codecparse */
    codecparse = gst_element_factory_make ("h264parse", "h264-parser");
    if (!codecparse) {
      g_printerr ("codecparse element could not be created. Exiting.\n");
    }
    /* create mux */
    mux = gst_element_factory_make (NVDS_ELEM_MUX_MP4, "mux");
    if (!mux) {
      g_printerr ("mux element could not be created. Exiting.\n");
    }
  
    /* create sink */
    sink = gst_element_factory_make (NVDS_ELEM_SINK_FILE, "filesink");
    if (!sink) {
      g_printerr ("sink element could not be created. Exiting.\n");
    }
    g_object_set (G_OBJECT (sink), "location", "capture.mp4", "sync", 0, "async" , FALSE, NULL);
  
  //   /* Finally render the osd output */
  #ifdef PLATFORM_TEGRA
    transform = gst_element_factory_make ("nvegltransform", "nvegl-transform");
  #endif
  //   sink = gst_element_factory_make (NVDS_ELEM_SINK_FILE, "filesink");
  //   g_object_set (G_OBJECT (sink), "location", "capture.mp4", "sync", 0, "async" , FALSE, NULL);
  
    if (!pgie || !nvtracker || !nvdsanalytics || !nvvidconv ||
        !nvosd || !nvvidconv1 || !cap_filter || !encoder || !codecparse || !mux || !sink) {
      g_printerr ("One element could not be created. Exiting.\n");
      return -1;
    }
  
  #ifdef PLATFORM_TEGRA
    if(!transform) {
      g_printerr ("One tegra element could not be created. Exiting.\n");
      return -1;
    }
  #endif
  
    g_object_set (G_OBJECT (streammux), "width", MUXER_OUTPUT_WIDTH, "height",
        MUXER_OUTPUT_HEIGHT, "batch-size", num_sources,
        "batched-push-timeout", MUXER_BATCH_TIMEOUT_USEC, NULL);
  
    /* Configure the nvinfer element using the nvinfer config file. */
    g_object_set (G_OBJECT (pgie),
        "config-file-path", "nvdsanalytics_pgie_config.txt", NULL);
  
    /* Configure the nvtracker element for using the particular tracker algorithm. */
    g_object_set (G_OBJECT (nvtracker),
        "ll-lib-file", "/opt/nvidia/deepstream/deepstream-5.0/lib/libnvds_nvdcf.so",
        "ll-config-file", "tracker_config.yml", "tracker-width", 640, "tracker-height", 480,
         NULL);
  
    /* Configure the nvdsanalytics element for using the particular analytics config file*/
    g_object_set (G_OBJECT (nvdsanalytics),
        "config-file", "config_nvdsanalytics.txt",
         NULL);
  
    /* Override the batch-size set in the config file with the number of sources. */
    g_object_get (G_OBJECT (pgie), "batch-size", &amp;pgie_batch_size, NULL);
    if (pgie_batch_size != num_sources) {
      g_printerr
          ("WARNING: Overriding infer-config batch-size (%d) with number of sources (%d)\n",
          pgie_batch_size, num_sources);
      g_object_set (G_OBJECT (pgie), "batch-size", num_sources, NULL);
    }
  
    tiler_rows = (guint) sqrt (num_sources);
    tiler_columns = (guint) ceil (1.0 * num_sources / tiler_rows);
    /* we set the tiler properties here */
    g_object_set (G_OBJECT (tiler), "rows", tiler_rows, "columns", tiler_columns,
        "width", TILED_OUTPUT_WIDTH, "height", TILED_OUTPUT_HEIGHT, 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);
  
    /* Set up the pipeline */
    /* we add all elements into the pipeline */
  #ifdef PLATFORM_TEGRA
    gst_bin_add_many (GST_BIN (pipeline), pgie, nvtracker, nvdsanalytics ,
            nvvidconv, nvosd, nvvidconv1, cap_filter, encoder, codecparse, mux, sink,
        NULL);
  
    /* we link the elements together
     * nvstreammux -&gt; nvinfer -&gt; nvtracker -&gt; nvdsanalytics -&gt; nvtiler -&gt;
     * nvvideoconvert -&gt; nvosd -&gt; transform -&gt; sink
     */
    if (!gst_element_link_many (streammux, pgie, nvtracker, nvdsanalytics,
                                nvvidconv, nvosd, nvvidconv1, cap_filter, encoder, codecparse, mux, sink, NULL)) {
      g_printerr ("Elements could not be linked. Exiting.\n");
      return -1;
    }
  #else
    gst_bin_add_many (GST_BIN (pipeline), pgie, nvtracker, nvdsanalytics,
                      nvvidconv, nvosd, nvvidconv1, cap_filter, encoder, codecparse, mux, sink, NULL);
    /* we link the elements together
     * nvstreammux -&gt; nvinfer -&gt; nvtracker -&gt; nvdsanalytics -&gt; nvtiler -&gt;
     * nvvideoconvert -&gt; nvosd -&gt; sink
     */
    if (!gst_element_link_many (streammux, pgie, nvtracker, nvdsanalytics,
        nvvidconv, nvosd, nvvidconv1, cap_filter, encoder, codecparse, mux, 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 nvdsanalytics element, since by that time, the buffer
     * would have had got all the metadata.
     */
    nvdsanalytics_src_pad = gst_element_get_static_pad (nvdsanalytics, "src");
    if (!nvdsanalytics_src_pad)
      g_print ("Unable to get src pad\n");
    else
      gst_pad_add_probe (nvdsanalytics_src_pad, GST_PAD_PROBE_TYPE_BUFFER,
          nvdsanalytics_src_pad_buffer_probe, NULL, NULL);
  
    /* Set the pipeline to "playing" state */
    g_print ("Now playing:");
    for (i = 0; i &lt; 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");
    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;
  }
  </code></pre>
  </blockquote>
  
  <p>Please let me know if any other information is required from my side. Thank you in advance.</p>