1 引 言
本文旨在研究基于ARM微处理器的MPEG-4视频解码技术,主要应用在手持移动设备中。利用嵌入式系统实现MPEG-4视频解码,处理器的选择是关键。在嵌入式系统中常用的RISC处理器是ARM核,主要是因为它具有体积小,功耗低,成本低,性价比高的特点,这对于移动应用领域非常重要。ARM7系列微处理器为低功耗的32位RISC处理器,最适合于对价位和功耗要求较高的消费类应用。本解码器定位于低分辨率和低帧率的应用场合,因此选择在ARM7TDMI核上实现解码功能。要实现更高帧率和分辨率的解码,可将软件直接应用在更高端的处理器上。
2 MPEG-4视频解码算法的优化与实现
MPEG-4标准可以划分为一套子标准,标准的每一部分都有各自最适合的应用场合。MPEG-4 SVP就是一种特殊的、简单的MPEG-4实现,SVP代表Simple Visual Profile。这部分是专门针对手持式产品中无线视频传输应用场合而制定的。由于本解码器应用在手持移动设备视频解码的场合,因此选用MPEG-4 SVP作为解码算法。
本文选用ARM7TDMI作为核心处理器进行MPEG-4视频解码器的开发。在实际开发过程中,针对ARM7TDMI的结构和MPEG-4的算法特点,做了大量优化工作,保证了解码的精度,大幅度提高了解码的速度。解码器的具体功能如表1所列。
表1 基于ARM7TDMI的MPEG-4视频解码器功能表
功能
| 系统实现
| 压缩标准 | MPEG-4 SVP | 输入图像分辨率 | QCIF(176×144,如果选用更高端处理器,则可支持更高分辨率) | 解码帧率 | 15fps(如果选用更高端处理器,则可支持更高帧率) | VOP类型 | IVOP+PVOP | DC/AC逆预测 | 支持 | Inter4V模式 | 支持 | 逆量化方法 | H.263(MPEG可选) | 逆扫描方式 | Zigzag扫描+水平交替扫描+垂直交替扫描 | 输出图像格式 | 4∶2∶0 YUV | 2.1 解码器算法
解码过程实际上就是从视频编码码流中恢复出VOP数据的过程。图1描述了一个视频解码过程。解码器主要包含两部分: 运动解码和纹理解码。I帧中只含有纹理信息,因此只须解码纹理信息即可恢复I帧。而P帧中不仅包含纹理信息,还包含运动信息,所以须解码运动信息,获得运动矢量并进行运动补偿。另外,还须进行纹理解码获得残差值,将这两部分组合起来才能重建P帧。
图1 MPEG4 SVP的解码过程
解码器的实现主要是提供一个简单的接口函数,供解码时调用。该接口函数根据解码的不同需要和不同阶段提供了5个入口。5个接口函数中: 4个供初始化、预处理及后续处理时调用;剩余1个是帧解码的实现函数。图2为帧解码主程序的流程图。
图2 帧解码主程序的流程图。
解码过程的计算主要集中在如下几个模块:IDCT、运动补偿MC、逆量化、逆扫描、逆预测以及变长解码VLD。表2给出了优化前解码过程的特征信息。
从表2中可以看出,上述运算模块在解码过程中占有很大比例。对以上各模块进行优化的效果将直接反映在解码器的实时效率上。
表2 优化前解码过程的特征信息
各单元名称
| 各单元所占时间比例/%
| IDCT
| 40
| 逆量化,逆扫描和逆预测
| 24
| 数据分析和变长解码
| 14
| 2.2 ARM平台下算法的优化
ARM结构是基于RISC原理的,指令集和相关的解码机制都比CISC要简单得多。它能高效地输出指令,快速送出实时中断响应;它还进行了管道设置,处理和存储系统的所有部分可以持续地运转。在典型的情况下,当一条指令被执行时,其后续指令正在被解码;而第三条指令便从存储器中取出。ARM7TDMI并不具有指令或数据的高速缓存,主要被用于控制核心,而非数据处理。但通过对其特性的灵活运用,可以使其非常容易地应用于视频解码过程。对MPEG4视频解码器的算法优化主要从以下几方面入手:
(1) 算法的优化
这里是指高级C语言转化算法以简化计算量, 用最佳算法实现解码中的各模块。
① IDCT算法的选择
IDCT运行次数多,运算量很大,其变换的快慢直接影响解码的速度。本文采用一种称为AAN的快速算法。其一维8点的DCT变换通过16点DFT来实现,而16点DFT又可通过FFT实现;二维8×8的DCT运算仅需80次乘法和464次加法操作,大大减小了这部分的运算量。用AAN算法实现IDCT运算时,实际上是用IDFT取代IDCT,所以首先要得到DFT系数。方法是逆量化后直接将DCT系数分别乘以尺度因子,也就是说将尺度变换与逆量化结合。
② 除法运算的消除
一个除法操作须花费60~120个周期进行处理,而一个乘法操作最多需要4个周期。在除法可以被乘法代替而不丧失准确性的计算中,这样做是非常有好处的。在反向DC系数预测过程中,DC系数重构后,立即对其进行逆量化,从而消除除法运算。
③ 存储访问的减少
在任何实现中尽可能减少存储访问都是非常有价值的。由于ARM7TDMI内没有缓存,每次访问都是对外部存储器进行的,所以这样做尤为重要。通过在任何可能的地方结合解码过程,访问的次数即可减少。I帧中反向DC系数预测与DC系数逆量化的结合、逆扫描与变长解码的结合,以及逆量化与IDCT的结合,P帧中变长解码、逆扫描与反量化的结合,对于每个非零系数只需一次读入和一次存储。同时,像素重建也在IDCT之后立即进行。这样对每个系数来说,又减少了一次读入和存储。
(2) 根据ARM7TDMI芯片结构的优化
这里的优化主要体现在节约寄存器资源。任何一种芯片的寄存器资源都是有限的,ARM7TDMI的通用寄存器总数为31个,对于小规模应用程序是足够了,但在MPEG4解码过程中往往会用到较多的寄存器,所以仍须节俭。方法如下: 其一,在可能的情况下尽量少用寄存器,比如可对一个寄存器多次使用。其二,根据具体情况选择最优的变量类型,在局部变量中,使用int类型效率最高;而对于全局变量,使用short类型,则可减小Flash的使用量。
(3) 汇编/结构层的优化
尽管编译器可以产生汇编代码,但为了使代码效率更高,根据ARM7TDMI的特性对模块IDCT、IQ、VLD、DC/AC预测和MC进行手工汇编编码。下面详细阐述不同的优化方法及其所使用的模块。
① 内部循环的解开
循环的解开其实也是为了增强程序中的并行处理能力。对于解循环,不能在解开的循环中保留线性过程,即指令在执行过程中的结果不能作为后续指令的输入数据;否则也就失去了并行处理能力,解循环也就失去了意义。
② 乘法和除法尽量用移位运算来完成
对于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视频解码节约大量的数据处理时间。由实验结果可见,本视频解码器能较好地满足低分辨率、低帧率场合实时解码的要求。
4 MPEG4视频解码的嵌入式系统实现
实现本解码器的主要硬件平台是Easy ARM2200,如图5所示。它是一款功能强大的32位ARM单片机开发板,采用了Philips公司的ARM7TDMIS核,以及总线开放的单片机LPC2210,具有JTAG调试功能。
图5 Easy ARM2200开发板
开发板上除了提供键盘、LED和RS232等一些常用功能部件外,还具有4Mb SRAM、16Mb FLASH、IDE硬盘接口、CF存储卡接口、以太网接口和Modem接口等。
本文选择在μClinux操作系统上调试MPEG4解码程序。调试过程分为以下几个步骤:
- 建立μClinux开发环境;
- 在μClinux下开发应用程序;
- 添加应用程序到目标系统并调试。
图6 为一个基于μClinux的嵌入式系统典型框架结构图。
图6 基于μClinux嵌入式系统框图
(1) 建立μClinux开发环境
为了实现基于μClinux的应用系统的开发,建立或拥有一个完备的μClinux开发环境是十分必要的。建立μClinux开发环境主要包括以下3个步骤:
- 建立交叉编译器;
- 编译μClinux内核;
- 加载内核。
在完成上述所有工作后,一个嵌入式应用开发平台就已经搭建好了。在这个平台之上,可以根据不同需要开发嵌入式应用。
(2) 在μClinux下开发应用程序
基于μClinux系统的应用程序的开发,通常是在标准Linux平台上用交叉编译工具armelfgcc来完成的。ADS和armelfgcc都是ARM公司提供的软件开发工具,它们都支持ARM指令集,但部分伪指令集不同。因此为了将在ADS1.2环境下优化好的源代码移植到armelfgcc环境下,就需要对源代码的伪指令作修改, 然后用armelfgcc编译源文件,以生成可在目标板上运行的可执行程序。
(3) 添加应用程序到目标系统并调试
要在硬件板上调试,就必须首先把应用软件的可执行程序添加到目标系统中。有多种途径可以达到这一目的。本文使用的是网络方法,通过以太网接口从网络添加用户程序到目标系统中运行。
完成上述工作后,MPEG4解码程序就可以在μClinux系统上运行了,解码结果数据流通过以太网动态传输到PC机上。对几个典型QCIF格式图像解码的帧率如表5所列。
视频序列
| 解码的实际帧率/帧/s
| news
| 35
| foreman
| 16
| miss_am
| 37
| carphone
| 17
| salesman
| 36
| trevor
| 17
|
表5 在μClinux操作系统中MPEG4视频解码的帧率
观察发现与前面的软件仿真结果是一致的。对于序列news、miss_am和salesman这些运动动作不太大的图像,解码帧率明显较高;而对于foreman、carphone和trevor这些运动动作较大的图像,解码帧率就较低。
实验结果表明,本系统可以实现低帧率、低分辨率的嵌入式MPEG4视频实时解码。
5 结束语
本文重点研究了基于ARM开发平台对MPEG4实时解码的算法优化及其硬件实现。主要完成了以下几方面工作: 针对ARM7TDMI的体系结构,对解码的关键部分进行了算法优化和代码优化,从而极大地提高了解码速度;针对具体的硬件平台——基于ARM7TDMI的Eeay ARM2200开发板,建立了μClinux开发环境,在其上开发应用程序,添加到目标系统中并调试,最后完成了15fps的MPEG4视频解码嵌入式系统的实时实现。
随着人们对视觉媒体的要求越来越高,基于嵌入式系统视频解码技术将具有越来越广阔的前景。 |