nonai_2d模块如何使用

Viewed 131

我希望使用nonai_2d的CRC功能进行图像类型转换,参考sample_mcm例程添加了对应的start和exit,并且做了sys_bind,也申请了vb,但是运行之后系统一直提示类似没有缓冲区的报错,请教一下nonai_2d模块的要如何使用,vb的申请有什么原则吗
重现步骤

在sample_face_detect中添加的nonai_2d的相关代码
1.include和define

#include "mpi_nonai_2d_api.h"
#include "k_nonai_2d_comm.h"

#define VICAP_OUTPUT_BUF_NUM        10
#define NONAI_2D_BUF_NUM            10

#define TOTAL_ENABLE_2D_CH_NUMS     6
#define NONAI_2D_RGB_CH             4
#define NONAI_2D_BIND_CH_0          0
#define NONAI_2D_BIND_CH_1          1
#define NONAI_2D_BIND_CH_2          2

2.系统的绑定解绑

int sample_unbind(void)
{
    k_s32 ret;
    k_mpp_chn vicap_mpp_chn;
    k_mpp_chn nonai_2d_mpp_chn;
    k_mpp_chn vo_mpp_chn;
    vicap_mpp_chn.mod_id = K_ID_VI;
    vicap_mpp_chn.dev_id = vicap_dev;
    vicap_mpp_chn.chn_id = vicap_chn;

    nonai_2d_mpp_chn.mod_id = K_ID_NONAI_2D;
    nonai_2d_mpp_chn.dev_id = 0;
    nonai_2d_mpp_chn.chn_id = NONAI_2D_BIND_CH_0;

    vo_mpp_chn.mod_id = K_ID_VO;
    vo_mpp_chn.dev_id = K_VO_DISPLAY_DEV_ID;
    vo_mpp_chn.chn_id = K_VO_DISPLAY_CHN_ID1;

    ret = kd_mpi_sys_unbind(&vicap_mpp_chn, &nonai_2d_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    ret = kd_mpi_sys_unbind(&vicap_mpp_chn, &vo_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);
    return ret;
}

int sample_sys_bind_init(void)
{
    k_s32 ret = 0;
    k_mpp_chn vicap_mpp_chn;
    k_mpp_chn nonai_2d_mpp_chn;
    k_mpp_chn vo_mpp_chn;
    vicap_mpp_chn.mod_id = K_ID_VI;
    vicap_mpp_chn.dev_id = vicap_dev;
    vicap_mpp_chn.chn_id = vicap_chn;

    nonai_2d_mpp_chn.mod_id = K_ID_NONAI_2D;
    nonai_2d_mpp_chn.dev_id = 0;
    nonai_2d_mpp_chn.chn_id = NONAI_2D_BIND_CH_0;

    vo_mpp_chn.mod_id = K_ID_VO;
    vo_mpp_chn.dev_id = K_VO_DISPLAY_DEV_ID;
    vo_mpp_chn.chn_id = K_VO_DISPLAY_CHN_ID1;

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &nonai_2d_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &vo_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    return ret;
}

3.vb申请

int sample_vb_init(void)
{
    k_s32 ret;
    k_vb_config config;
    memset(&config, 0, sizeof(config));
    config.max_pool_cnt = 64;
    //VB for YUV420SP output
    config.comm_pool[0].blk_cnt = 4;
    config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[0].blk_size = VICAP_ALIGN_UP((ISP_CHN0_WIDTH * ISP_CHN0_HEIGHT * 3 / 2), VICAP_ALIGN_1K);

    //VB for RGB888 output
    config.comm_pool[1].blk_cnt = 2;
    config.comm_pool[1].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[1].blk_size = VICAP_ALIGN_UP((ISP_CHN1_HEIGHT * ISP_CHN1_WIDTH * 3 ), VICAP_ALIGN_1K);

    //VB for nonai_2d
    config.comm_pool[2].blk_cnt = NONAI_2D_BUF_NUM;
    config.comm_pool[2].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[2].blk_size = VICAP_ALIGN_UP((ISP_CHN0_WIDTH * ISP_CHN0_HEIGHT * 3), 0x1000);

    ret = kd_mpi_vb_set_config(&config);
    if (ret) {
        printf("vb_set_config failed ret:%d\n", ret);
        return ret;
    }

    k_vb_supplement_config supplement_config;
    memset(&supplement_config, 0, sizeof(supplement_config));
    supplement_config.supplement_config |= VB_SUPPLEMENT_JPEG_MASK;

    ret = kd_mpi_vb_set_supplement_config(&supplement_config);
    if (ret) {
        printf("vb_set_supplement_config failed ret:%d\n", ret);
        return ret;
    }
    ret = kd_mpi_vb_init();
    if (ret) {
        printf("vb_init failed ret:%d\n", ret);
    }

    return ret;
}

4.nonai_2d的初始化与退出

int nonai_2d_start(void)
{
    int i, ret;
    k_nonai_2d_chn_attr attr_2d;


    for(i = 0; i < TOTAL_ENABLE_2D_CH_NUMS; i++)
    {
        attr_2d.mode = K_NONAI_2D_CALC_MODE_CSC;
        if(i == NONAI_2D_RGB_CH)
        {
            attr_2d.dst_fmt = PIXEL_FORMAT_RGB_888_PLANAR;
        }
        else
        {
            attr_2d.dst_fmt = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
        }
        ret = kd_mpi_nonai_2d_create_chn(i, &attr_2d);
        CHECK_RET(ret, __func__, __LINE__);

        ret = kd_mpi_nonai_2d_start_chn(i);
        CHECK_RET(ret, __func__, __LINE__);
        printf("nonai_2d_start_chn[%d] success\n",i);
    }

    return K_SUCCESS;
}

int nonai_2d_exit(void)
{
    int ret = 0;
    int i;

    for(i = 0; i < TOTAL_ENABLE_2D_CH_NUMS; i++)
    {
        kd_mpi_nonai_2d_stop_chn(i);
        kd_mpi_nonai_2d_destroy_chn(i);
    }

    ret = kd_mpi_nonai_2d_close();
    CHECK_RET(ret, __func__, __LINE__);

    return K_SUCCESS;
}

期待结果和实际结果

一直在提示
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960

软硬件版本信息

东山PI

错误日志

这是大核运行的log

msh /sharefs/app>./sample_face_detect.elf test.kmodel
press 'q' to exit application!!
mirror mirror is 0 , sensor tpye is 52
[D/lt9611] vtotal 1125 vactive 1080 htotal_sys 400

<0>[6] [vi] wait stop timeout

[tuning] dev: 0
acq_win.width: 1920
acq_win.height: 1080
pipe_ctrl: 4261412857
sensor_fd: 10
sensor_type: 52
sensor_name: gc2093_csi2
database_name: gc2093-1920x1080
buffer_num: 0
buffer_size: 0
[tuning] chn: 0
out_win.width: 1920
out_win.height: 1080
bit_width: 0
pix_format: 5
buffer_num: 10
buffer_size: 3110912
yraw_size: 0
uv_size: 0
v_size: 0
block_type: 1
wait_time: 500
chn_enable: 1
VsiCamDeviceCreate hw:0-vt:0 created!
kd_mpi_isp_set_output_chn_format, width(1920), height(1080), pix_format(5)
kd_mpi_isp_set_output_chn_format, width(1280), height(720), pix_format(16)
[dw] init, version Nov  6 2024 14:31:08
nonai_2d_start_chn[0] success
nonai_2d_start_chn[1] success
nonai_2d_start_chn[2] success
nonai_2d_start_chn[3] success
nonai_2d_start_chn[4] success
nonai_2d_start_chn[5] success
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
q<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960

<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
kd_mpi_isp_stop_stream chn enable is 1
kd_mpi_isp_stop_stream chn enable is 1
kd_mpi_isp_stop_stream chn enable is 0
release reserved vb 272513024
release reserved vb 0
<3>[4] [Func]:__vb_destory_pool [Line]:368 [Info]:Blk in this pool(2) occupied by someone, please release it first!
<3>[4] [Func]:vb_do_exit [Line]:1592 [Info]:destory pool [2] failed
fastboot_app, kd_mpi_vb_exit failed.

尝试解决过程

我在没有将vi与nonai绑定的时候运行程序,是可以正常运行的,绑定之后就开始报错了

补充材料

完整的mian.cc文件如下

// #include <rtthread.h>
#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>
#include <atomic>
#include <nncase/runtime/runtime_op_utility.h>
#include "mobile_retinaface.h"
#include "mpi_sys_api.h"

using namespace nncase;
using namespace nncase::runtime;
using namespace nncase::runtime::detail;

/* vicap */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <signal.h>
#include <atomic>
#include <fcntl.h>
#include <pthread.h>
#include <time.h>
#include <sys/mman.h>
#include "k_module.h"
#include "k_type.h"
#include "k_vb_comm.h"
#include "k_video_comm.h"
#include "k_sys_comm.h"
#include "mpi_vb_api.h"
#include "mpi_vicap_api.h"
#include "mpi_isp_api.h"
#include "mpi_sys_api.h"
#include "k_vo_comm.h"
#include "mpi_vo_api.h"
#include "vo_test_case.h"

#include "mpi_vo_api.h"
#include "sys/ioctl.h"

#include "k_connector_comm.h"
#include "mpi_connector_api.h"

#include "k_autoconf_comm.h"

#include "mpi_nonai_2d_api.h"
#include "k_nonai_2d_comm.h"

#define VICAP_OUTPUT_BUF_NUM        10
#define NONAI_2D_BUF_NUM            10

#define TOTAL_ENABLE_2D_CH_NUMS     6
#define NONAI_2D_RGB_CH             4
#define NONAI_2D_BIND_CH_0          0
#define NONAI_2D_BIND_CH_1          1
#define NONAI_2D_BIND_CH_2          2

#define CHANNEL 3

#define ISP_CHN1_HEIGHT (720)
#define ISP_CHN1_WIDTH  (1280)
#define ISP_CHN0_WIDTH  (1920)
#define ISP_CHN0_HEIGHT (1080)

#define ISP_INPUT_WIDTH (1920)
#define ISP_INPUT_HEIGHT (1080)

#define LCD_WIDTH       (1920)
#define LCD_HEIGHT      (1080)

static inline void CHECK_RET(k_s32 ret, const char *func, const int line)
{
    if (ret)
        printf("error ret %d, func %s line %d\n", ret, func, line);
}

int sample_sys_bind_init(void);

std::atomic<bool> quit(true);

bool app_run = true;

uint64_t perf_get_smodecycles(void)
{
    uint64_t cnt;
    __asm__ __volatile__(
        "rdcycle %0" : "=r"(cnt)
    );
    return cnt;
}

k_vo_draw_frame vo_frame = (k_vo_draw_frame) {
    1,
    16,
    16,
    128,
    128,
    1
};

int vo_creat_layer_test(k_vo_layer chn_id, layer_info *info)
{
    k_vo_video_layer_attr attr;

    // check layer
    if ((chn_id >= K_MAX_VO_LAYER_NUM) || ((info->func & K_VO_SCALER_ENABLE) && (chn_id != K_VO_LAYER0))
            || ((info->func != 0) && (chn_id == K_VO_LAYER2)))
    {
        printf("input layer num failed \n");
        return -1 ;
    }

    memset(&attr, 0, sizeof(attr));

    // set offset
    attr.display_rect = info->offset;
    // set act
    attr.img_size = info->act_size;
    // sget size
    info->size = info->act_size.height * info->act_size.width * 3 / 2;
    //set pixel format
    attr.pixel_format = info->format;
    if (info->format != PIXEL_FORMAT_YVU_PLANAR_420)
    {
        printf("input pix format failed \n");
        return -1;
    }
    // set stride
    attr.stride = (info->act_size.width / 8 - 1) + ((info->act_size.height - 1) << 16);
    // set function
    attr.func = info->func;
    // set scaler attr
    attr.scaler_attr = info->attr;

    // set video layer atrr
    kd_mpi_vo_set_video_layer_attr(chn_id, &attr);

    // enable layer
    kd_mpi_vo_enable_video_layer(chn_id);

    return 0;
}

k_s32 sample_connector_init(void)
{
    k_u32 ret = 0;
    k_s32 connector_fd;
    k_connector_type connector_type = LT9611_MIPI_4LAN_1920X1080_30FPS;
	k_connector_info connector_info;

    memset(&connector_info, 0, sizeof(k_connector_info));

    //connector get sensor info
    ret = kd_mpi_get_connector_info(connector_type, &connector_info);
    if (ret) {
        printf("sample_vicap, the sensor type not supported!\n");
        return ret;
    }

    connector_fd = kd_mpi_connector_open(connector_info.connector_name);
    if (connector_fd < 0) {
        printf("%s, connector open failed.\n", __func__);
        return K_ERR_VO_NOTREADY;
    }

    // set connect power
    kd_mpi_connector_power_set(connector_fd, K_TRUE);
    // connector init
    kd_mpi_connector_init(connector_fd, connector_info);

    return 0;
}

static k_s32 vo_layer_vdss_bind_vo_config(void)
{
    layer_info info;
    k_vo_layer chn_id = K_VO_LAYER1;

    memset(&info, 0, sizeof(info));

    sample_connector_init();

    info.act_size.width = LCD_WIDTH;
    info.act_size.height = LCD_HEIGHT;
    info.format = PIXEL_FORMAT_YVU_PLANAR_420;
    info.func = K_ROTATION_0;
    info.global_alptha = 0xff;
    info.offset.x = 0;
    info.offset.y = 0;
    vo_creat_layer_test(chn_id, &info);
    return 0;
}

static void sample_vo_fn(void *arg)
{
    usleep(10000);
    vo_layer_vdss_bind_vo_config();
    sample_sys_bind_init();
    return;
}

static void *sample_vo_thread(void *arg)
{
    sample_vo_fn(arg);
    return NULL;
}

k_vicap_dev vicap_dev;
k_vicap_chn vicap_chn;
k_vicap_dev_attr dev_attr;
k_vicap_chn_attr chn_attr;
k_vicap_sensor_info sensor_info;
k_vicap_sensor_type sensor_type;
k_video_frame_info dump_info;

int sample_unbind(void)
{
    k_s32 ret;
    k_mpp_chn vicap_mpp_chn;
    k_mpp_chn nonai_2d_mpp_chn;
    k_mpp_chn vo_mpp_chn;
    vicap_mpp_chn.mod_id = K_ID_VI;
    vicap_mpp_chn.dev_id = vicap_dev;
    vicap_mpp_chn.chn_id = vicap_chn;

    nonai_2d_mpp_chn.mod_id = K_ID_NONAI_2D;
    nonai_2d_mpp_chn.dev_id = 0;
    nonai_2d_mpp_chn.chn_id = NONAI_2D_BIND_CH_0;

    vo_mpp_chn.mod_id = K_ID_VO;
    vo_mpp_chn.dev_id = K_VO_DISPLAY_DEV_ID;
    vo_mpp_chn.chn_id = K_VO_DISPLAY_CHN_ID1;

    ret = kd_mpi_sys_unbind(&vicap_mpp_chn, &nonai_2d_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    ret = kd_mpi_sys_unbind(&vicap_mpp_chn, &vo_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);
    return ret;
}

int sample_sys_bind_init(void)
{
    k_s32 ret = 0;
    k_mpp_chn vicap_mpp_chn;
    k_mpp_chn nonai_2d_mpp_chn;
    k_mpp_chn vo_mpp_chn;
    vicap_mpp_chn.mod_id = K_ID_VI;
    vicap_mpp_chn.dev_id = vicap_dev;
    vicap_mpp_chn.chn_id = vicap_chn;

    nonai_2d_mpp_chn.mod_id = K_ID_NONAI_2D;
    nonai_2d_mpp_chn.dev_id = 0;
    nonai_2d_mpp_chn.chn_id = NONAI_2D_BIND_CH_0;

    vo_mpp_chn.mod_id = K_ID_VO;
    vo_mpp_chn.dev_id = K_VO_DISPLAY_DEV_ID;
    vo_mpp_chn.chn_id = K_VO_DISPLAY_CHN_ID1;

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &nonai_2d_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &vo_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    return ret;
}

int sample_vb_init(void)
{
    k_s32 ret;
    k_vb_config config;
    memset(&config, 0, sizeof(config));
    config.max_pool_cnt = 64;
    //VB for YUV420SP output
    config.comm_pool[0].blk_cnt = 4;
    config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[0].blk_size = VICAP_ALIGN_UP((ISP_CHN0_WIDTH * ISP_CHN0_HEIGHT * 3 / 2), VICAP_ALIGN_1K);

    //VB for RGB888 output
    config.comm_pool[1].blk_cnt = 2;
    config.comm_pool[1].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[1].blk_size = VICAP_ALIGN_UP((ISP_CHN1_HEIGHT * ISP_CHN1_WIDTH * 3 ), VICAP_ALIGN_1K);

    //VB for nonai_2d
    config.comm_pool[2].blk_cnt = NONAI_2D_BUF_NUM;
    config.comm_pool[2].mode = VB_REMAP_MODE_NOCACHE;
    config.comm_pool[2].blk_size = VICAP_ALIGN_UP((ISP_CHN0_WIDTH * ISP_CHN0_HEIGHT * 3), 0x1000);

    ret = kd_mpi_vb_set_config(&config);
    if (ret) {
        printf("vb_set_config failed ret:%d\n", ret);
        return ret;
    }

    k_vb_supplement_config supplement_config;
    memset(&supplement_config, 0, sizeof(supplement_config));
    supplement_config.supplement_config |= VB_SUPPLEMENT_JPEG_MASK;

    ret = kd_mpi_vb_set_supplement_config(&supplement_config);
    if (ret) {
        printf("vb_set_supplement_config failed ret:%d\n", ret);
        return ret;
    }
    ret = kd_mpi_vb_init();
    if (ret) {
        printf("vb_init failed ret:%d\n", ret);
    }

    return ret;
}

int sample_vivcap_init( void )
{
    k_s32 ret = 0;
    // sensor_type = OV_OV5647_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR;
    sensor_type = GC2093_MIPI_CSI2_1920X1080_30FPS_10BIT_LINEAR;
    vicap_dev = VICAP_DEV_ID_0;

    memset(&sensor_info, 0, sizeof(k_vicap_sensor_info));
    ret = kd_mpi_vicap_get_sensor_info(sensor_type, &sensor_info);
    if (ret) {
        printf("sample_vicap, the sensor type not supported!\n");
        return ret;
    }

    memset(&dev_attr, 0, sizeof(k_vicap_dev_attr));
    dev_attr.acq_win.h_start = 0;
    dev_attr.acq_win.v_start = 0;
    dev_attr.acq_win.width = ISP_INPUT_WIDTH;
    dev_attr.acq_win.height = ISP_INPUT_HEIGHT;
    dev_attr.mode = VICAP_WORK_ONLINE_MODE;

    dev_attr.pipe_ctrl.data = 0xFFFFFFFF;
    dev_attr.pipe_ctrl.bits.af_enable = 0;
    dev_attr.pipe_ctrl.bits.ahdr_enable = 0;
    dev_attr.pipe_ctrl.bits.dnr3_enable = 0;


    dev_attr.cpature_frame = 0;
    memcpy(&dev_attr.sensor_info, &sensor_info, sizeof(k_vicap_sensor_info));

    ret = kd_mpi_vicap_set_dev_attr(vicap_dev, dev_attr);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_set_dev_attr failed.\n");
        return ret;
    }

    memset(&chn_attr, 0, sizeof(k_vicap_chn_attr));

    //set chn0 output yuv420sp
    // chn_attr.out_win = dev_attr.acq_win;
    // chn_attr.crop_win = chn_attr.out_win;
    chn_attr.out_win.h_start = 0;
    chn_attr.out_win.v_start = 0;
    chn_attr.out_win.width = ISP_CHN0_WIDTH;
    chn_attr.out_win.height = ISP_CHN0_HEIGHT;
    chn_attr.crop_win = dev_attr.acq_win;
    chn_attr.scale_win = chn_attr.out_win;
    chn_attr.crop_enable = K_FALSE;
    chn_attr.scale_enable = K_FALSE;
    // chn_attr.dw_enable = K_FALSE;
    chn_attr.chn_enable = K_TRUE;
    chn_attr.pix_format = PIXEL_FORMAT_YVU_PLANAR_420;
    chn_attr.buffer_num = VICAP_MAX_FRAME_COUNT;//at least 3 buffers for isp
    chn_attr.buffer_size = VICAP_ALIGN_UP((ISP_CHN0_WIDTH * ISP_CHN0_HEIGHT * 3 / 2), VICAP_ALIGN_1K);;
    vicap_chn = VICAP_CHN_ID_0;

    // printf("sample_vicap ...kd_mpi_vicap_set_chn_attr, buffer_size[%d]\n", chn_attr.buffer_size);
    ret = kd_mpi_vicap_set_chn_attr(vicap_dev, vicap_chn, chn_attr);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_set_chn_attr failed.\n");
        return ret;
    }

    //set chn1 output rgb888p
    chn_attr.out_win.h_start = 0;
    chn_attr.out_win.v_start = 0;
    chn_attr.out_win.width = ISP_CHN1_WIDTH ;
    chn_attr.out_win.height = ISP_CHN1_HEIGHT;

    chn_attr.crop_win = dev_attr.acq_win;
    chn_attr.scale_win = chn_attr.out_win;
    chn_attr.crop_enable = K_FALSE;
    chn_attr.scale_enable = K_FALSE;
    // chn_attr.dw_enable = K_FALSE;
    chn_attr.chn_enable = K_TRUE;
    chn_attr.pix_format = PIXEL_FORMAT_BGR_888_PLANAR;
    chn_attr.buffer_num = VICAP_MAX_FRAME_COUNT;//at least 3 buffers for isp
    chn_attr.buffer_size = VICAP_ALIGN_UP((ISP_CHN1_HEIGHT * ISP_CHN1_WIDTH * 3 ), VICAP_ALIGN_1K);

    // printf("sample_vicap ...kd_mpi_vicap_set_chn_attr, buffer_size[%d]\n", chn_attr.buffer_size);
    ret = kd_mpi_vicap_set_chn_attr(vicap_dev, VICAP_CHN_ID_1, chn_attr);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_set_chn_attr failed.\n");
        return ret;
    }
    // set to header file database parse mode
    ret = kd_mpi_vicap_set_database_parse_mode(vicap_dev, VICAP_DATABASE_PARSE_XML_JSON);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_set_database_parse_mode failed.\n");
        return ret;
    }

    // printf("sample_vicap ...kd_mpi_vicap_init\n");
    ret = kd_mpi_vicap_init(vicap_dev);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_init failed.\n");
        return ret;
    }
    ret = kd_mpi_vicap_start_stream(vicap_dev);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_start_stream failed.\n");
        return ret;
    }
    return ret;
}

