② 乘法和除法尽量用移位运算来完成
对于2的幂次乘法或除法使用移位将会提高不少效率,一条除法指令使用的周期数远远多于移位指令。
③ 尽可能将循环内部的负荷放到循环外面
这点很重要,因为许多循环内部包括一条或几条运算语句,这些语句将被重复运算,因此如果事先设定一个变量,然后赋上那几条运算语句的值,并替换到循环外部,则会极大地节省芯片资源,特别是对于循环中含有除法运算的情况。在逆量化循环运算中,存在着大量冗余计算,原因在于逆量化运算中参数的重复计算,而对于每帧解码VOP,这些参数是唯一的。因此,可将这些参数的计算放到逆量化循环外面,则每帧只须计算一次。这样即可节约大量的指令周期。
④ 功能参数的优化数量
在ARM编译的过程中,子程序的参数是通过寄存器R0~R3来传递的。如果所传递的参数多于4个,那么超出的参数将被压入栈内;当它们在函数中被第一次访问时,便会从栈中弹出。通过把参数的数量减少到4个或者少于4个,则可直接使用,而无需任何的调入,因为这些值都可从寄存器中获得。
⑤ 利用LDM和STM减少存储器的访问
批量加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。这种特性非常有用,因为与单字加载/存储相比,它在执行周期上花费更少。因此它在IDCT中得到了有效的利用,用于同一时刻取出一行的所有系数。同样在运动补偿过程中,一组数据字在指令的一次执行中获得,并且暂时存储在多个寄存器中以便日后使用。
⑥ 指令的有条件执行
有条件执行的特性被ARM7TDMI的所有算法和数据移位指令支持。这是一项可选的特性。它在指令被执行时设置标记。有条件执行通常用于循环退出条件和饱和条件,可以节省退出循环中的一个指令CMP。对于循环次数很多的情况,即使是一个指令的减少也有很大的好处。在变长解码中就很好地利用了这种特性。
⑦ 一种用于运动补偿的有效优化方法
解码过程中处理的像素是8位。如果运动补偿是在字节或像素的基础上执行,那么字节加载和存储将被使用,它是存储器访问中代价最高的操作。因为ARM7TDMI是32位微处理器,存储器可以按字读取数据,因此设计出一种有效的运动补偿方法,即在字数据的基础上进行操作。利用这种方法,便可以用一种非常有效的方式同时对4像素进行运动补偿。
下面以水平方向的半像素补偿为例,讲述补偿的过程。补偿的原理如图3所示。
首先读入一个字到寄存器中,从低到高的数据依次对应的是像素0、像素1、像素2和像素3;然后将读码流指针增加1字节,再读取下一个字到另一寄存器中,从低到高的数据依次对应的为像素1、像素2、像素3和像素4。示意图如图4所示。
图3 半像素内插示意图 图4 4像素补偿原理示意图
半像素补偿可由x=(A+B+1-rounding_control)/2来实现。式中: A和B为参考帧中两个相邻的像素数据;rounding_control可取0或1。
按照补偿公式对上述两个寄存器进行相加移位操作,但是对应像素两两相加时可能会产生进位。为了解决这个问题,须设置保护位,具体方法如下:
- 将上述两个寄存器中的任意一个(如寄存器1)与0xFEFEFEFF相“与”,则寄存器1中像素1、2、3的最低位被清0,即将后一字节的最低位设置为前一字节的保护位。而对于第3字节,因为寄存器本身带有进位状态标志,所以无需另外设置。
- 如果rounding_control为0,则将寄存器2与0x01010101相加,然后再和0xFEFEFEFF相“与”,设置进位保护位;如果rounding_control为1,则直接将寄存器2和0xFEFEFEFF相“与”。
- 将以上两步的结果相加,判断进位状态标志。若有进位,则将相加结果的最高位,即寄存器的第31位置1,最后右移1位。所得结果即补偿后的4个像素值。
在同时对4像素进行补偿的过程中,只有当相邻两像素的最高位都为1时,才会有进位产生。使用这种补偿方法其实牺牲了部分精度,但这里只是使所影响的像素值增加了1,所以影响并不大,而且可以使补偿速度大大提升。同时对4像素进行补偿的过程中,寄存器加载需要3个周期,存储需要2个周期,共有两次加载和一次存储操作,中间的加法和移位操作需要6个指令周期,共需14个周期。如果对上面4个像素分别进行补偿,则需5次加载操作和4次存储操作,共23个周期,另外中间计算还需12个周期,所以共需35个周期。可见,牺牲部分精度换取补偿速度是很值得的。
对于垂直方向和水平垂直方向的半像素补偿,其原理与水平方向相同。
3 实验结果与数据分析
通过优化,MPEG4的解码性能有了较大的提升。在ADS1.2环境下分别对各模块进行C算法优化和ARM代码优化,结果如表3所列。按调用一次模块函数所需周期数进行统计。
表3 仿真器上各模块单独统计(使用QCIF格式图像news)
所优化模块名称
C优化(cycles)/个
ARM优化(cycles)/个
优化率/%
DC/AC预测
703
534
24.04
逆扫描/VLD
1 730
1 118
35.38
逆量化/IDCT
6 032
2 562
57.53
运动补偿
17 143
8 471
50.59
这些模块是解码过程中经常会调用的函数,因此,这些函数的优化将使解码速度有明显的提高。
表4比较了不同序列的15帧QCIF格式视频解码优化前后所需的带宽。这些图像具有不同的复杂度,因而结果也不一样。
表4 对不同序列的优化结果(15fps QCIF格式)
视频序列①
优化前所需带宽/MHz
优化后所需带宽/MHz
news
27.24
16.86
foreman
64.83
48.78
miss_am
27.71
15.95
carphone
52.54
34.52
salesman
28.06
16.56
trevor
52.56
34.24
注: ① 为标准视频测试序列。
解码速度基本取决于图像画面的运动情况和颜色是否丰富。从上面的数据可以看出对于不同的序列,其解码速度也不同。news、salesman和miss_am之所以很快,是因为图像背景静止,只有肩部和头部有运动,所以P帧的编码数据量较少,解码速度较高。另外,如果图像很简单(单调),其能量集中到DC系数(直流分量)上,交流系数会出现多个零,因此变长解码速度就会较高,从而节约了解码时间。
从仿真速度分析,通过本文所总结的ARM7TDMI上视频解码的优化方法,可以使MPEG4视频解码节约大量的数据处理时间。由实验结果可见,本视频解码器能较好地满足低分辨率、低帧率场合实时解码的要求。