久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

博客專欄

EEPW首頁 > 博客 > 征程 6E/M|多 camera 場景示例

征程 6E/M|多 camera 場景示例

發布人:地平線開發者 時間:2025-09-06 來源:工程師 發布文章
1. 功能概述

本 sample 提供全鏈路場景 1V,4V,7V 使用演示,實現單路及多路 VIO 接入,逐級經過 ISP、PYM、BPU、CODEC 模塊處理。

1.1. 軟件架構說明

本 sample 調用 VIO API 來實現整個數據通路,實現單路、多路 camera 接入,并能夠 dump 每一路數據的圖像。調用 BPU API 使用 BPU 模塊,并依賴 libhbucp.so 等庫中的算法 API 實現對視頻圖像的目標檢測與識別。調用 MediaCodec API,經過 VPU 實現對視頻圖像的編碼,保存為本地的 H265 格式視頻。

軟件控制圖如下:

../../_images/vio_full_link_sample_soft.png

1.2. 硬件數據流說明

每個場景的圖中已經標明硬件連接關系。

1V 場景如下:

../../_images/1V.png

4V 場景如下:

../../_images/4V.png

7V 場景如下:

../../_images/7V.png

1.3. 代碼位置及目錄結構

sample 代碼位置在 SDK 工程目錄 {sdk_dir}/test/samples/platform_samples/source/S83_Sample/S83E06_Tros/vio_full_link_sample

目錄結構如下:

vio_full_link_sample/
    ├── Kconfig
    ├── Makefile
    ├── Makefile.in
    ├── cfg                              # JSON files    
    ├── lib                              # dynamic libraries    
    |   ├── libhbucp.so
    |   └── ...
    ├── res
    |   └── fcos.hbm                     # model hbm file    
    └── src
        ├── include
        ├── utils                        # utility codes        
        |   ├── bpu_dnn.cpp
        |   ├── codec_venc.c
        |   └── ...
        ├── vio_full_link_sample.c       # core code        
        ├── run_vio_full_link_sample.sh  # sample execution script        
        ├── run_vio_full_link_sample_4V.sh  # sample execution script        
        ├── run_vio_full_link_sample_7V.sh  # sample execution script        
        └── Makefile

根目錄包含 Kconfig 和外部接口的 Makefile, Kconfig 用于控制本 sample 是否加入整體編譯; 根目錄中的 cfg 目錄包含本 sample 用到的 JSON 配置文件; lib 目錄包含本 sample 用到的動態庫;res 目錄包含本 sample 用到的 hbm 模型文件。

src 目錄下的 Makefile 用于 src 目錄下的編譯; vio_full_link_sample.c 是 main 入口的所在文件; run_vio_full_link_sample.sh run_vio_full_link_sample_4V.sh run_vio_full_link_sample_7V.sh 是本 sample 在板端的運行腳本; src 目錄中的 include 目錄為頭文件所在目錄;utils 目錄包含一些功能性代碼。

1.4. API 流程說明

API 流程圖如下:

../../_images/api_flow.png

需要注意的是,當將 pym 數據幀送入 VPU 編碼時,對應 buffer 會先放入 buf_ctl 的狀態隊列中,當該幀編碼完成后才會釋放。

主干代碼:

