MPP VIN 设计及接口说明
MPP VIN 模块主要实现两个功能:
- 
                
对上封装了 DVP、Camera 驱动的 ioctl 接口 (尽量做到和 Linux MPP VIN 保持一致)
 - 
                
对视频 Buf 队列的管理,实现了 DVP 应用、DVP 驱动之间的 Buf 轮转管理

图 1. MPP VIN 模块的软件框架  
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)