int nonai_2d_start(void)
{
    int i, ret;
    k_nonai_2d_chn_attr attr_2d;


    for(i = 0; i < TOTAL_ENABLE_2D_CH_NUMS; i++)
    {
        attr_2d.mode = K_NONAI_2D_CALC_MODE_CSC;
        if(i == NONAI_2D_RGB_CH)
        {
            attr_2d.dst_fmt = PIXEL_FORMAT_RGB_888_PLANAR;
        }
        else
        {
            attr_2d.dst_fmt = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
        }
        ret = kd_mpi_nonai_2d_create_chn(i, &attr_2d);
        CHECK_RET(ret, __func__, __LINE__);

        ret = kd_mpi_nonai_2d_start_chn(i);
        CHECK_RET(ret, __func__, __LINE__);
        printf("nonai_2d_start_chn[%d] success\n",i);
    }

    return K_SUCCESS;
}

int nonai_2d_exit(void)
{
    int ret = 0;
    int i;

    for(i = 0; i < TOTAL_ENABLE_2D_CH_NUMS; i++)
    {
        kd_mpi_nonai_2d_stop_chn(i);
        kd_mpi_nonai_2d_destroy_chn(i);
    }

    ret = kd_mpi_nonai_2d_close();
    CHECK_RET(ret, __func__, __LINE__);

    return K_SUCCESS;
}

