项目1:RV1126+FFMPEG多路码流推流第二讲:RV1126的VI模块讲解
本文介绍了视觉项目中VI视频输入模块的配置流程,该模块是摄像头数据入口。主要步骤包括:1)配置RV1126_VI_CONFIG结构体参数,包括分辨率(1920x1080)、缓冲区数量(3)、图像格式(NV12)等;2)调用rkmedia_vi_init函数初始化并使能VI模块;3)将VI模块ID存入vi_containers数组统一管理。该模块通过RK_MPI_VI_SetChnAttr和RK_M
一.本章节介绍:
本章节主要是介绍视觉项目的VI视频输入模块的讲解,VI视频模块是所有摄像头数据的入口。VI模块的配置在源文件rkmedia_module_function.cpp里面。
二.VI模块的思维导图:

上面思维导图主要是描述VI模块设置的大致流程,首先对RV1126_VI_CONFIG结构体进行参数设置,然后调用rkmedia_vi_init对VI模块进行设置和使能,设置完成后再把VI的模块ID放到VI数组里面(vi_containers)。
三.VI模块代码的截图
下图就是整个VI模块配置的具体参数,这里使用设置的结构体是RV1126_VI_CONFIG。RV1126_VI_CONFIG里面主要包含了VI_CHN_ATTR_S结构体进行设置。
typedef struct
{
unsigned int id;
VI_CHN_ATTR_S attr;
} RV1126_VI_CONFIG;
rkmedia_function_init();
RV1126_VI_CONFIG rkmedia_vi_config;
memset(&rkmedia_vi_config, 0, sizeof(rkmedia_vi_config));
rkmedia_vi_config.id = 0;
rkmedia_vi_config.attr.pcVideoNode = CMOS_DEVICE_NAME; // VIDEO视频节点路径,
rkmedia_vi_config.attr.u32BufCnt = 3; // VI捕获视频缓冲区计数,默认是3
rkmedia_vi_config.attr.u32Width = 1920; // 视频输入的宽度,一般和CMOS摄像头或者外设的宽度一致
rkmedia_vi_config.attr.u32Height = 1080; // 视频输入的高度,一般和CMOS摄像头或者外设的高度一致
rkmedia_vi_config.attr.enPixFmt = IMAGE_TYPE_NV12; // 视频输入的图像格式,默认是NV12(IMAGE_TYPE_NV12)
rkmedia_vi_config.attr.enBufType = VI_CHN_BUF_TYPE_MMAP; // VI捕捉视频的类型
rkmedia_vi_config.attr.enWorkMode = VI_WORK_MODE_NORMAL; // VI的工作模式,默认是NORMAL(VI_WORK_MODE_NORMAL)
int ret = rkmedia_vi_init(&rkmedia_vi_config); // 初始化VI工作
if (ret != 0)
{
printf("vi init error\n");
}
else
{
printf("vi init success\n");
RV1126_VI_CONTAINTER vi_container;
vi_container.id = 0;
vi_container.vi_id = rkmedia_vi_config.id;
set_vi_container(0, &vi_container); // 设置VI容器
}
id:VI模块的id号,用于初始化和使能VI模块
pcVideoNode: 摄像头的视频节点,这里默认是rkispp_scale0
u32BufCnt:缓冲区计数,默认是3
u32Width:VI模块分辨率宽度1920
u32Height:VI模块分辨率高度1080
enPixFmt:图像格式默认是NV12,这里填的是IMAGE_TYPE_NV12
enBufType:VI模块捕捉视频的类型,这里默认填写MMAP
enWorkMode:VI工作模式,这里写的是VI_WORK_MODE_NORMAL
填写完上述的配置参数后,就会调用rkmedia_vi_init这个自己封装的函数,这个函数主要是实现VI模块的初始化和使能的具体操作,具体看下图
int rkmedia_vi_init(RV1126_VI_CONFIG *rv1126_vi_config)
{
int ret;
VI_CHN_ATTR_S vi_attr = rv1126_vi_config->attr;
unsigned int id = rv1126_vi_config->id;
//vi_attr.pcVideoNode = CMOS_DEVICE_NAME;//
//初始化VI模块
ret = RK_MPI_VI_SetChnAttr(CAMERA_ID, id, &vi_attr);
//使能VI模块
ret |= RK_MPI_VI_EnableChn(CAMERA_ID, id);
if (ret != 0)
{
printf("create vi failed.....\n", ret);
return -1;
}
return 0;
}
rkmedia_vi_init这个自定义函数里面,关键是对VI进行初始化和使能,它分别调用了RK_MPI_VI_SetChnAttr的API对VI模块的属性进行初始化,然后再调用RK_MPI_VI_EnableChn对其使能。
设置完VI模块后,就要把VI模块的ID号设置到容器里面,调用自己封装的函数是set_vi_container
if (ret != 0)
{
printf("vi init error\n");
}
else
{
printf("vi init success\n");
RV1126_VI_CONTAINTER vi_container;
vi_container.id = 0;
vi_container.vi_id = rkmedia_vi_config.id;
set_vi_container(0, &vi_container); // 设置VI容器
}
set_vi_container(0, &vi_container)的具体实现:
int set_vi_container(unsigned int index, RV1126_VI_CONTAINTER *vi_container)
{
pthread_mutex_lock(&all_containers_mutex);
all_containers.vi_containers[index] = *vi_container;
pthread_mutex_unlock(&all_containers_mutex);
return 0;
}
在这个自定义的函数里面,最主要是把VI的ID号存放在VI模块数组里面(vi_containers),具体结构如下代码:
typedef struct
{
unsigned int container_id;
RV1126_VI_CONTAINTER vi_containers[ALL_CONTAINER_NUM];
RV1126_AI_CONTAINTER ai_containers[ALL_CONTAINER_NUM];
RV1126_VENC_CONTAINER venc_containers[ALL_CONTAINER_NUM];
RV1126_AENC_CONTAINER aenc_containers[ALL_CONTAINER_NUM];
}RV1126_ALL_CONTAINER;
RV1126_ALL_CONTAINER结构体里面包含了四个模块的数组存储分别是VI模块(vi_contaianers)、AI模块(ai_containers)、VENC模块(venc_containers)、AENC模块(aenc_containers)。这四个模块容器就是分别存储,四个模块的ID号,让其能够更加方便的管理起来。

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)