直接预测是B帧上一种独有的预测方式,其中直接预测又分为两种模式: 时域直接模式(temporal direct)、空域直接模式(spatial direct)。html
在分析这两种模式以前,有一个前提概念须要了解:共同位置4x4子宏块分割块(co-located 4x4 sub-macroblock partitions),下面简称为co-located。编码
共同位置4x4子宏块分割块,故名思义,该块大小为4x4。co-located的主要功能是获得出该4x4块的运动向量以及参考帧,以供后面的直接预测作后续处理,若是当前宏块进行的是直接预测,不管时域或空域,都会用到该co-located,所以须要先求出该4x4co-located的具体位置。spa
要求co-located的位置,首先须要知道co-located所在的图像colPic的位置,colPic能够肯定在当前图像的第一个后向参考图像RefPicList1[ 0 ]内,可是colPic能够为帧或场,这取决于当期图像与参考图像,是以帧图像进行编码,仍是以场图像进行编码,或者以互补场对(宏块级帧场自适应)方式进行编码。htm
topAbsDiffPOCbottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|topAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Top,CurrPic)|bottomAbsDiffPOC=|DiffPicOrderCnt(firstRefPicL1Bottom,CurrPic)|blog
添加这些条件是为了在采用宏块级帧场自适编码方式时,应选择距离当前图像最近的顶场或底场做为col_Pic索引
注:其实第二项RefPicList1[ 0 ]是一个被动选项,由于它是根据当前图像的编码方式是帧、场或宏块帧场自适应决定的,若是当前图像是场,那么RefPicList1[ 0 ]就有多是已解码的场或者以解码帧中的一场;若是当前图像是帧(非MBAFF),那么RefPicList1[ 0 ]就是帧;若是当前宏块是帧而且为MBAFF,那么RefPicList1[ 0 ]就是一个互补场对(两个场能够组成一个帧)队列
实际上,若是获得了colPic,就能够经过当前宏块的16个4x4块的绝对位置(以4x4块为单位相对于图像左上角(0,0)的绝对位置( opic_block_x,opic_block_y)),获得co-located在colPic的位置。get
(注:像在jm18.6中,实际计算时,不会出现当前图像为场,colPic为帧的状况,由于场的参考图像都会被分为场后加入参考图像队列,因此最终计算时也会先根据当前场的是顶场或底场挑出参考帧中对应的场做为colPic )it
在标准中,先定位co-located所在宏块mbAddrCol,而后再定位co-located在该宏块内的地址(xcol,yM)。因为采用了不一样于上述的4x4块定位方法,因此计算方式略复杂,可是获得的结果是同样的,最终会定位到同一个co-locatedio
mbAddrCol1mbAddrCol2mbAddrCol3mbAddrCol4mbAddrCol5mbAddrCol6mbAddrCol7=2×PicWidthInMbs×(CurrMbAddr/PicWidthInMbs)+(CurrMbAddr % PicWidthInMbs)+PicWidthInMbs×(yCol/8)=2×CurrMbAddr+(yCol/8)=2×CurrMbAddr+bottom_field_flag=PicWidthInMbs×(CurrMbAddr/(2×PicWidthInMbs))+(CurrMbAddr % PicWidthInMbs)=CurrMbAddr/2=2×(CurrMbAddr/2)+((topAbsDiffPOC<bottomAbsDiffPOC)?0:1)=2×(CurrMbAddr/2)+(yCol/8)mbAddrCol1=2×PicWidthInMbs×(CurrMbAddr/PicWidthInMbs)+(CurrMbAddr % PicWidthInMbs)+PicWidthInMbs×(yCol/8)mbAddrCol2=2×CurrMbAddr+(yCol/8)mbAddrCol3=2×CurrMbAddr+bottom_field_flagmbAddrCol4=PicWidthInMbs×(CurrMbAddr/(2×PicWidthInMbs))+(CurrMbAddr % PicWidthInMbs)mbAddrCol5=CurrMbAddr/2mbAddrCol6=2×(CurrMbAddr/2)+((topAbsDiffPOC<bottomAbsDiffPOC)?0:1)mbAddrCol7=2×(CurrMbAddr/2)+(yCol/8)
(FAQ:为什么表中没有FRM与AFRM配对?由于一个sps内只能定义为FRM或者AFRM(MBAFF),在一个序列内二者是不可能共存的;为什么表中能够有FRM与FLD共存?由于sps能够定义PAFF(图像帧场自适应))
另外,为了减小计算量,还能够设定direct_8x8_inference_flag等于1,这样会致使每一个8x8块共用一个4x4的co-located,共用方式为一个宏块的4个8x8块分别只用该宏块4个角的4x4块做为co-located
(注:至于如何从8x8块中选取该4x4块并沿用其参考索引,标准中并无规定,具体能够看本文最后的代码是如何作的)
该模式是基于下图求出当前4x4块的先后向mvL0与mvL1,以及前向参考帧List0 reference的索引
已知的变量有:
未知的变量有:
求解方法:
因为这些在标准(8.4.1.2.3)中讲的都很是细致,因此这里简要说明一下而已。
空域模式基于一种假设:当前编码宏块与其相邻宏块都向着同一个方向运动,你们有着相似的运动向量与参考帧(以下图)。在这种假设前提上,空域模式主要思想为采用相邻块来对当前宏块的参考索引以及运动向量进行预测。因为标准中8.4.1.3有很是详细的描述,因此在此略过。
可是上述假设也颇有可能不成立,有可能当前宏块的相邻块都是运动的,但当前宏块是静止的(以下图)。好比说当前宏块是背景的一部分,而相邻块则是移动着的前景。这时候就须要判断当前宏块是不是运动的,以获得更准确的空域预测,co-located在这里就是用来判断当前宏块是不是运动宏块的。若是co-located的mvCol[0]与mvCol[1]能保证在某个范围以内,则代表当前宏块为静止宏块,那么将把当前宏块的mvL0与mvL1赋值为0,具体在标准8.4.1.2.2中描述得至关详细,不做细述。