记录一下rv1126的软件开发记录,同时分享一些学习经验以供参考。
本篇只介绍了RKMedia中的视频输入这部分。
编译环境:Ubuntu18.04
模块:RKMedia
视频输入也简称为VI,这个模块用于读取sensor的数据。 该模块是对V4L2接口的封装,依赖Linux的V4L2驱动架构。ISP/ISPP/VICAP驱动通过V4L2架构向用户层提供文件节点(如:/dev/video0),VI通过操作文件节点实现参数配置视频帧的读取等操作。
VI的创建需要指定视频节点(VideoNode),比如“/dev/video0”。每个视频节点对应一路视频流。单摄像头能提供多种分辨率的视频流,比如RV1126/RV1109平台的ISPP可同时提供4种分辨率视频流,也是因为ISPP驱动向用户层提供了4个视频节点。
对于带有RKISP的平台(如:RV1126/RV1109),每个接入ISPP的Camera都将向用户提供4个视频节点,如下表所示。以“rkispp_”开头的名称是驱动提供的一种别名机制,在VI内部会翻译为对应的/dev/videoX节点,使用者只需使用这4个固定名称,就能获取不同分辨率的视频流。
VI通道属性结构体指针:VI_CHN_ATTR_S
typedef char RK_CHAR;
typedef enum rkVI_CHN_WORK_MODE {
VI_WORK_MODE_NORMAL = 0,
// for vi single caculate luma.
// In this mode, vi has no output,
// and data cannot be obtained from vi.
VI_WORK_MODE_LUMA_ONLY
} VI_CHN_WORK_MODE;
typedef enum rkVI_CHN_BUF_TYPE {
VI_CHN_BUF_TYPE_DMA = 0, // Default
VI_CHN_BUF_TYPE_MMAP,
} VI_CHN_BUF_TYPE;
typedef struct rkVI_CHN_ATTR_S {
const RK_CHAR *pcVideoNode;
RK_U32 u32Width;
RK_U32 u32Height;
IMAGE_TYPE_E enPixFmt;
RK_U32 u32BufCnt; // VI capture video buffer cnt.
// VI capture video buffer type.
VI_CHN_BUF_TYPE enBufType;
VI_CHN_WORK_MODE enWorkMode;
} VI_CHN_ATTR_S;
结构体成员介绍:
pcVideoNode:video节点路径
u32Width: video宽度
u32Height: video高度
enPixFmt: video格式
u32BufCnt: VI捕获的视频缓冲区计数
enBufType: VIBuf类型
enWorkMode:VI通道工作模式
pcVideoNode :一定要注意在创建通道的时候视频节点要正确,可以通过v4l2-ctl 先对视频节点进行图像抓取,能够正常抓取的话在进行一下路径传递;
v4l2-ctl 视频抓取命令:
// -d + 视频节点
//视频宽高为:width、height
//视频格式:pixelformat
//图像保存路径:stream-to
v4l2-ctl -d /dev/video13 \
--set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
--stream-mmap=3 \
--stream-skip=3 \
--stream-to=/tmp/nv12.bin \
--stream-count=1 \
--stream-poll
u32BufCnt :通道确定后设置缓冲区计数,在缓冲区存的几帧图像
u32Width :视频宽 1920
u32Height:视频高 1080
enPixFmt :视频格式 NV12
enWorkMode :VI_WORK_MODE_NORMAL
VI_CHN_ATTR_S vi_chn_attr;
vi_chn_attr.pcVideoNode = /dev/video13;
vi_chn_attr.u32BufCnt = 3;
vi_chn_attr.u32Width = 1920;
vi_chn_attr.u32Height = 1080;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;
ret = RK_MPI_VI_SetChnAttr(s32CamId, 0, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(s32CamId, 0);
if (ret) {
printf("Create VI[0] failed! ret=%d\n", ret);
return -1;
}
函数解析:
创建一个VI通道用于接收视频流:
ViPipe :VI管道号
ViChn : VI通道号
pstChnAttr:VI通道属性结构体指针
RK_S32 RK_MPI_VI_SetChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, const VI_CHN_ATTR_S *pstChnAttr)
RK_S32 RK_MPI_VI_SetChnAttr(VI_PIPE ViPipe, VI_CHN ViChn, const VI_CHN_ATTR_S *pstChnAttr)
VI管道号 和 ViChn通道号要注意设置要一致。
设置完毕之后开启视频流就行了,在结束后一定要关闭通道。
//开启VI流
ret = RK_MPI_VI_StartStream(s32CamId, 0);
if (ret) {
printf("Start VI[0] failed! ret=%d\n", ret);
return -1;
}
while (!quit) {
usleep(500000);
}
//通道关闭
RK_MPI_VI_DisableChn(s32CamId, 0);