mpeg2解码过程,标准解读part1
(零)总体框图:
(一)高层语法结构
重构场图将成对相伴而形成重构帧。
如果progressive_sequence==1,则重构帧将以帧周期为时间间隔从解码过程输出。
如果progressive_sequence==0,则重构帧将被分成一个重构场的序列,在解码过程输出端以有规律的长周期为时间间隔而出现。如果一个帧图的repeat_frist_field==1,则这个帧的第一场将在第二场后被重复。
(二)变长码解码
用cc指代颜色分量,他与下表中所述的块号相关。于是,对于Y分量,cc为0,对Cb分量cc为1,对于Cr分量cc为2。
比如,在块号为7的时候,对4:2:2,cc的值为2。
1.内部块中的DC系数
DC系数的编码分为两种情况,一种是内部块的第一个系数,一种是非内部块的第一个系数
1)内部块的第一个系数
DC系数有两个码表,根据cc的值(0或者非0)来选择码表。
在ffmpeg的代码中,mpeg12enc.c里面,encode_dc函数,表明了如何对DC进行编码。ffmpeg的DC的码表用数mpeg1_lum_dc_uni和数组mpeg1_chr_dc_uni保存。这两个数组,即保存了编码码字的长度,也保存了编码码字的code,方法是,数组的每一个元素的第8个比特表示码字长度,剩余的比特表示了码字code。因此在encode_dc这个函数的putbits要将码表的第八位析出来作为码字长度,将码表向右移八位表示编码的码字code。
编码仍旧按照前缀+INFO的方法,前缀包含了INFO长度的信息,因此,在解码的时候,首先读出前缀,就可以知道INFO的长度,从而解码出DC系数。
下面两个表表明了DC的编码前缀或INFO长度的对应关系
编码的时候,由于编码的DC系数是当前DC系数与前一帧的DC系数的差值diff,这个diff的范围是[-255, 255],因而首先将difference做一个映射,映射为非负的整数,方法如下:
if (difference >= 0)
diff = difference;
else
diff = (difference - 1) + 512;
接下来计算diff的位宽,得到dct_dc_size_luminance或者dct_dc_size_chrominace,然后根据上面两个码表,查出前缀,最后,按照前缀+INFO的方式将编码后的数据写到比特流中。这里的INFO就是diff。
ffmpeg代码中码表的初始化在函数ff_mpeg1_encode_init里面完成。
2)非内部块的第一个系数
当DC的绝对值为1的时候,编码码字为1x,x表示DC的符号,-1时x为1,1时x为0。码字长度为2。
当DC的绝对值不为1的时候,把它按照其他系数来处理进行编码。
2.其他系数
mpeg2宏块内的编码思想是:由于一个宏块中绝大部分系数都是0,zig-zag扫描过后出现的情况是:level1, 0, 0, ... , 0, level2, 0, ..., 0, level3, ..., ..., leveln, 0, ..., 0。其中levelx表示非零的系数,每一个非零系数后面跟了若干个0(0的个数可能为0),这个0的长度被称作run(游程),统计出(level,run)对,然后对每一对(run,level)查表编码。
而其中的码表总共有两个,选择方式如下:
一些(run,level)对,没有相应的变长码与之对应,是因为他们在统计学上很少出现,于是采用换码编码,用定长编码对他们进行编码,具体做法是:在换码VLC的后面跟一个6bit定长码表示run,在跟12bit定长码表示signed_level。
posted on 2009-09-04 16:33 vincenzo.lai 阅读(2438) 评论(0) 编辑 收藏 举报