视频处理子系统 (VPSS)
概述
VPSS(Video Process Sub-System)是视频处理子系统,支持的具体图像处理功能包括CROP、Scale、像素格式转换、固定角度旋转、Cover/Coverex、 Mirror/Flip、压缩解压等。
功能描述
基本概念
| 功能 | 描述 |
|---|---|
| GROUP | VPSS 对用户提供组(GROUP)的概念。最大个数请参见 VPSS_MAX_GRP_NUM 定义,各 GROUP 分时复用硬件设备,硬件依次处理各个组提交的任务。 |
| CHANNEL | VPSS 组的通道。提供多个通道,每个通道具有缩放、裁剪等功能。把图像裁剪、缩放成用户设置的目标分辨率输出。 |
| CROP | 裁剪,分为 2 种: 组裁剪、通道裁剪。
|
| 像素格式转换 | 支持输入输出图像的数据格式转换,例如 NV12->RGB888P 等。 |
| Scale | 缩放,对图像进行缩小或放大处理。 |
| Mirror/Flip | Mirror 即水平镜像,Flip 即垂直翻转。可使用 Mirror + Flip 实现 180° 旋转。 |
| FRC(帧率控制) | 帧率控制分为两种:组帧率控制和通道帧率控制。
|
| Cover | 视频遮挡区域,调用 VGS 对 VPSS 通道的输出图像填充纯色块。 |
| Overlay | 视频叠加区域,调用 VGS 对 VPSS 通道的输出图像叠加位图。 |
| Mosaic | 马赛克,调用 VGS 对 VPSS 通道的输出图像填充马赛克块。 |
| RGN 通道配置 | VPSS Group 和通道均支持 Overlay/Cover/Mosaic/Line 等功能。
|
| 固定角度旋转 | 支持 0°、90°、180°、270° 固定角度旋转。 |
| 通道工作模式 | VPSS 通道工作模式主要分为两种,通过改变 VPSS_CHN_MODE_E 切换模式:
|
像素格式排布
PIXEL_FORMAT_E 枚举按⼤端模式定义,即枚举定义代表的数据存储排布是按⼤端模式排布,以RGB888/ARGB8888格式的图像存储为例:
RGB888格式的图像存储⽰意图(⼤端模式)如下所示。

ARGB8888格式的图像存储⽰意图(⼤端模式)如下所示。

注意
PIXEL_FORMAT_E枚举按⼤端模式定义,但 ARGB1555、RGB565 两种格式处理特殊,现做统⼀约束,要求输⼊图像为 ARGB1555/RGB565 格式时,图像数据在内存中排列统⼀按⼩端存放,对应的PIXEL_FORMAT_E枚举值如下:
枚举 存储说明 ZH_FMT_RGB565 图像数据在内存中排布为 BGR565 小端,R 在低位。 ZH_FMT_BGR565 图像数据在内存中排布为 RGB565 小端,R 在高位。 ZH_FMT_ARGB1555 图像数据在内存中排布为 BGRA551 小端,A 在低位。 ZH_FMT_BGRA5551 图像数据在内存中排布为 ARGB1555 小端,A 在高位 。 其他 RGB 格式建议按⼤端排布,若待处理图像数据是按⼩端排布,则对应的
PIXEL_FORMAT_E枚举值也需按照反向配置。如待处理图像为 ARGB8888 ⼩端存储( A 在⾼位),枚举值要配置为ZH_FMT_BGRA8888。
应用方式
VPSS 在系统中的定位如下图所示。

通过调用 SYS 模块的绑定接⼝,可与 VDEC/VI 和 VO/VENC/SVP 等模块进行绑定,其中前者为 VPSS 的输入源,后者为 VPSS 的接收者。
用户可通过 VPSS MPI 接⼝对 Group 进行管理。每个 Group 仅可与—个输入源绑定。
Group 的通道有两种工作模式:USER 和 PASSTHOUGH,两种模式间可动态切换。两种模式下各通道均可与多个接收者绑定。
- USER 模式下主要用于⾮绑定模式下,从通道手动取帧,用于 AI 算法、用户数据分析处理等场景。
- PASSTHOUGH 模式主要用于预览和回放场景下做播放控制,如电子放大。
芯片处理流程
- VPSS USER 模式数据流图如下所示。

- VPSS PAST 模式数据流图如下所示。

