Toybrick

rk3588使用rga进行颜色转换

lanth

注册会员

积分
147
发表于 2023-12-16 18:55:11    查看: 3469|回复: 3 | [复制链接]    打印 | 显示全部楼层
本帖最后由 lanth 于 2023-12-16 18:57 编辑

如果使用rga进行颜色转换,通过dma申请内存,rga最多可以支持多少路摄像头的图像进行颜色转换,我在使用rga对4路mipi摄像头进行颜色转换会出现虚拟内存不足导致系统崩溃重启,总的内存8g,还有其他程序一起跑的情况下。如果要进行颜色转换还有其他方法吗?有对应的例子吗?代码如下:可以帮我检查一下代码出现的错误吗?谢谢.

static const char* heap_names[] = {
  DMA_HEAP_UNCACHE_PATH,        /* 0 - default */
  DMA_HEAP_PATH,                /* 1 -*/
  DMA_HEAP_DMA32_UNCACHE_PATCH, /* 2 -*/
  DMA_HEAP_DMA32_PATCH,         /* 3 -*/
  CMA_HEAP_UNCACHE_PATH,        /* 4 -*/
  CMA_HEAP_PATH,                /* 5 -*/
};



bool GstApp::convertColor(const std::vector<uint8_t>& in, const RgaSURF_FORMAT in_format,
                          std::vector<uint8_t>& out, const RgaSURF_FORMAT out_format,
                          const size_t width, const size_t height, int dma_path)
{
  if (in.empty()) return false;
  if (in_format == out_format) {
    out = in;
    return true;
  }

  uint8_t *src_buf, *dst_buf;
  int src_dma_fd, dst_dma_fd;
  int ret = 0;
  int src_buf_size, dst_buf_size;

  src_buf_size = width * height * get_bpp_from_format(in_format);
  dst_buf_size = width * height * get_bpp_from_format(out_format);

  ret = dma_buf_alloc(heap_names[dma_path], src_buf_size, &src_dma_fd, (void**)&src_buf);
  if (ret < 0) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): alloc src dma_heap buffer failed!", __FUNCTION__);
    return false;
  }
  // /* 将CPU缓存中的数据同步到DMA缓冲区*/
  // if (dma_path == 1 || dma_path == 3) {
  //   dma_sync_cpu_to_device(src_dma_fd);
  // }
  //图像拷贝,使用rga不占用cpu
  if (!imgCopy(src_buf, in.data(), in_format, width, height)) {
    dma_buf_free(src_buf_size, &src_dma_fd, src_buf);
    return false;
  }

  rga_buffer_handle_t src_handle, dst_handle;
  rga_buffer_t src_img, dst_img;

  memset(&src_img, 0, sizeof(src_img));
  memset(&dst_img, 0, sizeof(dst_img));

  //使用dma分配内存
  ret = dma_buf_alloc(heap_names[dma_path], dst_buf_size, &dst_dma_fd, (void**)&dst_buf);
  if (ret < 0) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): alloc dst dma_heap buffer failed!", __FUNCTION__);
    dma_buf_free(src_buf_size, &src_dma_fd, src_buf);
    return false;
  }
  // /* 将CPU缓存中的数据同步到DMA缓冲区*/
  // if (dma_path == 1 || dma_path == 3) {
  //   dma_sync_cpu_to_device(src_dma_fd);
  //   dma_sync_device_to_cpu(dst_dma_fd);
  // }
  //映射dma物理地址到rga
  src_handle = importbuffer_fd(src_dma_fd, src_buf_size);
  dst_handle = importbuffer_fd(dst_dma_fd, dst_buf_size);

  if (src_handle == 0 || dst_handle == 0) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): importbuffer failed!", __FUNCTION__);
    dma_buf_free(src_buf_size, &src_dma_fd, src_buf);
    dma_buf_free(dst_buf_size, &dst_dma_fd, dst_buf);
    return false;
  }
  //绑定
  src_img = wrapbuffer_handle(src_handle, width, height, in_format);
  dst_img = wrapbuffer_handle(dst_handle, width, height, out_format);
  if (dma_path == 2) {
    //设置使用RGA2
    imconfig(IM_CONFIG_SCHEDULER_CORE, IM_SCHEDULER_RGA2_CORE0);
  } else {
    //设置使用RGA3
    imconfig(IM_CONFIG_SCHEDULER_CORE, IM_SCHEDULER_RGA3_CORE0 | IM_SCHEDULER_RGA3_CORE1);
  }
  // nv12->rgb
  ret = imcvtcolor(src_img, dst_img, in_format, out_format);

  if (ret != IM_STATUS_SUCCESS) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): imcvtcolor running failed:%s", __FUNCTION__,
                       imStrError((IM_STATUS)ret));
    if (src_handle > 0) releasebuffer_handle(src_handle);
    if (dst_handle > 0) releasebuffer_handle(dst_handle);
    dma_buf_free(src_buf_size, &src_dma_fd, src_buf);
    dma_buf_free(dst_buf_size, &dst_dma_fd, dst_buf);
    return false;
  }
  if (src_handle > 0) releasebuffer_handle(src_handle);
  dma_buf_free(src_buf_size, &src_dma_fd, src_buf);

  // 拷贝输出
  out.clear();
  out.resize(dst_buf_size);
  // /* 将DMA缓冲区中的数据同步到CPU缓存 */
  // if (dma_path == 1 || dma_path == 3) {
  //   dma_sync_device_to_cpu(dst_dma_fd);
  // }
  if (!imgCopy(out.data(), dst_buf, out_format, width, height)) {
    if (dst_handle > 0) releasebuffer_handle(dst_handle);
    dma_buf_free(dst_buf_size, &dst_dma_fd, dst_buf);
    return false;
  }
  //使用imgRgaApi需要16位对齐
  // if () {
  //   GstApp::RgaData rga;
  //   rga.in_height = height;
  //   rga.in_width = width;
  //   rga.out_height = width;
  //   rga.out_width = height;
  //   rga.img_usage = IM_USAGE::IM_HAL_TRANSFORM_ROT_90;
  //   camera_stream_->imgRgaApi(out.data(), dst_buf, out_format, GstApp::RgaApi::IMGROTATE, rga);
  // }

  //释放dma内存
  if (dst_handle > 0) releasebuffer_handle(dst_handle);
  dma_buf_free(dst_buf_size, &dst_dma_fd, dst_buf);
  return true;
}

