一、 MPP 模块 API
1) 系统控制
测试基础 API:
HI_MPI_SYS_GetVersion:获取MPP 的版本号。
使用实例:
MPP_VERSION_S pstVersion;
s32Ret = HI_MPI_SYS_GetVersion(&pstVersion);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetVersion failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("%s\n",pstVersion.aVersion);
|
结果输出:
HI_VERSION=Hi3559AV100_MPP_V2.0.3.1 B020 Release
|
HI_MPI_SYS_GetChipId:获取当前芯片的ID。
s32Ret = HI_MPI_SYS_GetChipId(&pu32ChipId);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetChipId failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("chip id is %#x\n",pu32ChipId);
|
结果输出:
chip id is 0x3559av100
|
HI_MPI_SYS_GetCustomCode:获取当前芯片的CustomCode。
HI_U32 pu32CustomCode;
s32Ret = HI_MPI_SYS_GetCustomCode(&pu32CustomCode);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetCustomCode failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("CustomCode is %#x\n",pu32CustomCode);
|
结果输出:
Customcode is 0
|
HI_MPI_SYS_GetCurPTS:获取当前时间戳。
HI_U64 pu64CurPTS;
s32Ret = HI_MPI_SYS_GetCurPTS(&pu64CurPTS);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetCurPTS failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("pu64CurPTS is %#x\n",pu64CurPTS);
s32Ret = HI_MPI_SYS_GetCurPTS(&pu64CurPTS);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetCurPTS failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("pu64CurPTS is %#x\n",pu64CurPTS);
|
pu64CurPTS is 0x9fa48efc
pu64CurPTS is 0x9fa48f0a
|
HI_MPI_SYS_InitPTSBase:初始化MPP 时间戳。
媒体业务没有启动时调用该接口:
HI_U64 u64PTSBase=0;
s32Ret = HI_MPI_SYS_InitPTSBase(u64PTSBase);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_InitPTSBase failed with %d!\n", s32Ret);
}
|
HI_MPI_SYS_SyncPTS:同步MPP 时间戳。
s32Ret = HI_MPI_SYS_SyncPTS(pu64CurPTS+1000000);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_SyncPTS failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("pu64CurPTS is %lld\n",pu64CurPTS);
|
结果输出:
pu64CurPTS is 11188002027
注意:对当前系统时间戳(微秒级)进行微调,微调后不会出现时间戳回退现象。在多片之
间做同步时,由于单板的时钟源误差可能比较大,建议一秒钟进行一次时间戳微调。
|
HI_MPI_SYS_GetScaleCoefLevel:获取 VPSS 和 VGS 缩放系数等级。
SCALE_RANGE_S pstScaleRange;
SCALE_COEFF_LEVEL_S pstScaleCoeffLevel;
pstScaleRange.enHorizontal = SCALE_RANGE_0;
pstScaleRange.enVertical = SCALE_RANGE_0;
s32Ret = HI_MPI_SYS_GetScaleCoefLevel(&pstScaleRange,&pstScaleCoeffLevel);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetScaleCoefLevel failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("enHorChr is %d,enHorLum is %d,enVerChr is %d,enVerLum is %d\n",pstScaleCoeffLevel.enHorChr,
pstScaleCoeffLevel.enHorLum,pstScaleCoeffLevel.enVerChr,pstScaleCoeffLevel.enVerLum);
|
结果输出:
enHorChr is 0,enHorLum is 0,enVerChr is 0,enVerLum is 0
|
HI_MPI_SYS_GetTimeZone:获取时区信息
HI_S32 ps32TimeZone;
s32Ret = HI_MPI_SYS_GetTimeZone(&ps32TimeZone);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_SYS_GetTimeZone failed with %d!\n", s32Ret);
goto EXIT0;
}
printf("ps32TimeZone is %ld\n",ps32TimeZone);
|
结果输出:
ps32TimeZone is 0
|
2) VI
1. VI 接入数据流在 HISI3559AV100 上的实现
在下图中红框部分可见 imx334 共有 8 lane 的数据输出通道,实际使用中 sensor 配置的是 4 lane 的数据输出。
4 lane 数据输出对应的 Sensor Scenario 为上图红框中所示。软件中的模式为模式 7。
sys_config.c 的配置:
sns0 使用的是 imx334
MIPI RX 配置:
说明:
INPUT_MODE_MIPI :MIPI方式输入数据
MIPI_DATA_RATE_X1:一个时钟一个数据位
DATA_TYPE_RAW_12BIT 表明 MIPI RX 以 RAW12 帧格式接收数据
VI_MODE_MIPI, /* MIPI RAW mode */
|
表明 VI Dev 使用 RAW 帧数据格式接收 MIPI 端发送过来的数据
说明:表明PIPE以什么帧格式从WCH写出,在这里是 PIXEL_FORMAT_RGB_BAYER_12BPP
注意:它的输入帧格式是VI DEV转换后的格式,如VI_DATA_SEQ_UVUV
说明:表明 VI 通道以什么帧格式写出,在这里最终输出的数据格式是PIXEL_FORMAT_YVU_SEMIPLANAR_420
2. VI 功能 API 测试,如下:
a. Framerate control
stChnAttr.stFrameRate.s32SrcFrameRate = 20;
stChnAttr.stFrameRate.s32DstFrameRate = 20;
|
|
b. CROP
下例裁剪的位置为 1 号区域,原图像大小为 3840*2160,裁剪的大小为 1920*1080:
VI_CROP_INFO_S pstCropInfo;
RECT_S croprect;
croprect.u32Height = 1080;
croprect.u32Width = 1920;
croprect.s32X = 0;
croprect.s32Y = 0;
pstCropInfo.bEnable = HI_TRUE;
pstCropInfo.enCropCoordinate = VI_CROP_ABS_COOR;
pstCropInfo.stCropRect = croprect;
s32Ret = HI_MPI_VI_SetChnCrop(0, 0, &pstCropInfo);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VI_SetChnCrop failed with %d!\n", s32Ret);
}
|
|
c. Mirror Flip
stChnAttr.bFlip = HI_TRUE;
stChnAttr.bMirror = HI_TRUE;
|
也可通过旋转获取 Mirror+Flip 的功能
ROTATION_E enRotation;
enRotation = ROTATION_180;
s32Ret = HI_MPI_VI_SetChnRotation(0, ViChn, enRotation);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VI_SetChnRotation failed with %d!\n", s32Ret);
}
|
注意:VI在线VPSS 在线模式、VI离线VPSS 在线模式,VI并行VPSS 并行模式下,不
支持本接口。仅支持 90/180/270 度旋转
d. LDC 的使用:
stLDCAttr.bEnable = HI_TRUE;
stLDCAttr.stAttr.bAspect = 0;
stLDCAttr.stAttr.s32XRatio = 100;
stLDCAttr.stAttr.s32YRatio = 100;
stLDCAttr.stAttr.s32XYRatio = 100;
stLDCAttr.stAttr.s32CenterXOffset = 0;
stLDCAttr.stAttr.s32CenterYOffset = 0;
stLDCAttr.stAttr.s32DistortionRatio = 500;
s32Ret = HI_MPI_VI_SetChnLDCAttr(ViPipe,ViChn,&stLDCAttr);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VI_SetChnLDCAttr failed witfh %d\n", s32Ret);
goto EXIT;
}
|
e. ROTATE 的使用
s32Ret = HI_MPI_VI_SetChnRotation(ViPipe,ViChn,ROTATION_90);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VI_SetChnLDCAttr failed witfh %d\n", s32Ret);
goto EXIT;
}
|
f. SPREAD 的使用
stSpreadAttr.bEnable = HI_TRUE;
stSpreadAttr.u32SpreadCoef = 16;
stSpreadAttr.stDestSize.u32Width = 3840;
stSpreadAttr.stDestSize.u32Height= 2160;
s32Ret = HI_MPI_VI_SetChnSpreadAttr(ViPipe,ViChn,&stSpreadAttr);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("HI_MPI_VI_SetChnSpreadAttr failed witfh %d\n", s32Ret);
goto EXIT;
}
|
g. DIS 的使用
stDISAttr.bEnable = HI_TRUE;
s32Ret = HI_MPI_VI_SetChnDISAttr(ViPipe, ViChn, &stDISAttr);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("set dis attr failed.s32Ret:0x%x !\n", s32Ret);
goto EXIT8;
}
|
h. 扩展通道的使用主要可通过以下三步
.设置扩展通道的通道属性
.通过 MPI 获取扩展通道的图像帧
.调用 VGS 模块实现相应子功能
3) VPSS
a. VPSS 通道设定 180 度旋转
两者同时生效:180 度旋转
b. VPSS 组裁剪与通道裁剪
VPSS_CROP_INFO_S pstCropInfo;
pstCropInfo.bEnable = HI_TRUE;
pstCropInfo.enCropCoordinate = VPSS_CROP_ABS_COOR;
pstCropInfo.stCropRect.s32X = 0;
pstCropInfo.stCropRect.s32Y = 0;
pstCropInfo.stCropRect.u32Width = 2400;
pstCropInfo.stCropRect.u32Height = 1600;
s32Ret = HI_MPI_VPSS_SetGrpCrop(VpssGrp, &pstCropInfo);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("HI_MPI_VPSS_SetGrpCrop(grp:%d) failed with %#x!\n", VpssGrp, s32Ret);
return HI_FAILURE;
}
for (j = 0; j < VPSS_MAX_PHY_CHN_NUM; j++)
{
if(HI_TRUE == pabChnEnable[j])
{
VpssChn = j;
s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &pastVpssChnAttr[VpssChn]);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr failed with %#x\n", s32Ret);
return HI_FAILURE;
}
pstCropInfo.stCropRect.u32Width = 1920;
pstCropInfo.stCropRect.u32Height = 1080;
s32Ret = HI_MPI_VPSS_SetChnCrop(VpssGrp, VpssChn, &pstCropInfo);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("HI_MPI_VPSS_SetChnCrop(grp:%d) failed with %#x!\n", VpssGrp, s32Ret);
return HI_FAILURE;
}
|
c. VPSS 通道增加了旋转功能后,vb buffer数目要加 1,否则可能不出图。
ROTATION_E enRotation;
enRotation=ROTATION_180;
s32Ret = HI_MPI_VPSS_SetChnRotation(VpssGrp0, VpssChn[0], enRotation);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("HI_MPI_VPSS_SetChnRotation(grp:%d) failed with %#x!\n", VpssGrp0, s32Ret);
return HI_FAILURE;
}
|
若通过 cat /proc/umap/vpss 发现帧率异常,可增加 vb buffer 数目 4~5 之间
d. VPSS 通道的缩放功能是通过设置以下进行设置,内部会自动做缩放的动作。
stVpssChnAttr[0].u32Width = 640;//stSize.u32Width;
stVpssChnAttr[0].u32Height = 360;//stSize.u32Height;
|
4) VO
a. 概述说明
VO(Video Output,视频输出)模块主动从内存相应位置读取视频和图形数据,并通
过相应的显示设备输出视频和图形。芯片支持的显示/回写设备、视频层和图形层情况,如下所示:
图像层、视频层、通道、以及设备之间的关系如下图所示。
|
|
5) VGS
VGS 的缩放:
特点:缩放任务不限制用户输入输出使用同一块 BUFFER
VGS 的划线:
特点:划线任务限制用户输入输出使用同一块 BUFFER
VGS 的旋转:
特点:需要申请输入图像 BUFFER 和输出图像 BUFFER
VGS 的 COVER:
特点:输入输出图像用同一块 BUFFER
VGS 的 OSD
特点:输入输出图像用同一块 BUFFER
存在问题:
成功运行,但屏幕上未正确显示字体
内存未进行释放,每次运行都进行了重新申请(已解决)
-------------------------------------------------------------------------------------------------------------------------------------------------------------
关于 S32V BSP 调试与进阶的更多博文内容可以通过关注大大通,或者扫描以下二维码即可链接到上一篇博文《 S32V GPIO 设备驱动 》, 二维码如下所示:
二、 附件
海思官方参考资料:
1、HiMPP V4.0 媒体处理软件开发参考.pdf
2、HiMPP V4.0 媒体处理软件 FAQ.pdf
评论