MPP VIN 设计及接口说明
MPP VIN 模块主要实现两个功能:
-
对上封装了 DVP、Camera 驱动的 ioctl 接口(尽量做到和 Linux MPP VIN 保持一致)
-
对视频 Buf 队列的管理,实现了 DVP 应用、DVP 驱动之间的 Buf 轮转管理
Buf 队列管理
VIN 模块中的队列管理,参考了 Linux 的 V4L2 框架,通过 struct vb_queue
结构中的两个 Buf 队列来管理,DVP 驱动中还需要维护一个 list 来配合 DVP 控制器的地址更新。 整个 Buf 流转的过程如下图:
-
queued_list:是一些空闲 Buf,等待 Sensor 的数据到来后,DVP 驱动会从这个队列中找可用 Buf 来保存下一帧数据。
-
done_list:是一些填了视频数据的 Buf,等待用户来处理这些数据,一般用户处理完后需要将 Buf 还给驱动,也就是通过 Q_BUF 命令还给 queued_list。
-
从图中的流转过程看,运行期间,在某一时刻,DVP 需要使用一个 Buf,APP 需要使用一个 Buf,Q_BUF 需要有一个 Buf 在等待(否则 DVP 的 done 中断来了后发现没有等待的 Q_BUF 会发生丢帧),一共 至少要有 3 个 Buf。
-
以 YUV422 格式计算,有两个 plane,在 L2 框架中这一组 plane 算一个 Buf,3 个 Buf 就需要申请 6 个 plane,
总大小 = 长 * 宽 * 2 * 3
。
对于每一帧图像数据来说,DVP 的输出有两个 plane:Y 和 UV。针对 DVP 的两种输出格式:YUV422_COMBINED_NV16 和 NV12,两个 plane 的空间大小如下表:
- | YUV422_COMBINED_NV16 | YUV420_COMBINED_NV12 |
---|---|---|
Plane Y | Width * height | Width * height |
Plane UV | Width * height | Width * height / 2 |
根据前面对“Buf 队列管理”的分析可知:我们要分配的内存空间 至少要有 3 个 Buf,每个 Buf 包含两个 Plane。
接口设计
函数原型 | int mpp_vin_init(char *camera) |
---|---|
功能说明 | 初始化 VIN 模块,包括打开 Camera 设备、DVP 设备、为 Video Buf 分配内存池 |
参数定义 | camera - 摄像头的设备名称 |
返回值 | 0,成功;<0,失败 |
注意事项 | 内存池默认配置 8 MB,需要根据实际的应用场景来修改 |
函数原型 | int mpp_vin_deinit(void) |
---|---|
功能说明 | 释放 VIN 模块的资源,包括关闭 Camera 设备和 DVP 设备,释放 Video Buf 内存池 |
参数定义 | 无 |
返回值 | 无 |
注意事项 | - |
函数原型 | int mpp_dvp_ioctl(int cmd, void *arg) |
---|---|
功能说明 | DVP 设备的 ioctl 接口 |
参数定义 |
cmd - ioctl 命令码
arg - ioctl 命令相应的参数
|
返回值 | 0,成功;<0,失败 |
注意事项 | - |
参考 Demo
命令行工具 test_dvp 实现了一个完整的 Sensor->DVP->DE
数据通路,从 Camera
采集数据、然后会显到 DE 的 Video layer。 整体的处理流程如下图(图中按照访问对象分为三列,实际上整体是串行执行):
将当前 Buf 传给 Video Layer
环节,如果打开了旋转功能(参数 -a ),会先将 Buf 送给 GE 旋转,然后才给 DE 去显示。此 Demo 的代码实现可作为 MPP VIN 的 APP 设计参考:(详见 test_dvp.c)