VPSS 通道工作于 PAST 模式下,大部分数据处理(如上图虚线框内)是 VPSS 将处理参数透传给 VO 模块,由 VO 模块来—次性完成实际处理,进⽽节省硬件资源占用。
注意
在 PAST 模式时,如果当前为绑定状态时(自动送帧给下级时),RGN Attach 到通道的贴图无效。
输入输出特性
输出图像格式及对齐方式
VPSS对齐方式均采用像素对齐。各芯片支持详情见下表:
| 数据格式 | 宽度对齐像素 | 高度对齐像素 | 像素字节宽度(bit) |
|---|---|---|---|
| ZH_FMT_YUV420SP ZH_FMT_YUV420SP_VU | 16 | 1 | 8 |
示例代码
ZH_S32 s32Ret = ZH_SUCCESS;
VPSS_GRP VpssGrp = 0;
VPSS_CHN VpssChn[VPSS_MAX_CHN_NUM] = { VPSS_CHN0, VPSS_CHN1, VPSS_CHN2, VPSS_CHN3 };
VPSS_GRP_ATTR_S stGrpVpssAttr; VPSS_CHN_ATTR_S stVpssChnAttr;
stGrpVpssAttr.u32MaxW = SRC_WIDTH;
stGrpVpssAttr.u32MaxH = SRC_HEIGHT;
stGrpVpssAttr.enPixelFormat = ZH_FMT_YUV420SP;
stGrpVpssAttr.enCompressMode = COMPRESS_AFBC_16x16;
stGrpVpssAttr.stFrameRate.s32SrcFrameRate = -1;
stGrpVpssAttr.stFrameRate.s32DstFrameRate = -1;
s32Ret = ZH_MPI_VPSS_CreateGrp(VpssGrp, &stGrpVpssAttr);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
stCropInfo.bEnable = ZH_TRUE;
stCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
stCropInfo.stCropRect.s32X = 640;
stCropInfo.stCropRect.s32Y = 360;
stCropInfo.stCropRect.u32Width = 640;
stCropInfo.stCropRect.u32Height = 360;
s32Ret = ZH_MPI_VPSS_SetGrpCrop(VpssGrp, &stCropInfo);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_GetGrpCrop(VpssGrp, &stCropInfo);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
memset(&stVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S));
stVpssChnAttr.enChnMode = VPSS_CHN_MODE_USER;
stVpssChnAttr.enCompressMode = COMPRESS_MODE_NONE;
stVpssChnAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
stVpssChnAttr.enPixelFormat = ZH_FMT_YUV420SP;
stVpssChnAttr.stFrameRate.s32SrcFrameRate = -1;
stVpssChnAttr.stFrameRate.s32DstFrameRate = -1;
stChnCropInfo.bEnable = ZH_TRUE;
stChnCropInfo.enCropCoordinate = VPSS_CROP_RATIO_COOR;
stChnCropInfo.stCropRect.s32X = 500;
stChnCropInfo.stCropRect.s32Y = 500;
stChnCropInfo.stCropRect.u32Width = 500;
stChnCropInfo.stCropRect.u32Height = 500;
for (ZH_S32 i = 0; i < VPSS_MAX_CHN_NUM; i++) {
stVpssChnAttr.u32Width = SRC_WIDTH / VPSS_MAX_CHN_NUM * (i + 1);
stVpssChnAttr.u32Height = SRC_HEIGHT / VPSS_MAX_CHN_NUM * (i + 1);
s32Ret = ZH_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn[i], &stVpssChnAttr);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_GetChnAttr(VpssGrp, VpssChn[i], &stVpssChnAttr);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_SetChnCrop(VpssGrp, VpssChn[i], &stChnCropInfo);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_GetChnCrop(VpssGrp, VpssChn[i], &stChnCropInfo);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_EnableChn(VpssGrp, VpssChn[i]);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
}
s32Ret = ZH_MPI_VPSS_StartGrp(VpssGrp);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
s32Ret = ZH_MPI_VPSS_StopGrp(VpssGrp);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
for (ZH_S32 i = 0; i < VPSS_MAX_CHN_NUM; i++) {
s32Ret = ZH_MPI_VPSS_DisableChn(VpssGrp, VpssChn[i]);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
}
s32Ret = ZH_MPI_VPSS_DestroyGrp(VpssGrp);
if (s32Ret != ZH_SUCCESS) {
return s32Ret;
}
API 参考
该功能模块为用户提供以下 API:
- ZH_MPI_VPSS_CreateGrp:创建一个 VPSS GROUP。
- ZH_MPI_VPSS_DestroyGrp:销毁一个 VPSS GROUP。
- ZH_MPI_VPSS_StartGrp:启用 VPSS GROUP。
- ZH_MPI_VPSS_StopGrp:禁用 VPSS GROUP。
- ZH_MPI_VPSS_ResetGrp:重置一个 VPSS GROUP。
- ZH_MPI_VPSS_GetGrpAttr:获取 VPSS GROUP 属性。
- ZH_MPI_VPSS_SetGrpAttr:设置VPSS GROUP 属性。
- ZH_MPI_VPSS_SetGrpCrop:设置 VPSS GROUP CROP 功能属性。
- ZH_MPI_VPSS_GetGrpCrop:获取 VPSS GROUP CROP 功能属性。
- ZH_MPI_VPSS_SetGrpRotation:设置 VPSS GROUP 图像固定角度旋转属性。
- ZH_MPI_VPSS_GetGrpRotation:获取 VPSS GROUP 图像固定角度旋转属性。
- ZH_MPI_VPSS_SendFrame:用户向 VPSS GROUP 发送数据。
- ZH_MPI_VPSS_GetGrpFrame:用户从 VPSS GROUP 获取一帧原始图像。
- ZH_MPI_VPSS_ReleaseGrpFrame:用户释放一帧原始图像。
- ZH_MPI_VPSS_EnableBackupFrame:使能 VPSS GROUP backup 帧。
- ZH_MPI_VPSS_DisableBackupFrame:不使能 VPSS GROUP backup 帧。
- ZH_MPI_VPSS_SetChnAttr:设置 VPSS 通道属性。
- ZH_MPI_VPSS_GetChnAttr:获取 VPSS 通道属性。
- ZH_MPI_VPSS_EnableChn:启用 VPSS 通道。
- ZH_MPI_VPSS_DisableChn:禁用 VPSS 通道。
- ZH_MPI_VPSS_SetChnCrop:设置 VPSS 通道裁剪功能属性。
- ZH_MPI_VPSS_GetChnCrop:获取 VPSS 通道裁剪功能属性。
- ZH_MPI_VPSS_SetChnRotation:设置 VPSS 通道图像固定角度旋转属性。
- ZH_MPI_VPSS_GetChnRotation:获取 VPSS 通道图像固定角度旋转属性。
- ZH_MPI_VPSS_SetChnRotationEx:设置 VPSS 通道的任意角度旋转属性。
- ZH_MPI_VPSS_GetChnRotationEx:获取 VPSS 通道的任意角度旋转属性。
- ZH_MPI_VPSS_GetChnFrame:用户获取一帧通道图像。
- ZH_MPI_VPSS_ReleaseChnFrame:用户释放一帧通道图像。
- ZH_MPI_VPSS_AttachMbPool:将 VPSS 通道绑定到某个视频缓存 MB 池中。
- ZH_MPI_VPSS_DetachMbPool:将 VPSS 通道从某个视频缓存 MB 池中解绑定。
- ZH_MPI_VPSS_GetChnFd:获取 VPSS 通道对应的设备文件句柄。
- ZH_MPI_VPSS_CloseFd:关闭设备和通道的文件描述符。
- ZH_MPI_VPSS_SetModParam:设置 VPSS 的模块参数。
- ZH_MPI_VPSS_GetModParam:获取 VPSS 的模块参数。
ZH_MPI_VPSS_CreateGrp
描述
创建一个 VPSS GROUP。
语法
ZH_S32 ZH_MPI_VPSS_CreateGrp(VPSS_GRP VpssGrp, const VPSS_GRP_ATTR_S *pstGrpAttr);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0, VPSS_MAX_GRP_NUM)。 | 输入 |
| pstGrpAttr | const VPSS_GRP_ATTR_S* | VPSS GROUP 属性指针。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
不支持重复创建。重复创建返回 ZH_ERR_VPSS_NOT_PERM 错误。
ZH_MPI_VPSS_DestroyGrp
描述
销毁一个 VPSS GROUP。
语法
ZH_S32 ZH_MPI_VPSS_DestroyGrp(VPSS_GRP VpssGrp);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 不支持重复销毁,重复销毁返回 ZH_ERR_VPSS_UNEXIST 错误。
- 调用此接⼝之前,必须先调用 ZH_MPI_VPSS_StopGrp 禁用此 GROUP。
- 调用此接⼝时,会—直等待此 GROUP 当前任务处理结束才会真正销毁。
ZH_MPI_VPSS_StartGrp
描述
启用 VPSS GROUP。
语法
ZH_S32 ZH_MPI_VPSS_StartGrp(VPSS_GRP VpssGrp);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 同组调用该函数仅第一次调用成功,重复调用返回失败。
ZH_MPI_VPSS_StopGrp
描述
禁用 VPSS GROUP。
语法
ZH_S32 ZH_MPI_VPSS_StopGrp(VPSS_GRP VpssGrp);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 同组调用该函数仅第一次调用成功,重复调用返回失败。
ZH_MPI_VPSS_ResetGrp
描述
复位 VPSS GROUP。
语法
ZH_S32 ZH_MPI_VPSS_ResetGrp(VPSS_GRP VpssGrp);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 组及通道中待处理或待消耗的数据将会被释放。
ZH_MPI_VPSS_GetGrpAttr
描述
获取 VPSS GROUP 属性。
语法
ZH_S32 ZH_MPI_VPSS_GetGrpAttr(VPSS_GRP VpssGrp, VPSS_GRP_ATTR_S *pstGrpAttr);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| pstGrpAttr | VPSS_GRP_ATTR_S* | VPSS GROUP 属性指针。 | 输出 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- GROUP 属性必须合法,其中部分静态属性不可动态设置。
ZH_MPI_VPSS_SetGrpAttr
描述
设置 VPSS GROUP 属性。
语法
ZH_S32 ZH_MPI_VPSS_SetGrpAttr(VPSS_GRP VpssGrp, const VPSS_GRP_ATTR_S *pstGrpAttr);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| pstGrpAttr | const VPSS_GRP_ATTR_S* | VPSS GROUP 属性指针。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- GROUP 属性必须合法,其中部分静态属性不可动态设置。
ZH_MPI_VPSS_SetGrpCrop
描述
设置 VPSS CROP 功能属性。
语法
ZH_S32 ZH_MPI_VPSS_SetGrpCrop(VPSS_GRP VpssGrp, const VPSS_CROP_INFO_S *pstCropInfo);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| pstCropInfo | const VPSS_CROP_INFO_S* | CROP 功能参数。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败 ,请参见VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 相对模式裁剪时,裁剪区域坐标取值范围为 [0, 999],裁剪区域宽高取值范围为 [1,1000]。
- CROP 区域的尺⼨不能小于 VPSS 最小尺⼨,不能超过 VPSS 支持的最大输入分辨率;裁剪区域起始点不支持负坐标,裁剪区域右边界不能超出 VPSS 支持的最大输入宽度,裁剪区域下边界不能超出 VPSS 支持的最大输入高度。
- 如果裁剪区域超出图像范围,则裁剪坐标向原点方向移动,优先保证裁剪出的宽高与所设置的参数相同。
- 如果裁剪宽度大于输入图像宽度,则裁剪输出宽度调整为输入图像宽度。
- 如果裁剪高度大于输入图像高度,则裁剪输出高度调整为输入图像高度。
- 在有绑定 VO 时,不推荐使用此接⼝做电子放大,建议通道模式设置为 PAST 模式,并使用 ZH_MPI_VPSS_SetChnCrop 做电子放大功能。
- 通道设置为 PAST 时,只有在绑定了 VO 的情况下才生效。
ZH_MPI_VPSS_GetGrpCrop
描述
获取 VPSS CROP 功能属性。
语法
ZH_S32 ZH_MPI_VPSS_GetGrpCrop(VPSS_GRP VpssGrp, VPSS_CROP_INFO_S *pstCropInfo);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| pstCropInfo | VPSS_CROP_INFO_S* | CROP 功能参数。 | 输出 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
GROUP 必须已创建。
ZH_MPI_VPSS_SetGrpRotation
描述
设置 VPSS GROUP 图像固定角度旋转属性。
语法
ZH_S32 ZH_MPI_VPSS_SetGrpRotation(VPSS_GRP VpssGrp, ROTATION_E enRotation);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| enRotation | ROTATION_E | 旋转属性。 | 输入 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
- GROUP 必须已创建。
- 仅支持 0 度、90 度、180 度、270 度的旋转,不支持任意角度旋转。
ZH_MPI_VPSS_GetGrpRotation
描述
获取 VPSS GROUP 图像固定角度旋转属性。
语法
ZH_S32 ZH_MPI_VPSS_GetGrpRotation(VPSS_GRP VpssGrp, ROTATION_E *penRotation);
参数
| 参数名 | 数据类型 | 描述 | 输入/输出 |
|---|---|---|---|
| VpssGrp | VPSS_GRP | VPSS GROUP 号。 取值范围:[0,VPSS_MAX_GRP_NUM)。 | 输入 |
| penRotation | ROTATION_E* | 旋转属性。 | 输出 |
返回值
| 返回值 | 描述 |
|---|---|
| 0 | 成功。 |
| ⾮ 0 | 失败,请参见 VPSS 错误码。 |
注意事项
GROUP 必须已创建。
ZH_MPI_VPSS_SendFrame
描述
用户向 VPSS 发送数据。
语法
ZH_S32 ZH_MPI_VPSS_SendFrame(VPSS_GRP VpssGrp, VPSS_GRP_PIPE VpssGrpPipe, const VIDEO_FRAME_INFO_S *pstVideoFrame, ZH_S32 s32MilliSec);
参数