bool GstApp::imgCopy(void* dst, const void* src, const RgaSURF_FORMAT in_format, const size_t width,
                     const size_t height)
{
  if (dst == NULL || src == NULL) {
    return false;
  }

  uint8_t* src_buf = (uint8_t*)src;
  uint8_t* dst_buf = (uint8_t*)dst;
  rga_buffer_handle_t src_handle, dst_handle;
  int ret = 0;
  rga_buffer_t src_img, dst_img;
  int src_buf_size, dst_buf_size;

  src_buf_size = width * height * get_bpp_from_format(in_format);
  dst_buf_size = width * height * get_bpp_from_format(in_format);

  memset(&src_img, 0, sizeof(src_img));
  memset(&dst_img, 0, sizeof(dst_img));
  //映射虚拟地址到rga
  src_handle = importbuffer_virtualaddr(src_buf, width, height, in_format);
  dst_handle = importbuffer_virtualaddr(dst_buf, width, height, in_format);

  if (src_handle == 0 || dst_handle == 0) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): importbuffer failed!", __FUNCTION__);
    if (src_handle > 0) releasebuffer_handle(src_handle);
    if (dst_handle > 0) releasebuffer_handle(dst_handle);
    return false;
  }
  //绑定
  src_img = wrapbuffer_handle(src_handle, width, height, in_format);
  dst_img = wrapbuffer_handle(dst_handle, width, height, in_format);

  //设置使用RGA3
  imconfig(IM_CONFIG_SCHEDULER_CORE, IM_SCHEDULER_RGA3_CORE0 | IM_SCHEDULER_RGA3_CORE1);
  /*
   * Copy the src image to the dst buffer.
      --------------        --------------
      |            |        |            |
      |  src_image |   =>   |  dst_image |
      |            |        |            |
      --------------        --------------
   */
  ret = imcopy(src_img, dst_img);
  if (ret != IM_STATUS_SUCCESS) {
    ROS_ERROR_THROTTLE(5, "GstCam::%s(): imcvtcolor running failed:%s", __FUNCTION__,
                       imStrError((IM_STATUS)ret));
    if (src_handle > 0) releasebuffer_handle(src_handle);
    if (dst_handle > 0) releasebuffer_handle(dst_handle);
    return false;
  }
  dst = (void*)dst_buf;
  if (src_handle > 0) releasebuffer_handle(src_handle);
  if (dst_handle > 0) releasebuffer_handle(dst_handle);
  return true;
}


回复

使用道具 举报

jefferyzhang

版主

积分
13606
发表于 2023-12-20 08:48:24 | 显示全部楼层
RGA本身不占用DDR,他只是一个dsp,不存在多少路的问题,分时复用。
虚拟内存不够请检查自己代码,RGA只是一个IP核,不是软件。
然后你代码里imgCopy用虚拟地址喂RGA本身就是一个很低效的操作
回复

使用道具 举报

lanth

注册会员

积分
147
 楼主| 发表于 2023-12-26 09:52:35 | 显示全部楼层
jefferyzhang 发表于 2023-12-20 08:48
RGA本身不占用DDR,他只是一个dsp,不存在多少路的问题,分时复用。
虚拟内存不够请检查自己代码,RGA只是 ...

那使用dma分配内存,如何进行内存拷贝和颜色转换两个步骤呢?有具体的步骤吗
回复

使用道具 举报

jefferyzhang

版主

积分
13606
发表于 2023-12-26 11:17:49 | 显示全部楼层
importbuffer_fd 就可以引用dma地址
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

产品中心 购买渠道 开源社区 Wiki教程 资料下载 关于Toybrick


快速回复 返回顶部 返回列表