Edit online

MPP VIN 设计及接口说明

13 Dec 2024
Read time: 3 minute(s)

MPP VIN 模块主要实现两个功能:

  1. 对上封装了 DVP、Camera 驱动的 ioctl 接口(尽量做到和 Linux MPP VIN 保持一致)

  2. 对视频 Buf 队列的管理,实现了 DVP 应用、DVP 驱动之间的 Buf 轮转管理


    vin_structure

    1. MPP VIN 模块的软件框架

Buf 队列管理

VIN 模块中的队列管理,参考了 Linux 的 V4L2 框架,通过 struct vb_queue 结构中的两个 Buf 队列来管理,DVP 驱动中还需要维护一个 list 来配合 DVP 控制器的地址更新。 整个 Buf 流转的过程如下图:


vin_buf_list

2. MPP VIN 中的 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

接口设计

1. mpp_vin_init
函数原型 int mpp_vin_init(char *camera)
功能说明 初始化 VIN 模块,包括打开 Camera 设备、DVP 设备、为 Video Buf 分配内存池
参数定义 camera - 摄像头的设备名称
返回值 0,成功;<0,失败
注意事项 内存池默认配置 8 MB,需要根据实际的应用场景来修改
2. mpp_vin_deinit
函数原型 int mpp_vin_deinit(void)
功能说明 释放 VIN 模块的资源,包括关闭 Camera 设备和 DVP 设备,释放 Video Buf 内存池
参数定义
返回值
注意事项 -
3. mpp_dvp_ioctl
函数原型 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。 整体的处理流程如下图(图中按照访问对象分为三列,实际上整体是串行执行):


vin_demo_flow

3. MPP VIN Demo 中的处理流程
提示:
test-dvp 支持了 先旋转再显示,上图中为了简化并未展示 GE 的处理。在图中
将当前 Buf 传给 Video Layer
环节,如果打开了旋转功能(参数 -a ),会先将 Buf 送给 GE 旋转,然后才给 DE 去显示。

此 Demo 的代码实现可作为 MPP VIN 的 APP 设计参考:(详见 test_dvp.c)