static void *exit_app(void *arg)
{
    printf("press 'q' to exit application!!\n");
    while(getchar() != 'q')
    {
        usleep(10000);
    }
    app_run = false;
    return NULL;
}

int main(int argc, char *argv[])
{
    /*Allow one frame time for the VO to release the VB block*/
    k_u32 display_ms = 1000 / 33;
    int face_count = 1;

    int num = 0;
    int ret;

    if (argc != 2)
    {
        std::cerr << "Usage: " << argv[0] << " <kmodel>" << std::endl;
        return -1;
    }

    pthread_t vo_thread_handle;
    pthread_t exit_thread_handle;
    pthread_create(&exit_thread_handle, NULL, exit_app, NULL);
    size_t size = CHANNEL * ISP_CHN1_HEIGHT * ISP_CHN1_WIDTH;;

    MobileRetinaface model(argv[1], CHANNEL, ISP_CHN1_HEIGHT, ISP_CHN1_WIDTH);
    DetectResult box_result;
    std::vector<face_coordinate> boxes;

    ret = sample_vb_init();
    if(ret) {
        goto vb_init_error;
    }

    pthread_create(&vo_thread_handle, NULL, sample_vo_thread, NULL);
    ret = sample_vivcap_init();
    pthread_join(vo_thread_handle, NULL);
    if(ret) {
        goto vicap_init_error;
    }
    nonai_2d_start();

    while(app_run)
    {
        memset(&dump_info, 0 , sizeof(k_video_frame_info));
        ret = kd_mpi_vicap_dump_frame(vicap_dev, VICAP_CHN_ID_1, VICAP_DUMP_YUV, &dump_info, 1000);
        if (ret) {
            quit.store(false);
            printf("sample_vicap...kd_mpi_vicap_dump_frame failed.\n");
            break;
        }

        auto vbvaddr = kd_mpi_sys_mmap(dump_info.v_frame.phys_addr[0], size);
        // memcpy(vaddr, (void *)vbvaddr, ISP_CHN1_HEIGHT * ISP_CHN1_WIDTH * 3);
        boxes.clear();

        model.run(reinterpret_cast<uintptr_t>(vbvaddr), reinterpret_cast<uintptr_t>(dump_info.v_frame.phys_addr[0]));
        kd_mpi_sys_munmap(vbvaddr, size);
        // get face boxes
        box_result = model.get_result();
        boxes = box_result.boxes;

        if(boxes.size() < face_count)
        {
            for (size_t i = boxes.size(); i < face_count; i++)
            {
                vo_frame.draw_en = 0;
                vo_frame.frame_num = i + 1;
                kd_mpi_vo_draw_frame(&vo_frame);
            }
        }

        for (size_t i = 0, j = 0; i < boxes.size(); i += 1)
        {
            // std::cout << "[" << boxes[i].x1 << ", " << boxes[i].y1 << ", " << boxes[i].x2 <<", " << boxes[i].y2 << "]" << std::endl;
            vo_frame.draw_en = 1;
            /* vo rotation 270 */
            vo_frame.line_x_start = ((uint32_t)boxes[i].y1) * ISP_CHN0_HEIGHT / ISP_CHN1_HEIGHT;
            vo_frame.line_y_start = 1920 - (((uint32_t)boxes[i].x2) * ISP_CHN0_WIDTH / ISP_CHN1_WIDTH);
            vo_frame.line_x_end = ((uint32_t)boxes[i].y2) * ISP_CHN0_HEIGHT / ISP_CHN1_HEIGHT;
            vo_frame.line_y_end = 1920 - (((uint32_t)boxes[i].x1) * ISP_CHN0_WIDTH / ISP_CHN1_WIDTH);
            vo_frame.frame_num = ++j;
            kd_mpi_vo_draw_frame(&vo_frame);
        }

        face_count = boxes.size();
        ret = kd_mpi_vicap_dump_release(vicap_dev, VICAP_CHN_ID_1, &dump_info);
        if (ret) {
            printf("sample_vicap...kd_mpi_vicap_dump_release failed.\n");
        }
    }

app_exit:
    pthread_join(exit_thread_handle, NULL);
    for(size_t i = 0;i < boxes.size();i++)
    {
        vo_frame.draw_en = 0;
        vo_frame.frame_num = i + 1;
        kd_mpi_vo_draw_frame(&vo_frame);
    }
    boxes.clear();
    ret = kd_mpi_vicap_stop_stream(vicap_dev);
    if (ret) {
        printf("sample_vicap, stop stream failed.\n");
    }
    ret = kd_mpi_vicap_deinit(vicap_dev);
    if (ret) {
        printf("sample_vicap, kd_mpi_vicap_deinit failed.\n");
        return ret;
    }

vicap_init_error:
    kd_mpi_vo_disable_video_layer(K_VO_LAYER1);
    nonai_2d_exit();
    sample_unbind();
    usleep(1000 * display_ms);

    ret = kd_mpi_vb_exit();
    if (ret) {
        printf("fastboot_app, kd_mpi_vb_exit failed.\n");
        return ret;
    }

vb_init_error:
    return 0;
}

