接下来的工作主要是在libyami的decoder中加入对MPEG2解码的支持,为了完成这部分的工作,首先要对MPEG2的算法有一定的了解。本周主要针对MPEG2解码算法进行了解,并阅读相关的代码。
首先介绍一下MPEG-2视频源数据结构。编码的视频数据是由称作“层”的比特流序列组成,通常这些视频比特流可看作语法等级体系,其中一个语法结构包含一个或更多的从属结构。例如,结构“picture_data()”包含一个或更多的语法结构“slice()”,而“slice()”又包含一个或者更多有序结构“macroblock()”。编码的比特流中最高语法结构就是视频序列。一个视频序列以一个序列头开始,后面可选地跟着一组图像的头和一个或更多的编码帧。帧在编码比特流中的顺序就是解码器处理它们的顺序,但不一定就是显示顺序。视频序列以一个sequence_end_code终止。MPEG-2的编码码流分为六个层次。从上至下依次为:视频序列层(sequence)、图组层(GOP),图像层(picture),组块层(slice),宏块层(Macroblock)和块层(block)。除宏块层和块层,上面四层中都有相应的起始码。
MPEG-2定义了三种编码帧类型,分别为I帧、P帧和B帧。三种帧采用不同的编码原则:I帧采用帧内编码方式,其帧中所有宏块的编码方式都是帧内编码(intra模式,表示数据的编码与其他帧图像的数据无关)。P帧和B帧采用帧间预测的方式,P帧图像采用前向时间预测,一部分宏块是帧间编码,另一部分是帧内编码,具体的编码方式由运动搜索的结果决定。B帧图像采用双向时间预测,宏块的编码方式只有帧间。
下面来介绍三种帧图像的主要特点。
I帧:
一个完整的帧内压缩算法,解码时仅用I帧的数据就可重构完整图像。
I帧描述了图像背景和运动主题的详情。
I帧不需要参考其他画面的生成,不需要考虑运动矢量。
是P帧和B帧的参考帧,其质量直接影响到同组中以后各帧的解码质量
是图组GOP的基础帧,每个图组的第一帧必须是I帧。
所占据的数据信息在三种帧类型中是最大的。
P帧:
P帧属于前向预测的帧间编码,只参考前面靠近它的I帧或P帧。
采用运动补偿的方法传送它与前面I/P帧的差值及运动向量,解码时必须将参考帧的预测值与预测误差求和后才能重构完整的P帧图像。
P帧可以是后面P帧的参考帧,也可以是其前后B帧的参考帧。
由于P帧可能用作参考帧,所以它可能造成解码错误的扩散。
B帧:
双向预测编码帧,可有前面的I/P帧和后面的P帧来进行预测。
B帧传送的是它与前面的I帧或P帧和后面的P帧之间的预测误差及运动矢量。
B帧压缩比最高,因为它只反映两参考帧之间运动主体的变化情况,所以预测比较准确。
由于不是参考帧,不会造成解码错误的扩散。
软件中的算法依功能划分,解码系统由9大功能性模块组成,依数据流的流向排列为:取数据及数据调整(getbits);解序列数据(gethdr);解图像组(getpic);解变长码参数(getvlc);解块变长码(getblk);反离散余弦变换(IDCT);解运动向量(motion);图像预测补偿(recon);显示(display)。另外,还需要其他模块来协调功能性模块的工作,即功能控制(mpeg2dec)、空间域分级控制(spatscal)、存储(store)、帧数据缓冲控制(subspic)和系统控制(systems)。
硬件解码器划分为以下几个模块:
定长码解码模块(parser):负责对压缩码流中slice层以上的码流解码。
可变长解码模块(VLD):负责对slice层以下,块级以上的码流解码,并解出运动向量。
哈弗曼解码模块:负责块级数据的可变长解码和完成反扫描模块。
反量化模块(IQ):通过量化参数重构DCT系数。
反离散余弦变换模块:负责对block大小的DCT系数做逆变化,得到残差数据。
运动补偿模块:根据运动向量找出预测数据,并将预测数据和残差数据相加,得到最终的解码采样值。
以上对MPEG2视频的解码作了大致的了解。关于代码部分也已经进行了总体的阅读,掌握总体的结构,但是一些细节的部分还需要好好考虑,因为在porting的过程中虽然整体框架没有较大的改动,但是从C语言转换到C++还是有较多变化的。由于之前并没有接触过C++,所以看起来有些吃力。下周工作安排:
快速了解C++的相关语法包括类的应用,虚函数之类。
整理出修改的思路。