int main(int argc, char *argv[])
{
    int ret = 0;
    pthread_t thid[HB_VIO_PIPELINE_MAX];    
    uint32_t pipe_id[HB_VIO_PIPELINE_MAX]; 
    
    signal(SIGINT, get_exit_signal);    
    
    // get opts
    ret = get_opts_for_vio(argc, argv);    
    if (ret < 0) {     
        vio_print_err("get opts err!\n");
        return -1;    
    }
    
#ifdef ENABLE_BPU
    ret = bpu_dnn_init(g_bpu_hbm);
    if (ret < 0) {
        vio_print_err("bpu_hbm_init\n");    
        goto err;
    }
#endif

    ret = hb_vio_init(g_vpm_config);    
    if (ret < 0) {    
        vio_print_err("hb_vio_init\n");    
        goto err; 
    }
    
    ret = hb_cam_init(0, g_cam_config);    
    if (ret < 0) {     
        hb_vio_deinit();        
        vio_print_err("hb_cam_init\n");        
        goto err;    
    }
    
#ifdef ENABLE_HBPLAYER
    vio_full_link_sample_event = hb_tool_start_transfer(0);    
    if (vio_full_link_sample_event != NULL) {        
       hb_tool_event_setcb(vio_full_link_sample_event, NULL, NULL, NULL, NULL, NULL);    
    } else {        
       vio_print_err("vio_full_link_sample_event is NULL\n");        
       ret = -1;        
       goto err;    
    }
#endif

    start_timer();    
    for (uint32_t id = 0; id < HB_VIO_PIPELINE_MAX; id++) { 
        if (((g_port_mask >> id) & 0x0001) == 0)     
           continue;        
           
           ret = hb_vio_start_pipeline(id);        
           if (ret < 0) {         
              hb_cam_deinit(0);         
              hb_vio_deinit();            
              vio_print_err("hb_vio_start_pipeline");            
              goto err;        
           }        
           else {          
               vio_print_info("hb_vio_start_pipeline done");        
           }        
           ret = hb_cam_start(id);        
           if (ret < 0) {         
               hb_vio_stop_pipeline(id);            
               hb_cam_deinit(0);            
               hb_vio_deinit();            
               vio_print_err("hb_cam_start");           
               goto err;      
           }        
           pipe_id[id] = id;
#ifdef ENABLE_MULTI_MEDIA  
           ret = pthread_create(&codec_thid[id], NULL, codec_encoding,                 
                    (void *)(&pipe_id[id]));        
           vio_print_dbg("pipe(%d)Test encode work thread---running.\n", id);
#endif        

           ret = pthread_create(&thid[id], NULL, vio_worker_thread,                       
                       (void *)(&pipe_id[id]));        
           
           vio_print_dbg("pipe(%d)Test vio work thread---running.\n", id);    
}

sleep(1);    

for (uint32_t id = 0; id < HB_VIO_PIPELINE_MAX; id++) {        
     if (((g_port_mask >> id) & 0x0001) == 0)  
        continue;        
     vio_print_dbg("pipe(%d)Test vio work thread---try stop.\n", id);    
}    

for (uint32_t id = 0; id < HB_VIO_PIPELINE_MAX; id++) {    
    if (((g_port_mask >> id) & 0x0001) == 0)        
        continue;        
    pthread_join(thid[id], NULL);        
    vio_print_dbg("pipe(%d)Test vio work thread---join done.\n", id);    
}    

for (uint32_t id = 0; id < HB_VIO_PIPELINE_MAX; id++) {        
    if (((g_port_mask >> id) & 0x0001) == 0)            
       continue;        
    
    ret = hb_cam_stop(id);        
    if (ret < 0) {            
        hb_vio_stop_pipeline(id);            
        hb_cam_deinit(0);            
        hb_vio_deinit();            
        vio_print_err("hb_cam_stop");            
        goto err;        
    }        
    ret = hb_vio_stop_pipeline(id);        
    if (ret < 0) {            
        hb_cam_deinit(0);            
        hb_vio_deinit();            
        vio_print_err("hb_vio_stop_pipeline");            
        goto err;        
    }        
    }
    
#ifdef ENABLE_MULTI_MEDIA    
    for (uint32_t id = 0; id < HB_VIO_PIPELINE_MAX; id++) {        
        if (((g_port_mask >> id) & 0x0001) == 0)            
           continue;        
        pthread_join(codec_thid[id], NULL);        
        vio_print_dbg("pipe(%d)Test encode work thread---join done.\n", id);       
    }

#endif

#ifdef ENABLE_BPU    
   bpu_dnn_deinit();
#endif    

   ret = hb_cam_deinit(0);    
   ret |= hb_vio_deinit();
   
err:    
    return ret;
}

