前言:以下為芯馳 X9 safety domain 的 fastrvc 快啟倒車影像 demo 的使用方法和代碼解析,以下實驗現象基於 X9HP PTG4.3。
一、VDSP(CV engine)
- vdsp.elf:固件為該引擎獨立的運行固件,由芯馳提供,PTG4.3 中位於 SDK 的 freertos_safety/res/early_app/ 下。初始化時 CPU 會將該固件加載至約定地址處,之後會啟動引擎以運行固件。
- MappingTable.bin:映射參數表,搭載圖像處理的參數,加載到 vdsp sharing memory
二、代碼路徑
源碼:
freertos_safety/application/early_app/fastrvc/src/fast_rvc.c
固件資源:
freertos_safety/res/early_app/fastavm/vdsp.elf freertos_safety/res/early_app/fastavm/MappingTable.bin
倒車軌跡圖片資源:
freertos_safety/res/early_app/fastavm/bp.png freertos_safety/res/early_app/fastavm/angle_0.png freertos_safety/res/early_app/fastavm/angle_1.png freertos_safety/res/early_app/fastavm/angle_2.png
三、代碼解析
整個 fastrvc 功能由三個線程完成:fast_rcv_show_task,fast_rcv_detect_task,fast_rcv_lvgl_task
fast_rcv_show_task 後視攝像頭圖像顯示
- 初始化攝像頭,並設置顯示相關的配置。CAM_ID 要根據不同的情況設置不同的值。
- 初始化 g2d
- 判斷是否開啟 vdsp。默認開啟,初始化 VDSP(CV engine) 視覺引擎
- Android 未啟動或車輛處於後退狀態時,進行圖像顯示。車輛處於後退狀態時,使用 g2d + vdsp(如果未開啟 vdsp,則僅使用 g2d) 對圖像進行處理再顯示。
以下為線程大致框架,篇幅有限,省略代碼保留大致流程:
static int fast_rcv_show_task(void *args) {
int ret = 0;
int frm_cnt = 0;
u8 cam_id = 0;
uint32_t buf_index = 0;
uint64_t timestamp = 0;
unsigned long cur;
uint32_t buf_size;
int show_index = 0;
char payload[2] = {0, 0};
struct sdm_buffer *bufs;
struct sdm_post_config *post;
fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;
//① 初始化攝像頭,並設置顯示相關的配置。CAM_ID 要根據不同的情況設置不同的值。
rvc_data->cam_id = CAM_ID;
ret = csi_entry(rvc_data->cam_id);
......
disp_layer_data_init(post->bufs);
//② 初始化 g2d
......
//③ 默認開啟,初始化 VDSP(CV engine) 視覺引擎,加載 early_app/fastrvc/vdsp.elf 和 early_app/fastrvc/MappingTable.bin
#if SUPPORT_VDSP_DIST
rvc_vdsp_init(rvc_data);
#endif
......
//④ Android 未啟動或車輛處於後退狀態時,進行圖像顯示
while (!android_state || rvc_data->new_car_status) {
//⑤ 車輛處於後退狀態時,使用 g2d + vdsp(如果未開啟 vdsp,則僅使用 g2d) 對圖像進行處理再顯示
if (rvc_data->new_car_status) {
#if SUPPORT_VDSP_DIST
/* g2d + vdsp + disp */
......
/* L.0 - convert YUV => RGB */
......
#endif
/* L.1 - VDSP distortion */
//看 vdsp_start_one_frame 的實現,似乎並沒有進行圖像變形,而是只是給 vdsp 發送了 show_buf 和 tmp_buf 的地址,進行了 tmp_buf 到 show_buf 數據的拷貝
......
/* L.2 - to display */
......
//如果不開啟 vdsp 引擎的話,則僅使用 g2d 進行圖像處理
#else
/* g2d + disp */
......
#endif
}
else//車輛不處於後退狀態
{
if (scs_csi_get_buf(cam_id, &buf_index, ×tamp) < 0) {
printf("<%d, %s>:wrn:\n", __LINE__, __func__);
continue;
}
post = &rvc_data->post;
bufs = rvc_data->post.bufs;
bufs->addr[0] = (unsigned long)rvc_data->show_buf[show_index];
bufs->src_stride[0] = DISP_W * 3;
bufs->layer_en = 0;
//顯示
ret = sdm_post(rvc_data->disp_handle, post);
show_index = !show_index;
scs_csi_set_buf(cam_id, buf_index);
}
}
//關閉釋放所有資源
......
return 0;
}
|
fast_rcv_detect_task 車輛後退檢測
- 創建 gpio 句柄,用來檢測車輛的後退狀態
- 開啟這個宏則隨機模擬車輛後退狀態,否則則通過 gpio 讀取
- new_car_status 指示當前汽車狀態,如果狀態發生變化且車輛後退,更新 rvc_data 的狀態以通知其他線程。
以下為線程處理流程:
static int fast_rcv_detect_task(void *args) {u8 is_car_back = 0;char payload[2] = {0, 0};void *rvc_gpio_handle;fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;
//① 創建 gpio 句柄,用來檢測車輛的後退狀態if (!hal_dio_creat_handle(&rvc_gpio_handle, g_gpio_res.res_id[0])) {printf("<%d, %s>:err:\n", __LINE__, __func__);return -1;}
while (1){/* car angle detect */if (android_state == 0) {mutex_acquire(&rvc_data->data_mutex);rvc_data->new_angle_index = 0;mutex_release(&rvc_data->data_mutex);}//② 開啟這個宏則隨機模擬車輛後退狀態,否則則通過 gpio 讀取,測試情況下建議開啟#if REPEAT_CAR_BACK_TESTunsigned int rand1 = ((unsigned int)rand()) % 100 + 400;unsigned int rand2 = ((unsigned int)rand()) % 100 + 400;//後退與非後退狀態交替出現隨機時間,建議調試圖像時 is_car_back 恆等於 1,避免閃到眼睛is_car_back = !is_car_back;if(is_car_back == 1)thread_sleep(rand1);/*thread_sleep(500);*/elsethread_sleep(rand2);/*thread_sleep(500);*/#else/* car back detect, user to open *///is_car_back = (u8)hal_dio_read_channel(rvc_gpio_handle, RVC_DETECT_GPIO)#endif//③ new_car_status 指示當前汽車狀態,如果狀態發生變化且車輛後退,更新 rvc_data 的狀態以通知其他線程。if (rvc_data->new_car_status != is_car_back) {//android_state 指示 ap1(Android)的啟動狀態,如果 Android 已啟動完成,則向 Android 發送當前汽車狀態。if (android_state == 1) {/* notify ap */payload[0] = 0x01;payload[1] = rvc_data->new_car_status;ipcc_channel_sendto(rvc_data->ipcc_chan, 300, payload,sizeof(payload), 100);}
fast_rcv_lvgl_task 倒車方向邊框線顯示
- lvgl 圖形庫初始化
- 獲取當前活動的顯示螢幕
- 設置螢幕的背景透明度並獲取螢幕大小。
- 設置倒車軌跡背景圖的顯示
- 設置倒車軌跡彎曲角度圖片的顯示
- 創建線程,線程中根據 android_state、new_car_status、new_angle_index 來決定是否顯示倒車軌跡及倒車軌跡彎曲角度
- 刷新顯示
- 調用 lvgl 庫的事件處理函數
以下為線程處理流程:
static int fast_rcv_lvgl_task(void *args) {uint32_t screen_w;uint32_t screen_h;char angle_path[128] = {0};fast_rvc_data_t *rvc_data = (fast_rvc_data_t *)args;
//① lvgl 圖形庫初始化lvgl_init();
//thread_sleep(40); /* wait camera showed *///② 獲取當前活動的顯示螢幕rvc_data->lvgl_screen = lv_disp_get_scr_act(get_display(LCD_ID));//③ 設置螢幕的背景透明度並獲取螢幕大小。lv_obj_set_style_local_bg_opa(rvc_data->lvgl_screen, LV_OBJ_PART_MAIN,LV_STATE_DEFAULT, LV_OPA_TRANSP);get_lvgl_screen_size(rvc_data->lvgl_screen, &screen_w, &screen_h);//④ 設置倒車軌跡背景圖的顯示rvc_data->img_bg = lv_img_create(rvc_data->lvgl_screen, NULL);lv_img_set_src(rvc_data->img_bg, (char *)("S:/early_app/fastrvc/bg.png"));lv_obj_set_pos(rvc_data->img_bg, ((LCD_W - 960)/2), ((LCD_H - 720)/2));lv_obj_set_hidden(rvc_data->img_bg, 0);//⑤ 設置倒車軌跡彎曲角度圖片的顯示rvc_data->img_angle = lv_img_create(rvc_data->lvgl_screen, NULL);memset(angle_path, 0, sizeof(angle_path));sprintf(angle_path, "S:/early_app/fastrvc/angle_%d.png", rvc_data->new_angle_index);lv_img_set_src(rvc_data->img_angle, angle_path);lv_obj_set_pos(rvc_data->img_angle, ((LCD_W - 960)/2), ((LCD_H - 720)/2));lv_obj_set_hidden(rvc_data->img_angle, 0);
//⑥ 創建線程,線程中根據 android_state、new_car_status、new_angle_index 來決定是否顯示倒車軌跡及倒車軌跡彎曲角度rvc_data->lv_line_task = lv_task_create(lv_line_task_cb, 50/*ms*/,LV_TASK_PRIO_LOW, rvc_data);//⑦ 刷新顯示lv_set_flush_enabled_for_disp(get_display(LCD_ID), true);while (1) {//⑧ 調用 lvgl 庫的事件處理函數lv_task_handler();thread_sleep(50);if (0) {uint64_t time_cur;uint32_t ms, us;time_cur = current_time_hires();ms = (uint32_t)(time_cur / 1000);us = (uint32_t)(time_cur % 1000);printf("time=%d.%03d\n", ms, us);}}
return 0;}
四、編譯運行
-
編譯
修改 json 文件配置:
添加 freertos config:ENABLE_FASTRVC=true SUPPORT_VDSP_DIST=true
添加 "gen-pac" 資源打包:"safety-res":"fastrvc"
修改 freertos_safety/application/early_app/fastrvc/src/fast_rvc.c:
#define REPEAT_CAR_BACK_TEST 1 #define CAM_ID 0 //修改為適配的 CAM_ID,可參考啟動時 cam_serviy 的列印信息 -
運行 fastrvc 上電快速自啟。
五、調試方法
- safety 命令 fastrvc_new_car_status:
通過命令修改車輛狀態,來決定是否顯示倒車影像。但由於 fast_rcv_detect_task 線程是 while 循環運行,並隊車輛狀態進行翻轉,因此命令只在該線程休眠時有效。可通過修改代碼來使命令持續有效。 - safety 命令 fastrvc_new_angle_index:
通過命令修改倒車軌跡角度。但由於 lv_line_task_cb 線程是 while 循環運行,並隊倒車軌跡角度進行翻轉,因此命令只在該線程休眠時有效。可通過修改代碼來使命令持續有效。
六、客制化部分
-
圖像配置。
大部分可通過 fastrvc.c 宏定義部分來配置圖像參數。
修改圖像格式(RGB/YUV 等),需要手動修改大部分代碼邏輯,所有涉及 csi、g2d、disp init 部分、buffer size 部分及 fast_rcv_show_task 的相關邏輯。一般情況下不修改。/* performance test */#define PERF_TEST 0/* pressure test */#define REPEAT_CAR_BACK_TEST 1/* fisheye distortion */#define SUPPORT_VDSP_DIST 1
#define LCD_ID INFOTAINMENT#define LCD_W 1920 //LCD 螢幕寬#define LCD_H 720 //LCD 螢幕高
#define DISP_W 1280 //倒車影像區域的寬#define DISP_H 720 //倒車影像區域的高#define DISP_X ((LCD_W - DISP_W)/2) //倒車影像區域顯示起點--X 軸#define DISP_Y ((LCD_H - DISP_H)/2) //倒車影像區域顯示起點--Y 軸
#define CAM_ID 0 //framework 層的 camera id#define CAM_BUF_CNT 3 //camera 圖像緩衝區個數#define CAM_W 1280 //圖像源寬度#define CAM_H 720 //圖像源高度
/* detection gpio */#define RVC_DETECT_GPIO PortConf_PIN_GPIO_A6 //此 gpio 口狀態用於判定是否發生了車輛後退
//vdsp 固件配置,勿更改#define VDSP_ELF_PATH "early_app/fastrvc/vdsp.elf"#define MAP_TAB_PATH "early_app/fastrvc/MappingTable.bin"#define VDSP_FW_RUNTIME_MEM (ap2p(VDSP_MEMBASE)) -
倒車軌跡算法
根據需要修改 fast_rcv_lvgl_task。
總結:以上為芯馳 X9 safety domain 的 fastrvc 快啟倒車影響 demo 的使用方法和代碼解析。
評論