3 Answers

请问您的代码里使用nonai_2d的目的是什么?
通过您的代码,我了解到您从sensor获取两路数据流:一路是用于VO显示的yuv420sp格式,另一路是用于AI分析的rgbp888格式。
如果您的需求是这样,不需要使用nonai_2d进行格式转换,因为sensor支持yuv420sp和rgbp888格式输出。

我是想测试我的yuvsensor,是用HDMI转换成mipi的yuv输入来作为sensor使用的,相关驱动已经适配好了,能在sample_mcm中运行,想要移植到face_detect中运行。在vicap work_only_mcm_mode 的情况下好像需要借助nonai_2d来使用,直接使用yuvsensor发现出问题,所以我才退一步先用能运行的gc2093来测试nonai_2d的使用。

nonai_2d的具体使用方法:
请仔细阅读 sample_mcm 代码,里面已经包含了 nonai_2d 的详细使用方法。

以下是 sample_mcm 代码中 nonai_2d 的具体使用思路。更详细的内容需要阅读 API 接口文档和 demo 来掌握。

1. 初始化 nonai_2d 通道

参照 nonai_2d_start 函数,内部会创建并启用 nonai_2d 通道:

kd_mpi_nonai_2d_create_chn
kd_mpi_nonai_2d_start_chn