獲取及處理數據的代碼:

   int vio_worker_func(uint32_t pipe_id, int loop_count)    
   {            
           int ret = 0;            
           pym_buffer_v3_t pym_buf;            
           VIO_DATA_TYPE_E pym_data_type;            
           pym_data_type = HB_VIO_PYM_DATA_V3;            
           dp_info_t dump_info = {0};            
           
           ret = hb_vio_get_data(pipe_id, pym_data_type, &pym_buf);            
           if (ret < 0) {                    
                   vio_print_err("Pipe(%u) HB_VIO_PYM_ADV_DATA get failed\n", pipe_id);   
                   goto err;            
           }    
    #ifdef ENABLE_BPU            
           if (((g_bpu_enable_mask >> pipe_id) & 0x0001) != 0) {                    
                   address_info_t img_info_bpu;                    
                   memset(&img_info_bpu, 0, sizeof(address_info_t));                    
                   ret = pym_layer_img_info_attach(&pym_buf, (PYM_LAYER_TYPE)g_pym_show_layer, &img_info_bpu);                    
                   if (ret < 0) {                            
                           vio_print_err("pipe(%u)pym frame%d buf%d attch failed.\n", pipe_id, pym_buf.pym_img_info.frame_id,                                      
                                     pym_buf.pym_img_info.buf_index);                      
                           goto err;                    
                   }                    
                   pthread_mutex_lock(&g_pym_lock);                    
                   bpu_dnn_process(pipe_id, img_info_bpu.addr[0], img_info_bpu.width, img_info_bpu.height);                    
                   pthread_mutex_unlock(&g_pym_lock);                    
                   //vio_print_info("pipe(%u) bpu process done\n", pipe_id);            
         }    
   #endif    
   
   #ifdef ENABLE_HBPLAYER
           if (g_pym_show_layer >= PYM_DS0_DATA && g_pym_show_layer < PYM_INVAILD_DATA) {                    pym_img_hbplayer_show((void *)vio_full_link_sample_event, &pym_buf, (PYM_LAYER_TYPE)g_pym_show_layer);            
           }    
   #endif            
           if (g_pym_save >= loop_count) {                    
                   //worker thread dump                    
                   dump_info.pipe_id = pipe_id;                    
                   dump_info.enable = PYM_BUF_DUMP;                    
                   memcpy(&dump_info.pym_buf, &pym_buf, sizeof(pym_buffer_v3_t));                    dp_worker_data_process(&dump_info);            
                   
           }
           
#ifdef ENABLE_MULTI_MEDIA    
    if (g_codec_save >= loop_count) {        
        push_pym_buffer_to_post_for_codec(pipe_id, &pym_buf, FALSE);        
        if (g_codec_save == loop_count)     {            
           // if last frame, push an empty frame more.            
           push_pym_buffer_to_post_for_codec(pipe_id, NULL, TRUE);        
        }    
    } else {        
        ret = hb_vio_free_pymbuf(pipe_id, pym_data_type, &pym_buf);        
        if (ret < 0) {       
            vio_print_err("pipe(%u)pym frame%d buf%d free failed.\n", pipe_id, pym_buf.pym_img_info.frame_id,                    
            pym_buf.pym_img_info.buf_index);            
            goto err;        
        }    
}#else    
     ret = hb_vio_free_pymbuf(pipe_id, pym_data_type, &pym_buf);    
     if (ret < 0) {        
         vio_print_err("pipe(%u)pym frame%d buf%d free failed.\n", pipe_id, pym_buf.pym_img_info.frame_id,                
         pym_buf.pym_img_info.buf_index);        
         goto err;    
     }
#endif    

   err:            
            eturn ret;    
   }
二. 編譯
2.1. 編譯環境

本 sample 的編譯環境使用 SDK 中的 build 工具,請參考: Build 環境建立。

2.2. 編譯說明

本 sample 編譯依賴 VPS 系統相關的頭文件:

#include "hb_vin_data_info.h"
#include "hb_vpm_data_info.h"
#include "hb_vio_interface.h"

使用 BPU 時,需要 BPU 模型處理相關的頭文件:

#include "base/algorithm.h"
#include "base/perception_common.h"
#include "hobot/dnn/hb_dnn.h"
#include "hobot/hb_ucp.h"
#include "hobot/hb_ucp_sys.h"

使用 VPU 時,需要 MM&CODEC 系統相關的頭文件:

#include "hb_media_codec.h"
#include "hb_media_error.h"
#include 
#include 
#include "buf_queue.h"

使用 hbplayer 時,需要 hbplayer 相關的頭文件:

#include "hb_tool_server.h"

sample 編譯依賴的庫:

LIBS += -lvio -lpthread -lalog -lhbmem

使能 BPU 編譯依賴的庫:

LIBS += -lbpu -ldnn -lopencv_world -lhlog -lhbucp

備注

當前本 sample 中使用的 dnn 版本: ucp_j6-v3.0.6_daily040101815

使能 MM&Codec 編譯依賴的庫:

LIBS += -lmultimedia -lavformat -lavcodec -lavutil -lswresample

使能 hbplayer 編譯依賴的庫:

LIBS += -lhbplayer

編譯命令:

進入SDK所在目錄{sdk_dir},并source構建環境(參見上)。
# 編譯本sample:
bdm libvio-full-link-sample
# 輸出文件:{sdk_dir}/out/debug-gcc_{gcc_version}/build/test/samples/platform_samples/source/S83_Sample/S83E06_Tros/vio_full_link_sample
三. 運行
3.1. 支持平臺

Matrix 6E/M

