Memory leaks reading images from Native Buffer

Hello,

Shortly:

  1. I have two CSI cameras and Jetson TX1;
  2. I have tried sycnhSensor example - works fine;
  3. I have made an OpenCVConsumer, using some ideas other people provided in the forum. It works for the first 400 frames.

Code example:

while (true){
      Argus::Status status;
      /* Acquire the frame generated by the capture request */
      UniqueObj<EGLStream::Frame> frame_l (m_FrameConsumer_l->acquireFrame(1000000000, &status));
      if (status != STATUS_OK) CONSUMER_PRINT("Failed to acquire left frame");

      UniqueObj<EGLStream::Frame> frame_r (m_FrameConsumer_r->acquireFrame(1000000000, &status));
      if (status != STATUS_OK) CONSUMER_PRINT("Failed to acquire right frame");
      EGLStream::IFrame *iFrame_l = interface_cast<EGLStream::IFrame>(frame_l);

      EGLStream::IFrame *iFrame_r = interface_cast<EGLStream::IFrame>(frame_r);
      if(!iFrame_l || !iFrame_r) break;
      CONSUMER_PRINT("Acquired Left Frame: %llu, time %llu\n",
                       static_cast<unsigned long long>(iFrame_l->getNumber()),
                       static_cast<unsigned long long>(iFrame_l->getTime()));
      CONSUMER_PRINT("Acquired Right Frame: %llu, time %llu\n",
                       static_cast<unsigned long long>(iFrame_r->getNumber()),
                       static_cast<unsigned long long>(iFrame_r->getTime()));

      /* Get the image from the frame */
      EGLStream::Image *image_l  = iFrame_l->getImage();
      EGLStream::Image *image_r  = iFrame_r->getImage();
      if(!image_l || !image_r) CONSUMER_PRINT("Failed to get the images");

/* Create an NvBuffer */
      EGLStream::NV::IImageNativeBuffer *iImageNativeBuffer_l = interface_cast<EGLStream::NV::IImageNativeBuffer>(image_l);
      if(!iImageNativeBuffer_l) CONSUMER_PRINT("Failed to create an IImageNativeBuffer");
      EGLStream::NV::IImageNativeBuffer *iImageNativeBuffer_r = interface_cast<EGLStream::NV::IImageNativeBuffer>(image_r);
      if(!iImageNativeBuffer_r) CONSUMER_PRINT("Failed to create an IImageNativeBuffer");

      int dmabuf_fd_l = iImageNativeBuffer_l->createNvBuffer(STREAM_SIZE, NvBufferColorFormat_YUV420, NvBufferLayout_Pitch, &status);
      if (status != STATUS_OK) CONSUMER_PRINT("Failed to create a native buffer");
      int dmabuf_fd_r = iImageNativeBuffer_r->createNvBuffer(STREAM_SIZE, NvBufferColorFormat_YUV420, NvBufferLayout_Pitch, &status);
      if (status != STATUS_OK) CONSUMER_PRINT("Failed to create a native buffer");

      NvBufferParams params_l, params_r;
      int ret = NvBufferGetParams(dmabuf_fd_l, &params_l);
      if (ret < 0) CONSUMER_PRINT("Failed to obtain params");
      ret = NvBufferGetParams(dmabuf_fd_r, &params_r);
      if (ret < 0) CONSUMER_PRINT("Failed to obtain params");
      int i = 0;
        
      uint8_t* data_mem_l = static_cast<uint8_t*>(mmap(NULL, params_l.pitch[i] * params_l.height[i], PROT_READ, MAP_SHARED, dmabuf_fd_l, params_l.offset[i]));
      uint8_t* data_mem_r = static_cast<uint8_t*>(mmap(NULL, params_r.pitch[i] * params_r.height[i], PROT_READ, MAP_SHARED, dmabuf_fd_r, params_r.offset[i]));
      if (data_mem_r == MAP_FAILED)
         printf("mmap failed : %s\n", strerror(errno));

const cv::Mat left = cv::Mat (params_l.height[i], params_l.width[i], CV_8UC1, data_mem_l, params_l.pitch[i]);
      const cv::Mat right = cv::Mat (params_r.height[i], params_r.width[i], CV_8UC1, data_mem_r, params_r.pitch[i]);
      cv::imshow("left", left);
      cv::imshow("right", right);

      cv::waitKey(1);

/* Destroy NvBuffers */
      ret = NvBufferDestroy(dmabuf_fd_l);
      if (ret < 0) CONSUMER_PRINT("Failed to Destroy buff");
      ret = NvBufferDestroy(dmabuf_fd_r);
      if (ret < 0) CONSUMER_PRINT("Failed to Destroy buff");
}

So I have tried various resolutions and pixel formats - it works fine for the first 400 frames, later I get the following error:

NvRmChannelSubmit: NvError_IoctlFailed with error code 22
NvRmPrivFlush: NvRmChannelSubmit failed (err = 196623, SyncPointIdx = 56, SynchPointValue = 0)

I have noticed that it only happens if mmap is executed(uncommented).

Hi stereoIV,

I guess this issue should not only happen on 2 sensor. Could you send me your sample in private message? I could take a look.

It was a memory leak, I was not using mmap properly.
Another question - is it possible to use libargus applications without display? Because whenever I try to run any sample or my own app via ssh I get the run time error, saying:

(Argus) Error NotSupported: Failed to initialize EGLDisplay (in src/eglutils/EGLUtils.cpp, function getDefaultDisplay(), line 75)

And the thing is that I do not use the display anywhere.

Do you try export DISPLAY=:0 ?

It seems that it helped. Thank you!

Another issue that I have came across is that sometimes the cameras would not launch:

CONSUMER_PRINT("Waiting until producer is connected...\n");
if (iStream->waitUntilConnected() != STATUS_OK)
        ORIGINATE_ERROR("Stream failed to connect.");

So it gets stuck at this moment and I have to restart the Jetson board in order to get it working.

CONSUMER: Waiting until producer is connected...

Is there a way to solve this either in code or using some API/command line to restart libargus daemon…?

Did you try it on reference sensor board? Can we get your APP to repo the problem?

Hi WayneWWW / stereoIV,

I seem to be facing a similar issue of memory leak. Could you please tell me what was incorrect in your implementation of mmap API and how you corrected it as I am using the same API and facing the same error.

Would be really grateful if you could share some code as well if its not an issue.

Thanks

Please refer to sample of using APIs in nvbuf_utils.h
https://devtalk.nvidia.com/default/topic/1026106/jetson-tx1/usage-of-nvbuffer-apis/post/5224382/#5224382