The RK3588S includes an RGA3, which is essentially a 2D graphics transform gas pedal capable of supporting typical 2D image transform processing such as scaling, merging, and watermark overlay. The maximum supported resolution is 8192x8192 for image processing.
Since there is an open source sdk, it is recommended to build the SDK on the PC side to ensure a consistent build environment. the cross-compile environment that comes with the SDK is the same as the environment on the board.
RGA library source code can only be obtained from the SDK, you can pull the entire SDK. RGA source code is in the root directory of the SDK under the
external/linux-rga
it is recommended to copy the source code to a separate working directory to use!
If you don't want to download the whole SDK, you can download the linux-rga package from the following link
First configure the cross-compilation environment. In the SDK root directory , execute the following lines
DIR=$(pwd)
export PATH=$PATH:${DIR}/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=aarch64
In the rga working directory, open the toolchains directory.
Then modify the compiler directory in the toolchain_linux.cmake file as follows
# Replace XXX with the path to the SDK.
SET(TOOLCHAIN_HOME "XXX/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu")
Then execute it in the rga working directory .
./cmake-linux.sh
You can compile it, and the message when the compilation is finished is as follows
After compiling, you can see the following file in the build/build_linux directory
librga.a is the static library librga.so is the dynamic library under samples/im2d_api_demo there is a rgaImDemo as a test demo.
Place the rgaImDemo file generated in the previous step on the board. First, verify that the environment on the board is correct by running
./rgaImDemo --querystring
.
If you see the following result, it means the environment on the board is OK.
Find a test image, this image needs to be 1280x720 in rgba8888 format, there are two of them in samples/sample_file
, here we use in1w1280-h720-rgba8888.bin. on PC you can use YUView to view the RAW format image. In YUView you can see the content as follows
Put it in the /usr/data/ directory on the board and rename it in0w1280-h720-rgba8888.bin
root@linaro-alip:~# ls -ll /usr/data
-rw-rw-rw- 1 root root 3686400 November 26 2023 in0w1280-h720-rgba8888.bin
Then test the image scaling and rotation transformations, which are the most commonly used functions within RGA
# resize to 720p
root@linaro-alip:~# ./rgaImDemo --resize up
Start selecting mode 0
im2d resize ..
up resize ...
MODE = 2
open file
rga_api version 1.8.1_[3]
resizing .... cost time 3927 us, Run successfully
open /usr/data/out0w1920-h1080-rgba8888.bin and write ok
root@linaro-alip:~#
root@linaro-alip:~#
# resize to 480p
root@linaro-alip:~# ./rgaImDemo --resize down
Start selecting mode 0
im2d resize ..
down resize ...
MODE = 2
open file
rga_api version 1.8.1_[3]
resizing .... cost time 2429 us, Run successfully
open /usr/data/out0w720-h480-rgba8888.bin and write ok
root@linaro-alip:~#
root@linaro-alip:~#
root@linaro-alip:~#
# Rotate 90 degrees
root@linaro-alip:~# ./rgaImDemo --rotate 90
Start selecting mode 0
im2d rotate ..
rotation 90 ...
MODE = 4
open file
rga_api version 1.8.1_[3]
rotating .... cost time 3192 us, Run successfully
open /usr/data/out0w720-h1280-rgba8888.bin and write ok
Then put the generated 3 files on the PC's YUView to view them
The following is an example of the im2d_api_demo source code in the demo, which introduces the use of the RGA dynamic library.
This source file is located in the samples directory of the linux-rga project.
First look at the main function, which first uses readArguments to parse out all the parameters, and then according to the parameter type, performs different actions
int main(int argc, char* argv[]) {
int ret = 0, while_time = 0;
int parm_data[MODE_MAX] = {0};
int COLOR;
IM_USAGE ROTATE;
IM_USAGE FLIP;
int MODE;
IM_INFORMATION IM_INFO;
IM_STATUS STATUS;
im_rect src_rect;
im_rect dst_rect;
rga_buffer_t src;
rga_buffer_t dst;
rga_buffer_handle_t src_handle;
rga_buffer_handle_t dst_handle;
char* src_buf = NULL;
char* dst_buf = NULL;
memset(&src_rect, 0, sizeof(src_rect));
memset(&dst_rect, 0, sizeof(dst_rect));
memset(&src, 0, sizeof(src));
memset(&dst, 0, sizeof(dst));
MODE = readArguments(argc, argv, parm_data);
...
/********** Get parameters **********/
if(MODE != MODE_QUERYSTRING) {
src_buf = (char*)malloc(SRC_WIDTH*SRC_HEIGHT*get_bpp_from_format(SRC_FORMAT));
dst_buf = (char*)malloc(DST_WIDTH*DST_HEIGHT*get_bpp_from_format(DST_FORMAT));
ret = get_buf_from_file(src_buf, SRC_FORMAT, SRC_WIDTH, SRC_HEIGHT, 0);
...
if(MODE == MODE_BLEND || MODE == MODE_FILL) {
ret = get_buf_from_file(dst_buf, DST_FORMAT, DST_WIDTH, DST_HEIGHT, 1);
...
} else {
memset(dst_buf,0x00,DST_WIDTH*DST_HEIGHT*get_bpp_from_format(DST_FORMAT));
}
src_handle = importbuffer_virtualaddr(src_buf, SRC_WIDTH, SRC_HEIGHT, SRC_FORMAT);
...
dst_handle = importbuffer_virtualaddr(dst_buf, DST_WIDTH, DST_HEIGHT, DST_FORMAT);
...
src = wrapbuffer_handle(src_handle, SRC_WIDTH, SRC_HEIGHT, SRC_FORMAT);
dst = wrapbuffer_handle(dst_handle, DST_WIDTH, DST_HEIGHT, DST_FORMAT);
...
}
do {
...
switch(MODE) {
case MODE_QUERYSTRING :
IM_INFO = (IM_INFORMATION)parm_data[MODE_QUERYSTRING];
printf("\n%s\n", querystring(IM_INFO));
break;
case MODE_COPY : //rgaImDemo --copy
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imcopy(src, dst);
...
break;
case MODE_RESIZE : //rgaImDemo --resize=up/down
releasebuffer_handle(dst_handle);
dst_handle = -1;
switch(parm_data[MODE_RESIZE]) {
case IM_UP_SCALE :
if (dst_buf != NULL) {
free(dst_buf);
dst_buf = NULL;
}
dst_buf = (char*)malloc(1920*1080*get_bpp_from_format(DST_FORMAT));
...
memset(dst_buf,0x00,1920*1080*get_bpp_from_format(DST_FORMAT));
dst_handle = importbuffer_virtualaddr(dst_buf, 1920, 1080, DST_FORMAT);
...
dst = wrapbuffer_handle(dst_handle, 1920, 1080, DST_FORMAT);
...
break;
case IM_DOWN_SCALE :
if (dst_buf != NULL) {
free(dst_buf);
dst_buf = NULL;
}
dst_buf = (char*)malloc(720*480*get_bpp_from_format(DST_FORMAT));
memset(dst_buf,0x00,720*480*get_bpp_from_format(DST_FORMAT));
dst_handle = importbuffer_virtualaddr(dst_buf, 720, 480, DST_FORMAT);
...
dst = wrapbuffer_handle(dst_handle, 720, 480, DST_FORMAT);
...
break;
}
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imresize(src, dst);
break;
case MODE_CROP : //rgaImDemo --crop
src_rect.x = 100;
src_rect.y = 100;
src_rect.width = 300;
src_rect.height = 300;
ret = imcheck(src, dst, src_rect, dst_rect, IM_CROP);
...
STATUS = imcrop(src, dst, src_rect);
...
break;
case MODE_ROTATE : //rgaImDemo --rotate=90/180/270
ROTATE = (IM_USAGE)parm_data[MODE_ROTATE];
if (IM_HAL_TRANSFORM_ROT_90 == ROTATE || IM_HAL_TRANSFORM_ROT_270 == ROTATE) {
dst.width = src.height;
dst.height = src.width;
dst.wstride = src.hstride;
dst.hstride = src.wstride;
}
ret = imcheck(src, dst, src_rect, dst_rect, ROTATE);
...
STATUS = imrotate(src, dst, ROTATE);
...
break;
case MODE_FLIP : //rgaImDemo --flip=H/V
FLIP = (IM_USAGE)parm_data[MODE_FLIP];
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imflip(src, dst, FLIP);
...
break;
case MODE_TRANSLATE : //rgaImDemo --translate
src_rect.x = 300;
src_rect.y = 300;
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imtranslate(src, dst, src_rect.x, src_rect.y);
...
break;
case MODE_BLEND : //rgaImDemo --blend
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imblend(src, dst);
...
break;
case MODE_CVTCOLOR : //rgaImDemo --cvtcolor
src.format = RK_FORMAT_RGBA_8888;
dst.format = RK_FORMAT_YCbCr_420_SP;
...
ret = imcheck(src, dst, src_rect, dst_rect);
...
STATUS = imcvtcolor(src, dst, src.format, dst.format);
...
break;
case MODE_FILL : //rgaImDemo --fill=blue/green/red
COLOR = parm_data[MODE_FILL];
dst_rect.x = 100;
dst_rect.y = 100;
dst_rect.width = 300;
dst_rect.height = 300;
ret = imcheck(src, dst, src_rect, dst_rect, IM_COLOR_FILL);
...
STATUS = imfill(dst, dst_rect, COLOR);
...
break;
...
}
...
/********** release rga buffer handle **********/
releasebuffer_handle(src_handle);
releasebuffer_handle(dst_handle);
/********** output buf data to file **********/
if (src_buf != NULL) {
free(src_buf);
src_buf = NULL;
}
if (dst_buf != NULL) {
output_buf_data_to_file(dst_buf, dst.format, dst.wstride, dst.hstride, 0);
free(dst_buf);
dst_buf = NULL;
}
return 0;
}
Each case is then processed by calling imcheck to check if the parameters are legal and if the current hardware supports the operation.
And then call different processing, for example
imcopy is to perform a single fast image copy operation from the src channel image buffer to the dst channel image buffer.
imresize is image scaling
imcrop is image cropping
imrotate is image rotation
Overall, RK's RGA library API is relatively simple to call, and the demo project is relatively clear.
The specific RGA API can refer to the RGA documentation in docs/cn/Common/RGA/Rockchip_Developer_Guide_RGA_CN.pdf.