3.2. 硬件環境搭建

接口連接如下:

../../_images/hardware.png

模組:聯創模組 OVX8B、OVX3C,SENSING-ISX031。

具體型號:

主前視聯創 x8b:LCE_M24F121D12_S1ROT8E5;

窄前視聯創 x8b:LCE_M24F30D12_S1ROT8E5;

后視聯創 x3c:LCE_GM24F60D12_S2T0E6;

4 個周視聯創 x3c:LCE_GM24F103D12_S2R8T0E6;

4 個環視森云 isx031c:SENSING_M24F190D4_SOROT7。

連接方式:

一路 OVX8B FOV120 通過 4 合 1 線束的 A 口連接到板子的 DES1;

一路 OVX8B FOV30 通過 4 合 1 線束的 C 口連接到板子的 DES1;

一路 OVX3C FOV60 通過 4 合 1 線束的 D 口連接到板子的 DES1;

四路 OVX3C FOV100 通過通過 4 合 1 線束的 ABCD 口連接到板子的 DES2;

四路 ISX031C 通過 4 合 1 線束的 ABCD 口連接到板子的 DES3。

3.3. 板端部署及配置

刷寫系統軟件鏡像后,本 sample 的可執行文件位于板端: /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/

需要用到的資源:

  • 需要用到的配置文件位于板端: /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/

  • 需要用到的資源文件位于板端: /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/

  • 需要用到的第三方庫位于板端: /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/lib/

3.4. 運行指南
3.4.1. 運行方法

1V 測試命令,可直接執行提供的 sample 運行腳本:

bash /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/run_vio_full_link_sample.sh

或使用完整指令:

export LD_LIBRARY_PATH=/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/lib:$LD_LIBRARY_PATH
/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/vio_full_link_sample \
-v /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_1V_cpe0_sen_cim0_isp0_pym0_mode2_sample/vpm_config.json \
-c /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/case_matrix/1V_OVX8B_RX0/hb_j6dev.json \
-O /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm -m 1 -o 1 -j 1 -l 1000 -s 10 -f 100 -e 0

4V 測試命令,可直接執行提供的 sample 運行腳本:

bash /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/run_vio_full_link_sample_4V.sh

或使用完整指令:

export LD_LIBRARY_PATH=/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/lib:$LD_LIBRARY_PATH
/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/vio_full_link_sample \
-v /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_4V_cpe1_sen_cim1_isp1_pym1_mode1_sample/vpm_config.json \
-c /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_4V_cpe1_sen_cim1_isp1_pym1_mode1_sample/hb_j6dev.json \
-O /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm -m 15 -o 15 -j 15 -l 1000 -s 10 -f 10 -e 0

7V 測試命令,可直接執行提供的 sample 運行腳本:

bash /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/run_vio_full_link_sample_7V.sh

或使用完整指令:

export LD_LIBRARY_PATH=/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/lib:$LD_LIBRARY_PATH
/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/vio_full_link_sample \
-v /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_7V_cpe01_sen_cim01_isp01_pym01_sample/vpm_config.json \
-c /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_7V_cpe01_sen_cim01_isp01_pym01_sample/hb_j6dev.json \
-O /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm -m 254 -o 254 -j 254 -l 1000 -s 10 -f 10 -e 0
3.4.2. 運行命令行說明

vio_full_link_sample :應用程序名字。

下面的表格是具體參數的說明:
在這里插入圖片描述

例如上面的 1V 測試命令:

/app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/vio_full_link_sample \
-v /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_1V_cpe0_sen_cim0_isp0_pym0_mode2_sample/vpm_config.json \
-c /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/case_matrix/1V_OVX8B_RX0/hb_j6dev.json \
-O /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm -m 1 -o 1 -j 1 -l 1000 -s 10 -f 100 -e 0

-v 參數是 /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/Scenario_1V_cpe0_sen_cim0_isp0_pym0_mode2_sample/vpm_config.json,代表 VIO 配置文件的所在位置,json 里面的具體配置可參考 VPS 配置文件說明。

-c 參數是 /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/cfg/case_matrix/1V_OVX8B_RX0/hb_j6dev.json,代表 camera 的配置文件的所在位置,json 里面的具體配置可參考 征程 6X camera 配置文件說明。

-O 參數是 /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm,代表 hbm 模型文件的所在位置。

-m 參數是 1,表示使能 pipe0 數據流。

-o 參數是 1,表示對 pipe0 數據流進行 BPU 處理。

-j 參數是 1,表示對 pipe0 數據流進行 VPU 硬件編碼。

