Green blocks in the videos when we transcode from H265 to H264

Continuing the discussion from Issue with smart record If we record through h265 stream:

**• Hardware Platform -----> 4060
**• DeepStream Version ------> 7.1
**• TensorRT Version ---------> 8.6.2.1
**• NVIDIA GPU Driver Version --------> 560.35.05

I tried by implementing transcode functionality in the populate_rtspsrc_bin_video in opt/nvidia/deepstream/deepstream-7.1/sources/gst-plugins/gst-nvurisrcbin/gstdsnvurisrcbin.cpp. Below is my modified code of populate_rtspsrc_bin_video().

populate_rtspsrc_bin_video (GstDsNvUriSrcBin * bin, GstPad * pad,
    const char *encoding_name)
{
  GstCapsUPtr caps = NULL;
  GstCapsFeatures *feature = NULL;

  if (bin->video_elem_populated) {
    GstPadUPtr sinkpad = gst_element_get_static_pad (bin->depay, "sink");
    return gst_pad_link (pad, sinkpad) == GST_PAD_LINK_OK;
  }

  if (!bin->depay) {
    if (!g_strcmp0 (encoding_name, "H264")) {
      bin->depay = gst_element_factory_make ("rtph264depay", "depay");
      bin->parser = gst_element_factory_make ("h264parse", "parser");
    } else if (!g_strcmp0 (encoding_name, "H265")) {
      bin->depay = gst_element_factory_make ("rtph265depay", "depay");
      bin->parser = gst_element_factory_make ("h265parse", "parser");

      bin->caps_filter_h265 = gst_element_factory_make("capsfilter", "caps_filter_h265");
      GstCaps *h265_caps = gst_caps_new_simple("video/x-h265", "alignment", G_TYPE_STRING, "au", NULL);
      g_object_set(G_OBJECT(bin->caps_filter_h265), "caps", h265_caps, NULL);
      gst_caps_unref(h265_caps);

      bin->decoder = gst_element_factory_make("nvv4l2decoder", "h265_decoder");
      bin->transcode_queue = gst_element_factory_make("queue", "transcode_queue");
      bin->h264_encoder = gst_element_factory_make("nvv4l2h264enc", "h264_encoder");

      bin->caps_filter_h264 = gst_element_factory_make("capsfilter", "caps_filter_h264");
      GstCaps *h264_caps = gst_caps_new_simple("video/x-h264", "alignment", G_TYPE_STRING, "au", NULL);
      g_object_set(G_OBJECT(bin->caps_filter_h264), "caps", h264_caps, NULL);
      gst_caps_unref(h264_caps);

      bin->h264_parser = gst_element_factory_make("h264parse", "h264_parser");
    } else if (!g_strcmp0 (encoding_name, "MP4V-ES")) {
      bin->depay = gst_element_factory_make ("rtpmp4vdepay", "depay");
      bin->parser = gst_element_factory_make ("mpeg4videoparse", "parser");
    } else {
      GST_ELEMENT_ERROR (bin, STREAM, FAILED, ("%s not supported",
              encoding_name), (NULL));
      return FALSE;
    }

    if (!bin->depay) {
      GST_ELEMENT_ERROR (bin, STREAM, FAILED, ("Failed to create 'depay'"),
          (NULL));
      return FALSE;
    }

    if (!g_strcmp0 (encoding_name, "H265")) {
      gst_bin_add_many (GST_BIN (bin), bin->depay, bin->parser,
                        bin->caps_filter_h265, bin->decoder, bin->transcode_queue,
                        bin->h264_encoder, bin->caps_filter_h264, bin->h264_parser, NULL);

      NVGSTDS_LINK_ELEMENT (bin->depay, bin->parser, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->parser, bin->caps_filter_h265, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->caps_filter_h265, bin->decoder, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->decoder, bin->transcode_queue, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->transcode_queue, bin->h264_encoder, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->h264_encoder, bin->caps_filter_h264, FALSE);
      NVGSTDS_LINK_ELEMENT (bin->caps_filter_h264, bin->h264_parser, FALSE);
    } else {
      gst_bin_add_many (GST_BIN (bin), bin->depay, bin->parser, NULL);
      NVGSTDS_LINK_ELEMENT (bin->depay, bin->parser, FALSE);
    }

    if (!gst_element_sync_state_with_parent (bin->depay) ||
        !gst_element_sync_state_with_parent (bin->parser) ||
        (!g_strcmp0 (encoding_name, "H265") &&
         (!gst_element_sync_state_with_parent (bin->caps_filter_h265) ||
          !gst_element_sync_state_with_parent (bin->decoder) ||
          !gst_element_sync_state_with_parent (bin->transcode_queue) ||
          !gst_element_sync_state_with_parent (bin->h264_encoder) ||
          !gst_element_sync_state_with_parent (bin->caps_filter_h264) ||
          !gst_element_sync_state_with_parent (bin->h264_parser)))) {
      GST_ELEMENT_ERROR (bin, STREAM, FAILED, ("Failed to sync state"), (NULL));
      return FALSE;
    }
  }

  GstPadUPtr sinkpad = gst_element_get_static_pad (bin->depay, "sink");
  if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
    return FALSE;
  }

  bin->tee_rtsp_pre_decode =
      gst_element_factory_make ("tee", "tee_rtsp_pre_decode");
  if (!bin->tee_rtsp_pre_decode) {
    GST_ELEMENT_ERROR (bin, RESOURCE, FAILED,
        ("Failed to create 'tee_rtsp'"), (NULL));
    return FALSE;
  }

  bin->tee_rtsp_post_decode =
      gst_element_factory_make ("tee", "tee_rtsp_post_decode");
  if (!bin->tee_rtsp_post_decode) {
    GST_ELEMENT_ERROR (bin, RESOURCE, FAILED,
        ("Failed to create 'tee_rtsp'"), (NULL));
    return FALSE;
  }

  bin->dec_que = gst_element_factory_make ("queue", "dec_que");
  if (!bin->dec_que) {
    GST_ELEMENT_ERROR (bin, RESOURCE, FAILED,
        ("Failed to create 'queue'"), (NULL));
    return FALSE;
  }

  if (bin->config->rtsp_reconnect_interval_sec > 0) {
    NVGSTDS_ELEM_ADD_PROBE (bin,
        bin->depay, "src", rtspsrc_monitor_probe_func,
        GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, bin);
  }

  bin->decodebin = gst_element_factory_make ("decodebin", "decodebin");
  if (!bin->decodebin) {
    GST_ELEMENT_ERROR (bin, STREAM, FAILED,
        ("Failed to create 'decodebin'"), (NULL));
    return FALSE;
  }

  g_signal_connect (G_OBJECT (bin->decodebin), "child-added",
      G_CALLBACK (decodebin_child_added), bin);


  bin->cap_filter = gst_element_factory_make ("queue", "queue");
  if (!bin->cap_filter) {
    GST_ELEMENT_ERROR (bin, STREAM, FAILED,
        ("Failed to create 'queue'"), (NULL));
    return FALSE;
  }

  g_signal_connect (G_OBJECT (bin->decodebin), "pad-added",
      G_CALLBACK (cb_newpad2), bin);

  bin->nvvidconv = gst_element_factory_make ("nvvideoconvert", "nvvidconv");
  g_object_set (G_OBJECT (bin->nvvidconv), "disable-passthrough", bin->config->disable_passthrough, NULL);
  g_object_set (G_OBJECT (bin->nvvidconv), "gpu-id", bin->config->gpu_id, NULL);

  if (!bin->nvvidconv) {
    GST_ELEMENT_ERROR (bin, STREAM, FAILED,
        ("Could not create element 'nvvidconv_elem'"), (NULL));
    return FALSE;
  }
  caps = gst_caps_new_empty_simple ("video/x-raw");
  feature = gst_caps_features_new ("memory:NVMM", NULL);
  gst_caps_set_features (caps, 0, feature);

  bin->cap_filter1 =
      gst_element_factory_make ("capsfilter", "src_cap_filter_nvvidconv");
  if (!bin->cap_filter1) {
    GST_ELEMENT_ERROR (bin, STREAM, FAILED,
        ("Could not create 'queue'"), (NULL));
    return FALSE;
  }

  g_object_set (G_OBJECT (bin->cap_filter1), "caps", caps.get (), NULL);

  gst_bin_add_many (GST_BIN (bin),
      bin->tee_rtsp_pre_decode, bin->dec_que,
      bin->tee_rtsp_post_decode, bin->decodebin,
      bin->cap_filter, bin->nvvidconv, bin->cap_filter1, NULL);

  if (!gst_element_sync_state_with_parent (bin->tee_rtsp_pre_decode) ||
      !gst_element_sync_state_with_parent (bin->dec_que) ||
      !gst_element_sync_state_with_parent (bin->tee_rtsp_post_decode) ||
      !gst_element_sync_state_with_parent (bin->decodebin) ||
      !gst_element_sync_state_with_parent (bin->cap_filter) ||
      !gst_element_sync_state_with_parent (bin->nvvidconv) ||
      !gst_element_sync_state_with_parent (bin->cap_filter1)) {
    GST_ELEMENT_ERROR (bin, STREAM, FAILED,
        ("Failed to sync child states"), (NULL));
    return FALSE;
  }

  // If H265 input, link H264 parser to tee
  if (!g_strcmp0 (encoding_name, "H265"))
    NVGSTDS_LINK_ELEMENT (bin->h264_parser, bin->tee_rtsp_pre_decode, FALSE);
  else
    NVGSTDS_LINK_ELEMENT (bin->parser, bin->tee_rtsp_pre_decode, FALSE);

  link_element_to_tee_src_pad (bin->tee_rtsp_pre_decode, bin->dec_que);
  NVGSTDS_LINK_ELEMENT (bin->dec_que, bin->decodebin, FALSE);

  if (bin->recordCtx && (bin->config->smart_rec_mode == 0 || bin->config->smart_rec_mode == 1))
    link_element_to_tee_src_pad (bin->tee_rtsp_pre_decode,
        bin->recordCtx->recordbin);

  link_element_to_tee_src_pad (bin->tee_rtsp_post_decode, bin->cap_filter);
  NVGSTDS_LINK_ELEMENT (bin->cap_filter, bin->nvvidconv, FALSE);
  NVGSTDS_LINK_ELEMENT (bin->nvvidconv, bin->cap_filter1, FALSE);

  GstPadUPtr target_pad = gst_element_get_static_pad (bin->cap_filter1, "src");
  GstPad *src_pad = gst_ghost_pad_new_from_template ("vsrc_0", target_pad,
      gst_static_pad_template_get (&gst_nvurisrc_bin_vsrc_template));

  gst_pad_add_probe (src_pad, GST_PAD_PROBE_TYPE_QUERY_BOTH,
      src_pad_query_probe, bin, NULL);

  gst_pad_set_active (src_pad, TRUE);
  gst_element_add_pad (GST_ELEMENT (bin), src_pad);

  bin->video_elem_populated = TRUE;
  return TRUE;
}