2. 启动 nonai_2d 数据转换

2.1 绑定模式

如果 nonai_2d 仅用于处理 pipeline 数据流,且用户层不需要获取转换后的数据,则可以使用绑定模式。例如:

  • 在内核态实现 sensor 数据显示到 VO:
    vicap(yuv422) -> nonai_2d(yuv420sp) -> vo
    
  • 在内核态实现 sensor 数据编码:
    vicap(yuv422) -> nonai_2d(yuv420sp) -> venc
    

使用 kd_mpi_sys_bind 实现此功能。

2.2 非绑定模式

如果用户层需要获取 nonai_2d 转换后的数据流,则不能使用绑定模式。例如:

  • sample_mcm 代码中,如何把 sensor 数据传输给 AI 模块,参照 nonai_2d_work 函数,NONAI_2D_RGB_CH 通道用于此功能。
  • vicap(yuv422) 数据流通过 nonai_2d 转换为 rgbp888,并在用户层传输给 AI 模块使用:
    vicap(yuv422) -> nonai_2d(rgbp888)
    
  • 使用以下接口发送和获取转换后的图形数据:
    kd_mpi_nonai_2d_send_frame
    kd_mpi_nonai_2d_get_frame
    

你好,请问vb的分配有什么讲究吗,根据我的报错log来看,似乎是blk分配出了问题,能分析一下我的log信息吗

