海思多媒体处理平台(MPP)分为:视频输入(VI),视频处理(VPSS),视频编码(VENC),视频解码(VDEC),视频输出(VO)、视频侦测分析(VDA),音频输入(AI),音频输出(AO),音频编码(AENC),音频解码(ADEC),区域管理(REGION)等模块. 这里介绍视频解码(VDEC)和视频输出模块(VO)。
VO与自己的显示设备密切相关,在使用VO之前,应该了解自己的显示设备的接口方式及时序等信息。
测试使用开发板的配置:
Hi3521A VO:
海思设备的HDMI开发,可以参考官方提供的《HDMI 开发参考.pdf》,其基本内容有:
HDMI 的音频不能单独输出,必须依赖于视频输出,且 HDMI 的时钟来源于 VO 的时钟,因此接口调用顺序上需要先使能 VO,再调用 HDMI 接口,然后配置音视频输出。此外 Hi35xx 芯片内置的 HDMI 不支持 HDCP、CEC 功能。
正确加载驱动之后,直接调用SAMPLE_COMM_VO_HdmiStart 函数就可以启动HDMI接口。
注意,在调试HDMI的时候,因为HDMI的引脚可以被复用成普通GPIO口,所以如果调试不通的时候,可以先检查一下HDMI引脚的配置。
这里不关联视频输入VI,直接使用一个H264文件来模拟h264视频流,
每次读取一个自己数据,找到帧的开始位置,然后再找到下一帧开始的位置,中间就是一帧完整的数据
先根据视频文件的分辨率设置一帧数据的最大空间大小,将这个值作为最小空间一次从文件中读取出来。再从这包数据中找出帧的开始位置和结束位置,下次读取的时候按结束位置来读取,剩下的数据包不用处理。
海思sample_vdec 中使用的就是方法2,代码如下:
else if ( (pstVdecThreadParam->s32StreamMode==VIDEO_MODE_FRAME) && (pstVdecThreadParam->enType == PT_H264) )
{
bFindStart = HI_FALSE;
bFindEnd = HI_FALSE;
/**每次偏移到下一帧开始的位置**/
fseek(fpStrm, s32UsedBytes, SEEK_SET);
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
if (s32ReadLen == 0)
{
if (pstVdecThreadParam->bLoopSend)
{
s32UsedBytes = 0;
fseek(fpStrm, 0, SEEK_SET);
s32ReadLen = fread(pu8Buf, 1, pstVdecThreadParam->s32MinBufSize, fpStrm);
}
else
{
break;
}
}
/**查找开始位置**/
for (i=0; i 0) s32ReadLen = i;
if (bFindStart == HI_FALSE)
{
printf("SAMPLE_TEST: chn %d can not find start code!s32ReadLen %d, s32UsedBytes %d. \n",
pstVdecThreadParam->s32ChnId, s32ReadLen, s32UsedBytes);
}
else if (bFindEnd == HI_FALSE)
{
s32ReadLen = i+5;
}
}
解码模块基本上参考手册上的接口说明就可以实现。
这里将将4个h264文件模拟成数据流输入到解码模块, 将解码模块与输出模块绑定,在显示屏中以4分屏显示4路画面,效果如下:
在海思Hi3521A 设备上实时解码4路1080P@30fps 从画面上看不会出现卡顿问题,但是CPU占用率非常高。
本章频测工程可以从「目录与序言」提供的地址去获取
本专栏第一篇文章「目录与序言」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解。