once I downloaded and checked my recorded videos which consists of green blocks on the frames. I have attached a frame below. please check the above modified code and please let us know why is it happening and what is the fix for this?

  1. I dont find the code for NvDsSRStart, NvDsSRStop in smart record. Is it open source or not?
    Thank you @fanzh
  1. did the “green blocks” issue happen at the begnning or after a while? Here are some steps to narrow down this issue.
    1.1 if linking decoder to nveglglessink or filesink, does this issue still persist? wondering if the raw data is fine. Here are some samples.
gst-launch-1.0  filesrc location=/opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 ! qtdemux ! h264parse ! nvv4l2decoder ! nveglglessink
gst-launch-1.0 filesrc location=720p.yuv ! videoparse width=1280 height=720 format=i420 framerate=1/1 ! nvvideoconvert ! 'video/x-raw,format=NV12' !  filesink location=3.yuv

1.2 if linking nvv4l2h264enc to filesink, does this issue still persist? wondering if the H264 data is fine. Here is a sample.

gst-launch-1.0  filesrc location=/opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 ! qtdemux ! h264parse ! nvv4l2decoder  ! nvvideoconvert ! 'video/x-raw(memory:NVMM),format=I420' ! nvv4l2h264enc bitrate=1000000 ! filesink location=test.264
  1. currently, smart recording low-level implementation is closed source.

There is no update from you for a period, assuming this is not an issue anymore. Hence we are closing this topic. If need further support, please open a new one. Thanks

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.