Toybrick
标题:
rk3588使用rga进行颜色转换
[打印本页]
作者:
lanth
时间:
2023-12-16 18:55
标题:
rk3588使用rga进行颜色转换
本帖最后由 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
时间:
2023-12-20 08:48
RGA本身不占用DDR,他只是一个dsp,不存在多少路的问题,分时复用。
虚拟内存不够请检查自己代码,RGA只是一个IP核,不是软件。
然后你代码里imgCopy用虚拟地址喂RGA本身就是一个很低效的操作
作者:
lanth
时间:
2023-12-26 09:52
jefferyzhang 发表于 2023-12-20 08:48
RGA本身不占用DDR,他只是一个dsp,不存在多少路的问题,分时复用。
虚拟内存不够请检查自己代码,RGA只是 ...
那使用dma分配内存,如何进行内存拷贝和颜色转换两个步骤呢?有具体的步骤吗
作者:
jefferyzhang
时间:
2023-12-26 11:17
importbuffer_fd 就可以引用dma地址
欢迎光临 Toybrick (https://t.rock-chips.com/)
Powered by Discuz! X3.3