帧间预测简要流程
Inter 进行解码的基本单位是pu, 读一个pu 相关的信息,然后解码相应的pu块。 pu块的信息包括mv的信息等,解码pu块就是利用mv 从相应的参考帧中去出参考的块,然后利用参考块插值或者不插值出预测块。
1、参考帧数据的来源
主要是m_apcRefPicList这个参考数据是怎么得来的,有调用getRefPic( RefPicListe, IntiRefIdx) 实际是返回的m_apcRefPicList。
TComPic* getRefPic( RefPicListe, IntiRefIdx) { return m_apcRefPicList[e][iRefIdx]; }
可以看到 这个列表包含下面两个reference list, 对于P帧来说只用list 0, b帧两个都有可能用到。
REF_PIC_LIST_0 = 0, ///< reference list 0
REF_PIC_LIST_1 = 1, ///< reference list 1
在TDecTop.cpp 中xDecodeSlice 中调用decodeSliceHeader 之后会将dpb 的buffer list 设置到 调用 pcSlice->setRefPicList( m_cListPic, true ) 设置到m_apcRefPicList 中。 decodeSliceHeader里面主要是解析rps相关的信息,rps 是存储在slice header 中。rps 的相关信息在附录中。
m_cListPic:dpb的buffer 列表 在 xDecodeSlice调用xActivateParameterSets,在xActivateParameterSets调用 xGetNewPicBuffer 去取一块buffer (实际是创建TComPic 相关的类),这个类中存储解码相关的数据,然后将申请到的TComPic 放到m_cListPic 的队列里面。
setRefPicList:取出rcListPic 经过一系列的转换 然后放到 m_apcRefPicList[REF_PIC_LIST_0], m_apcRefPicList[REF_PIC_LIST_1] 中。
从上面可以看出,m_cListPic (dpb buffer) 到m_apcRefPicList(参考帧列表) buffer 的在dpb index 和在referce index 已经变化了,但是我们可以通过poc 来进行一样对应。
2、在预测中的使用
现在理清楚了帧间那边参考数据的来源, 现在回过头来看一下inter 那边使用的数据。
首先是decodePUWise , 分析merge 的情况,如果解析到merge,那么会时间空间构造5个mv的候选类别。时间上面就是左,上,左右等几个方位,空间就是去colrefpic的mv,空间距离上面最多又4个候选的mv,时间上面最多有1个候选的mv, 在HM中的代码 为了B帧考虑, 因为B帧需要5个候选的mv 组合成10个一对mv来进行候选。所以候选mv存放的方式是下面这样,有b帧的时候奇数的位置有数据,没有b帧奇数位置没有数据。
3、MERGE模式
首先解析到Merge的index,然后解码端构造候选的mergelist。 构造pcMvFieldNeighbours的过程,cMvFieldNeighbours是一个10大小的数组,最大的候选mv list 是5,但是考虑的B帧由前向和后向的mv,所以设置成10。如果是P帧的情况,那么像下面,偶数位置的mv为0。
如果是B帧的情况, 奇数 偶数位置都有值。
首先根据下面图的方位5个候选块中4个候选块的运动信息,列表按照A1→B1→B0→A0→(B2)的顺序建立,其中B2为替补,即当A1, B1, B0,A0中有一个或多个不存在时,则需要使用B2的运动信息。
时域候选mv的构建 这里就是取的colrefpic的地方,取出colmv 然后放到候选列表里面。如果这个时候候选的还没有到达5,会取前面已经构建好重新构建几个mv。
b帧在前面每个候选项都构建后l0和l1的mv,在这边组合的时候是按照下面的顺序进行取的,比如combIdx 为0 的 是取候选列表里面第一个的L0 和第二个的L1,就是对应pcMvFieldNeighbours中的0 和 3 位置的数据。
在实际JM代码中
如果是pu的第一块,是没有传入uiMergeIndex,直接在decodePUWise 中进行取,
pcSubCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates );
否则 会传入uiMergeIndex, 在getInterMergeCandidates 如果说很快就构建好需要的候选mv 会提前退出来。
pcSubCU->getInterMergeCandidates( uiSubPartIdx-uiAbsPartIdx, uiPartIdx, cMvFieldNeighbours, uhInterDirNeighbours, numValidMergeCand, numSpatialMergeCandidates, uiMergeIndex );
Ps:
HEVC中每一个slice header都要包含当前帧的RPS数据(IDR条带除外,其RPS隐含为空);除此之外,即使是I帧的slice可能也包含RPS数据,因为按照解码顺序在它后面的帧可能会参考它之前的数据;RPS中图像的数量不能超过DPB的大小。
RPS使用POC标识参考帧,除了所在当前帧的POC之外,每一个slice header都直接包含(或者继承自SPS)RPS中每一帧图像的POC。
每个图像的RPS包含5个不同的参考图像表:
RefPicSetStCurrBefore:解码和输出顺序均在当前帧之前的短线参考帧,可用于当前帧的帧间预测;
RefPicSetStCurrAfter:解码顺序在当前帧之前,输出顺序在当前帧之后的短线参考帧,可用于当前帧的帧间预测;
RefPicSetStFoll:按解码顺序在当前帧之后的图像可用的短线参考帧,不能用于当前帧的帧间预测;
RefPicSetLtCurr:可用于当前帧的帧间预测的长线参考帧;
RefPicSetLtFoll:按解码顺序在当前帧之后的图像可用的长线参考帧,不能用于当前帧的帧间预测;
RPS根据参考图像类型的不同,分别使用三个循环迭代来传递数据:POC比当前帧更低的短线参考帧、POC比当前帧更高的短线参考帧、长线参考帧;除此之外,还将为每一帧传递一个标识used−by−curr−pic−X−flag来说明是否用作了当前帧的参考帧;