|
本帖最后由 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;
}
|
|