6.6.5. 设计说明¶
6.6.5.1. 源码说明¶
源代码位于 bsp/artinchip/
:
bsp/artinchip/drv/ve/aic_drv_ve.c, VE Driver 层实现
bsp/artinchip/hal/ve/aic_hal_ve.c, VE HAL 层实现
bsp/artinchip/include/drv/aic_drv_ve.h,VE Drv 层接口头文件
bsp/artinchip/include/hal/aic_hal_ve.h, VE HAL 层接口头文件
6.6.5.2. 模块架构¶
VE HAL :负责VE硬件资源初始化和获取等
VE DRV :对HAL层的封装,向上提供更简洁的接口
MPP :直接掉用HAL层接口,处理编解码逻辑,寄存器配置等
APP :应用层调用MPP层接口,即可实现对VE的操作

图 6.70 ve驱动框架¶
- 操作VE基本流程如下:
调用 drv_ve_open 打开 VE 驱动;
调用 drv_ve_control(IOC_VE_GET_CLIENT) 获取ve硬件设备独占权限;
程序完成一次独立的编解码任务:配置寄存器、等待VE当前任务完成;
调用 drv_ve_control(IOC_VE_PUT_CLIENT) 释放ve硬件设备独占权限;
视频帧解码完成,调用 drv_ve_close 关闭 VE 驱动。
6.6.5.3. 关键流程设计¶
6.6.5.3.1. 中断处理流程¶
1.VE 中断类型有三种,包括:finish 中断、error 中断、bit request 中断。
finish 中断表示 VE 任务正常结束
error 中断表示 VE 处理任务过程中出错
bit request 中断表示当前数据不足以完成一次完整的任务,需要继续发送数据
2.上层程序对VE中断的处理
finish 中断处理:VE 正常结束,释放 VE 硬件设备独占权限
bit request 中断处理:再次发送一笔数据,重新启动 VE 执行任务,重复以上过程,直到 VE 返回 finish 或 error 中断
error 中断:VE 执行出错,必须对 VE 进行硬件复位避免错误影响下次任务
等中断超时:此时 VE 出现未知异常,必须对 VE 进行硬件复位
注解
处理 bit request 中断时,不能释放 VE 硬件设备独占权限,因为两次任务处理有相关性。如果这两次任务之间执行其他任务,会影响 VE 内部状态,从而导致该次任务执行出错。
6.6.5.3.2. 多线程支持¶
VE 设备只有一个,所以同一时间只能执行一个任务。当多个线程同时操作 VE 驱动时,VE 只能分时复用。因此上层程序在操作 VE 之前,必须获得 VE 的独占权限。
VE 驱动通过 IOC_VE_GET_CLIENT/IOC_VE_PUT_CLIENT 这两个 drv_ve_control 接口为上层程序提供获取和释放 VE 独占权限功能。
为避免每个线程都执行 VE 驱动初始化等重复操作,建议用户态程序使用单例模式实现 VE 驱动调用。具体实现可参考 mpp 代码(packages/artinchip/mpp/ve/common/ve.c)。
6.6.5.4. 数据结构与接口设计¶
6.6.5.4.1. 数据结构设计¶
// 中断信息结构体
struct wait_info {
int wait_time;
unsigned int reg_status;
};
//VE 硬件抽象
struct aic_ve_client {
u32 status;
aicos_event_t wait_event;
aicos_mutex_t lock;
};
6.6.5.4.2. 接口设计¶
6.6.5.4.2.1. drv_ve_open¶
函数原型 |
struct aic_ve_client *drv_ve_open(void) |
---|---|
功能说明 |
打开 VE 设备 |
参数定义 |
无 |
返回值 |
VE 设备
|
注意事项 |
6.6.5.4.2.2. drv_ve_close¶
函数原型 |
int drv_ve_close(struct aic_ve_client *client) |
---|---|
功能说明 |
关闭 VE 设备 |
参数定义 |
client:VE设备
|
返回值 |
0:成功,其他:失败
|
注意事项 |
6.6.5.4.2.3. IOC_VE_GET_CLIENT¶
函数原型 |
int drv_ve_control(struct aic_ve_client *client, int cmd, void *arg) |
---|---|
功能说明 |
获取 VE 设备独占权限 |
参数定义 |
client:VE设备
cmd :IOC_VE_GET_CLIENT
arg:NULL
|
返回值 |
0:成功,其他:失败
|
注意事项 |
6.6.5.4.2.4. IOC_VE_PUT_CLIENT¶
函数原型 |
int drv_ve_control(struct aic_ve_client *client, int cmd, void *arg) |
---|---|
功能说明 |
释放 VE 设备独占权限 |
参数定义 |
client:VE设备
cmd:IOC_VE_PUT_CLIENT
arg:NULL
|
返回值 |
0:成功,其他:失败
|
注意事项 |
6.6.5.4.2.5. IOC_VE_WAIT¶
函数原型 |
int drv_ve_control(struct aic_ve_client *client, int cmd, void *arg) |
---|---|
功能说明 |
等待 VE 驱动编解码完成,并且获取 VE 寄存器状态 |
参数定义 |
client:drv_ve_open返回的VE硬件实例
cmd:IOC_VE_WAIT
arg:指向struct wait_info指针
|
返回值 |
0:成功,其他:失败
|
注意事项 |
6.6.5.4.2.6. IOC_VE_RESET¶
函数原型 |
int drv_ve_control(struct aic_ve_client *client, int cmd, void *arg) |
---|---|
功能说明 |
VE 驱动硬件复位 |
参数定义 |
client:VE设备
cmd:IOC_VE_RESET
arg:NULL
|
返回值 |
0:成功,其他:失败
|
注意事项 |
6.6.5.5. APP Demo参考¶
以下 demo 实现 VE 驱动基本调用流程,具体可参考 mpp 代码(packages/artinchip/mpp/ve/common/ve.c)
//* 1. 打开VE
struct aic_ve_client* client = drv_ve_open();
//* 2. 获取VE权限
ioctl(client, IOC_VE_GET_CLIENT,NULL);
//* 3. 配置寄存器(省略)
...
//* 4. 等VE中断
struct wait_info wt_info;
wt_info.wait_time = VE_TIMEOUT;
int ret = drv_ve_control(client, IOC_VE_WAIT, &wt_info);
if(ret < 0) {
// 中断超时,VE硬件复位
drv_ve_control(client, IOC_VE_RESET,NULL);
}
//* 5. 释放VE权限
drv_ve_control(client, IOC_VE_PUT_CLIENT,NULL);
//* 6. 关闭VE
drv_ve_close(client);