Sending dmabuf fd returned from jpeg_decode example to another process

On a Jetson AGX Thor, I am trying to pass the fd returned from NvJPEGDecoder (jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp) or from NvBufSurf::NvAllocate to another process.

To do that, I combine the steps in 06_jpeg_decode example with 13_argus_multi_camera transport example, where I send the file descriptor over socket with SCM_RIGHTS + the NvBufSurfaceMapParams. However, on the sender side (which runs the NvJPEGDecoder), when I try to run NvBufSurfaceGetMapParams, it prints “NvBufSurfaceCudaMemGetMapParams: Invalid argument extendedMapParams” and fails (return -1). It fails with both the fd returned from NvJPEGDecoder::decodeToFd, and the dmabuf_fd after NvTransform (created with NvBufSurf::NvAllocate).

Could you help me?

My code structure is something like:

#include "NvJpegDecoder.h"
#include "NvBufSurface.h"

#include <chrono>
#include <fstream>
#include <thread>
#include <iostream>


int main() {
  std::ifstream file("test.jpg", std::ios::binary | std::ios::ate);
  if (!file.is_open()) {
    return 1;
  }
  std::streamsize filesize = file.tellg();
  if (filesize <= 0) {
    return 1;
  }
  file.seekg(0, std::ios::beg);
  std::vector<unsigned char> jpeg_data(filesize);
  if (!file.read(reinterpret_cast<char*>(jpeg_data.data()), filesize)) {
    return 1;
  }
  const auto jpeg_size = filesize;

  auto* decoder = NvJPEGDecoder::createJPEGDecoder("jpeg_dec");
  decoder->setMemType(NVBUF_MEM_CUDA_DEVICE);
  decoder->setUseExternalBuffer(true);
  int tmp_fd;
  uint32_t pixfmt, width, height;
  decoder->decodeToFd(tmp_fd, jpeg_data.data(), jpeg_size, pixfmt, width, height);
  NvBufSurface *nvbuf_surf = 0;
  if (NvBufSurfaceFromFd(tmp_fd, (void **)(&nvbuf_surf)) == -1) {
    return -1;
  }

  NvBufSurf::NvCommonAllocateParams params = {0};
  params.memType = NVBUF_MEM_CUDA_PINNED;
  params.width = width;
  params.height = height;
  params.layout = NVBUF_LAYOUT_PITCH;
  params.colorFormat = NVBUF_COLOR_FORMAT_NV12_ER; // Convert to NV12_ER
  params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;

  int dst_dma_fd;
  if (NvBufSurf::NvAllocate(&params, 1, &dst_dma_fd) == -1) {
    return -1;
  }

  NvBufSurf::NvCommonTransformParams transform_params = {0};
  transform_params.src_top = 0;
  transform_params.src_left = 0;
  transform_params.src_width = width;
  transform_params.src_height = height;
  transform_params.dst_top = 0;
  transform_params.dst_left = 0;
  transform_params.dst_width = width;
  transform_params.dst_height = height;
  transform_params.flag = NVBUFSURF_TRANSFORM_FILTER;
  transform_params.flip = NvBufSurfTransform_None;
  transform_params.filter = NvBufSurfTransformInter_Nearest;

  if (NvBufSurf::NvTransform(&transform_params, tmp_fd, dst_dma_fd) == -1){
    NvBufSurf::NvDestroy(dst_dma_fd);
    return -1;
  }

  if (NvBufSurfaceFromFd(dst_dma_fd, (void**)(&nvbuf_surf)) == -1) {
    return -1;
  }
  NvBufSurfaceMapParams buf_par = {0};
  if (NvBufSurfaceGetMapParams(nvbuf_surf, 0, &buf_par) == -1) { /// This fails always, with both tmp_fd and dst_dma_fd
    return -1;
  }
  // Send dst_dma_fd over socket with SCM_RIGHTS + buf_par, and load with NvBufSurfaceImport
 
  return 0;
}

Ah, it works when I changed the memType to:

params.memType = NVBUF_MEM_SURFACE_ARRAY;