vb是mpp下所有模块公用的,如果使用不当,某些模块占用了vb,其他模块就无法及时获取到vb进而影响其功能,如报错:no blk, blk_size。

请问vb的comm_pool[i]不同的模块是如何找到属于自己的vb池的呢,这个comm_pool[i]的i取值有什么讲究吗

您的代码问题:

int sample_sys_bind_init(void)
{
    k_s32 ret = 0;
    k_mpp_chn vicap_mpp_chn;
    k_mpp_chn nonai_2d_mpp_chn;
    k_mpp_chn vo_mpp_chn;
    vicap_mpp_chn.mod_id = K_ID_VI;
    vicap_mpp_chn.dev_id = vicap_dev;
    vicap_mpp_chn.chn_id = vicap_chn;

    nonai_2d_mpp_chn.mod_id = K_ID_NONAI_2D;
    nonai_2d_mpp_chn.dev_id = 0;
    nonai_2d_mpp_chn.chn_id = NONAI_2D_BIND_CH_0;

    vo_mpp_chn.mod_id = K_ID_VO;
    vo_mpp_chn.dev_id = K_VO_DISPLAY_DEV_ID;
    vo_mpp_chn.chn_id = K_VO_DISPLAY_CHN_ID1;

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &nonai_2d_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    ret = kd_mpi_sys_bind(&vicap_mpp_chn, &vo_mpp_chn);
    CHECK_RET(ret, __func__, __LINE__);

    return ret;
}

需修改为将nonai_2d的输出作为VO的输入,此处绑定错误。其他部分如有问题请对照demo修改。

修改后仍然报错
<3>[24] [Func]:config_job [Line]:1391 [Info]:config_job>no blk, blk_size 3112960
<3>[24] [Func]:config_job [Line]:1391 [Info]:conf
ig_job>no blk, blk_size 3112960
kd_mpi_isp_stop_stream chn enable is 1
kd_mpi_isp_stop_stream chn enable is 1
kd_mpi_isp_stop_stream chn enable is 0
release reserved vb 278734848
release reserved vb 0
<3>[4] [Func]:__vb_destory_pool [Line]:368 [Info]:Blk in this pool(2) occupied by someone, please release it first!
<3>[4] [Func]:vb_do_exit [Line]:1592 [Info]:destory pool [2] failed
fastboot_app, kd_mpi_vb_exit failed. ret= ffffffff

这个应该如何解决

看log是运行结束时,某些模块退出时没有正常释放vb导致。需检查各模块是否调用了正常退出的代码。可以结合cat /proc/umap/vb 来查看各模块vb占用情况。