-l 參數是 1000,表示獲取 PYM 數據 1000 幀。

-s 參數是 10,表示 dump 前面 10 幀的數據。

-f 參數是 100,表示編碼前面 100 幀的數據,輸出 H265 視頻。

-e 參數是 0,表示通過 hbplayer 工具實時顯示 PYM DS0 層。

可增加 -t 參數,例如 -t 10000 表示程序獲取數據的最長運行時間為 10000ms。 當 -t 參數與 -l 參數同時使用時,各線程在滿足其中任意一個條件,即已獲取指定的數據幀數或者已達到指定的運行時間后就會退出,一般情況下不建議同時使用這兩個參數。

備注

BPU 對于 NV12 格式圖像處理要求 Stride 32 對齊,通常 Pym 輸出數據作為 BPU 輸入就需要 Stride 32 對齊,如果不對齊,BPU 處理結果會不正確。 如果要強制停止,需要兩次 ctrl+c 操作。原因是 hobot player 使用了 libevent 庫,第一次 ctrl+c 操作被它吃掉了。

3.4.3. 運行結果說明

sample 運行時,通過下面的命令可以看到每個 IP 的幀率:

cat  /sys/class/vps/flow/fps

sample 運行時的主要執行日志如下:

  • 成功加載 hbm 模型:

root@hobot:~# bash /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/bin/run_vio_full_link_sample_4V.sh
[DNN] HBTL_EXT_DNN log level:3
[UCP]: log level = 3[UCP]: UCP version = 3.0.6
[VP]: log level = 3[DNN]: log level = 3[HPL]: log level = 3[UCPT]: log level = 6[INFO] model is: /app/sample/S83_Sample/S83E06_Tros/vio_full_link_sample/res/fcos.hbm
[BPU][[BPU_MONITOR]][281472801308704][INFO]BPULib verison(2, 0, 5)[]!
[DNN]: 3.0.6_(4.0.19 HBRT)[INFO] Load model successfully!
start_hbplayer_thread start success. pid 281472495382208
create_socket_listen---177, listern 0xffff640154c0
create a listener, port is 10086
create_socket_event---202, t_base 0xaaab0d353e60 event base is 0xffff64014750, listener 0xffff640154c0
[15:07:04]start_callback_service[538] hbplayer L: start_dump_server_thread start success.

[INFO] pym: hb_vio_start_pipeline done[DBG] pym: pipe(0)Test vio work thread---running.
[DBG] pym: pipe(0) pym feedback worker_thread Ready !
[INFO] pym: hb_vio_start_pipeline done[DBG] pym: pipe(1)Test vio work thread---running.
[DBG] pym: pipe(1) pym feedback worker_thread Ready !
[INFO] pym: hb_vio_start_pipeline done[DBG] pym: pipe(2)Test vio work thread---running.
[DBG] pym: pipe(2) pym feedback worker_thread Ready !
[INFO] pym: hb_vio_start_pipeline done[DBG] pym: pipe(3)Test vio work thread---running.
[DBG] pym: pipe(3) pym feedback worker_thread Ready !

里面的相應的版本號會變動,僅供參考。

  • Dump、CODEC 編碼:

../../_images/dump_codec.png

  • 運行結束正常退出:

../../_images/4v_pass.png

查看運行時的幀率如下:

1V 場景如下:

../../_images/1v_fps.png

4V 場景如下:

../../_images/4v_fps.png

7V 場景如下:

../../_images/7v_fps.png

通過 -t 10000 指定運行時間為 10000ms。

3.4.4. 看圖結果

本 sample 支持通過 hbplayer 工具進行看圖。首先在 hbplayer 中設置平臺、IP 地址等相關參數:

../../_images/hbplayer_set.png

執行命令后,點擊 hbplayer 左側欄中的 connect 即可完成連接并在右側界面看到實時全鏈路場景圖像:

1V 場景如下:

../../_images/hbplayer_show.png

4V 場景如下:

../../_images/hbplayer_show4V.png

7V 場景如下:

../../_images/hbplayer_show7V.png

當滿足 -l 或 -t 參數指定的條件后,sample 將自動退出運行,也可通過 Ctrl+C 手動結束運行。

拿 1V 舉例,Dump 的 YUV 圖像以及 VPU 硬件編碼輸出的 H265 視頻保存在當前目錄下:

../../_images/saved_yuv.png

拿 1V 舉例,查看 H265 視頻:

../../_images/saved_codec.png


*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



相關推薦

技術專區

關閉