目录
前言
01 测试Demo大致流程图
02 代码分析
2.1 VI设备初始化
2.2 使能通道 —— RK_MPI_VI_EnableChn
2.3 VI 和 VENC绑定
2.4 创建 编码线程
前言
从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板
🎬 个人主页:@ChenPi
🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨
🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨
🛸推荐专栏3:《嵌入式音视频_@ChenPi的博客-CSDN博客》
🌺本篇简介 :使用RV1126进行编码测试
首先我们使用的硬件为瑞芯微的RV1126
kmedia是RK官方封装一层简易的API,把RGA、MPP、RKNN等等这些接口封装成高级的接口
该平台支持以下功能:
- VI(输入视频捕获)
- VO(视频输出显示)
- AI(音频采集)、AO(音频输出)
- VENC(H.265/H.264/JPEG/MJPEG编码)
- VDEC(H.265/H.264/JPEG、MJPEG 解码)
- RGA视频处理(包括旋转、缩放、裁剪)
- AENC(音频编码)、ADEC(音频解码)、
- MD(移动侦测)
- OD(遮挡侦测)
- VMIX(视频合成)
- MUXER(视频封装)
- VP(视频一入四出)
01 测试Demo大致流程图
因为这个测试Demo主要是编码进行视频编码
所以只用到VI和VENC
- VI(输入视频捕获)
- VENC(H.265/H.264/JPEG/MJPEG编码)
02 代码分析
2.1 VI设备初始化
VI设备初始化有两步
- 设置通道属性
- 使能通道
设置通道属性 —— RK_MPI_VI_SetChnAttr
设置通道的属性关键在于VI_CHN_ATTR_S结构体
结构体原型:
typedef struct rkVI_CHN_ATTR_S {
const RK_CHAR *pcVideoNode; //video节点路径
RK_U32 u32Width; //分辨率宽度
RK_U32 u32Height; //分辨率高度
IMAGE_TYPE_E enPixFmt; //(VI格式)
RK_U32 u32BufCnt; // 映射类型默认是:MMAP
VI_CHN_BUF_TYPE enBufType; // VI通道模式
VI_CHN_WORK_MODE enWorkMode; //VI工作模式
} VI_CHN_ATTR_S;
需要注意的点:
结构体中的enBufType //VI 捕 捉 视 频 的 类 型 :
- DMA 模 式(VI_CHN_BUF_TYPE_DMA)
- MMAP 模式(VI_CHN_BUF_TYPE_MMAP)
DMA:指的是直接访问内存的方式,相当于音视频数据直接从硬件传输到内存里面。这种方式的优点就
是两边传输的速度非常之快,但缺点就是非常消耗硬件资源,对硬件外设资源要求较高。
MMAP:指的是内存映射,这种方式就是把硬件外设、磁盘的文件映射到虚拟内存上面。然后用户只需
要对虚拟内存进行读写操作就可以对硬件外设进行操作了。这种方法的优点是用户不需要直接操作硬件就能够修改硬件的内容,换言之就是对硬件的消耗没那么大。
但是缺点就是:
第一,它的读写速度相对 DMA来说没那么快;
第二,有时候硬件写到虚拟内存的数据可能会出现丢失情况,导致数据出现丢失的情况。
2.2 使能通道 —— RK_MPI_VI_EnableChn
VENC的初始化:关键在于VENC_CHN_ATTR_S结构体,这个结构体是VENC设置的结构体
RV1126 编码器参数结构体包含在 VENC 通道属性结构体里面,我们可以看到 VENC 通道结
构 体 里 面 包 含 三 个 重 要 结 构 体 : 分 别 是
- VENC_ATTR_S( 编 码 器 基 础 属 性 结 构 体 )
- VENC_RC_ATTR_S(编码码率控制属性结构体)
- VENC_GOP_ATTR_S(编码器 GOP 属性结构体)
设置完上述成员变量后,则使用RK_MPI_VENC_CreateChn创建编码层。
2.3 VI 和 VENC绑定
设置完VI模块和VENC模块后,需要进行绑定VI和VENC才能够正常采集到编码数据。
采集的时候用到的结构体·MPP_CHN_S
typedef struct rkMPP_CHN_S {
MOD_ID_E enModId;
RK_S32 s32DevId;
RK_S32 s32ChnId;
} MPP_CHN_S;
其中MPP_CHN_S的enModId是模块的ID、 s32ChnId是通道id。
这里分别创建两个MPP_CHN_S结构体,
- VI的MPP_CHN_S,它的enModId选择的是RK_ID_VI,s32Id应该和VI创建的ID进行适配;
- VENC的MPP_CHN_S,它的enModId选择的是RK_ID_VENC,s32ChnId和VENC创建的Id对应。
创建完两个MPP_CHN_S结构体后,利用RK_MPI_SYS_BIND把VI和VENC进行绑定。
2.4 创建 编码线程
从collect_venc_thread线程主要作用是获取VENC编码的码流数据,并实时保存到H264文件。
在这个线程里面,有几个重要的API需要讲解:
RK_MPI_SYS_GetMediaBuffer的作用是获取对应通道的数据,
这个API第一个参数是模块ID,第二个参数是通道ID,第三个参数阻塞时间这里默认是-1不阻塞。
获取VENC通道的数据后,这其中
- RK_MPI_MB_GetPtr是获取VENC缓冲区数据,
- RK_MPI_MB_GetSize是获取VENC的缓冲区长度,并把缓冲区数据fwrite写到H264文件。